* [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-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 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
* 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 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
* [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-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 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 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-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 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 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-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 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 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
* 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
* [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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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 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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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 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-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 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 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-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 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-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
* 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
* [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
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
* 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
* [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
* 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 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-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 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
* 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
* [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
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
* 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
* [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
* 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
* 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
* [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 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
* 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
* [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 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.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-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
* [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
* 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
* [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
* 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.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-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
* [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 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-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 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
* 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
* [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-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 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 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-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 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 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-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 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 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-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 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 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-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 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 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-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 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 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
* [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-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 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
* 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
* [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: [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 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-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 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 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-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 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 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-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 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 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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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 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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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
* 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
* [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 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
* 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
* [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
* [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
* [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-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 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-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
* 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
* [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
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
* 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
* [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 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 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] 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, 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
@ 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, 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
* [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, 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-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, 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
* [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-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 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 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] 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] 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
[parent not found: <20151219035802.GA28424@rob-hp-laptop>]
* 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 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
* 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] 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
* [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-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 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
* 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
* [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 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
* 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 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 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
* [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 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 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-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 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
* 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
* [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
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
* 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 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 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
* [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-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 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 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-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 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 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-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 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 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-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 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 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-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 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 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 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 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 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 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
* [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] 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] 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 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
* [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] 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 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 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 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 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
* [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-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 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
* 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
* [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
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
* 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
* [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
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
* 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
* [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
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
* 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 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
* [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 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
* 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
* [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
* 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 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 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
* 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
* [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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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-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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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
* [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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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
* 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
* [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
* 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 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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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-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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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
* [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 = ð0;
+ ethernet1 = ð1;
+ };
+
+ 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
* 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
* [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
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
* 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
* [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
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
* 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
* [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
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
* 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
* [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
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
* 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
* [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
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
* 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
* [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
* 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
* 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
* [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
* 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
* 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
* [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
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
* 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
* [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
* 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
* 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
* [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 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] 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