summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ns9xxx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ns9xxx')
-rw-r--r--arch/arm/mach-ns9xxx/Kconfig604
-rw-r--r--arch/arm/mach-ns9xxx/Makefile45
-rw-r--r--arch/arm/mach-ns9xxx/cc9p9215_devices.c681
-rw-r--r--arch/arm/mach-ns9xxx/cc9p9215_devices.h45
-rw-r--r--arch/arm/mach-ns9xxx/cc9p9360_devices.c232
-rw-r--r--arch/arm/mach-ns9xxx/cc9p9360_devices.h32
-rw-r--r--arch/arm/mach-ns9xxx/ccw9p9215_devices.c379
-rw-r--r--arch/arm/mach-ns9xxx/ccw9p9215_devices.h12
-rw-r--r--arch/arm/mach-ns9xxx/ccx9c_devices.c218
-rw-r--r--arch/arm/mach-ns9xxx/ccx9c_devices.h32
-rw-r--r--arch/arm/mach-ns9xxx/clock.c128
-rw-r--r--arch/arm/mach-ns9xxx/clock.h3
-rw-r--r--arch/arm/mach-ns9xxx/cme9210_devices.c251
-rw-r--r--arch/arm/mach-ns9xxx/cme9210_devices.h26
-rw-r--r--arch/arm/mach-ns9xxx/gpio-ns921x.c41
-rw-r--r--arch/arm/mach-ns9xxx/gpio-ns9360.c122
-rw-r--r--arch/arm/mach-ns9xxx/gpio.c119
-rw-r--r--arch/arm/mach-ns9xxx/gpiolib-ns921x.c76
-rw-r--r--arch/arm/mach-ns9xxx/gpiolib-ns921x.h12
-rw-r--r--arch/arm/mach-ns9xxx/gpiolib-ns9360.c59
-rw-r--r--arch/arm/mach-ns9xxx/gpiolib-ns9360.h12
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/board.h8
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/display/CUSTOM.h18
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/display/Kconfig36
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/display/LQ057Q3DC12I.h27
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/display/LQ064V3DG01.h28
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/display/VGA.h29
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/display/displays.h46
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/dma-ns921x.h140
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/fim-firmware.h101
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/fim-ns921x.h466
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/fim-uncompress.h93
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/gpio.h470
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/hardware.h8
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/irqs.h94
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/module.h10
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/ns921x-serial.h22
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/ns9360fb.h26
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/ns9xxx-pwm.h146
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/processor.h2
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/regs-bbu.h69
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/regs-io-ns921x.h41
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/regs-iohub-ns921x.h133
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/regs-lcd-ns9360.h88
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/regs-sys-common.h47
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/regs-sys-ns921x.h154
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/regs-sys-ns9360.h37
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/spi.h28
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/system.h23
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/timex.h2
-rw-r--r--arch/arm/mach-ns9xxx/include/mach/uncompress.h185
-rw-r--r--arch/arm/mach-ns9xxx/irq-ns921x.c57
-rw-r--r--arch/arm/mach-ns9xxx/irq.c326
-rw-r--r--arch/arm/mach-ns9xxx/irq.h16
-rw-r--r--arch/arm/mach-ns9xxx/leds.c64
-rw-r--r--arch/arm/mach-ns9xxx/mach-cc7ucamry.c23
-rw-r--r--arch/arm/mach-ns9xxx/mach-cc9c.c176
-rw-r--r--arch/arm/mach-ns9xxx/mach-cc9p9215.c23
-rw-r--r--arch/arm/mach-ns9xxx/mach-cc9p9215js.c192
-rw-r--r--arch/arm/mach-ns9xxx/mach-cc9p9360js.c187
-rw-r--r--arch/arm/mach-ns9xxx/mach-ccw9c.c176
-rw-r--r--arch/arm/mach-ns9xxx/mach-ccw9p9215.c23
-rw-r--r--arch/arm/mach-ns9xxx/mach-ccw9p9215js.c242
-rw-r--r--arch/arm/mach-ns9xxx/mach-cme9210.c24
-rw-r--r--arch/arm/mach-ns9xxx/mach-cme9210js.c109
-rw-r--r--arch/arm/mach-ns9xxx/mach-inc20otter.c23
-rw-r--r--arch/arm/mach-ns9xxx/mach-otter.c23
-rw-r--r--arch/arm/mach-ns9xxx/ns9215_devices.c299
-rw-r--r--arch/arm/mach-ns9xxx/ns9215_devices.h14
-rw-r--r--arch/arm/mach-ns9xxx/ns921x_devices.c798
-rw-r--r--arch/arm/mach-ns9xxx/ns921x_devices.h37
-rw-r--r--arch/arm/mach-ns9xxx/ns9360_devices.c813
-rw-r--r--arch/arm/mach-ns9xxx/ns9360_devices.h32
-rw-r--r--arch/arm/mach-ns9xxx/pm-ns921x.c173
-rw-r--r--arch/arm/mach-ns9xxx/processor-ns921x.c379
-rw-r--r--arch/arm/mach-ns9xxx/processor-ns921x.h44
-rw-r--r--arch/arm/mach-ns9xxx/processor-ns9360.c75
-rw-r--r--arch/arm/mach-ns9xxx/processor-ns9360.h30
-rw-r--r--arch/arm/mach-ns9xxx/time-ns921x.c195
-rw-r--r--arch/arm/mach-ns9xxx/time-ns9360.c5
80 files changed, 9812 insertions, 472 deletions
diff --git a/arch/arm/mach-ns9xxx/Kconfig b/arch/arm/mach-ns9xxx/Kconfig
index dd0cd5ac4b8b..7edebdcf1c59 100644
--- a/arch/arm/mach-ns9xxx/Kconfig
+++ b/arch/arm/mach-ns9xxx/Kconfig
@@ -2,29 +2,149 @@ if ARCH_NS9XXX
menu "NS9xxx Implementations"
-config NS9XXX_HAVE_SERIAL8250
+config DIGI_UNSUPPORTED
+ def_bool n
+ help
+ This symbol is used to disable some options in the kernel
+ configuration that are not supported by Digi Embedded Linux.
+
+config PROCESSOR_NS921X
+ bool
+
+config RESET_DISABLED_MODULES
+ bool "reset disabled modules"
+ depends on BROKEN && PROCESSOR_NS921X
+ help
+ If you say Y here, cpu components that are not used are not only
+ disabled in the SYS_CLOCK register but also reset using the SYS_RESET
+
+ Currently this breaks the serial console.
+
+config PROCESSOR_NS9210
+ bool
+ select PROCESSOR_NS921X
+
+config PROCESSOR_NS9215
bool
+ select PROCESSOR_NS921X
config PROCESSOR_NS9360
bool
+ select USB_ARCH_HAS_OHCI
+
+config MODULE_CC9C
+ bool
+ select PROCESSOR_NS9360
+
+config MODULE_CC7UCAMRY
+ bool
+ select PROCESSOR_NS9210
+
+config MODULE_CC9P9215
+ bool
+ select PROCESSOR_NS9215
+
+config MODULE_CCW9P9215
+ bool
+ select PROCESSOR_NS9215
config MODULE_CC9P9360
bool
select PROCESSOR_NS9360
+config MODULE_CME9210
+ bool
+ select PROCESSOR_NS9210
+
+config MODULE_CCW9C
+ bool
+ select PROCESSOR_NS9360
+
+config MODULE_INC20OTTER
+ bool
+ select PROCESSOR_NS9210
+
config BOARD_A9M9750DEV
- select NS9XXX_HAVE_SERIAL8250
+ bool
+
+config BOARD_JSCC9P9215
+ bool
+
+config BOARD_JSCCW9P9215
bool
config BOARD_JSCC9P9360
bool
+config BOARD_JSCME9210
+ bool
+
+config BOARD_UNCBAS
+ bool
+
+choice
+ prompt "NS9xxx Implementations"
+
+config MACH_CC7UCAMRY
+ bool "ConnectCore 7U Camry"
+ depends on DIGI_UNSUPPORTED
+ select MODULE_CC7UCAMRY
+ select BOARD_UNCBAS
+ help
+ Say Y here if you are using the CC7U Camry module.
+
+ This is a modified ConnectCore 7U with an NS9210 processor
+ instead of an NS7520.
+
+config MACH_CC9C
+ bool "ConnectCore 9C"
+ select MODULE_CC9C
+ help
+ Say Y here if you are using the ConnectCore 9C.
+
+config MACH_CCW9C
+ bool "ConnectCore Wi-9C"
+ select MODULE_CCW9C
+ help
+ Say Y here if you are using the ConnectCore Wi-9C.
+
+config MACH_CC9P9215
+ bool "ConnectCore 9P 9215"
+ select MODULE_CC9P9215
+ help
+ Say Y here if you are using the ConnectCore 9P 9215 module on an
+ currently unsupported board.
+
+config MACH_CC9P9215JS
+ bool "ConnectCore 9P 9215 on a JSCC9P9215 Devboard"
+ select MODULE_CC9P9215
+ select BOARD_JSCC9P9215
+ help
+ Say Y here if you are using the ConnectCore 9P 9215 module
+ on a JSCC9P9215 Development Board.
+
+config MACH_CCW9P9215
+ bool "ConnectCore Wi-9P 9215"
+ select MODULE_CCW9P9215
+ help
+ Say Y here if you are using the ConnectCore Wi-9P 9215 module on an
+ currently unsupported board.
+
+config MACH_CCW9P9215JS
+ bool "ConnectCore Wi-9P 9215 on a JSCCW9P9215 Devboard"
+ select MODULE_CCW9P9215
+ select BOARD_JSCCW9P9215
+ help
+ Say Y here if you are using the ConnectCore Wi-9P 9215 module
+ on a JSCCW9P9215 Development Board.
+
config MACH_CC9P9360DEV
bool "ConnectCore 9P 9360 on an A9M9750 Devboard"
+ depends on DIGI_UNSUPPORTED
select MODULE_CC9P9360
select BOARD_A9M9750DEV
help
- Say Y here if you are using the Digi ConnectCore 9P 9360
+ Say Y here if you are using the ConnectCore 9P 9360
on an A9M9750 Development Board.
config MACH_CC9P9360JS
@@ -32,8 +152,482 @@ config MACH_CC9P9360JS
select MODULE_CC9P9360
select BOARD_JSCC9P9360
help
- Say Y here if you are using the Digi ConnectCore 9P 9360
- on an JSCC9P9360 Development Board.
+ Say Y here if you are using the ConnectCore 9P 9360
+ on a JSCC9P9360 Development Board.
+
+config MACH_CME9210
+ bool "Digi Connect ME 9210"
+ select MODULE_CME9210
+
+config MACH_CME9210JS
+ bool "Digi Connect ME 9210 on Devboard"
+ select MODULE_CME9210
+ select BOARD_JSCME9210
+
+config MACH_INC20OTTER
+ bool "Inc20-Otter"
+ depends on DIGI_UNSUPPORTED
+ select MODULE_INC20OTTER
+
+config MACH_OTTER
+ bool "Otter"
+ depends on DIGI_UNSUPPORTED
+ select PROCESSOR_NS9210
+
+endchoice
+
+config NS9XXX_HAVE_GPIO_LIB
+ bool "Use GPIO_LIB" if DIGI_UNSUPPORTED
+ default y
+ select ARCH_REQUIRE_GPIOLIB
+
+if (MACH_CC9C || MACH_CCW9C)
+
+comment "ConnectCore 9C/Wi-9C configuration"
+
+config CCX9C_SERIAL_PORTA
+ bool "Serial port A"
+ default y
+ depends on SERIAL_NS9360 && !CCX9C_SPI_PORTA
+
+choice
+ prompt "port configuration"
+ depends on CCX9C_SERIAL_PORTA
+ default CCX9C_SERIAL_PORTA_FULL
+
+config CCX9C_SERIAL_PORTA_RXTX
+ bool "RX/TX only"
+
+config CCX9C_SERIAL_PORTA_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CCX9C_SERIAL_PORTA_FULL
+ bool "Full port"
+
+endchoice
+
+config CCX9C_SPI_PORTA
+ bool "SPI port A"
+ default n
+ depends on SPI_NS9360
+
+config CCX9C_SERIAL_PORTB
+ bool "Serial port B"
+ default y
+ depends on SERIAL_NS9360 && !CCX9C_SPI_PORTB
+
+choice
+ prompt "port configuration"
+ depends on CCX9C_SERIAL_PORTB
+ default CCX9C_SERIAL_PORTB_FULL
+
+config CCX9C_SERIAL_PORTB_RXTX
+ bool "RX/TX only"
+
+config CCX9C_SERIAL_PORTB_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CCX9C_SERIAL_PORTB_FULL
+ bool "Full port"
+
+endchoice
+
+config CCX9C_SPI_PORTB
+ bool "SPI port B"
+ default y
+ depends on SPI_NS9360
+
+config CCX9C_SERIAL_PORTC
+ bool "Serial port C"
+ default y
+ depends on SERIAL_NS9360 && !CCX9C_SPI_PORTC && !CCX9C_FB
+
+choice
+ prompt "port configuration"
+ depends on CCX9C_SERIAL_PORTC
+ default CCX9C_SERIAL_PORTC_FULL
+
+config CCX9C_SERIAL_PORTC_RXTX
+ bool "RX/TX only"
+
+config CCX9C_SERIAL_PORTC_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CCX9C_SERIAL_PORTC_FULL
+ bool "Full port"
+
+endchoice
+
+config CCX9C_SPI_PORTC
+ bool "SPI port C"
+ default n
+ depends on SPI_NS9360 && !CCX9C_FB
+
+config CCX9C_SERIAL_PORTD
+ bool "Serial port D"
+ default y
+ depends on SERIAL_NS9360 && !CCX9C_SPI_PORTD && !CCX9C_FB
+
+choice
+ prompt "port configuration"
+ depends on CCX9C_SERIAL_PORTD
+ default CCX9C_SERIAL_PORTD_FULL
+
+config CCX9C_SERIAL_PORTD_RXTX
+ bool "RX/TX only"
+
+config CCX9C_SERIAL_PORTD_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CCX9C_SERIAL_PORTD_FULL
+ bool "Full port"
+
+endchoice
+
+config CCX9C_SPI_PORTD
+ bool "SPI port D"
+ default n
+ depends on SPI_NS9360 && !CCX9C_FB
+
+config CCX9C_FB
+ bool "Framebuffer"
+ default y
+ depends on FB_NS9360
+
+config CCX9C_TOUCH
+ bool "Touchscreen"
+ default y
+ depends on TOUCHSCREEN_ADS7846 && CCX9C_FB && CCX9C_SPI_PORTB
+
+endif ## if (MACH_CC9C || MACH_CCW9C)
+
+
+if (MACH_CC9P9215JS || MACH_CCW9P9215JS)
+
+comment "ConnectCore 9P/Wi-9P 9215 configuration"
+
+config CC9P9215JS_SERIAL_PORTA
+ bool "Serial port A"
+ default y
+ depends on SERIAL_NS921X && !CC9P9215JS_SPI
+
+choice
+ prompt "port configuration"
+ depends on CC9P9215JS_SERIAL_PORTA
+ default CC9P9215JS_SERIAL_PORTA_FULL
+
+config CC9P9215JS_SERIAL_PORTA_RXTX
+ bool "RX/TX only"
+
+config CC9P9215JS_SERIAL_PORTA_RXTX485
+ bool "RX/TX/RTS (RTS for RS-485 transceiver control)"
+ help
+ This mode enables the RS-485 transceiver control functionality
+ of the RTS line in the serial port.
+
+config CC9P9215JS_SERIAL_PORTA_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CC9P9215JS_SERIAL_PORTA_FULL
+ bool "Full port"
+
+endchoice
+
+config CC9P9215JS_SERIAL_PORTB
+ bool "Serial port B"
+ default y
+ depends on SERIAL_NS921X
+
+choice
+ prompt "port configuration"
+ depends on CC9P9215JS_SERIAL_PORTB
+ default CC9P9215JS_SERIAL_PORTB_FULL
+
+config CC9P9215JS_SERIAL_PORTB_RXTX
+ bool "RX/TX only"
+
+config CC9P9215JS_SERIAL_PORTB_RXTX485
+ bool "RX/TX/RTS (RTS for RS-485 transceiver control)"
+ help
+ This mode enables the RS-485 transceiver control functionality
+ of the RTS line in the serial port.
+
+config CC9P9215JS_SERIAL_PORTB_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CC9P9215JS_SERIAL_PORTB_FULL
+ bool "Full port"
+
+endchoice
+
+config CC9P9215JS_SERIAL_PORTC
+ bool "Serial port C"
+ default y
+ depends on SERIAL_NS921X
+
+choice
+ prompt "port configuration"
+ depends on CC9P9215JS_SERIAL_PORTC
+ default CC9P9215JS_SERIAL_PORTC_FULL
+
+config CC9P9215JS_SERIAL_PORTC_RXTX
+ bool "RX/TX only"
+
+config CC9P9215JS_SERIAL_PORTC_RXTX485
+ bool "RX/TX/RTS (RTS for RS-485 transceiver control)"
+ help
+ This mode enables the RS-485 transceiver control functionality
+ of the RTS line in the serial port.
+
+config CC9P9215JS_SERIAL_PORTC_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CC9P9215JS_SERIAL_PORTC_FULL
+ bool "Full port"
+
+endchoice
+
+config CC9P9215JS_SERIAL_PORTD
+ bool "Serial port D"
+ default y
+ depends on SERIAL_NS921X
+
+choice
+ prompt "port configuration"
+ depends on CC9P9215JS_SERIAL_PORTD
+ default CC9P9215JS_SERIAL_PORTD_FULL
+
+config CC9P9215JS_SERIAL_PORTD_RXTX
+ bool "RX/TX only"
+
+config CC9P9215JS_SERIAL_PORTD_RXTX485
+ bool "RX/TX/RTS (RTS for RS-485 transceiver control)"
+ help
+ This mode enables the RS-485 transceiver control functionality
+ of the RTS line in the serial port.
+
+config CC9P9215JS_SERIAL_PORTD_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CC9P9215JS_SERIAL_PORTD_FULL
+ bool "Full port"
+
+endchoice
+
+config CC9P9215JS_SPI
+ bool "SPI port"
+ default y
+ depends on SPI_NS921X
+
+config CC9P9215JS_EDT_DISPLAY_QVGA
+ bool "Support for the EDT QVGA TFT Display"
+ default n
+ select FB_HX8347
+
+config CC9P9215JS_TOUCH
+ bool "Touchscreen"
+ default y
+ depends on TOUCHSCREEN_ADS7846 && CC9P9215JS_EDT_DISPLAY_QVGA && CC9P9215JS_SPI
+
+endif ## if (MACH_CC9P9215JS || MACH_CCW9P9215JS)
+
+
+if MACH_CC9P9360JS
+
+comment "ConnectCore 9P 9360 configuration"
+
+config CC9P9360JS_SERIAL_PORTA
+ bool "Serial port A"
+ default y
+ depends on SERIAL_NS9360 && !CC9P9360JS_SPI_PORTA
+
+choice
+ prompt "port configuration"
+ depends on CC9P9360JS_SERIAL_PORTA
+ default CC9P9360JS_SERIAL_PORTA_FULL
+
+config CC9P9360JS_SERIAL_PORTA_RXTX
+ bool "RX/TX only"
+
+config CC9P9360JS_SERIAL_PORTA_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CC9P9360JS_SERIAL_PORTA_FULL
+ bool "Full port"
+
+endchoice
+
+config CC9P9360JS_SPI_PORTA
+ bool "SPI port A"
+ default n
+ depends on SPI_NS9360
+
+config CC9P9360JS_SERIAL_PORTB
+ bool "Serial port B"
+ default y
+ depends on SERIAL_NS9360 && !CC9P9360JS_SPI_PORTB
+
+choice
+ prompt "port configuration"
+ depends on CC9P9360JS_SERIAL_PORTB
+ default CC9P9360JS_SERIAL_PORTB_FULL
+
+config CC9P9360JS_SERIAL_PORTB_RXTX
+ bool "RX/TX only"
+
+config CC9P9360JS_SERIAL_PORTB_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CC9P9360JS_SERIAL_PORTB_FULL
+ bool "Full port"
+
+endchoice
+
+config CC9P9360JS_SPI_PORTB
+ bool "SPI port B"
+ default y
+ depends on SPI_NS9360
+
+config CC9P9360JS_SERIAL_PORTC
+ bool "Serial port C"
+ default y
+ depends on SERIAL_NS9360 && !CC9P9360JS_SPI_PORTC && !CC9P9360JS_FB
+
+choice
+ prompt "port configuration"
+ depends on CC9P9360JS_SERIAL_PORTC
+ default CC9P9360JS_SERIAL_PORTC_FULL
+
+config CC9P9360JS_SERIAL_PORTC_RXTX
+ bool "RX/TX only"
+
+config CC9P9360JS_SERIAL_PORTC_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CC9P9360JS_SERIAL_PORTC_FULL
+ bool "Full port"
+
+endchoice
+
+config CC9P9360JS_SPI_PORTC
+ bool "SPI port C"
+ default n
+ depends on SPI_NS9360 && !CC9P9360JS_FB
+
+config CC9P9360JS_SERIAL_PORTD
+ bool "Serial port D"
+ default y
+ depends on SERIAL_NS9360 && !CC9P9360JS_SPI_PORTD && !CC9P9360JS_FB
+
+choice
+ prompt "port configuration"
+ depends on CC9P9360JS_SERIAL_PORTD
+ default CC9P9360JS_SERIAL_PORTD_FULL
+
+config CC9P9360JS_SERIAL_PORTD_RXTX
+ bool "RX/TX only"
+
+config CC9P9360JS_SERIAL_PORTD_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CC9P9360JS_SERIAL_PORTD_FULL
+ bool "Full port"
+
+endchoice
+
+config CC9P9360JS_SPI_PORTD
+ bool "SPI port D"
+ default n
+ depends on SPI_NS9360 && !CC9P9360JS_FB
+
+config CC9P9360JS_FB
+ bool "Framebuffer"
+ default y
+ depends on FB_NS9360
+
+config CC9P9360JS_TOUCH
+ bool "Touchscreen"
+ default y
+ depends on TOUCHSCREEN_ADS7846 && CC9P9360JS_FB && CC9P9360JS_SPI_PORTB
+
+# Commented out as cc9p9360 does not assemble 0 ohm R2
+# resistor which routes the RTC alarm to the CPU
+#config EXTERNAL_RTC_ALARM
+# bool "External RTC Alarm interrupt"
+# default n
+# depends on !CC9P9360JS_SERIAL_PORTA_FULL
+# help
+# This enables the interrupt coming from the external
+# I2C DS1337 Real Time Clock.
+#comment "--- External RTC Alarm interrupt (disable Serial port A Full)"
+# depends on CC9P9360JS_SERIAL_PORTA_FULL
+
+endif ## if MACH_CC9P9360JS
+
+
+if MACH_CME9210JS
+
+comment "Digi Connect ME 9210 configuration"
+
+config CME9210JS_SERIAL_PORTA
+ bool "Serial port A"
+ default y
+ depends on SERIAL_NS921X
+
+choice
+ prompt "port configuration"
+ depends on CME9210JS_SERIAL_PORTA
+ default CME9210JS_SERIAL_PORTA_RXTX
+
+config CME9210JS_SERIAL_PORTA_RXTX
+ bool "RX/TX only"
+
+config CME9210JS_SERIAL_PORTA_RXTX485
+ bool "RX/TX/RTS (RTS for RS-485 transceiver control)"
+ help
+ This mode enables the RS-485 transceiver control functionality
+ of the RTS line in the serial port.
+
+config CME9210JS_SERIAL_PORTA_CTSRTSRXTX
+ bool "CTS/RTS/RX/TX"
+
+config CME9210JS_SERIAL_PORTA_FULL
+ bool "Full port"
+
+endchoice
+
+config CME9210JS_SERIAL_PORTC
+ bool "Serial port C (only modules with JTAG-header)"
+ depends on SERIAL_NS921X && !I2C_NS9XXX
+ help
+ Enable serial port C on Connect ME9210 module. You can only
+ use this port if your module has the JTAG-header!
+ This port shares GPIOs with I2C bus, so I2C must be disabled.
+
+choice
+ prompt "port configuration"
+ depends on CME9210JS_SERIAL_PORTC
+ default CME9210JS_SERIAL_PORTC_RXTX
+
+config CME9210JS_SERIAL_PORTC_RXTX
+ bool "RX/TX only"
+
+endchoice
+
+config CME9210JS_SPI
+ bool "SPI port"
+ depends on !CME9210JS_SERIAL_PORTA
+
+config GPIO_ETH_ACTIVITY_LED
+ bool "Ethernet activity LED"
+ depends on NS9XXX_ETH
+ default y
+ help
+ Enables the use of GPIO14 as Ethernet RX/TX activity LED
+
+endif ## if MACH_CME9210JS
+
+source "arch/arm/mach-ns9xxx/include/mach/display/Kconfig"
endmenu
diff --git a/arch/arm/mach-ns9xxx/Makefile b/arch/arm/mach-ns9xxx/Makefile
index 41efaf9ad50b..63aae2d39ef3 100644
--- a/arch/arm/mach-ns9xxx/Makefile
+++ b/arch/arm/mach-ns9xxx/Makefile
@@ -1,12 +1,45 @@
-obj-y := clock.o generic.o gpio.o irq.o
+obj-y := clock.o gpio.o irq.o
+ifeq ($(CONFIG_GPIOLIB),y)
+gpio-$(CONFIG_PROCESSOR_NS921X) += gpiolib-ns921x.o
+gpio-$(CONFIG_PROCESSOR_NS9360) += gpiolib-ns9360.o
+endif
+
+obj-$(CONFIG_MACH_CC7UCAMRY) += mach-cc7ucamry.o
+obj-$(CONFIG_MACH_CC9C) += mach-cc9c.o
+obj-$(CONFIG_MACH_CC9P9215) += mach-cc9p9215.o
+obj-$(CONFIG_MACH_CC9P9215JS) += mach-cc9p9215js.o
obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
obj-$(CONFIG_MACH_CC9P9360JS) += mach-cc9p9360js.o
+obj-$(CONFIG_MACH_CME9210) += mach-cme9210.o
+obj-$(CONFIG_MACH_CME9210JS) += mach-cme9210js.o
+obj-$(CONFIG_MACH_CCW9P9215) += mach-ccw9p9215.o
+obj-$(CONFIG_MACH_CCW9P9215JS) += mach-ccw9p9215js.o
+obj-$(CONFIG_MACH_CCW9C) += mach-ccw9c.o
+obj-$(CONFIG_MACH_INC20OTTER) += mach-inc20otter.o
+obj-$(CONFIG_MACH_OTTER) += mach-otter.o
+
+obj-$(CONFIG_PROCESSOR_NS921X) += gpio-ns921x.o irq-ns921x.o processor-ns921x.o time-ns921x.o ns921x_devices.o
+obj-$(CONFIG_PROCESSOR_NS9215) += ns9215_devices.o
+obj-$(CONFIG_PROCESSOR_NS9360) += gpio-ns9360.o processor-ns9360.o time-ns9360.o ns9360_devices.o
+
+obj-$(CONFIG_MODULE_CC9P9215) += cc9p9215_devices.o
+ifeq ($(CONFIG_MODULE_CCW9P9215),y)
+CFLAGS_ccw9p9215_devices.o += -I$(srctree)/drivers/net/wireless/digiPiper/
+CFLAGS_mach-ccw9p9215js.o += -I$(srctree)/drivers/net/wireless/digiPiper/
+endif
+obj-$(CONFIG_MODULE_CCW9P9215) += cc9p9215_devices.o ccw9p9215_devices.o
+obj-$(CONFIG_MODULE_CC9P9360) += cc9p9360_devices.o
+obj-$(CONFIG_MODULE_CC9C) += ccx9c_devices.o
+obj-$(CONFIG_MODULE_CCW9C) += ccx9c_devices.o
+obj-$(CONFIG_MODULE_CME9210) += cme9210_devices.o
-obj-$(CONFIG_PROCESSOR_NS9360) += gpio-ns9360.o processor-ns9360.o time-ns9360.o
+obj-$(CONFIG_LEDS_CPU) += leds.o
-obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o
-obj-$(CONFIG_BOARD_JSCC9P9360) += board-jscc9p9360.o
+# Power Management
+obj-$(CONFIG_PM) += pm.o
+pm-$(CONFIG_PROCESSOR_NS921X) += pm-ns921x.o
+ifeq ($(CONFIG_PM_VERBOSE),y)
+CFLAGS_pm-ns921x.o += -DDEBUG
+endif
-# platform devices
-obj-$(CONFIG_NS9XXX_HAVE_SERIAL8250) += plat-serial8250.o
diff --git a/arch/arm/mach-ns9xxx/cc9p9215_devices.c b/arch/arm/mach-ns9xxx/cc9p9215_devices.c
new file mode 100644
index 000000000000..9de10e6e9666
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/cc9p9215_devices.c
@@ -0,0 +1,681 @@
+/*
+ * arch/arm/mach-ns9xxx/cc9p9215_devices.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/clk.h>
+#include <linux/gpio.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <mach/fim-ns921x.h>
+#include <mach/hardware.h>
+#include <mach/regs-sys-common.h>
+#include <mach/regs-sys-ns921x.h>
+#include <mach/regs-mem.h>
+
+#include <video/hx8347fb.h>
+#include <linux/fb.h>
+#include <linux/mmc/host.h>
+#include <linux/w1-gpio.h>
+
+#include "ns921x_devices.h"
+#include "cc9p9215_devices.h"
+#include "clock.h"
+
+/*
+ * Pick Digi's internal FIM board
+ * Use internal board, defined to 1
+ * Use newer boards, defined to 0
+ */
+#if 0
+#define INT_FIM_BOARD
+#endif
+
+#if defined(CONFIG_NS9XXX_ETH) || defined(CONFIG_NS9XXX_ETH_MODULE)
+static int cc9p9215_phy_endisable(struct clk *clk, int enable)
+{
+ int ret;
+
+ if (enable) {
+ ret = gpio_request(90, "ns9xxx-eth-phy");
+ if (ret)
+ return ret;
+
+ gpio_direction_output(90, 1);
+ } else {
+ gpio_set_value(90, 0);
+ gpio_free(90);
+ }
+
+ return 0;
+}
+
+static struct clk phyclk = {
+ .name = "ns9xxx-eth-phy",
+ .id = -1,
+ .owner = THIS_MODULE,
+ .endisable = cc9p9215_phy_endisable,
+};
+
+void __init ns9xxx_add_device_cc9p9215_eth(void)
+{
+ int gpio[] = {32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49};
+ int func[] = {0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int dir[] = {0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ if (clk_register(&phyclk))
+ return;
+
+ ns9xxx_add_device_ns921x_eth(&phyclk, 0, gpio, func,
+ dir, ARRAY_SIZE(gpio));
+}
+#else
+void __init ns9xxx_add_device_cc9p9215_eth(void) {}
+#endif
+
+#if defined(CONFIG_I2C_NS9XXX) || defined(CONFIG_I2C_NS9XXX_MODULE)
+static void cc9p9215_i2c_gpio_reconfigure(void)
+{
+ gpio_configure_ns921x(102, 0, 0, 2, 0);
+ gpio_configure_ns921x(103, 0, 0, 2, 0);
+}
+
+static struct plat_ns9xxx_i2c ns9xxx_device_cc9p9215_i2c_data = {
+ .gpio_scl = 102,
+ .gpio_sda = 103,
+ .speed = 100000,
+ .gpio_configuration_func = cc9p9215_i2c_gpio_reconfigure,
+};
+
+void __init ns9xxx_add_device_cc9p9215_i2c(void)
+{
+ ns9xxx_add_device_ns921x_i2c(&ns9xxx_device_cc9p9215_i2c_data);
+}
+#else
+void __init ns9xxx_add_device_cc9p9215_i2c(void) {}
+#endif
+
+#if defined(CONFIG_SERIAL_NS921X) || defined(CONFIG_SERIAL_NS921X_MODULE)
+void __init ns9xxx_add_device_cc9p9215_uarta(int gpio_nr)
+{
+ ns9xxx_add_device_ns921x_uarta(0, gpio_nr, 0);
+}
+
+void __init ns9xxx_add_device_cc9p9215_uartb(int gpio_nr)
+{
+ ns9xxx_add_device_ns921x_uartb(51, gpio_nr, 0);
+}
+
+void __init ns9xxx_add_device_cc9p9215_uartc(int gpio_nr)
+{
+ ns9xxx_add_device_ns921x_uartc(8, gpio_nr, 0);
+}
+
+void __init ns9xxx_add_device_cc9p9215_uartd(int gpio_nr)
+{
+ ns9xxx_add_device_ns921x_uartd(59, gpio_nr, 0);
+}
+#else
+void __init ns9xxx_add_device_cc9p9215_uarta(int gpio_nr) {}
+void __init ns9xxx_add_device_cc9p9215_uartb(int gpio_nr) {}
+void __init ns9xxx_add_device_cc9p9215_uartc(int gpio_nr) {}
+void __init ns9xxx_add_device_cc9p9215_uartd(int gpio_nr) {}
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP)
+static struct physmap_flash_data ns9xxx_device_cc9p9215_flash_data = {
+ .width = 2,
+};
+
+void __init ns9xxx_add_device_cc9p9215_flash(void)
+{
+ ns9xxx_add_device_ns921x_flash(&ns9xxx_device_cc9p9215_flash_data);
+}
+#else
+void __init ns9xxx_add_device_cc9p9215_flash(void) {}
+#endif
+
+#if defined(CONFIG_SPI_NS921X) || defined(CONFIG_SPI_NS921X_MODULE)
+/* SPI ports and their related GPIOs */
+static struct spi_ns9xxx_data ns9xxx_device_cc9p9215_spi_data = {
+ .gpios = {7, 3, 5, 0},
+ .gpio_funcs = { NS921X_GPIO_FUNC_4,
+ NS921X_GPIO_FUNC_4,
+ NS921X_GPIO_FUNC_4,
+ NS921X_GPIO_FUNC_4 },
+ .nr_gpios = 4,
+};
+
+void __init ns9xxx_add_device_cc9p9215_spi(void) {
+ ns9xxx_add_device_ns921x_spi(&ns9xxx_device_cc9p9215_spi_data);
+}
+#else
+void __init ns9xxx_add_device_cc9p9215_spi(void) {}
+#endif
+
+
+#if defined(CONFIG_FIM_ZERO_SERIAL)
+static struct fim_serial_platform_data fim_serial_data0 = {
+ .fim_nr = 0,
+#if defined(CONFIG_FIM_ZERO_SERIAL_CTSRTS)
+ NS921X_FIM_SERIAL_GPIOS(69, 68, /* RX + TX */
+ 70, 71, /* RTS + CTS */
+ NS921X_GPIO_FUNC_0),
+#else
+ NS921X_FIM_SERIAL_GPIOS(69, 68, /* RX + TX */
+ FIM_GPIO_DONT_USE, /* RTS */
+ FIM_GPIO_DONT_USE, /* CTS */
+ NS921X_GPIO_FUNC_0),
+#endif
+};
+struct platform_device ns921x_fim_serial0 = {
+ .name = "fim-serial",
+ .id = 0,
+ .dev.platform_data = &fim_serial_data0,
+};
+EXPORT_SYMBOL(ns921x_fim_serial0);
+#endif /* CONFIG_FIM_ZERO_SERIAL */
+
+#if defined(CONFIG_FIM_ONE_SERIAL)
+static struct fim_serial_platform_data fim_serial_data1 = {
+ .fim_nr = 1,
+#if defined(CONFIG_FIM_ONE_SERIAL_CTSRTS)
+ NS921X_FIM_SERIAL_GPIOS(73, 72, /* RX + TX */
+ 74, 75, /* RTS + CTS */
+ NS921X_GPIO_FUNC_1),
+#else
+ NS921X_FIM_SERIAL_GPIOS(73, 72, /* RX + TX */
+ FIM_GPIO_DONT_USE, /* RTS */
+ FIM_GPIO_DONT_USE, /* CTS */
+ NS921X_GPIO_FUNC_1),
+#endif
+};
+struct platform_device ns921x_fim_serial1 = {
+ .name = "fim-serial",
+ .id = 1,
+ .dev.platform_data = &fim_serial_data1,
+};
+EXPORT_SYMBOL(ns921x_fim_serial1);
+#endif /* CONFIG_FIM_ONE_SERIAL */
+
+
+#if defined(CONFIG_FIM_ZERO_SDIO)
+static struct fim_sdio_platform_data fim_sdio_data0 = {
+ .fim_nr = 0,
+ .host_caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ,
+#if defined(INT_FIM_BOARD)
+ NS921X_FIM_SDIO_GPIOS(68, 69, 70, 71, /* D0 to D3 */
+ 72, 73, /* WP + CD */
+ 76, 77, /* CLK + CMD */
+ NS921X_GPIO_FUNC_0),
+#else
+ NS921X_FIM_SDIO_GPIOS_FIM(68, 69, 70, 71, /* D0 to D3 */
+ 76, 77, /* CLK + CMD */
+ NS921X_GPIO_FUNC_0),
+ .cd_gpio_nr = 101, /* CD as external intrrupt */
+ .cd_gpio_func = NS921X_GPIO_FUNC_2,
+
+ .wp_gpio_nr = 100, /* WP as normal GPIO */
+ .wp_gpio_func = NS921X_GPIO_FUNC_3,
+#endif
+};
+struct platform_device ns921x_fim_sdio0 = {
+ .name = "fim-sdio",
+ .id = 0,
+ .dev.platform_data = &fim_sdio_data0,
+};
+EXPORT_SYMBOL(ns921x_fim_sdio0);
+#endif /* CONFIG_FIM_ZERO_SDIO */
+
+
+#if defined(CONFIG_FIM_ONE_SDIO)
+static struct fim_sdio_platform_data fim_sdio_data1 = {
+ .fim_nr = 1,
+ .host_caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ,
+#if defined(INT_FIM_BOARD)
+ NS921X_FIM_SDIO_GPIOS(68, 69, 70, 71, /* D0 to D3 */
+ 72, 73, /* WP + CD */
+ 76, 77, /* CLK + CMD */
+ NS921X_GPIO_FUNC_1),
+#else
+ NS921X_FIM_SDIO_GPIOS_FIM(72, 73, 74, 75, /* D0 to D3 */
+ 78, 79, /* CLK + CMD */
+ NS921X_GPIO_FUNC_1),
+ .cd_gpio_nr = 101, /* CD as external intrrupt */
+ .cd_gpio_func = NS921X_GPIO_FUNC_2,
+
+ .wp_gpio_nr = 100, /* WP as normal GPIO */
+ .wp_gpio_func = NS921X_GPIO_FUNC_3,
+#endif
+};
+struct platform_device ns921x_fim_sdio1 = {
+ .name = "fim-sdio",
+ .id = 1,
+ .dev.platform_data = &fim_sdio_data1,
+};
+EXPORT_SYMBOL(ns921x_fim_sdio1);
+#endif /* CONFIG_FIM_ONE_SDIO */
+
+
+#if defined(CONFIG_FIM_ZERO_CAN) || defined(CONFIG_PROCESSOR_NS9215)
+static struct fim_can_platform_data fim_can_data0 = {
+ .fim_nr = 0,
+ .fim_can_bitrate = 500000,
+ NS921X_FIM_CAN_GPIOS( 96, 97, /* RX + TX */
+ NS921X_GPIO_FUNC_2),
+};
+struct platform_device ns921x_fim_can0 = {
+ .name = "fim-can",
+ .id = 0,
+ .dev.platform_data = &fim_can_data0,
+};
+EXPORT_SYMBOL(ns921x_fim_can0);
+#endif /* CONFIG_FIM_ZERO_CAN */
+
+#if defined(CONFIG_FIM_ONE_CAN)
+static struct fim_can_platform_data fim_can_data1 = {
+ .fim_nr = 1,
+ .fim_can_bitrate = 500000,
+#if defined(INT_FIM_BOARD)
+ NS921X_FIM_CAN_GPIOS( 68, 69, /* RX + TX */
+ NS921X_GPIO_FUNC_2),
+#else
+ NS921X_FIM_CAN_GPIOS( 98, 99, /* RX + TX */
+ NS921X_GPIO_FUNC_2),
+#endif
+};
+struct platform_device ns921x_fim_can1 = {
+ .name = "fim-can",
+ .id = 1,
+ .dev.platform_data = &fim_can_data1,
+};
+EXPORT_SYMBOL(ns921x_fim_can1);
+#endif /* CONFIG_FIM_ONE_CAN */
+
+#if defined(CONFIG_FIM_ZERO_W1)
+static struct w1_gpio_platform_data fim_w1_data0 = {
+ .pin = 68,
+ .is_open_drain = 0,
+};
+struct platform_device ns921x_fim0_w1 = {
+ .name = "w1-gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &fim_w1_data0,
+ },
+};
+EXPORT_SYMBOL(ns921x_fim0_w1);
+#endif /* CONFIG_FIM_ZERO_W1 */
+
+#if defined(CONFIG_FIM_ONE_W1)
+static struct w1_gpio_platform_data fim_w1_data1 = {
+ .pin = 72,
+ .is_open_drain = 0,
+};
+struct platform_device ns921x_fim1_w1 = {
+ .name = "w1-gpio",
+ .id = 1,
+ .dev = {
+ .platform_data = &fim_w1_data1,
+ },
+};
+EXPORT_SYMBOL(ns921x_fim1_w1);
+#endif /* CONFIG_FIM_ONE_W1 */
+
+#if defined(CONFIG_FIM_ZERO_USB)
+static struct fim_usb_platform_data fim_usb_data0 = {
+ .fim_nr = 0,
+
+ /* The setup of the pull-ups must be fixed in the driver, however print a warning */
+#if defined(INT_FIM_BOARD)
+#warning "Internal FIM board has a different pull-ups configuration"
+ NS921X_FIM_USB_GPIOS(68, 69, 70, 71, /* VP + VM + RCV + OE_L */
+ 72, 73, /* ENUM + SPND */
+ NS921X_GPIO_FUNC_0,
+ NS921X_GPIO_FUNC_GPIO),
+#else
+ NS921X_FIM_USB_GPIOS(68, 69, 70, 71, /* VP + VM + RCV + OE_L */
+ 76, 77, /* ENUM + SPND */
+ NS921X_GPIO_FUNC_0,
+ NS921X_GPIO_FUNC_GPIO),
+#endif
+};
+struct platform_device ns921x_fim_usb0 = {
+ .name = "fim-usb",
+ .id = 0,
+ .dev.platform_data = &fim_usb_data0,
+};
+EXPORT_SYMBOL(ns921x_fim_usb0);
+#endif /* CONFIG_FIM_ZERO_USB */
+
+#if defined(CONFIG_FIM_ONE_USB)
+static struct fim_usb_platform_data fim_usb_data1 = {
+ .fim_nr = 1,
+ NS921X_FIM_USB_GPIOS(72, 73, 74, 75, /* VP + VM + RCV + OE_L */
+ 78, 79, /* ENUM + SPND */
+ NS921X_GPIO_FUNC_1,
+ NS921X_GPIO_FUNC_GPIO),
+};
+struct platform_device ns921x_fim_usb1 = {
+ .name = "fim-usb",
+ .id = 1,
+ .dev.platform_data = &fim_usb_data1,
+};
+EXPORT_SYMBOL(ns921x_fim_usb1);
+#endif /* CONFIG_FIM_ONE_USB */
+
+#if defined(CONFIG_CC9P9215JS_EDT_DISPLAY_QVGA)
+#ifdef CONFIG_CC9P9215JS_DISPLAY_USES_DMA
+#include <mach/dma-ns921x.h>
+struct ext_dma_desc_t dmadesc[3];
+#endif
+
+void __init cc9p9215_edt_qvga_lcd_setup_cs(void)
+{
+ /* LCD required the extended wait register to be set */
+ writel(3, MEM_SMEW);
+ /* 16 bit bus width and enable exteneded wait */
+ writel(MEM_SMC_PB_1 | MEM_SMC_EW_ON | MEM_SMC_MW_16, MEM_SMC(0));
+ /* Static Memory Write Enable Delay x */
+ writel(4, MEM_SMWED(0));
+ /* Static Memory Output Enable Delay x */
+ writel(0, MEM_SMOED(0));
+ /* Static Memory Read Delay x */
+ writel(0, MEM_SMRD(0));
+ /* Static Memory Page Mode Read Delay 0 */
+ writel(0, MEM_SMPMRD(0));
+ /* Static Memory Write Delay */
+ writel(0, MEM_SMWD(0));
+ /* Static Memory Turn Round Delay x */
+ writel(0, MEM_SWT(0));
+ /* Enable the CS0 access */
+ writel(readl(SYS_SMCSSMM(0)) | SYS_SMCSSMM_CSEx_EN, SYS_SMCSSMM(0));
+}
+
+
+int cc9p9215_edt_qvga_lcd_register_gpios(struct hx8347fb_pdata *pdata)
+{
+ if (gpio_request(pdata->rst_gpio, "lcd-rst"))
+ goto err;
+
+ gpio_direction_output(pdata->rst_gpio, 0);
+
+ if (gpio_request(pdata->enable_gpio, "lcd-enable"))
+ goto err1;
+
+ gpio_direction_output(pdata->enable_gpio, 0);
+
+ return 0;
+err1:
+ gpio_free(pdata->rst_gpio);
+err:
+ return -EBUSY;
+}
+
+/* Configuration for the EDT QVGA display, most of the settings have
+ * been taken from a Himax application note */
+unsigned char edt_qvga_lcd_init[][3] = {
+ /* Index, value, delay to write next register in ms*/
+ {0x46, 0x94, 0},
+ {0x47, 0x41, 0},
+ {0x48, 0x00, 0},
+ {0x49, 0x33, 0},
+ {0x4a, 0x23, 0},
+ {0x4b, 0x45, 0},
+ {0x4c, 0x44, 0},
+ {0x4d, 0x77, 0},
+ {0x4e, 0x12, 0},
+ {0x4f, 0xcc, 0},
+ {0x50, 0x46, 0},
+ {0x51, 0x82, 0},
+ {0x02, 0x00, 0}, /* Column address start 2 */
+ {0x03, 0x00, 0}, /* Column address start 1 */
+ {0x04, 0x01, 0}, /* Column address end 2 */
+ {0x05, 0x3f, 0}, /* Column address end 1 */
+ {0x06, 0x00, 0}, /* Row address start 2 */
+ {0x07, 0x00, 0}, /* Row address start 1 */
+ {0x08, 0x00, 0}, /* Row address end 2 */
+ {0x09, 0xef, 0}, /* Row address end 1 */
+ {0x01, 0x06, 0},
+ {0x16, 0x68, 0},
+ {0x23, 0x95, 0},
+ {0x24, 0x95, 0},
+ {0x25, 0xff, 0},
+ {0x27, 0x02, 0},
+ {0x28, 0x02, 0},
+ {0x29, 0x02, 0},
+ {0x2a, 0x02, 0},
+ {0x2c, 0x02, 0},
+ {0x2d, 0x02, 0},
+ {0x3a, 0x01, 0},
+ {0x3b, 0x01, 0},
+ {0x3c, 0xf0, 0},
+ {0x3d, 0x00, 20},
+ {0x35, 0x38, 0},
+ {0x36, 0x78, 0},
+ {0x3e, 0x38, 0},
+ {0x40, 0x0f, 0},
+ {0x41, 0xf0, 0},
+ {0x19, 0x49, 0},
+ {0x93, 0x0f, 10},
+ {0x20, 0x40, 0},
+ {0x1d, 0x07, 0},
+ {0x1e, 0x00, 0},
+ {0x1f, 0x04, 0},
+ {0x44, 0x40, 0},
+ {0x45, 0x12, 10},
+ {0x1c, 0x04, 20},
+ {0x43, 0x80, 5},
+ {0x1b, 0x08, 40},
+ {0x1b, 0x10, 40},
+ {0x90, 0x7f, 0},
+ {0x26, 0x04, 40},
+ {0x26, 0x24, 0},
+ {0x26, 0x2c, 40},
+ {0x26, 0x3c, 0},
+ {0x57, 0x02, 0},
+ {0x55, 0x00, 0},
+ {0x57, 0x00, 0}
+};
+
+
+static void cc9p9215_lcd_reset(struct hx8347fb_par *par)
+{
+ gpio_set_value(par->pdata->rst_gpio, 0);
+ mdelay(100);
+ gpio_set_value(par->pdata->rst_gpio, 1);
+}
+
+static void cc9p9215_lcd_enable(struct hx8347fb_par *par, int state)
+{
+ gpio_set_value(par->pdata->enable_gpio, state);
+}
+
+static void cc9p9215_lcd_set_idx(struct hx8347fb_par *par, u8 idx)
+{
+ writeb(idx, par->mmio_cmd);
+}
+
+static void cc9p9215_lcd_wr_reg(struct hx8347fb_par *par, u8 reg, u16 data)
+{
+ writeb(reg, par->mmio_cmd);
+ writew(data, par->mmio_data);
+}
+
+#ifdef CONFIG_CC9P9215JS_DISPLAY_USES_DMA
+static irqreturn_t fb_extdma(int irq, void *dev_id)
+{
+ u32 status;
+
+ status = readl(NS921X_DMA_STIE(1));
+
+ if (status & (NS921X_DMA_STIE_NCIP | NS921X_DMA_STIE_NRIP)) {
+ writel(status, NS921X_DMA_STIE(1));
+ }
+
+ return IRQ_HANDLED;
+}
+#endif
+
+static void cc9p9215_lcd_wr_data(struct hx8347fb_par *par, u16 *buf, int len)
+{
+#ifdef CONFIG_CC9P9215JS_DISPLAY_USES_DMA
+#if 0
+ /* CE=0, CG=1, SW=16bit, DW=16bit, SB=16 bytes, DB=1 unit, SAI=0, DAI=1 */
+ writel(NS921X_DMA_CR_CG | NS921X_DMA_CR_SW_16b | \
+ NS921X_DMA_CR_DW_16b | NS921X_DMA_CR_SB_16B | \
+ NS921X_DMA_CR_DB_1B | NS921X_DMA_CR_DINC_N, NS921X_DMA_CR(1));
+ /* CE=1, CG=1, SW=16bit, DW=16bit, SB=16 bytes, DB=1 unit, SAI=0, DAI=1 */
+ writel(NS921X_DMA_CR_CE | readl(NS921X_DMA_CR(1)), NS921X_DMA_CR(1));*/*/*/
+#endif
+#else
+ int i, wcycles;
+ u16 *data = buf;
+
+ wcycles = len >> 1;
+
+ for (i = 0; i < wcycles; i++)
+ writew(*data++, par->mmio_data);
+#endif
+}
+
+static int cc9p9215_lcd_init(struct hx8347fb_par *par)
+{
+ int i, ret = 0;
+ u8 reg;
+
+ if (cc9p9215_edt_qvga_lcd_register_gpios(par->pdata))
+ return -EINVAL;
+
+ cc9p9215_lcd_enable(par, 0);
+ cc9p9215_lcd_reset(par);
+ cc9p9215_edt_qvga_lcd_setup_cs();
+
+ mdelay(50);
+
+ writeb(HIMAX_ID_CODE, par->mmio_cmd);
+ if ((reg = readb(par->mmio_data)) != 0x47) {
+ pr_debug("%s: HX8347 controller not detected REG[0x67] = 0x%02x\n", __func__, reg);
+ ret = -EIO;
+ goto err_detect;
+ }
+
+#ifdef CONFIG_CC9P9215JS_DISPLAY_USES_DMA
+ writel(SYS_CLOCK_EXTDMA | readl(SYS_RESET), SYS_RESET);
+ writel(SYS_CLOCK_EXTDMA | readl(SYS_CLOCK), SYS_CLOCK);
+
+ dmadesc[0].src = (u32)par->info->screen_base;
+ dmadesc[0].dest = (u32)par->info->fix.smem_start;
+ dmadesc[0].length = (u16)(par->info->fix.smem_len / 3);
+ dmadesc[0].control = EXT_DMA_DESC_CTRL_FULL;
+
+ dmadesc[1].src = (u32)(par->info->screen_base + par->info->fix.smem_len / 3);
+ dmadesc[1].dest = (u32)par->info->fix.smem_start;
+ dmadesc[1].length = (u16)(par->info->fix.smem_len / 3);
+ dmadesc[1].control = EXT_DMA_DESC_CTRL_FULL;
+
+ dmadesc[2].src = (u32)(dmadesc[1].src + par->info->fix.smem_len / 3);
+ dmadesc[2].dest = (u32)par->info->fix.smem_start;
+ dmadesc[2].length = (u16)(par->info->fix.smem_len / 3);
+ dmadesc[2].control = EXT_DMA_DESC_CTRL_WRAP | \
+ EXT_DMA_DESC_CTRL_LAST | \
+ EXT_DMA_DESC_CTRL_FULL;
+
+ /* Setup the DMA Controllers */
+ writel(&dmadesc[0], NS921X_DMA_BDP(1));
+ writel(NS921X_DMA_STIE_NCIE | NS921X_DMA_STIE_ECIE | \
+ NS921X_DMA_STIE_NRIE | NS921X_DMA_STIE_CAIE, NS921X_DMA_STIE(1));
+
+ ret = request_irq(IRQ_NS921X_EXTDMA, fb_extdma, 0, "fb_extdma", NULL);
+ if (ret) {
+ pr_debug("%s: err_request_irq_extdmairq %d -> %d\n", __func__, IRQ_NS921X_EXTDMA, ret);
+ return ret;
+ }
+#endif
+
+ for (i=0; i < (sizeof(edt_qvga_lcd_init)/3); i++) {
+
+ cc9p9215_lcd_wr_reg(par, edt_qvga_lcd_init[i][0],
+ edt_qvga_lcd_init[i][1]);
+ mdelay(edt_qvga_lcd_init[i][2]);
+ }
+
+ return 0;
+
+err_detect:
+ gpio_free(par->pdata->rst_gpio);
+ gpio_free(par->pdata->enable_gpio);
+
+ return ret;
+}
+
+static void cc9p9215_lcd_cleanup(struct hx8347fb_par *par)
+{
+ gpio_direction_input(par->pdata->rst_gpio);
+ gpio_direction_input(par->pdata->enable_gpio);
+ gpio_free(par->pdata->rst_gpio);
+ gpio_free(par->pdata->enable_gpio);
+}
+
+static struct resource cc9p9215js_lcd_res[] = {
+ {
+ .start = 0x40000000,
+ .end = 0x40000001,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0x40000002,
+ .end = 0x40000003,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS921X_EXTDMA,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct hx8347fb_pdata c9p9215js_lcd_pdata = {
+ .owner = THIS_MODULE,
+ .reset = cc9p9215_lcd_reset,
+ .bl_enable = cc9p9215_lcd_enable,
+ .init = cc9p9215_lcd_init,
+ .cleanup = cc9p9215_lcd_cleanup,
+ .set_idx = cc9p9215_lcd_set_idx,
+ .wr_reg = cc9p9215_lcd_wr_reg,
+ .wr_data = cc9p9215_lcd_wr_data,
+ .rst_gpio = 86,
+ .enable_gpio = 87,
+ .usedma = 0,
+ .xres = 320,
+ .yres = 240,
+ .bits_per_pixel = 16,
+};
+
+static struct platform_device edt_qvga_lcd = {
+ .name = "hx8347",
+ .id = 0,
+ .dev = {
+ .platform_data = &c9p9215js_lcd_pdata,
+ },
+ .resource = cc9p9215js_lcd_res,
+ .num_resources = ARRAY_SIZE(cc9p9215js_lcd_res),
+};
+
+void __init ns9xxx_add_device_cc9p9215_edt_diplay(void)
+{
+ platform_device_register(&edt_qvga_lcd);
+}
+#else
+void __init ns9xxx_add_device_cc9p9215_edt_diplay(void) {}
+#endif
+
diff --git a/arch/arm/mach-ns9xxx/cc9p9215_devices.h b/arch/arm/mach-ns9xxx/cc9p9215_devices.h
new file mode 100644
index 000000000000..916815b3a484
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/cc9p9215_devices.h
@@ -0,0 +1,45 @@
+/*
+ * arch/arm/mach-ns9xxx/cc9p9215_devices.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+void __init ns9xxx_add_device_cc9p9215_eth(void);
+void __init ns9xxx_add_device_cc9p9215_i2c(void);
+void __init ns9xxx_add_device_cc9p9215_uarta(int gpio_start);
+void __init ns9xxx_add_device_cc9p9215_uartb(int gpio_start);
+void __init ns9xxx_add_device_cc9p9215_uartc(int gpio_start);
+void __init ns9xxx_add_device_cc9p9215_uartd(int gpio_start);
+void __init ns9xxx_add_device_cc9p9215_flash(void);
+void __init ns9xxx_add_device_cc9p9215_spi(void);
+void __init ns9xxx_add_device_cc9p9215_edt_diplay(void);
+
+#define ns9xxx_add_device_cc9p9215_uarta_rxtx() \
+ ns9xxx_add_device_cc9p9215_uarta(2)
+#define ns9xxx_add_device_cc9p9215_uarta_ctsrtsrxtx() \
+ ns9xxx_add_device_cc9p9215_uarta(4)
+#define ns9xxx_add_device_cc9p9215_uarta_full() \
+ ns9xxx_add_device_cc9p9215_uarta(8)
+#define ns9xxx_add_device_cc9p9215_uartb_rxtx() \
+ ns9xxx_add_device_cc9p9215_uartb(2)
+#define ns9xxx_add_device_cc9p9215_uartb_ctsrtsrxtx() \
+ ns9xxx_add_device_cc9p9215_uartb(4)
+#define ns9xxx_add_device_cc9p9215_uartb_full() \
+ ns9xxx_add_device_cc9p9215_uartb(8)
+#define ns9xxx_add_device_cc9p9215_uartc_rxtx() \
+ ns9xxx_add_device_cc9p9215_uartc(2)
+#define ns9xxx_add_device_cc9p9215_uartc_ctsrtsrxtx() \
+ ns9xxx_add_device_cc9p9215_uartc(4)
+#define ns9xxx_add_device_cc9p9215_uartc_full() \
+ ns9xxx_add_device_cc9p9215_uartc(8)
+#define ns9xxx_add_device_cc9p9215_uartd_rxtx() \
+ ns9xxx_add_device_cc9p9215_uartd(2)
+#define ns9xxx_add_device_cc9p9215_uartd_ctsrtsrxtx() \
+ ns9xxx_add_device_cc9p9215_uartd(4)
+#define ns9xxx_add_device_cc9p9215_uartd_full() \
+ ns9xxx_add_device_cc9p9215_uartd(8)
diff --git a/arch/arm/mach-ns9xxx/cc9p9360_devices.c b/arch/arm/mach-ns9xxx/cc9p9360_devices.c
new file mode 100644
index 000000000000..12ebf16818f8
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/cc9p9360_devices.c
@@ -0,0 +1,232 @@
+/*
+ * arch/arm/mach-ns9xxx/cc9p9360_devices.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/gpio.h>
+#include <linux/platform_device.h>
+
+#include "ns9360_devices.h"
+#include "cc9p9360_devices.h"
+
+
+#if defined(CONFIG_MTD_NAND_CCX9X) || defined(CONFIG_MTD_NAND_CCX9X_MODULE)
+static struct ccx9x_nand_info ns9xxx_device_cc9p9360_nand_data = {
+ .addr_offset = 0x2000,
+ .cmd_offset = 0x4000,
+ .delay = 25,
+ .busy_pin = 49,
+};
+void __init ns9xxx_add_device_cc9p9360_nand(void)
+{
+ ns9xxx_add_device_ns9360_nand(&ns9xxx_device_cc9p9360_nand_data);
+}
+#else
+void __init ns9xxx_add_device_cc9p9360_nand(void) {}
+#endif
+
+#if defined(CONFIG_I2C_NS9XXX) || defined(CONFIG_I2C_NS9XXX_MODULE)
+static void cc9p9360_i2c_gpio_reconfigure(void)
+{
+ gpio_configure_ns9360(70, 0, 0, 2);
+ gpio_configure_ns9360(71, 0, 0, 2);
+}
+
+static struct plat_ns9xxx_i2c ns9xxx_device_cc9p9360_i2c_data = {
+ .gpio_scl = 70,
+ .gpio_sda = 71,
+ .speed = 100000,
+ .gpio_configuration_func = cc9p9360_i2c_gpio_reconfigure,
+};
+
+void __init ns9xxx_add_device_cc9p9360_i2c(void)
+{
+ ns9xxx_add_device_ns9360_i2c(&ns9xxx_device_cc9p9360_i2c_data);
+}
+#else
+void __init ns9xxx_add_device_cc9p9360_i2c(void) {}
+#endif
+
+#if defined(CONFIG_SERIAL_NS9360) || defined(CONFIG_SERIAL_NS9360_MODULE)
+void __init ns9xxx_add_device_cc9p9360_uarta_rxtx(void)
+{
+ int uarta_gpio[] = {8, 9};
+ ns9xxx_add_device_ns9360_uarta(uarta_gpio, ARRAY_SIZE(uarta_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uarta_ctsrtsrxtx(void)
+{
+ int uarta_gpio[] = {8, 9, 10, 11};
+ ns9xxx_add_device_ns9360_uarta(uarta_gpio, ARRAY_SIZE(uarta_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uarta_full(void)
+{
+ int uarta_gpio[] = {8, 9, 10, 11, 12, 13, 14, 15};
+ ns9xxx_add_device_ns9360_uarta(uarta_gpio, ARRAY_SIZE(uarta_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uartb_rxtx(void)
+{
+ int uartb_gpio[] = {0, 1};
+ ns9xxx_add_device_ns9360_uartb(uartb_gpio, ARRAY_SIZE(uartb_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uartb_ctsrtsrxtx(void)
+{
+ int uartb_gpio[] = {0, 1, 2, 3};
+ ns9xxx_add_device_ns9360_uartb(uartb_gpio, ARRAY_SIZE(uartb_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uartb_full(void)
+{
+ int uartb_gpio[] = {0, 1, 2, 3, 4, 5, 6, 7};
+ ns9xxx_add_device_ns9360_uartb(uartb_gpio, ARRAY_SIZE(uartb_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uartc_rxtx(void)
+{
+ int uartc_gpio[] = {40, 41};
+ ns9xxx_add_device_ns9360_uartc(uartc_gpio, ARRAY_SIZE(uartc_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uartc_ctsrtsrxtx(void)
+{
+ int uartc_gpio[] = {40, 41, 42, 43};
+ ns9xxx_add_device_ns9360_uartc(uartc_gpio, ARRAY_SIZE(uartc_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uartc_full(void)
+{
+ int uartc_gpio[] = {40, 41, 42, 43, 20, 21, 22, 23};
+ ns9xxx_add_device_ns9360_uartc(uartc_gpio, ARRAY_SIZE(uartc_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uartd_rxtx(void)
+{
+ int uartd_gpio[] = {44, 45};
+ ns9xxx_add_device_ns9360_uartd(uartd_gpio, ARRAY_SIZE(uartd_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uartd_ctsrtsrxtx(void)
+{
+ int uartd_gpio[] = {44, 45, 46, 47};
+ ns9xxx_add_device_ns9360_uartd(uartd_gpio, ARRAY_SIZE(uartd_gpio), 0);
+}
+
+void __init ns9xxx_add_device_cc9p9360_uartd_full(void)
+{
+ int uartd_gpio[] = {44, 45, 46, 47, 24, 25, 26, 27};
+ ns9xxx_add_device_ns9360_uartd(uartd_gpio, ARRAY_SIZE(uartd_gpio), 0);
+}
+#else
+void __init ns9xxx_add_device_cc9p9360_uarta_rxtx(void) {}
+void __init ns9xxx_add_device_cc9p9360_uarta_ctsrtsrxtx(void) {}
+void __init ns9xxx_add_device_cc9p9360_uarta_full(void) {}
+void __init ns9xxx_add_device_cc9p9360_uartb_rxtx(void) {}
+void __init ns9xxx_add_device_cc9p9360_uartb_ctsrtsrxtx(void) {}
+void __init ns9xxx_add_device_cc9p9360_uartb_full(void) {}
+void __init ns9xxx_add_device_cc9p9360_uartc_rxtx(void) {}
+void __init ns9xxx_add_device_cc9p9360_uartc_ctsrtsrxtx(void) {}
+void __init ns9xxx_add_device_cc9p9360_uartc_full(void) {}
+void __init ns9xxx_add_device_cc9p9360_uartd_rxtx(void) {}
+void __init ns9xxx_add_device_cc9p9360_uartd_ctsrtsrxtx(void) {}
+void __init ns9xxx_add_device_cc9p9360_uartd_full(void) {}
+#endif
+
+#if defined(CONFIG_FB_NS9360) || defined(CONFIG_FB_NS9360_MODULE)
+void __init ns9xxx_add_device_cc9p9360_fb(int power)
+{
+ int gpio[] = {19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41};
+ int func[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
+
+ ns9xxx_add_device_ns9360_fb(gpio, ARRAY_SIZE(gpio), func, power);
+}
+#else
+void __init ns9xxx_add_device_cc9p9360_fb(int power) {}
+#endif
+
+#if defined(CONFIG_SPI_NS9360) || defined(CONFIG_SPI_NS9360_MODULE)
+/* SPI ports and their related GPIOs */
+static struct spi_ns9xxx_data ns9xxx_device_cc9p9360_spi_porta_data = {
+ .gpios = {8, 9, 14, 15},
+ .gpio_funcs = { NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0 },
+ .nr_gpios = 4,
+};
+
+static struct spi_ns9xxx_data ns9xxx_device_cc9p9360_spi_portb_data = {
+ .gpios = {0, 1, 6, 7},
+ .gpio_funcs = { NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0 },
+ .nr_gpios = 4,
+};
+
+static struct spi_ns9xxx_data ns9xxx_device_cc9p9360_spi_portc_data = {
+ .gpios = {40, 41, 22, 23},
+ .gpio_funcs = { NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0 },
+ .nr_gpios = 4,
+};
+
+static struct spi_ns9xxx_data ns9xxx_device_cc9p9360_spi_portd_data = {
+ .gpios = {44, 45, 26, 27},
+ .gpio_funcs = { NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0,
+ NS9360_GPIO_FUNC_0 },
+ .nr_gpios = 4,
+};
+
+void __init ns9xxx_add_device_cc9p9360_spi_porta(void)
+{
+ ns9xxx_add_device_ns9360_spi_porta( &ns9xxx_device_cc9p9360_spi_porta_data );
+}
+
+void __init ns9xxx_add_device_cc9p9360_spi_portb(void)
+{
+ ns9xxx_add_device_ns9360_spi_portb( &ns9xxx_device_cc9p9360_spi_portb_data );
+}
+
+void __init ns9xxx_add_device_cc9p9360_spi_portc(void)
+{
+ ns9xxx_add_device_ns9360_spi_portc( &ns9xxx_device_cc9p9360_spi_portc_data );
+}
+
+void __init ns9xxx_add_device_cc9p9360_spi_portd(void)
+{
+ ns9xxx_add_device_ns9360_spi_portd( &ns9xxx_device_cc9p9360_spi_portd_data );
+}
+
+#else
+void __init ns9xxx_add_device_cc9p9360_spi_porta(void) {}
+void __init ns9xxx_add_device_cc9p9360_spi_portb(void) {}
+void __init ns9xxx_add_device_cc9p9360_spi_portc(void) {}
+void __init ns9xxx_add_device_cc9p9360_spi_portd(void) {}
+#endif
+
+#if defined(CONFIG_NS9XXX_ETH) || defined(CONFIG_NS9XXX_ETH_MODULE)
+void __init ns9xxx_add_device_cc9p9360_eth(void)
+{
+ int gpio[] = {50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64, 65};
+
+ ns9xxx_add_device_ns9360_eth(gpio, 16, 0, 0xfffffffd);
+}
+#else
+void __init ns9xxx_add_device_cc9p9360_eth(void) {}
+#endif
diff --git a/arch/arm/mach-ns9xxx/cc9p9360_devices.h b/arch/arm/mach-ns9xxx/cc9p9360_devices.h
new file mode 100644
index 000000000000..2c87238e2f4b
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/cc9p9360_devices.h
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-ns9xxx/cc9p9360_devices.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+void __init ns9xxx_add_device_cc9p9360_nand(void);
+void __init ns9xxx_add_device_cc9p9360_i2c(void);
+void __init ns9xxx_add_device_cc9p9360_uarta_rxtx(void);
+void __init ns9xxx_add_device_cc9p9360_uartb_rxtx(void);
+void __init ns9xxx_add_device_cc9p9360_uartc_rxtx(void);
+void __init ns9xxx_add_device_cc9p9360_uartd_rxtx(void);
+void __init ns9xxx_add_device_cc9p9360_uarta_ctsrtsrxtx(void);
+void __init ns9xxx_add_device_cc9p9360_uartb_ctsrtsrxtx(void);
+void __init ns9xxx_add_device_cc9p9360_uartc_ctsrtsrxtx(void);
+void __init ns9xxx_add_device_cc9p9360_uartd_ctsrtsrxtx(void);
+void __init ns9xxx_add_device_cc9p9360_uarta_full(void);
+void __init ns9xxx_add_device_cc9p9360_uartb_full(void);
+void __init ns9xxx_add_device_cc9p9360_uartc_full(void);
+void __init ns9xxx_add_device_cc9p9360_uartd_full(void);
+void __init ns9xxx_add_device_cc9p9360_fb(int power);
+void __init ns9xxx_add_device_cc9p9360_spi_porta(void);
+void __init ns9xxx_add_device_cc9p9360_spi_portb(void);
+void __init ns9xxx_add_device_cc9p9360_spi_portc(void);
+void __init ns9xxx_add_device_cc9p9360_spi_portd(void);
+void __init ns9xxx_add_device_cc9p9360_eth(void);
+void __init ns9xxx_add_device_cc9p9360_touch(void);
diff --git a/arch/arm/mach-ns9xxx/ccw9p9215_devices.c b/arch/arm/mach-ns9xxx/ccw9p9215_devices.c
new file mode 100644
index 000000000000..d5630571d59d
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/ccw9p9215_devices.c
@@ -0,0 +1,379 @@
+/*
+ * arch/arm/mach-ns9xxx/cc9p9215_devices.c
+ *
+ * Copyright (C) 2009 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/clk.h>
+#include <linux/gpio.h>
+#include <linux/mtd/physmap.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <mach/fim-ns921x.h>
+#include <mach/hardware.h>
+
+#include <mach/regs-sys-common.h>
+#include <mach/regs-sys-ns921x.h>
+#include <mach/regs-mem.h>
+
+#include <asm/leds.h>
+
+#include "pipermain.h"
+#include "mac.h"
+#include "airoha.h"
+
+/*
+ * Pick Digi's internal FIM board
+ * Use internal board, defined to 1
+ * Use newer boards, defined to 0
+ */
+#if defined(CONFIG_DIGI_PIPER_WIFI)
+
+/* Low level functions to access piper chip */
+static u32 read_reg(struct piper_priv *piperp, u8 reg)
+{
+ return ioread32(piperp->vbase + reg);
+}
+
+static int write_reg(struct piper_priv *piperp, u8 reg, u32 val, reg_op_t op)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&piperp->ac->reg_lock, flags);
+ switch (op) {
+ case op_write:
+ iowrite32(val, piperp->vbase + reg);
+ break;
+ case op_or:
+ iowrite32(val | ioread32(piperp->vbase + reg), piperp->vbase + reg);
+ break;
+ case op_and:
+ iowrite32(val & ioread32(piperp->vbase + reg), piperp->vbase + reg);
+ break;
+ default:
+ printk(KERN_WARNING PIPER_DRIVER_NAME
+ ": Invalid write register operation (%d)\n", op);
+ WARN_ON(1);
+ break;
+ }
+ spin_unlock_irqrestore(&piperp->ac->reg_lock, flags);
+
+ return 0;
+}
+
+/*
+ * This macro waits for the AES busy bit to clear if we are writing to the
+ * AES FIFO.
+ */
+#define wait_for_aes_ready() while ((addr == BB_AES_FIFO) \
+ && ((ioread32(piperp->vbase + BB_RSSI) \
+ & BB_RSSI_EAS_FIFO_FULL) != 0)) { \
+ udelay(1); \
+ }
+
+static int write_fifo(struct piper_priv *piperp, u8 addr, u8 *buf, int len)
+{
+ int wordIndex;
+ int wordLength = len / sizeof(unsigned int);
+ unsigned long flags;
+ bool loadingBeacon = (addr == BEACON_FIFO);
+
+ spin_lock_irqsave(&piperp->ac->reg_lock, flags);
+
+ if (loadingBeacon) {
+ /*
+ * If we are loading a new beacon, then adjust the address to point
+ * to the data FIFO, and set the beacon enable bit which tells piper
+ * to put this data into the beacon buffer.
+ */
+ addr = BB_DATA_FIFO;
+ iowrite32(ioread32(piperp->vbase + BB_GENERAL_CTL) | BB_GENERAL_CTL_BEACON_EN,
+ piperp->vbase + BB_GENERAL_CTL);
+ }
+
+ if (((unsigned)(buf) & 0x3) == 0) {
+ /*
+ * We come here if the data is 32-bit aligned. We can dispense
+ * with memcpys
+ */
+ if (wordLength == 1) {
+ /*
+ * Only 1 word of data, so just one write.
+ */
+ unsigned int *word = (unsigned int *)buf;
+
+ wait_for_aes_ready();
+ iowrite32(cpu_to_be32(*word), piperp->vbase + addr);
+ len -= 4;
+ } else {
+ /*
+ * More than one word of data, so set up a for loop.
+ */
+ for (wordIndex = 0; wordIndex < wordLength; wordIndex++) {
+ unsigned int *word = (unsigned int *)buf;
+
+ wait_for_aes_ready();
+ iowrite32(cpu_to_be32(word[wordIndex]), piperp->vbase + addr);
+ len -= 4;
+ }
+ }
+ } else {
+ /*
+ * Ugh! Data is not 32-bit aligned. We have to memcpy it!
+ */
+ for (wordIndex = 0; wordIndex < wordLength; wordIndex++) {
+ unsigned int word;
+
+ memcpy(&word, &buf[wordIndex * sizeof(unsigned int)],
+ sizeof(unsigned int));
+
+ wait_for_aes_ready();
+ iowrite32(cpu_to_be32(word), piperp->vbase + addr);
+ len -= 4;
+ }
+ }
+
+ if (len) {
+ /*
+ * Double Ugh! There was left over data at the end. We have to write
+ * the leftover data into the upper bytes of the last word, making
+ * sure the unused bytes are set to zero.
+ */
+ unsigned int word;
+
+ memcpy(&word, &buf[wordLength * sizeof(unsigned int)], sizeof(unsigned int));
+ word = cpu_to_be32(word);
+ switch (len) {
+ case 1:
+ word &= 0xff000000;
+ break;
+ case 2:
+ word &= 0xffff0000;
+ break;
+ case 3:
+ word &= 0xffffff00;
+ break;
+ default:
+ printk(KERN_WARNING PIPER_DRIVER_NAME
+ ": len = %d at end of piper_write\n", len);
+ break;
+ }
+ wait_for_aes_ready();
+ iowrite32(word, piperp->vbase + addr);
+ }
+
+ if (loadingBeacon) {
+ /*
+ * If we just loaded a beacon, then don't forget to turn off the
+ * load beacon bit.
+ */
+ iowrite32(ioread32(piperp->vbase + BB_GENERAL_CTL) & ~BB_GENERAL_CTL_BEACON_EN,
+ piperp->vbase + BB_GENERAL_CTL);
+ piperp->beacon.loaded = true;
+ }
+
+ spin_unlock_irqrestore(&piperp->ac->reg_lock, flags);
+
+ return 0;
+}
+
+/*
+ * This routine waits for the empty flag to clear when we are reading from
+ * the AES FIFO.
+ */
+#define wait_for_aes_not_empty() \
+ while ((addr == BB_AES_FIFO) \
+ && ((ioread32(piperp->vbase + BB_RSSI) & BB_RSSI_EAS_FIFO_EMPTY) != 0)) { \
+ udelay(1); \
+ if (--timeout == 0) { \
+ timeout = 10000; \
+ } \
+ }
+
+static int read_fifo(struct piper_priv *piperp, u8 addr, u8 *buf, int len)
+{
+ int wordIndex;
+ unsigned long flags;
+ int timeout = 10000;
+
+ spin_lock_irqsave(&piperp->ac->reg_lock, flags);
+
+ /*
+ * We can only read 32-bit words, so round the length up to an even multiple of
+ * 4 if necessary.
+ */
+ len += 3;
+ len &= 0xfffffc;
+
+ if ((len == 4) && ((((unsigned)buf) & 0x3) == 0)) {
+ unsigned *word = (unsigned *)buf;
+
+ wait_for_aes_not_empty();
+ *word = be32_to_cpu(ioread32(piperp->vbase + addr));
+ } else if ((((unsigned)buf) & 0x3) == 0) {
+ unsigned *word = (unsigned *)buf;
+
+ for (wordIndex = 0; wordIndex < (len / sizeof(unsigned)); wordIndex++) {
+ wait_for_aes_not_empty();
+ word[wordIndex] = be32_to_cpu(ioread32(piperp->vbase + addr));
+ }
+ } else {
+ /*
+ * If we come here, then the buffer is not aligned and we have to
+ * memcpy the data.
+ */
+ for (wordIndex = 0; wordIndex < (len / sizeof(unsigned)); wordIndex++) {
+ unsigned word;
+
+ wait_for_aes_not_empty();
+ word = be32_to_cpu(ioread32(piperp->vbase + addr));
+ memcpy(&buf[wordIndex * sizeof(unsigned)], &word, sizeof(word));
+ }
+ }
+ spin_unlock_irqrestore(&piperp->ac->reg_lock, flags);
+
+ return 0;
+}
+
+/* Initialize piper hardware, mac and dsp firmwares and mac address */
+static int piper_init_chip_hw(struct piper_priv *piperp)
+{
+ int ret;
+
+ piper_load_mac_firmware(piperp);
+ piper_load_dsp_firmware(piperp);
+
+ ret = piper_spike_suppression(piperp, true);
+ if (ret) {
+ printk(KERN_WARNING PIPER_DRIVER_NAME
+ ": spike suppresion error\n");
+ return ret;
+ }
+ piper_reset_mac(piperp);
+ piper_set_macaddr(piperp);
+
+ return ret;
+}
+
+static void ccw9p9215_piper_set_led(struct piper_priv *piperp, enum wireless_led led, int val)
+{
+ if(led == STATUS_LED)
+ leds_event(val ? led_green_on : led_green_off);
+}
+
+static void ccw9p9215_piper_reset(struct piper_priv *piperp, int reset)
+{
+ gpio_set_value(piperp->pdata->rst_gpio, !reset);
+}
+
+static int ccw9p9215_piper_init(struct piper_priv *piperp)
+{
+ ccw9p9215_piper_reset(piperp, 1);
+ mdelay(1);
+ ccw9p9215_piper_reset(piperp, 0);
+ mdelay(1);
+
+ /* Initialize functions to access register */
+ piperp->ac->wr_reg = write_reg;
+ piperp->ac->rd_reg = read_reg;
+ piperp->ac->wr_fifo = write_fifo;
+ piperp->ac->rd_fifo = read_fifo;
+
+ mdelay(1);
+
+ return piper_init_chip_hw(piperp);
+}
+
+static int ccw9p9215_piper_late_init(struct piper_priv *piperp)
+{
+ /* Configure irq gpio line */
+ gpio_configure_ns921x(piperp->pdata->irq_gpio, NS921X_GPIO_INPUT,
+ NS921X_GPIO_DONT_INVERT, NS921X_GPIO_FUNC_2,
+ NS921X_GPIO_ENABLE_PULLUP);
+
+ return 0;
+}
+
+static struct resource piper_resources[] = {
+ {
+ .start = 0x70000000,
+ .end = 0x70000000 + 0x100,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS9XXX_EXT0,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+/* describes the device */
+static struct platform_device piper_device = {
+ .id = 0,
+ .name = PIPER_DRIVER_NAME,
+ .num_resources = ARRAY_SIZE(piper_resources),
+ .resource = piper_resources,
+};
+
+void __init ns9xxx_add_device_ccw9p9215_wifi(struct piper_pdata *pdata)
+{
+ int ret;
+
+ if (!pdata)
+ return;
+
+ if (pdata->rst_gpio >= 0) {
+ ret = gpio_request(pdata->rst_gpio, PIPER_DRIVER_NAME "-reset-gpio");
+ if (ret != 0)
+ printk(KERN_WARNING PIPER_DRIVER_NAME
+ ": failed to request reset gpio %d\n", pdata->rst_gpio);
+ else {
+ /* Configure reset line and hold the chip in reset */
+ gpio_direction_output(pdata->rst_gpio, 0);
+ pdata->reset = ccw9p9215_piper_reset;
+ }
+ }
+
+ if (pdata->irq_gpio >= 0) {
+ ret = gpio_request(pdata->irq_gpio, PIPER_DRIVER_NAME "-irq-gpio");
+ if (ret != 0)
+ printk(KERN_WARNING PIPER_DRIVER_NAME
+ ": failed to request irq gpio %d\n", pdata->irq_gpio);
+ }
+
+ /* Configure the memory controller (CS3) with the appropriate settings */
+ /* 32 bit bus width */
+ writel(MEM_SMC_PB_1 | MEM_SMC_MW_32, MEM_SMC(3));
+ /* Static Memory Write Enable Delay x */
+ writel(0, MEM_SMWED(3));
+ /* Static Memory Output Enable Delay x */
+ writel(2, MEM_SMOED(3));
+ /* Static Memory Read Delay x */
+ writel(8, MEM_SMRD(3));
+ /* Static Memory Page Mode Read Delay 0 */
+ writel(0, MEM_SMPMRD(3));
+ /* Static Memory Write Delay */
+ writel(4, MEM_SMWD(3));
+ /* Static Memory Turn Round Delay x */
+ writel(2, MEM_SWT(3));
+ /* Enable the CS0 access */
+ writel(readl(SYS_SMCSSMM(3)) | SYS_SMCSSMM_CSEx_EN, SYS_SMCSSMM(3));
+
+ pdata->rf_transceiver = RF_AIROHA_7230;
+ pdata->init = ccw9p9215_piper_init;
+ pdata->late_init = ccw9p9215_piper_late_init;
+ pdata->set_led = ccw9p9215_piper_set_led;
+ piper_device.dev.platform_data = pdata;
+
+ platform_device_register(&piper_device);
+}
+
+#else
+void __init ns9xxx_add_device_ccw9p9215_wifi(struct piper_pdata *pdata) {}
+#endif
+
diff --git a/arch/arm/mach-ns9xxx/ccw9p9215_devices.h b/arch/arm/mach-ns9xxx/ccw9p9215_devices.h
new file mode 100644
index 000000000000..3e27884cd0d8
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/ccw9p9215_devices.h
@@ -0,0 +1,12 @@
+/*
+ * arch/arm/mach-ns9xxx/ccw9p9215_devices.h
+ *
+ * Copyright (C) 2009 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+void __init ns9xxx_add_device_ccw9p9215_wifi(struct piper_pdata *pdata);
diff --git a/arch/arm/mach-ns9xxx/ccx9c_devices.c b/arch/arm/mach-ns9xxx/ccx9c_devices.c
new file mode 100644
index 000000000000..6ec20a4971f0
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/ccx9c_devices.c
@@ -0,0 +1,218 @@
+/*
+ * arch/arm/mach-ns9xxx/ccx9c_devices.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+
+#include "ns9360_devices.h"
+#include "ccx9c_devices.h"
+
+#if defined(CONFIG_SPI_NS9360) || defined(CONFIG_SPI_NS9360_MODULE)
+/* SPI ports and their related GPIOs */
+static struct spi_ns9xxx_data ns9xxx_device_ccx9c_spi_porta_data = {
+ .gpios = {8, 9, 14, 15},
+ .nr_gpios = 4,
+};
+
+static struct spi_ns9xxx_data ns9xxx_device_ccx9c_spi_portb_data = {
+ .gpios = {0, 1, 6, 7},
+ .nr_gpios = 4,
+};
+
+static struct spi_ns9xxx_data ns9xxx_device_ccx9c_spi_portc_data = {
+ .gpios = {40, 41, 22, 23},
+ .nr_gpios = 4,
+};
+
+static struct spi_ns9xxx_data ns9xxx_device_ccx9c_spi_portd_data = {
+ .gpios = {44, 45, 26, 27},
+ .nr_gpios = 4,
+};
+#endif
+
+#if defined(CONFIG_MTD_NAND_CCX9X) || defined(CONFIG_MTD_NAND_CCX9X_MODULE)
+static struct ccx9x_nand_info ns9xxx_device_ccx9c_nand_data = {
+ .addr_offset = 0x8000,
+ .cmd_offset = 0x10000,
+ .delay = 25,
+};
+void __init ns9xxx_add_device_ccx9c_nand(void)
+{
+ ns9xxx_add_device_ns9360_nand(&ns9xxx_device_ccx9c_nand_data);
+}
+#else
+void __init ns9xxx_add_device_ccx9c_nand(void) {}
+#endif
+
+#if defined(CONFIG_I2C_NS9XXX) || defined(CONFIG_I2C_NS9XXX_MODULE)
+static void ccx9c_i2c_gpio_reconfigure(void)
+{
+ gpio_configure_ns9360(70, 0, 0, 2);
+ gpio_configure_ns9360(71, 0, 0, 2);
+}
+
+static struct plat_ns9xxx_i2c ns9xxx_device_ccx9c_i2c_data = {
+ .gpio_scl = 70,
+ .gpio_sda = 71,
+ .speed = 100000,
+ .gpio_configuration_func = ccx9c_i2c_gpio_reconfigure,
+};
+
+void __init ns9xxx_add_device_ccx9c_i2c(void)
+{
+ ns9xxx_add_device_ns9360_i2c(&ns9xxx_device_ccx9c_i2c_data);
+}
+#else
+void __init ns9xxx_add_device_ccx9c_i2c(void) {}
+#endif
+
+#if defined(CONFIG_SERIAL_NS9360) || defined(CONFIG_SERIAL_NS9360_MODULE)
+void __init ns9xxx_add_device_ccx9c_uarta_rxtx(void)
+{
+ int uarta_gpio[] = {8, 9};
+ ns9xxx_add_device_ns9360_uarta(uarta_gpio, ARRAY_SIZE(uarta_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uarta_ctsrtsrxtx(void)
+{
+ int uarta_gpio[] = {8, 9, 10, 11};
+ ns9xxx_add_device_ns9360_uarta(uarta_gpio, ARRAY_SIZE(uarta_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uarta_full(void)
+{
+ int uarta_gpio[] = { 8, 9, 10, 11, 12, 13, 14, 15};
+ ns9xxx_add_device_ns9360_uarta(uarta_gpio, ARRAY_SIZE(uarta_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uartb_rxtx(void)
+{
+ int uartb_gpio[] = {0, 1};
+ ns9xxx_add_device_ns9360_uartb(uartb_gpio, ARRAY_SIZE(uartb_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uartb_ctsrtsrxtx(void)
+{
+ int uartb_gpio[] = {0, 1, 2, 3};
+ ns9xxx_add_device_ns9360_uartb(uartb_gpio, ARRAY_SIZE(uartb_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uartb_full(void)
+{
+ int uartb_gpio[] = { 0, 1, 2, 3, 4, 5, 6, 7};
+ ns9xxx_add_device_ns9360_uartb(uartb_gpio, ARRAY_SIZE(uartb_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uartc_rxtx(void)
+{
+ int uartc_gpio[] = {40, 41};
+ ns9xxx_add_device_ns9360_uartc(uartc_gpio, ARRAY_SIZE(uartc_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uartc_ctsrtsrxtx(void)
+{
+ int uartc_gpio[] = {40, 41, 42, 43};
+ ns9xxx_add_device_ns9360_uartc(uartc_gpio, ARRAY_SIZE(uartc_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uartd_rxtx(void)
+{
+ int uartd_gpio[] = {44, 45};
+ ns9xxx_add_device_ns9360_uartd(uartd_gpio, ARRAY_SIZE(uartd_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uartd_ctsrtsrxtx(void)
+{
+ int uartd_gpio[] = {44, 45, 46, 47};
+ ns9xxx_add_device_ns9360_uartd(uartd_gpio, ARRAY_SIZE(uartd_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uartc_full(void)
+{
+ int uartc_gpio[] = {40, 41, 42, 43, 20, 21, 22, 23};
+ ns9xxx_add_device_ns9360_uartc(uartc_gpio, ARRAY_SIZE(uartc_gpio), 0);
+}
+
+void __init ns9xxx_add_device_ccx9c_uartd_full(void)
+{
+ int uartd_gpio[] = {44, 45, 46, 47, 24, 25, 26, 27};
+ ns9xxx_add_device_ns9360_uartd(uartd_gpio, ARRAY_SIZE(uartd_gpio), 0);
+}
+#else
+void __init ns9xxx_add_device_ccx9c_uarta_rxtx(void) {}
+void __init ns9xxx_add_device_ccx9c_uarta_ctsrtsrxtx(void) {}
+void __init ns9xxx_add_device_ccx9c_uarta_full(void) {}
+void __init ns9xxx_add_device_ccx9c_uartb_rxtx(void) {}
+void __init ns9xxx_add_device_ccx9c_uartb_ctsrtsrxtx(void) {}
+void __init ns9xxx_add_device_ccx9c_uartb_full(void) {}
+void __init ns9xxx_add_device_ccx9c_uartc_rxtx(void) {}
+void __init ns9xxx_add_device_ccx9c_uartc_ctsrtsrxtx(void) {}
+void __init ns9xxx_add_device_ccx9c_uartc_full(void) {}
+void __init ns9xxx_add_device_ccx9c_uartd_rxtx(void) {}
+void __init ns9xxx_add_device_ccx9c_uartd_ctsrtsrxtx(void) {}
+void __init ns9xxx_add_device_ccx9c_uartd_full(void) {}
+#endif
+
+#if defined(CONFIG_FB_NS9360) || defined(CONFIG_FB_NS9360_MODULE)
+void __init ns9xxx_add_device_ccx9c_fb(int power)
+{
+ int gpio[] = {19, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41};
+ int func[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2};
+
+ ns9xxx_add_device_ns9360_fb(gpio, ARRAY_SIZE(gpio), func, power);
+}
+#else
+void __init ns9xxx_add_device_ccx9c_fb(int power) {}
+#endif
+
+#if defined(CONFIG_SPI_NS9360) || defined(CONFIG_SPI_NS9360_MODULE)
+void __init ns9xxx_add_device_ccx9c_spi_porta(void)
+{
+ ns9xxx_add_device_ns9360_spi_porta( &ns9xxx_device_ccx9c_spi_porta_data );
+}
+
+void __init ns9xxx_add_device_ccx9c_spi_portb(void)
+{
+ ns9xxx_add_device_ns9360_spi_portb( &ns9xxx_device_ccx9c_spi_portb_data );
+}
+
+void __init ns9xxx_add_device_ccx9c_spi_portc(void)
+{
+ ns9xxx_add_device_ns9360_spi_portc( &ns9xxx_device_ccx9c_spi_portc_data );
+}
+
+void __init ns9xxx_add_device_ccx9c_spi_portd(void)
+{
+ ns9xxx_add_device_ns9360_spi_portd( &ns9xxx_device_ccx9c_spi_portd_data );
+}
+
+#else
+void __init ns9xxx_add_device_ccx9c_spi_porta(void) {}
+void __init ns9xxx_add_device_ccx9c_spi_portb(void) {}
+void __init ns9xxx_add_device_ccx9c_spi_portc(void) {}
+void __init ns9xxx_add_device_ccx9c_spi_portd(void) {}
+#endif
+
+#if defined(CONFIG_NS9XXX_ETH) || defined(CONFIG_NS9XXX_ETH_MODULE)
+void __init ns9xxx_add_device_ccx9c_eth(void)
+{
+ int gpio[] = {50, 51, 52, 53, 54, 55, 56, 57,
+ 58, 59, 60, 61, 62, 63, 64};
+
+ ns9xxx_add_device_ns9360_eth(gpio, 15, 0, 0xfffffffd);
+}
+#else
+void __init ns9xxx_add_device_ccx9c_eth(void) {}
+#endif
diff --git a/arch/arm/mach-ns9xxx/ccx9c_devices.h b/arch/arm/mach-ns9xxx/ccx9c_devices.h
new file mode 100644
index 000000000000..074197e29aba
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/ccx9c_devices.h
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-ns9xxx/ccx9c_devices.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+void __init ns9xxx_add_device_ccx9c_nand(void);
+void __init ns9xxx_add_device_ccx9c_i2c(void);
+void __init ns9xxx_add_device_ccx9c_uarta_rxtx(void);
+void __init ns9xxx_add_device_ccx9c_uartb_rxtx(void);
+void __init ns9xxx_add_device_ccx9c_uartc_rxtx(void);
+void __init ns9xxx_add_device_ccx9c_uartd_rxtx(void);
+void __init ns9xxx_add_device_ccx9c_uarta_ctsrtsrxtx(void);
+void __init ns9xxx_add_device_ccx9c_uartb_ctsrtsrxtx(void);
+void __init ns9xxx_add_device_ccx9c_uartc_ctsrtsrxtx(void);
+void __init ns9xxx_add_device_ccx9c_uartd_ctsrtsrxtx(void);
+void __init ns9xxx_add_device_ccx9c_uarta_full(void);
+void __init ns9xxx_add_device_ccx9c_uartb_full(void);
+void __init ns9xxx_add_device_ccx9c_uartc_full(void);
+void __init ns9xxx_add_device_ccx9c_uartd_full(void);
+void __init ns9xxx_add_device_ccx9c_fb(int power);
+void __init ns9xxx_add_device_ccx9c_spi_porta(void);
+void __init ns9xxx_add_device_ccx9c_spi_portb(void);
+void __init ns9xxx_add_device_ccx9c_spi_portc(void);
+void __init ns9xxx_add_device_ccx9c_spi_portd(void);
+void __init ns9xxx_add_device_ccx9c_eth(void);
+void __init ns9xxx_add_device_ccx9c_touch(void);
diff --git a/arch/arm/mach-ns9xxx/clock.c b/arch/arm/mach-ns9xxx/clock.c
index 44ed20d4a388..0344a519707b 100644
--- a/arch/arm/mach-ns9xxx/clock.c
+++ b/arch/arm/mach-ns9xxx/clock.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-ns9xxx/clock.c
*
- * Copyright (C) 2007 by Digi International Inc.
+ * Copyright (C) 2007-2008 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
@@ -61,22 +61,77 @@ EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clk_lock, flags);
+
module_put(clk->owner);
--clk->refcount;
+
+ spin_unlock_irqrestore(&clk_lock, flags);
}
EXPORT_SYMBOL(clk_put);
-static int clk_enable_unlocked(struct clk *clk)
+static int clk_enable_haslock(struct clk *clk);
+static int clk_disable_haslock(struct clk *clk);
+
+static void clk_disable_parent_haslock(struct clk *clk)
{
+ struct clk *parent = clk->parent;
int ret = 0;
- if (clk->parent) {
- ret = clk_enable_unlocked(clk->parent);
- if (ret)
- return ret;
+
+ if (parent)
+ ret = clk_disable_haslock(parent);
+
+ if (unlikely(ret))
+ pr_warning("failed to disable %s.%d clk -> %d\n",
+ parent->name, parent->id, ret);
+}
+
+static int clk_enable_haslocknchange(struct clk *clk)
+{
+ int ret = 0;
+
+ assert_spin_locked(&clk_lock);
+ BUG_ON(!test_bit(CLK_FLAG_CHANGESTATE, &clk->flags));
+
+ if (clk->usage++ == 0) {
+ if (clk->parent) {
+ ret = clk_enable_haslock(clk->parent);
+ if (ret)
+ goto err_enable_parent;
+ }
+
+ spin_unlock(&clk_lock);
+
+ if (clk->endisable)
+ ret = clk->endisable(clk, 1);
+
+ spin_lock(&clk_lock);
+
+ if (ret) {
+ clk_disable_parent_haslock(clk);
+err_enable_parent:
+
+ clk->usage = 0;
+ }
+
}
- if (clk->usage++ == 0 && clk->endisable)
- ret = clk->endisable(clk, 1);
+ return ret;
+}
+
+static int clk_enable_haslock(struct clk *clk)
+{
+ int ret;
+
+ assert_spin_locked(&clk_lock);
+ if (__test_and_set_bit(CLK_FLAG_CHANGESTATE, &clk->flags))
+ return -EBUSY;
+
+ ret = clk_enable_haslocknchange(clk);
+
+ clear_bit(CLK_FLAG_CHANGESTATE, &clk->flags);
return ret;
}
@@ -88,7 +143,7 @@ int clk_enable(struct clk *clk)
spin_lock_irqsave(&clk_lock, flags);
- ret = clk_enable_unlocked(clk);
+ ret = clk_enable_haslock(clk);
spin_unlock_irqrestore(&clk_lock, flags);
@@ -96,24 +151,60 @@ int clk_enable(struct clk *clk)
}
EXPORT_SYMBOL(clk_enable);
-static void clk_disable_unlocked(struct clk *clk)
+static int clk_disable_haslocknchange(struct clk *clk)
{
- if (--clk->usage == 0 && clk->endisable)
- clk->endisable(clk, 0);
+ int ret = 0;
- if (clk->parent)
- clk_disable_unlocked(clk->parent);
+ assert_spin_locked(&clk_lock);
+ BUG_ON(!test_bit(CLK_FLAG_CHANGESTATE, &clk->flags));
+
+ BUG_ON(clk->usage == 0);
+
+ if (--clk->usage == 0) {
+ spin_unlock(&clk_lock);
+
+ if (clk->endisable)
+ ret = clk->endisable(clk, 0);
+
+ spin_lock(&clk_lock);
+
+ if (ret == 0)
+ clk_disable_parent_haslock(clk);
+ else
+ clk->usage = 1;
+ }
+
+ return ret;
+}
+
+static int clk_disable_haslock(struct clk *clk)
+{
+ int ret;
+
+ if (__test_and_set_bit(CLK_FLAG_CHANGESTATE, &clk->flags))
+ return -EBUSY;
+
+ ret = clk_disable_haslocknchange(clk);
+
+ clear_bit(CLK_FLAG_CHANGESTATE, &clk->flags);
+
+ return ret;
}
void clk_disable(struct clk *clk)
{
+ int ret;
unsigned long flags;
spin_lock_irqsave(&clk_lock, flags);
- clk_disable_unlocked(clk);
+ ret = clk_disable_haslock(clk);
spin_unlock_irqrestore(&clk_lock, flags);
+
+ if (unlikely(ret))
+ pr_warning("failed to disable %s.%d clk -> %d\n",
+ clk->name, clk->id, ret);
}
EXPORT_SYMBOL(clk_disable);
@@ -138,6 +229,8 @@ int clk_register(struct clk *clk)
spin_lock_irqsave(&clk_lock, flags);
+ BUG_ON(clk->flags);
+
list_add(&clk->node, &clocks);
if (clk->parent)
@@ -181,9 +274,10 @@ static int clk_debugfs_show(struct seq_file *s, void *null)
spin_lock_irqsave(&clk_lock, flags);
list_for_each_entry(p, &clocks, node)
- seq_printf(s, "%s.%d: usage=%lu refcount=%lu rate=%lu\n",
+ seq_printf(s, "%s.%d: usage=%lu refcount=%lu rate=%lu parent=%s\n",
p->name, p->id, p->usage, p->refcount,
- p->usage ? clk_get_rate(p) : 0);
+ p->usage ? clk_get_rate(p) : 0,
+ p->parent ? p->parent->name : "<nil>");
spin_unlock_irqrestore(&clk_lock, flags);
diff --git a/arch/arm/mach-ns9xxx/clock.h b/arch/arm/mach-ns9xxx/clock.h
index b86c30dd79eb..9097fe971dfc 100644
--- a/arch/arm/mach-ns9xxx/clock.h
+++ b/arch/arm/mach-ns9xxx/clock.h
@@ -27,6 +27,9 @@ struct clk {
struct list_head node;
unsigned long refcount;
unsigned long usage;
+
+#define CLK_FLAG_CHANGESTATE 0
+ unsigned long flags;
};
int clk_register(struct clk *clk);
diff --git a/arch/arm/mach-ns9xxx/cme9210_devices.c b/arch/arm/mach-ns9xxx/cme9210_devices.c
new file mode 100644
index 000000000000..c3b3ff05b999
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/cme9210_devices.c
@@ -0,0 +1,251 @@
+ /*
+ * arch/arm/mach-ns9xxx/cme9210_devices.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/mtd/physmap.h>
+#include <mach/fim-ns921x.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/w1-gpio.h>
+
+#include "ns921x_devices.h"
+#include "cme9210_devices.h"
+
+#if defined(CONFIG_NS9XXX_ETH) || defined(CONFIG_NS9XXX_ETH_MODULE)
+void __init ns9xxx_add_device_cme9210_eth(void)
+{
+ int gpio[] = {
+#ifdef CONFIG_GPIO_ETH_ACTIVITY_LED
+ 14,
+#endif
+ 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49};
+ int func[] = {
+#ifdef CONFIG_GPIO_ETH_ACTIVITY_LED
+ 3,
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int dir[] = {
+#ifdef CONFIG_GPIO_ETH_ACTIVITY_LED
+ 1,
+#endif
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ ns9xxx_add_device_ns921x_eth(NULL, 0, gpio,
+ func, dir, ARRAY_SIZE(gpio));
+}
+#else
+void __init ns9xxx_add_device_cme9210_eth(void) {}
+#endif
+
+#if defined(CONFIG_I2C_NS9XXX) || defined(CONFIG_I2C_NS9XXX_MODULE)
+static void cme9210_i2c_gpio_reconfigure(void)
+{
+ gpio_configure_ns921x(9, 0, 0, 1, 0);
+ gpio_configure_ns921x(12, 0, 0, 1, 0);
+}
+
+static struct plat_ns9xxx_i2c ns9xxx_device_cme9210_i2c_data = {
+ .gpio_scl = 9,
+ .gpio_sda = 12,
+ .speed = 100000,
+ .gpio_configuration_func = cme9210_i2c_gpio_reconfigure,
+};
+
+void __init ns9xxx_add_device_cme9210_i2c(void)
+{
+ ns9xxx_add_device_ns921x_i2c(&ns9xxx_device_cme9210_i2c_data);
+}
+#else
+void __init ns9xxx_add_device_cme9210_i2c(void) {}
+#endif
+
+#if defined(CONFIG_SERIAL_NS921X) || defined(CONFIG_SERIAL_NS921X_MODULE)
+void __init ns9xxx_add_device_cme9210_uarta(int gpio_nr)
+{
+ ns9xxx_add_device_ns921x_uarta(0, gpio_nr, 0);
+}
+void __init ns9xxx_add_device_cme9210_uartc(int gpio_nr)
+{
+ ns9xxx_add_device_ns921x_uartc(8, gpio_nr, 0);
+}
+#else
+void __init ns9xxx_add_device_cme9210_uarta(int gpio_nr) {}
+void __init ns9xxx_add_device_cme9210_uartc(int gpio_nr) {}
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP)
+static struct physmap_flash_data ns9xxx_device_cme9210_flash_data = {
+ .width = 2,
+};
+
+void __init ns9xxx_add_device_cme9210_flash(void)
+{
+ ns9xxx_add_device_ns921x_flash(&ns9xxx_device_cme9210_flash_data);
+}
+#else
+void __init ns9xxx_add_device_cme9210_flash(void) {}
+#endif
+
+#if defined(CONFIG_SPI_NS921X) || defined(CONFIG_SPI_NS921X_MODULE)
+/* SPI ports and their related GPIOs */
+static struct spi_ns9xxx_data ns9xxx_device_cme9210_spi_data = {
+ .gpios = {7, 3, 5, 0},
+ .gpio_funcs = { NS921X_GPIO_FUNC_4,
+ NS921X_GPIO_FUNC_4,
+ NS921X_GPIO_FUNC_4,
+ NS921X_GPIO_FUNC_4 },
+ .nr_gpios = 4,
+};
+
+void __init ns9xxx_add_device_cme9210_spi(void)
+{
+ ns9xxx_add_device_ns921x_spi(&ns9xxx_device_cme9210_spi_data);
+}
+#else
+void __init ns9xxx_add_device_cme9210_spi(void) {}
+#endif
+
+/*
+ * XXX Need testing and it might be incomplete add_device()?
+ */
+
+#if defined(CONFIG_FIM_ZERO_SERIAL)
+static struct fim_serial_platform_data fim_serial_data0 = {
+ .fim_nr = 0,
+#if defined(CONFIG_FIM_ZERO_SERIAL_CTSRTS)
+ NS921X_FIM_SERIAL_GPIOS(2, 1, /* RX(2,23) + TX(1) */
+ 0, 3, /* RTS(0) + CTS(3) */
+ NS921X_GPIO_FUNC_2),
+#else
+ NS921X_FIM_SERIAL_GPIOS(2, 1, /* RX(2,23) + TX(1) */
+ FIM_GPIO_DONT_USE, /* RTS */
+ FIM_GPIO_DONT_USE, /* CTS */
+ NS921X_GPIO_FUNC_2),
+#endif
+};
+struct platform_device ns921x_fim_serial0 = {
+ .name = "fim-serial",
+ .id = 0,
+ .dev.platform_data = &fim_serial_data0,
+};
+EXPORT_SYMBOL(ns921x_fim_serial0);
+#endif /* CONFIG_FIM_ZERO_SERIAL */
+
+#if defined(CONFIG_FIM_ONE_CAN)
+static struct fim_can_platform_data fim_can_data1 = {
+ .fim_nr = 1,
+ .fim_can_bitrate = 500000,
+ NS921X_FIM_CAN_GPIOS( 23, 24, /* RX(2,23) + TX(6,24) */
+ NS921X_GPIO_FUNC_2),
+};
+struct platform_device ns921x_fim_can1 = {
+ .name = "fim-can",
+ .id = 1,
+ .dev.platform_data = &fim_can_data1,
+};
+EXPORT_SYMBOL(ns921x_fim_can1);
+#endif /* CONFIG_FIM_ONE_CAN */
+
+#if defined(CONFIG_FIM_ZERO_SDIO)
+static struct fim_sdio_platform_data fim_sdio_data0 = {
+ .fim_nr = 0,
+ .host_caps = 0,
+
+ .d0_gpio_nr = 0,
+ .d0_gpio_func = NS921X_GPIO_FUNC_2,
+ .d1_gpio_nr = FIM_GPIO_DONT_USE,
+ .d2_gpio_nr = FIM_GPIO_DONT_USE,
+ .d3_gpio_nr = FIM_GPIO_DONT_USE,
+
+ .clk_gpio_nr = 1,
+ .clk_gpio_func = NS921X_GPIO_FUNC_2,
+
+ .cmd_gpio_nr = 2,
+ .cmd_gpio_func = NS921X_GPIO_FUNC_2,
+
+ .cd_gpio_nr = 9,
+ .cd_gpio_func = NS921X_GPIO_FUNC_2,
+
+ .wp_gpio_nr = 6,
+ .wp_gpio_func = NS921X_GPIO_FUNC_3,
+};
+struct platform_device ns921x_fim_sdio0 = {
+ .name = "fim-sdio",
+ .id = 0,
+ .dev.platform_data = &fim_sdio_data0,
+};
+EXPORT_SYMBOL(ns921x_fim_sdio0);
+#endif /* CONFIG_FIM_ZERO_SDIO */
+
+/* The second SDIO-port will be available by the CC9P9210JS first */
+#if defined(CONFIG_FIM_ONE_SDIO)
+static struct fim_sdio_platform_data fim_sdio_data1 = {
+ .fim_nr = 1,
+ .host_caps = 0,
+
+ .d0_gpio_nr = 26,
+ .d0_gpio_func = NS921X_GPIO_FUNC_2,
+ .d1_gpio_nr = FIM_GPIO_DONT_USE,
+ .d2_gpio_nr = FIM_GPIO_DONT_USE,
+ .d3_gpio_nr = FIM_GPIO_DONT_USE,
+
+ .clk_gpio_nr = 27,
+ .clk_gpio_func = NS921X_GPIO_FUNC_2,
+
+ .cmd_gpio_nr = 28,
+ .cmd_gpio_func = NS921X_GPIO_FUNC_2,
+
+ .cd_gpio_nr = 9,
+ .cd_gpio_func = NS921X_GPIO_FUNC_2,
+
+ .wp_gpio_nr = 6,
+ .wp_gpio_func = NS921X_GPIO_FUNC_3,
+};
+struct platform_device ns921x_fim_sdio1 = {
+ .name = "fim-sdio",
+ .id = 1,
+ .dev.platform_data = &fim_sdio_data1,
+};
+EXPORT_SYMBOL(ns921x_fim_sdio1);
+#endif /* CONFIG_FIM_ONE_SDIO */
+
+#if defined(CONFIG_FIM_ZERO_W1)
+static struct w1_gpio_platform_data fim_w1_data0 = {
+ .pin = 1,
+ .is_open_drain = 0,
+};
+struct platform_device ns921x_fim0_w1 = {
+ .name = "w1-gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &fim_w1_data0,
+ },
+};
+EXPORT_SYMBOL(ns921x_fim0_w1);
+#endif /* CONFIG_FIM_ZERO_W1 */
+
+#if defined(CONFIG_FIM_ZERO_USB)
+static struct fim_usb_platform_data fim_usb_data0 = {
+ .fim_nr = 0,
+ NS921X_FIM_USB_GPIOS(0, 1, 2, /* VP + VM + RCV */
+ 3, 6, 9, /* OE_L + ENUM + SPND */
+ NS921X_GPIO_FUNC_2,
+ NS921X_GPIO_FUNC_GPIO),
+};
+struct platform_device ns921x_fim_usb0 = {
+ .name = "fim-usb",
+ .id = 0,
+ .dev.platform_data = &fim_usb_data0,
+};
+EXPORT_SYMBOL(ns921x_fim_usb0);
+#endif /* CONFIG_FIM_ZERO_USB */
diff --git a/arch/arm/mach-ns9xxx/cme9210_devices.h b/arch/arm/mach-ns9xxx/cme9210_devices.h
new file mode 100644
index 000000000000..606ed71a244f
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/cme9210_devices.h
@@ -0,0 +1,26 @@
+/*
+ * arch/arm/mach-ns9xxx/cme9210_devices.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+void __init ns9xxx_add_device_cme9210_eth(void);
+void __init ns9xxx_add_device_cme9210_uarta(int gpio_nr);
+void __init ns9xxx_add_device_cme9210_uartc(int gpio_nr);
+void __init ns9xxx_add_device_cme9210_flash(void);
+void __init ns9xxx_add_device_cme9210_spi(void);
+void __init ns9xxx_add_device_cme9210_i2c(void);
+
+#define ns9xxx_add_device_cme9210_uarta_rxtx() \
+ ns9xxx_add_device_cme9210_uarta(2)
+#define ns9xxx_add_device_cme9210_uarta_ctsrtsrxtx() \
+ ns9xxx_add_device_cme9210_uarta(4)
+#define ns9xxx_add_device_cme9210_uarta_full() \
+ ns9xxx_add_device_cme9210_uarta(8)
+#define ns9xxx_add_device_cme9210_uartc_rxtx() \
+ ns9xxx_add_device_cme9210_uartc(2)
diff --git a/arch/arm/mach-ns9xxx/gpio-ns921x.c b/arch/arm/mach-ns9xxx/gpio-ns921x.c
new file mode 100644
index 000000000000..fff11e82c862
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/gpio-ns921x.c
@@ -0,0 +1,41 @@
+/*
+ * arch/arm/mach-ns9xxx/gpio-ns921x.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#include <linux/module.h>
+
+#include <asm/gpio.h>
+#include <mach/irqs.h>
+
+static const struct gpio_to_irq_map gpio_to_irq_map_ns921x[] = {
+ { .gpio = 1, .irq = IRQ_NS9XXX_EXT0, .func = 1, },
+ { .gpio = 2, .irq = IRQ_NS9XXX_EXT1, .func = 1, },
+ { .gpio = 4, .irq = IRQ_NS9XXX_EXT2, .func = 1, },
+ { .gpio = 5, .irq = IRQ_NS9XXX_EXT3, .func = 1, },
+ { .gpio = 9, .irq = IRQ_NS9XXX_EXT0, .func = 2, },
+ { .gpio = 10, .irq = IRQ_NS9XXX_EXT1, .func = 2, },
+ { .gpio = 16, .irq = IRQ_NS9XXX_EXT0, .func = 2, },
+ { .gpio = 17, .irq = IRQ_NS9XXX_EXT1, .func = 2, },
+ { .gpio = 18, .irq = IRQ_NS9XXX_EXT2, .func = 2, },
+ { .gpio = 19, .irq = IRQ_NS9XXX_EXT3, .func = 2, },
+#if defined(CONFIG_PROCESSOR_NS9215)
+ { .gpio = 67, .irq = IRQ_NS9XXX_EXT3, .func = 2, },
+ { .gpio = 101, .irq = IRQ_NS9XXX_EXT3, .func = 2, },
+#endif
+ { .gpio = 104, .irq = IRQ_NS9XXX_EXT0, .func = 2, },
+ { .gpio = 105, .irq = IRQ_NS9XXX_EXT1, .func = 2, },
+ { .gpio = 106, .irq = IRQ_NS9XXX_EXT2, .func = 2, },
+};
+
+const struct gpio_to_irq_map *gpio_get_map_ns921x(unsigned gpio)
+{
+ return gpio_get_map(gpio, gpio_to_irq_map_ns921x,
+ ARRAY_SIZE(gpio_to_irq_map_ns921x));
+}
+EXPORT_SYMBOL(gpio_get_map_ns921x);
diff --git a/arch/arm/mach-ns9xxx/gpio-ns9360.c b/arch/arm/mach-ns9xxx/gpio-ns9360.c
index 377330c1b250..6bc3e74207d9 100644
--- a/arch/arm/mach-ns9xxx/gpio-ns9360.c
+++ b/arch/arm/mach-ns9xxx/gpio-ns9360.c
@@ -1,118 +1,34 @@
/*
* arch/arm/mach-ns9xxx/gpio-ns9360.c
*
- * Copyright (C) 2006,2007 by Digi International Inc.
+ * Copyright (C) 2008 by Digi International Inc.
* All rights reserved.
*
* 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/bug.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
#include <linux/module.h>
-#include <mach/regs-bbu.h>
-#include <mach/processor-ns9360.h>
+#include <asm/gpio.h>
+#include <mach/irqs.h>
-#include "gpio-ns9360.h"
+static const struct gpio_to_irq_map gpio_to_irq_map_ns9360[] = {
+ { .gpio = 1, .irq = IRQ_NS9XXX_EXT0, .func = 2, },
+ { .gpio = 7, .irq = IRQ_NS9XXX_EXT1, .func = 2, },
+ { .gpio = 11, .irq = IRQ_NS9XXX_EXT2, .func = 1, },
+ { .gpio = 13, .irq = IRQ_NS9XXX_EXT0, .func = 1, },
+ { .gpio = 18, .irq = IRQ_NS9XXX_EXT3, .func = 2, },
+ { .gpio = 28, .irq = IRQ_NS9XXX_EXT1, .func = 0, },
+ { .gpio = 32, .irq = IRQ_NS9XXX_EXT2, .func = 0, },
+ { .gpio = 40, .irq = IRQ_NS9XXX_EXT3, .func = 1, },
+ { .gpio = 68, .irq = IRQ_NS9XXX_EXT0, .func = 2, },
+ { .gpio = 69, .irq = IRQ_NS9XXX_EXT1, .func = 2, },
+};
-static inline int ns9360_valid_gpio(unsigned gpio)
+const struct gpio_to_irq_map *gpio_get_map_ns9360(unsigned gpio)
{
- return gpio <= 72;
-}
-
-static inline void __iomem *ns9360_gpio_get_gconfaddr(unsigned gpio)
-{
- if (gpio < 56)
- return BBU_GCONFb1(gpio / 8);
- else
- /*
- * this could be optimised away on
- * ns9750 only builds, but it isn't ...
- */
- return BBU_GCONFb2((gpio - 56) / 8);
-}
-
-static inline void __iomem *ns9360_gpio_get_gctrladdr(unsigned gpio)
-{
- if (gpio < 32)
- return BBU_GCTRL1;
- else if (gpio < 64)
- return BBU_GCTRL2;
- else
- /* this could be optimised away on ns9750 only builds */
- return BBU_GCTRL3;
-}
-
-static inline void __iomem *ns9360_gpio_get_gstataddr(unsigned gpio)
-{
- if (gpio < 32)
- return BBU_GSTAT1;
- else if (gpio < 64)
- return BBU_GSTAT2;
- else
- /* this could be optimised away on ns9750 only builds */
- return BBU_GSTAT3;
-}
-
-/*
- * each gpio can serve for 4 different purposes [0..3]. These are called
- * "functions" and passed in the parameter func. Functions 0-2 are always some
- * special things, function 3 is GPIO. If func == 3 dir specifies input or
- * output, and with inv you can enable an inverter (independent of func).
- */
-int __ns9360_gpio_configure(unsigned gpio, int dir, int inv, int func)
-{
- void __iomem *conf = ns9360_gpio_get_gconfaddr(gpio);
- u32 confval;
-
- confval = __raw_readl(conf);
- REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir);
- REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv);
- REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func);
- __raw_writel(confval, conf);
-
- return 0;
-}
-
-int ns9360_gpio_configure(unsigned gpio, int inv, int func)
-{
- if (likely(ns9360_valid_gpio(gpio))) {
- if (func == 3) {
- printk(KERN_WARNING "use gpio_direction_input "
- "or gpio_direction_output\n");
- return -EINVAL;
- } else
- return __ns9360_gpio_configure(gpio, 0, inv, func);
- } else
- return -EINVAL;
-}
-EXPORT_SYMBOL(ns9360_gpio_configure);
-
-int ns9360_gpio_get_value(unsigned gpio)
-{
- void __iomem *stat = ns9360_gpio_get_gstataddr(gpio);
- int ret;
-
- ret = 1 & (__raw_readl(stat) >> (gpio & 31));
-
- return ret;
-}
-
-void ns9360_gpio_set_value(unsigned gpio, int value)
-{
- void __iomem *ctrl = ns9360_gpio_get_gctrladdr(gpio);
- u32 ctrlval;
-
- ctrlval = __raw_readl(ctrl);
-
- if (value)
- ctrlval |= 1 << (gpio & 31);
- else
- ctrlval &= ~(1 << (gpio & 31));
-
- __raw_writel(ctrlval, ctrl);
+ return gpio_get_map(gpio, gpio_to_irq_map_ns9360,
+ ARRAY_SIZE(gpio_to_irq_map_ns9360));
}
+EXPORT_SYMBOL(gpio_get_map_ns9360);
diff --git a/arch/arm/mach-ns9xxx/gpio.c b/arch/arm/mach-ns9xxx/gpio.c
index 5503ca09c4ae..374e312bd7dd 100644
--- a/arch/arm/mach-ns9xxx/gpio.c
+++ b/arch/arm/mach-ns9xxx/gpio.c
@@ -1,61 +1,33 @@
/*
* arch/arm/mach-ns9xxx/gpio.c
*
- * Copyright (C) 2006,2007 by Digi International Inc.
+ * Copyright (C) 2006-2008 by Digi International Inc.
* All rights reserved.
*
* 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/kernel.h>
#include <linux/compiler.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/module.h>
-#include <linux/bitops.h>
-#include <mach/gpio.h>
-#include <mach/processor.h>
-#include <mach/processor-ns9360.h>
#include <asm/bug.h>
#include <asm/types.h>
+#include <asm/bitops.h>
-#include "gpio-ns9360.h"
-
-#if defined(CONFIG_PROCESSOR_NS9360)
-#define GPIO_MAX 72
-#elif defined(CONFIG_PROCESSOR_NS9750)
-#define GPIO_MAX 49
-#endif
+#include <mach/gpio.h>
+#include <mach/processor.h>
-/* protects BBU_GCONFx and BBU_GCTRLx */
-static spinlock_t gpio_lock = __SPIN_LOCK_UNLOCKED(gpio_lock);
+DEFINE_SPINLOCK(gpio_lock);
/* only access gpiores with atomic ops */
-static DECLARE_BITMAP(gpiores, GPIO_MAX + 1);
-
-static inline int ns9xxx_valid_gpio(unsigned gpio)
-{
-#if defined(CONFIG_PROCESSOR_NS9360)
- if (processor_is_ns9360())
- return gpio <= 72;
- else
-#endif
-#if defined(CONFIG_PROCESSOR_NS9750)
- if (processor_is_ns9750())
- return gpio <= 49;
- else
-#endif
- {
- BUG();
- return 0;
- }
-}
+static DECLARE_BITMAP(gpiores, NS9XXX_NUM_GPIO);
int gpio_request(unsigned gpio, const char *label)
{
- if (likely(ns9xxx_valid_gpio(gpio)))
+ if (likely(gpio_issocgpio(gpio)))
return test_and_set_bit(gpio, gpiores) ? -EBUSY : 0;
else
return -EINVAL;
@@ -64,84 +36,7 @@ EXPORT_SYMBOL(gpio_request);
void gpio_free(unsigned gpio)
{
- might_sleep();
clear_bit(gpio, gpiores);
return;
}
EXPORT_SYMBOL(gpio_free);
-
-int gpio_direction_input(unsigned gpio)
-{
- if (likely(ns9xxx_valid_gpio(gpio))) {
- int ret = -EINVAL;
- unsigned long flags;
-
- spin_lock_irqsave(&gpio_lock, flags);
-#if defined(CONFIG_PROCESSOR_NS9360)
- if (processor_is_ns9360())
- ret = __ns9360_gpio_configure(gpio, 0, 0, 3);
- else
-#endif
- BUG();
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- return ret;
-
- } else
- return -EINVAL;
-}
-EXPORT_SYMBOL(gpio_direction_input);
-
-int gpio_direction_output(unsigned gpio, int value)
-{
- if (likely(ns9xxx_valid_gpio(gpio))) {
- int ret = -EINVAL;
- unsigned long flags;
-
- gpio_set_value(gpio, value);
-
- spin_lock_irqsave(&gpio_lock, flags);
-#if defined(CONFIG_PROCESSOR_NS9360)
- if (processor_is_ns9360())
- ret = __ns9360_gpio_configure(gpio, 1, 0, 3);
- else
-#endif
- BUG();
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-
- return ret;
- } else
- return -EINVAL;
-}
-EXPORT_SYMBOL(gpio_direction_output);
-
-int gpio_get_value(unsigned gpio)
-{
-#if defined(CONFIG_PROCESSOR_NS9360)
- if (processor_is_ns9360())
- return ns9360_gpio_get_value(gpio);
- else
-#endif
- {
- BUG();
- return -EINVAL;
- }
-}
-EXPORT_SYMBOL(gpio_get_value);
-
-void gpio_set_value(unsigned gpio, int value)
-{
- unsigned long flags;
- spin_lock_irqsave(&gpio_lock, flags);
-#if defined(CONFIG_PROCESSOR_NS9360)
- if (processor_is_ns9360())
- ns9360_gpio_set_value(gpio, value);
- else
-#endif
- BUG();
-
- spin_unlock_irqrestore(&gpio_lock, flags);
-}
-EXPORT_SYMBOL(gpio_set_value);
diff --git a/arch/arm/mach-ns9xxx/gpiolib-ns921x.c b/arch/arm/mach-ns9xxx/gpiolib-ns921x.c
new file mode 100644
index 000000000000..e8a513171d26
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/gpiolib-ns921x.c
@@ -0,0 +1,76 @@
+/*
+ * arch/arm/mach-ns9xxx/gpiolib-ns921x.c
+ *
+ * Copyright (C) 2007-2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/errno.h>
+
+#include <asm/gpio.h>
+
+#include <mach/processor.h>
+
+static int ns921x_gpio_chip_get(struct gpio_chip *chip, unsigned offset)
+{
+ return gpio_get_value_ns921x(chip->base + offset);
+}
+
+static void ns921x_gpio_chip_set(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ gpio_set_value_ns921x_unlocked(chip->base + offset, value);
+}
+
+static int ns921x_gpio_chip_dir_input(struct gpio_chip *chip, unsigned offset)
+{
+ return gpio_direction_irqinput_ns921x_unlocked(chip->base + offset);
+}
+
+static int ns921x_gpio_chip_dir_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ return gpio_direction_output_ns921x_unlocked(chip->base + offset,
+ value);
+}
+
+static struct gpio_chip ns921x_gpio_chip = {
+ .label = "ns921x-system-gpio",
+ .direction_input = ns921x_gpio_chip_dir_input,
+ .direction_output = ns921x_gpio_chip_dir_output,
+ .get = ns921x_gpio_chip_get,
+ .set = ns921x_gpio_chip_set,
+ .base = 0,
+};
+
+static struct gpio_chip ns921x_gpio_a_chip = {
+ .label = "ns921x-system-gpio",
+ .direction_input = ns921x_gpio_chip_dir_input,
+ .direction_output = ns921x_gpio_chip_dir_output,
+ .get = ns921x_gpio_chip_get,
+ .set = ns921x_gpio_chip_set,
+ .base = 104,
+ .ngpio = 4,
+};
+
+int __init ns921x_gpio_init(void)
+{
+ int ret;
+
+ if (processor_is_ns9210())
+ ns921x_gpio_chip.ngpio = 50;
+ else if (processor_is_ns9215())
+ ns921x_gpio_chip.ngpio = 104;
+ else
+ return -EINVAL;
+
+ ret = gpiochip_add(&ns921x_gpio_chip);
+ if (ret)
+ return ret;
+
+ return gpiochip_add(&ns921x_gpio_a_chip);
+}
diff --git a/arch/arm/mach-ns9xxx/gpiolib-ns921x.h b/arch/arm/mach-ns9xxx/gpiolib-ns921x.h
new file mode 100644
index 000000000000..73b3a754b411
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/gpiolib-ns921x.h
@@ -0,0 +1,12 @@
+/*
+ * arch/arm/mach-ns9xxx/gpiolib-ns921x.h
+ *
+ * Copyright (C) 2006-2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+int __init ns921x_gpio_init(void);
diff --git a/arch/arm/mach-ns9xxx/gpiolib-ns9360.c b/arch/arm/mach-ns9xxx/gpiolib-ns9360.c
new file mode 100644
index 000000000000..310dde70fea6
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/gpiolib-ns9360.c
@@ -0,0 +1,59 @@
+/*
+ * arch/arm/mach-ns9xxx/gpiolib-ns9360.c
+ *
+ * Copyright (C) 2006-2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/bug.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include <asm/gpio.h>
+
+static int ns9360_gpio_chip_get(struct gpio_chip *chip, unsigned offset)
+{
+ return gpio_get_value_ns9360(chip->base + offset);
+}
+
+static void ns9360_gpio_chip_set(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ gpio_set_value_ns9360_unlocked(chip->base + offset, value);
+}
+
+static int ns9360_gpio_chip_dir_input(struct gpio_chip *chip, unsigned offset)
+{
+ return gpio_direction_irqinput_ns9360_unlocked(chip->base + offset);
+}
+
+static int ns9360_gpio_chip_dir_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ return gpio_direction_output_ns9360_unlocked(chip->base + offset,
+ value);
+}
+
+static struct gpio_chip ns9360_gpio_chip = {
+ .label = "ns9360-system-gpio",
+ .direction_input = ns9360_gpio_chip_dir_input,
+ .direction_output = ns9360_gpio_chip_dir_output,
+ .get = ns9360_gpio_chip_get,
+ .set = ns9360_gpio_chip_set,
+ .base = 0,
+ .ngpio = 72,
+};
+
+int __init ns9360_gpio_init(void)
+{
+ if (!processor_is_ns9360())
+ return -EINVAL;
+
+ return gpiochip_add(&ns9360_gpio_chip);
+}
+
diff --git a/arch/arm/mach-ns9xxx/gpiolib-ns9360.h b/arch/arm/mach-ns9xxx/gpiolib-ns9360.h
new file mode 100644
index 000000000000..ea37e0b4dd8c
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/gpiolib-ns9360.h
@@ -0,0 +1,12 @@
+/*
+ * arch/arm/mach-ns9xxx/gpiolib-ns9360.h
+ *
+ * Copyright (C) 2006-2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+int __init ns9360_gpio_init(void);
diff --git a/arch/arm/mach-ns9xxx/include/mach/board.h b/arch/arm/mach-ns9xxx/include/mach/board.h
index f7e9196eb9ab..247c0034e573 100644
--- a/arch/arm/mach-ns9xxx/include/mach/board.h
+++ b/arch/arm/mach-ns9xxx/include/mach/board.h
@@ -31,10 +31,18 @@
|| machine_is_cc9p9215js() \
)
+#define board_is_jsccw9p9215() (0 \
+ || machine_is_ccw9p9215js() \
+ )
+
#define board_is_jscc9p9360() (0 \
|| machine_is_cc9p9360js() \
)
+#define board_is_jscme9210() (0 \
+ || machine_is_cme9210js() \
+ )
+
#define board_is_uncbas() (0 \
|| machine_is_cc7ucamry() \
)
diff --git a/arch/arm/mach-ns9xxx/include/mach/display/CUSTOM.h b/arch/arm/mach-ns9xxx/include/mach/display/CUSTOM.h
new file mode 100644
index 000000000000..2eceb4b94494
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/display/CUSTOM.h
@@ -0,0 +1,18 @@
+
+
+
+/*
+#define CUSTOM_DISPLAY \
+{ \
+ .display_name = "CUSTOM", \
+ .width = , \
+ .height = , \
+ .control = NS9360_DISPLAY_CONTROL, \
+ .timing = { \
+ NS9360_DISPLAY_TIMING0, \
+ NS9360_DISPLAY_TIMING1, \
+ NS9360_DISPLAY_TIMING2, \
+ }, \
+ .clock = NS9360_DISPLAY_CLOCK, \
+}
+*/ \ No newline at end of file
diff --git a/arch/arm/mach-ns9xxx/include/mach/display/Kconfig b/arch/arm/mach-ns9xxx/include/mach/display/Kconfig
new file mode 100644
index 000000000000..842eb775185e
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/display/Kconfig
@@ -0,0 +1,36 @@
+# arch/arm/mach-ns9xxx/displays/Kconfig
+#
+# Copyright 2009 Digi International Inc
+#
+
+if (CC9P9360JS_FB || CCX9C_FB)
+
+comment "Display selection"
+
+config NS9XXX_FB_VGA
+ bool "CRT VGA video support"
+ depends on ! (CC9P9360JS_SERIAL_PORTA_FULL || CCX9C_SERIAL_PORTA_FULL || CCW9C_SERIAL_PORTA_FULL)
+ def_bool y
+ help
+ This enables the video support for the VGA intrface.
+
+config NS9XXX_FB_LQ057Q3DC12I
+ bool "LQ057Q3DC12I TFT LCD support"
+ depends on ! (CC9P9360JS_SERIAL_PORTA_FULL || CCX9C_SERIAL_PORTA_FULL || CCW9C_SERIAL_PORTA_FULL)
+ help
+ This enables the support for the LQ057Q3DC12I TFT display.
+
+config NS9XXX_FB_LQ064V3DG01
+ bool "LQ064V3DG01 TFT LCD support"
+ depends on ! (CC9P9360JS_SERIAL_PORTA_FULL || CCX9C_SERIAL_PORTA_FULL || CCW9C_SERIAL_PORTA_FULL)
+ help
+ This enables the support for the LQ064V3DG01 TFT display.
+
+config NS9XXX_FB_CUSTOM
+ bool "Custom display support"
+ depends on ! (CC9P9360JS_SERIAL_PORTA_FULL || CCX9C_SERIAL_PORTA_FULL || CCW9C_SERIAL_PORTA_FULL)
+ help
+ This enables the support for a customer specific display.
+ displays/CUSTOM.h has to be modified when selecting this.
+
+endif
diff --git a/arch/arm/mach-ns9xxx/include/mach/display/LQ057Q3DC12I.h b/arch/arm/mach-ns9xxx/include/mach/display/LQ057Q3DC12I.h
new file mode 100644
index 000000000000..afaf151cab2b
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/display/LQ057Q3DC12I.h
@@ -0,0 +1,27 @@
+
+#define LQ057Q3DC12I_DISPLAY \
+{ \
+ .display_name = "LQ057Q3DC12I", \
+ .width = 320, \
+ .height = 240, \
+ .control = LCD_CONTROL_WATERMARK | \
+ LCD_CONTROL_PWR | \
+ LCD_CONTROL_TFT | \
+ LCD_CONTROL_BGR | \
+ LCD_CONTROL_BPP_16 | \
+ LCD_CONTROL_EN, \
+ .timing = { \
+ LCD_TIMING0_HBP(8) | \
+ LCD_TIMING0_HFP(39) | \
+ LCD_TIMING0_HSW(2) | \
+ LCD_TIMING0_PPL(320 / 16 - 1),\
+ LCD_TIMING1_VBP(6) | \
+ LCD_TIMING1_VFP(5) | \
+ LCD_TIMING1_VSW(0) | \
+ LCD_TIMING1_LPP(240 - 1), \
+ LCD_TIMING2_CPL(320 - 1) | \
+ LCD_TIMING2_IHS | \
+ LCD_TIMING2_IVS, \
+ }, \
+ .clock = 7000000, \
+}
diff --git a/arch/arm/mach-ns9xxx/include/mach/display/LQ064V3DG01.h b/arch/arm/mach-ns9xxx/include/mach/display/LQ064V3DG01.h
new file mode 100644
index 000000000000..e801e5f0766e
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/display/LQ064V3DG01.h
@@ -0,0 +1,28 @@
+
+#define LQ064V3DG01_DISPLAY \
+{ \
+ .display_name = "LQ064V3DG01", \
+ .width = 640, \
+ .height = 480, \
+ .control = LCD_CONTROL_WATERMARK | \
+ LCD_CONTROL_PWR | \
+ LCD_CONTROL_TFT | \
+ LCD_CONTROL_BGR | \
+ LCD_CONTROL_BPP_16 | \
+ LCD_CONTROL_EN, \
+ .timing = { \
+ LCD_TIMING0_HBP(40) | \
+ LCD_TIMING0_HFP(8) | \
+ LCD_TIMING0_HSW(96) | \
+ LCD_TIMING0_PPL(640 / 16 - 1),\
+ LCD_TIMING1_VBP(31) | \
+ LCD_TIMING1_VFP(2) | \
+ LCD_TIMING1_VSW(2) | \
+ LCD_TIMING1_LPP(480 - 1), \
+ LCD_TIMING2_CPL(640 - 1) | \
+ LCD_TIMING2_IPC | \
+ LCD_TIMING2_IHS | \
+ LCD_TIMING2_IVS, \
+ }, \
+ .clock = 28000000, \
+}
diff --git a/arch/arm/mach-ns9xxx/include/mach/display/VGA.h b/arch/arm/mach-ns9xxx/include/mach/display/VGA.h
new file mode 100644
index 000000000000..63f79f2440a6
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/display/VGA.h
@@ -0,0 +1,29 @@
+
+#define VGA_DISPLAY \
+{ \
+ .display_name = "VGA", \
+ .width = 640, \
+ .height = 480, \
+ .control = LCD_CONTROL_WATERMARK | \
+ LCD_CONTROL_PWR | \
+ LCD_CONTROL_TFT | \
+ LCD_CONTROL_BGR | \
+ LCD_CONTROL_BPP_16 | \
+ LCD_CONTROL_EN, \
+ .timing = { \
+ LCD_TIMING0_HBP(40) | \
+ LCD_TIMING0_HFP(8) | \
+ LCD_TIMING0_HSW(96) | \
+ LCD_TIMING0_PPL(640 / 16 - 1),\
+ LCD_TIMING1_VBP(25) | \
+ LCD_TIMING1_VFP(2) | \
+ LCD_TIMING1_VSW(2) | \
+ LCD_TIMING1_LPP(480 - 1), \
+ LCD_TIMING2_CPL(640 - 1) | \
+ LCD_TIMING2_BCD | \
+ LCD_TIMING2_IPC | \
+ LCD_TIMING2_IHS | \
+ LCD_TIMING2_IVS, \
+ }, \
+ .clock = 0, /* external */ \
+}
diff --git a/arch/arm/mach-ns9xxx/include/mach/display/displays.h b/arch/arm/mach-ns9xxx/include/mach/display/displays.h
new file mode 100644
index 000000000000..5fa5ca1de4d6
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/display/displays.h
@@ -0,0 +1,46 @@
+/*
+ * arch/arm/mach-ns9xxx/displays/displays.h
+ *
+ * Copyright (C) 2009 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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 <mach/ns9360fb.h>
+
+#if defined(CONFIG_NS9XXX_FB_VGA)
+#include <mach/display/VGA.h>
+#endif
+
+#if defined(CONFIG_NS9XXX_FB_LQ057Q3DC12I)
+#include <mach/display/LQ057Q3DC12I.h>
+#endif
+
+#if defined(CONFIG_NS9XXX_FB_LQ064V3DG01)
+#include <mach/display/LQ064V3DG01.h>
+#endif
+
+#if defined(CONFIG_NS9XXX_FB_CUSTOM)
+#include <mach/display/CUSTOM.h>
+#endif
+
+/* List of supported displays */
+struct ns9360fb_display display_list[] = {
+#if defined(CONFIG_NS9XXX_FB_VGA)
+ VGA_DISPLAY,
+#endif
+#if defined(CONFIG_NS9XXX_FB_LQ057Q3DC12I)
+ LQ057Q3DC12I_DISPLAY,
+#endif
+#if defined(CONFIG_NS9XXX_FB_LQ064V3DG01)
+ LQ064V3DG01_DISPLAY,
+#endif
+#if defined(CONFIG_NS9XXX_FB_CUSTOM)
+ CUSTOM_DISPLAY,
+#endif
+};
+
+
diff --git a/arch/arm/mach-ns9xxx/include/mach/dma-ns921x.h b/arch/arm/mach-ns9xxx/include/mach/dma-ns921x.h
new file mode 100644
index 000000000000..9fcbee4caa39
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/dma-ns921x.h
@@ -0,0 +1,140 @@
+/*
+ * arch/arm/mach-ns9xxx/include/mach/dma-ns921x.h
+ *
+ * Copyright (C) 2009 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ */
+
+
+#ifndef __ASM_ARCH_NS921X_DMA_H
+#define __ASM_ARCH_NS921X_DMA_H
+
+#include <mach/hardware.h>
+
+/* External DMA control nad status registers. Valid channels are 1 and 2 */
+#define NS921X_DMA_BDP(x) __REG(0xa0800000 + ((x-1) & 0x1) * 0x10)
+#define NS921X_DMA_CR(x) __REG(0xa0800004 + ((x-1) & 0x1) * 0x10)
+#define NS921X_DMA_STIE(x) __REG(0xa0800008 + ((x-1) & 0x1) * 0x10)
+#define NS921X_DMA_PCS(x) __REG(0xa080000c + ((x-1) & 0x1) * 0x10)
+
+/* Control register masks */
+#define NS921X_DMA_CR_CE (0x1 << 31)
+#define NS921X_DMA_CR_CA (0x1 << 30)
+#define NS921X_DMA_CR_CG (0x1 << 29)
+#define NS921X_DMA_CR_SW_MA (0x3 << 27)
+#define NS921X_DMA_CR_SW_8b (0x0 << 27)
+#define NS921X_DMA_CR_SW_16b (0x1 << 27)
+#define NS921X_DMA_CR_SW_32b (0x2 << 27)
+#define NS921X_DMA_CR_DW_MA (0x3 << 25)
+#define NS921X_DMA_CR_DW_8b (0x0 << 25)
+#define NS921X_DMA_CR_DW_16b (0x1 << 25)
+#define NS921X_DMA_CR_DW_32b (0x2 << 25)
+#define NS921X_DMA_CR_SB_MA (0x3 << 23)
+#define NS921X_DMA_CR_SB_1B (0x0 << 23)
+#define NS921X_DMA_CR_SB_4B (0x1 << 23)
+#define NS921X_DMA_CR_SB_16B (0x2 << 23)
+#define NS921X_DMA_CR_SB_32B (0x3 << 23)
+#define NS921X_DMA_CR_DB_MA (0x3 << 21)
+#define NS921X_DMA_CR_DB_1B (0x0 << 21)
+#define NS921X_DMA_CR_DB_4B (0x1 << 21)
+#define NS921X_DMA_CR_DB_16B (0x2 << 21)
+#define NS921X_DMA_CR_DB_32B (0x3 << 21)
+#define NS921X_DMA_CR_SINC_N (0x1 << 20)
+#define NS921X_DMA_CR_DINC_N (0x1 << 19)
+#define NS921X_DMA_CR_POL (0x1 << 18)
+#define NS921X_DMA_CR_MODE (0x1 << 17)
+#define NS921X_DMA_CR_MODE_FBW (0x0 << 17)
+#define NS921X_DMA_CR_MODE_FBR (0x1 << 17)
+#define NS921X_DMA_CR_RESET (0x1 << 16)
+#define NS921X_DMA_CR_STATE_MA (0x3f << 10)
+#define NS921X_DMA_CR_INDEX_MA (0x3ff << 0)
+
+/* Status and interrupt enable masks */
+#define NS921X_DMA_STIE_NCIP (0x1 << 31)
+#define NS921X_DMA_STIE_ECIP (0x1 << 30)
+#define NS921X_DMA_STIE_NRIP (0x1 << 29)
+#define NS921X_DMA_STIE_CAIP (0x1 << 28)
+#define NS921X_DMA_STIE_PCIP (0x1 << 27)
+#define NS921X_DMA_STIE_NCIE (0x1 << 24)
+#define NS921X_DMA_STIE_ECIE (0x1 << 23)
+#define NS921X_DMA_STIE_NRIE (0x1 << 22)
+#define NS921X_DMA_STIE_CAIE (0x1 << 21)
+#define NS921X_DMA_STIE_PCIE (0x1 << 20)
+#define NS921X_DMA_STIE_IE_ALL (0x1f << 20)
+#define NS921X_DMA_STIE_WRAP (0x1 << 19)
+#define NS921X_DMA_STIE_DONE (0x1 << 18)
+#define NS921X_DMA_STIE_LAST (0x1 << 17)
+#define NS921X_DMA_STIE_FULL (0x1 << 16)
+#define NS921X_DMA_STIE_BLEN_MA (0xffff << 0)
+
+/* Peripheral CS register */
+#define NS921X_DMA_PCS_SEL_MA (0x3 << 0)
+#define NS921X_DMA_PCS_CS0 (0x0 << 0)
+#define NS921X_DMA_PCS_CS1 (0x1 << 0)
+#define NS921X_DMA_PCS_CS2 (0x2 << 0)
+#define NS921X_DMA_PCS_CS3 (0x3 << 0)
+
+#define EXT_DMA_DESC_CTRL_WRAP (0x1 << 15)
+#define EXT_DMA_DESC_CTRL_INT (0x1 << 14)
+#define EXT_DMA_DESC_CTRL_LAST (0x1 << 13)
+#define EXT_DMA_DESC_CTRL_FULL (0x1 << 12)
+#define EXT_DMA_DESC_CTRL_ALL (EXT_DMA_DESC_CTRL_FULL | \
+ EXT_DMA_DESC_CTRL_INT | \
+ EXT_DMA_DESC_CTRL_LAST | \
+ EXT_DMA_DESC_CTRL_WRAP)
+
+struct ext_dma_desc_t {
+ unsigned int src;
+ unsigned int length;
+ unsigned int dest;
+ unsigned short status;
+ unsigned short control;
+}__attribute__((__packed__));
+
+
+/*
+ * IO-HUB constans and macros
+ * The maximal number of DMA-buffer descriptors comes from the NET+OS
+ * distribution (iop_private.h)
+ */
+#define IOHUB_MAX_DMA_BUFFERS (64)
+#define IOHUB_MAX_DMA_LENGTH (65535)
+
+#define IOHUB_DMA_DESC_CTRL_WRAP EXT_DMA_DESC_CTRL_WRAP
+#define IOHUB_DMA_DESC_CTRL_INT EXT_DMA_DESC_CTRL_INT
+#define IOHUB_DMA_DESC_CTRL_LAST EXT_DMA_DESC_CTRL_LAST
+#define IOHUB_DMA_DESC_CTRL_FULL EXT_DMA_DESC_CTRL_FULL
+#define IOHUB_DMA_DESC_CTRL_ALL EXT_DMA_DESC_CTRL_ALL
+
+struct iohub_dma_desc_t {
+ unsigned int src;
+ unsigned int length;
+ unsigned int reserved;
+ unsigned short status;
+ unsigned short control;
+}__attribute__((packed, aligned));
+
+
+#define IOHUB_DMA_DESC_LENGTH sizeof(struct iohub_dma_desc_t)
+
+/* This is the FIFO used for the DMA-transfers of the IOHUB (e.g. FIMs) */
+struct iohub_dma_fifo_t {
+ int length;
+ struct iohub_dma_desc_t **descs;
+ dma_addr_t phys_descs;
+ struct iohub_dma_desc_t *first;
+ struct iohub_dma_desc_t *last;
+ struct iohub_dma_desc_t *dma_first;
+ struct iohub_dma_desc_t *dma_last;
+ struct iohub_dma_desc_t *dma_next;
+ struct iohub_dma_desc_t *next_free;
+ unsigned long rx_error, tx_error;
+ unsigned long rx_error1, tx_error2;
+}__attribute__((__packed__));
+
+#endif /* ifndef __ASM_ARCH_NS912X_DMA_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/fim-firmware.h b/arch/arm/mach-ns9xxx/include/mach/fim-firmware.h
new file mode 100644
index 000000000000..6bdd0e05333d
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/fim-firmware.h
@@ -0,0 +1,101 @@
+/*
+ * arch/arm/mach-ns9xxx/include/mach/fim-firmware.h
+ *
+ * Copyright (C) 2006 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * !Revision: $Revision: 1.0 $
+ * !Author: Luis Galdos
+ * !Desc:
+ * !References:
+ */
+
+
+#ifndef _FIM_FIRMWARE_H
+#define _FIM_FIRMWARE_H
+
+
+
+#define FIM_NUM_HWA_CONF_REGS (14)
+#define FIM_NS9215_MAX_INSTRUCTIONS (1024)
+
+
+typedef enum {
+ FIM_NS9215 = 0,
+} fim_processors_t;
+
+#define PROCESSOR_TYPE_VALID(t) (t == FIM_NS9215) /* || (t == ADD_NEW_ONE_HERE) */
+
+
+typedef enum {
+ FIM_FORMAT_0 = 0,
+} fim_formats_t;
+
+#define FORMAT_TYPE_VALID(t) (t == FIM_FORMAT_0) /* || (t == ADD_NEW_ONE_HERE) */
+
+typedef enum {
+ FIM_PROCESSOR_PIC0,
+ FIM_PROCESSOR_PIC1
+} fim_processor_index_t;
+
+typedef enum {
+ FIM_HW_ASSIST_MODE_NONE,
+ FIM_HW_ASSIST_MODE_GENERIC,
+ FIM_HW_ASSIST_MODE_CAN,
+} fim_hw_assit_t;
+
+typedef enum {
+ FIM_CLK_DIV_2,
+ FIM_CLK_DIV_4,
+ FIM_CLK_DIV_8,
+ FIM_CLK_DIV_16,
+ FIM_CLK_DIV_32,
+ FIM_CLK_DIV_64,
+ FIM_CLK_DIV_128,
+ FIM_CLK_DIV_256
+} fim_output_clk_div_t;
+
+typedef enum {
+ FIM_SIGBUS_SIGNAL_0,
+ FIM_SIGBUS_SIGNAL_1,
+ FIM_SIGBUS_SIGNAL_2,
+ FIM_SIGBUS_SIGNAL_3,
+ FIM_SIGBUS_SIGNAL_4,
+ FIM_SIGBUS_SIGNAL_5,
+ FIM_SIGBUS_SIGNAL_6,
+ FIM_SIGBUS_SIGNAL_7,
+ FIM_SIGBUS_CONTROL_0,
+ FIM_SIGBUS_CONTROL_1,
+ FIM_SIGBUS_CONTROL_2,
+ FIM_SIGBUS_CONTROL_3,
+ FIM_SIGBUS_16_BIT_BUS,
+ FIM_SIGBUS_24_BIT_BUS
+} fim_signal_bus_t;
+
+
+
+/*
+ * The macro FIM_FIRMWARE_BUILDER is set by the build-system of the FIM-firmware
+ * See the Makefile under ../firmware/Makefile for more infos.
+ */
+struct fim_program_t {
+ fim_processors_t processor;
+ fim_formats_t format;
+ fim_hw_assit_t hw_mode;
+ fim_output_clk_div_t clkdiv;
+ unsigned int hwa_cfg[FIM_NUM_HWA_CONF_REGS];
+ unsigned int length;
+#ifndef FIM_FIRMWARE_BUILDER
+ unsigned short data[FIM_NS9215_MAX_INSTRUCTIONS];
+#endif
+} __attribute__((packed, aligned));
+
+
+#endif /* _FIM_FIRMWARE_H */
+
+
+
diff --git a/arch/arm/mach-ns9xxx/include/mach/fim-ns921x.h b/arch/arm/mach-ns9xxx/include/mach/fim-ns921x.h
new file mode 100644
index 000000000000..6fbc61488f32
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/fim-ns921x.h
@@ -0,0 +1,466 @@
+/* -*- linux-c -*-
+ * arch/arm/mach-ns9xxx/include/mach/fim-ns921x.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * !Revision: $Revision: 1.25 $
+ * !Author: Silvano Najera, Luis Galdos
+ * !Descr:
+ * !References:
+ */
+
+
+#ifndef _NS921X_FIM_CORE_H
+#define _NS921X_FIM_CORE_H
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/platform_device.h>
+#include <linux/kfifo.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+
+#include <mach/dma-ns921x.h>
+
+
+#define FIM_MAX_FIRMWARE_NAME 32
+
+
+/* For DMA handling... */
+#define FIM_DMA_NCIP (0x1)
+#define FIM_DMA_NRIP (0x2)
+#define FIM_DMA_ECIP (0x4)
+#define FIM_DMA_CAIP (0x8)
+#define FIM_DMA_CANCELLED FIM_DMA_CAIP
+#define FIM_DMA_FLUSHED (0x10)
+#define FIM_DMA_SUCCESS (FIM_DMA_NCIP | FIM_DMA_NRIP)
+
+
+#define FIM_MAX_PIC_INDEX (1)
+#define FIM_MIN_PIC_INDEX (0)
+#define FIM_NR_PICS (FIM_MAX_PIC_INDEX-FIM_MIN_PIC_INDEX+1)
+
+
+/* @XXX: Place this macros in another place? */
+#define NS92XX_FIM_GEN_CTRL_STOP_PIC ~NS92XX_FIM_GEN_CTRL_PROGMEM
+#define NS92XX_FIM_GEN_CTRL_START_PIC NS92XX_FIM_GEN_CTRL_PROGMEM
+
+
+
+/* Please note that the maximal DMA-buffer size is 64kB */
+/* @FIXME: Check that the maximal size of the descriptors is littler than one page */
+#define PIC_DMA_RX_BUFFERS (10)
+#define PIC_DMA_TX_BUFFERS (10)
+#define PIC_DMA_BUFFER_SIZE (1 * PAGE_SIZE)
+
+/*
+ * Internal structure for handling with the DMA-buffer descriptors
+ * p_desc : Physical descriptors address
+ * v_desc : Virtual access address for the descriptors
+ * v_buf : Virtual address of the memory buffers
+ * length : Configured length of this buffer
+ * tasked : Used for locking the descriptor
+ */
+struct pic_dma_desc_t {
+ dma_addr_t src;
+ size_t length;
+ atomic_t tasked;
+ void *private;
+ int total_length;
+};
+
+
+/*
+ * Structure used by the FIM-API to configure the DMA-buffer and buffer-descriptors.
+ * rxnr : Number of RX-DMA-buffers
+ * rxsz : Size of each DMA-buffer (in Bytes)
+ * txnr : Number of TX-DMA-buffers
+ * txsz : Size for each TX-buffer (in Bytes)
+ */
+struct fim_dma_cfg_t {
+ int rxnr;
+ int rxsz;
+ int txnr;
+ int txsz;
+};
+
+
+/*
+ * This structure should be used for transferring data with the API
+ * length : Date length to transfer
+ * data : Data buffer
+ * private : The API will not touch this pointer
+ * sent : The external driver can use it for waking up sleeping processes
+ */
+struct fim_buffer_t {
+ int length;
+ unsigned char *data;
+ void *private;
+ int sent;
+};
+
+
+/* @TODO: We need perhaps another PIC-structure for the U-Boot */
+struct pic_t {
+ int irq;
+ struct device *dev;
+ struct fim_driver *driver;
+ void __iomem *reg_addr;
+ void __iomem *instr_addr;
+ void __iomem *hwa_addr;
+ void __iomem *iohub_addr;
+ spinlock_t lock;
+ int index;
+ atomic_t irq_enabled;
+ atomic_t requested;
+
+ /* RX-DMA structures */
+ struct iohub_dma_fifo_t rx_fifo;
+ spinlock_t rx_lock;
+ struct fim_dma_cfg_t dma_cfg;
+
+ /* Variables for the DMA-memory buffers */
+ dma_addr_t dma_phys;
+ void __iomem *dma_virt;
+ size_t dma_size;
+
+ /* Data for the handling of the TX-DMA buffers */
+ spinlock_t tx_lock;
+ struct pic_dma_desc_t *tx_desc;
+ struct iohub_dma_fifo_t tx_fifo;
+ atomic_t tx_tasked;
+ atomic_t tx_aborted;
+ struct tasklet_struct rx_tasklet;
+
+ /* Info data for the sysfs */
+ char fw_name[FIM_MAX_FIRMWARE_NAME];
+ int fw_length;
+
+ /* Functions for a low level access to the PICs */
+ int (* is_running)(struct pic_t *);
+ int (* start_at_zero)(struct pic_t *);
+ int (* stop_and_reset)(struct pic_t *);
+ int (* download_firmware)(struct pic_t *, const unsigned char *);
+ int (* get_ctrl_reg)(struct pic_t *, int , unsigned int *);
+ void (* set_ctrl_reg)(struct pic_t *, int , unsigned int );
+ int (* send_interrupt)(struct pic_t *, u32 );
+ void (* ack_interrupt)(struct pic_t * , int );
+};
+
+
+/*
+ * Structure with the GPIOs to use for the driver to be initialized
+ * nr : GPIO number
+ * name : Name to use for the GPIO
+ * picval : Value to pass to the PIC-firmware
+ * func : Function to be configured for the GPIO
+ */
+struct fim_gpio_t {
+ int nr;
+ char *name;
+ unsigned char picval; /* Value to pass to firmware */
+ unsigned int func;
+};
+
+#define FIM_LAST_GPIO -2
+#define FIM_GPIO_DONT_USE -1
+
+/*
+ * Internal structure for allocating a FIM driver
+ * picnr : Number of the PIC to use for this driver
+ * fw_code : Firmware code that should be used as firmware
+ * fw_name : Name of the firmware to get over the firmware layer
+ * driver : Driver structure
+ * dev : Device that should be set by the FIM-API
+ * driver_data : The API will not touch this member
+ * fim_isr : Called when the PIC generates an interrupt
+ * dma_tx_isr : TX-callback function. Called in interrupt context
+ * dma_rx_isr : RX-callback. Called inside the interrupt context
+ * dma_cfg : If NULL then the API will use the default config
+ * verbose : Used by the FIM-core for printing sys messages (debug, infos, etc.)
+ */
+struct fim_driver {
+ int picnr;
+ const unsigned char *fw_code;
+ const char *fw_name;
+ struct device_driver driver;
+ struct device *dev;
+ void (*fim_isr)(struct fim_driver *, int, unsigned char, unsigned int);
+ void (*dma_tx_isr)(struct fim_driver *, int, struct fim_buffer_t *);
+ void (*dma_rx_isr)(struct fim_driver *, int, struct fim_buffer_t *);
+ void (*dma_error_isr)(struct fim_driver *, ulong rx_err, ulong tx_err);
+ void *driver_data;
+ struct fim_dma_cfg_t *dma_cfg;
+ int verbose;
+};
+
+
+
+/*
+ * Structure for the FIM-devices with UART-support
+ * If a GPIO should not be used, then it's required to disable it by using the
+ * above macro 'FIM_GPIO_DONT_USE'
+ *
+ * fim_nr : Number of the FIM to use for the device
+ * gpio_nr : GPIO to use for the interface line
+ * fim_cfg : Currently not used
+ */
+struct fim_serial_platform_data {
+ int fim_nr;
+
+ int rx_gpio_nr;
+ unsigned int rx_gpio_func;
+ unsigned int rx_fim_cfg;
+
+ int tx_gpio_nr;
+ unsigned int tx_gpio_func;
+ unsigned int tx_fim_cfg;
+
+ int cts_gpio_nr;
+ unsigned int cts_gpio_func;
+ unsigned int cts_fim_cfg;
+
+ int rts_gpio_nr;
+ unsigned int rts_gpio_func;
+ unsigned int rts_fim_cfg;
+};
+
+
+/* Macro for the configuration of the GPIOs for the FIM-serial driver */
+#define NS921X_FIM_SERIAL_GPIOS(rx, tx, rts, cts, func) \
+ .rx_gpio_nr = rx, \
+ .rx_gpio_func = func, \
+ .tx_gpio_nr = tx, \
+ .tx_gpio_func = func, \
+ .rts_gpio_nr = rts, \
+ .rts_gpio_func = func, \
+ .cts_gpio_nr = cts, \
+ .cts_gpio_func = func
+
+
+/*
+ * Structure for the FIM-devices with SDIO-support
+ * If a GPIO should not be used, then it's required to disable it by using the
+ * macro 'FIM_GPIO_DONT_USE'
+ *
+ * fim_nr : Number of the FIM to use for the device
+ * host_caps : Specific host capabilities (see: linux/mmc/host.h)
+ */
+struct fim_sdio_platform_data {
+ int fim_nr;
+ unsigned int host_caps; /* Host capabilities */
+
+ int d0_gpio_nr; /* data 0 */
+ unsigned int d0_gpio_func;
+ int d1_gpio_nr; /* data 1 */
+ unsigned int d1_gpio_func;
+ int d2_gpio_nr; /* data 2 */
+ unsigned int d2_gpio_func;
+ int d3_gpio_nr; /* data 3 */
+ unsigned int d3_gpio_func;
+ int wp_gpio_nr; /* write protect */
+ unsigned int wp_gpio_func;
+ int cd_gpio_nr; /* card detect */
+ unsigned int cd_gpio_func;
+ int clk_gpio_nr; /* clock */
+ unsigned int clk_gpio_func;
+ int cmd_gpio_nr; /* command */
+ unsigned int cmd_gpio_func;
+};
+
+
+/*
+ * Use the below macro if all the GPIOs can be configured with the same function
+ * number (this is the normal case)
+ */
+#define NS921X_FIM_SDIO_GPIOS(d0, d1, d2, d3, wp, cd, clk, cmd, func) \
+ .d0_gpio_nr = d0, \
+ .d0_gpio_func = func, \
+ .d1_gpio_nr = d1, \
+ .d1_gpio_func = func, \
+ .d2_gpio_nr = d2, \
+ .d2_gpio_func = func, \
+ .d3_gpio_nr = d3, \
+ .d3_gpio_func = func, \
+ .wp_gpio_nr = wp, \
+ .wp_gpio_func = func, \
+ .cd_gpio_nr = cd, \
+ .cd_gpio_func = func, \
+ .clk_gpio_nr = clk, \
+ .clk_gpio_func = func, \
+ .cmd_gpio_nr = cmd, \
+ .cmd_gpio_func = func
+
+/*
+ * The new FIM board doesn't connect all the lines to the FIM. The CMD
+ * and CD are not connected to the FIM.
+ */
+#define NS921X_FIM_SDIO_GPIOS_FIM(d0, d1, d2, d3, clk, cmd, func) \
+ .d0_gpio_nr = d0, \
+ .d0_gpio_func = func, \
+ .d1_gpio_nr = d1, \
+ .d1_gpio_func = func, \
+ .d2_gpio_nr = d2, \
+ .d2_gpio_func = func, \
+ .d3_gpio_nr = d3, \
+ .d3_gpio_func = func, \
+ .clk_gpio_nr = clk, \
+ .clk_gpio_func = func, \
+ .cmd_gpio_nr = cmd, \
+ .cmd_gpio_func = func
+
+/*
+ * Structure for the FIM-devices with CAN-support
+ * If a GPIO should not be used, then it's required to disable it by using the
+ * above macro 'FIM_GPIO_DONT_USE'
+ *
+ * fim_nr : Number of the FIM to use for the device
+ * gpio_nr : GPIO to use for the interface line
+ */
+struct fim_can_platform_data {
+
+ int fim_nr;
+ int fim_can_bitrate;
+
+ int rx_gpio_nr;
+ unsigned int rx_gpio_func;
+ int tx_gpio_nr;
+ unsigned int tx_gpio_func;
+};
+
+/* Macro for the configuration of the GPIOs for the FIM CAN driver */
+#define NS921X_FIM_CAN_GPIOS(rx, tx, func) \
+ .rx_gpio_nr = rx, \
+ .rx_gpio_func = func, \
+ .tx_gpio_nr = tx, \
+ .tx_gpio_func = func
+
+/*
+ * Structure for the FIM-devices with USB support
+ * If a GPIO should not be used, then it's required to disable it by using the
+ * above macro 'FIM_GPIO_DONT_USE'
+ *
+ * fim_nr : Number of the FIM to use for the device
+ * gpio_nr : GPIO to use for the interface line
+ */
+struct fim_usb_platform_data {
+
+ int fim_nr;
+
+ int (*init)(struct device *);
+ int (*exit)(struct device *);
+
+ int vp_gpio_nr;
+ unsigned int vp_gpio_func;
+ int vm_gpio_nr;
+ unsigned int vm_gpio_func;
+ int rcv_gpio_nr;
+ unsigned int rcv_gpio_func;
+ int oe_l_gpio_nr;
+ unsigned int oe_l_gpio_func;
+ int enum_gpio_nr;
+ unsigned int enum_gpio_func;
+ int spnd_gpio_nr;
+ unsigned int spnd_gpio_func;
+};
+
+/*
+ * Macro for the configuration of the GPIOs for the FIM USB driver
+ * IMPORTANT: The FIM-firmware is able to control the DP, DM, OE and RCV pins, but NOT
+ * the lines for the enumeration (ENUM) and suspend (SPND). The 'func_out' defines the
+ * function for the output GPIOs
+ */
+#define NS921X_FIM_USB_GPIOS(vp, vm, rcv, oe_l, enume, spnd, func, func_out) \
+ .vp_gpio_nr = vp, \
+ .vp_gpio_func = func, \
+ .vm_gpio_nr = vm, \
+ .vm_gpio_func = func, \
+ .rcv_gpio_nr = rcv, \
+ .rcv_gpio_func = func, \
+ .oe_l_gpio_nr = oe_l, \
+ .oe_l_gpio_func = func, \
+ .enum_gpio_nr = enume, \
+ .enum_gpio_func = func_out, \
+ .spnd_gpio_nr = spnd, \
+ .spnd_gpio_func = func_out
+
+/* Macros for building the FIM-drivers as loadable modules */
+#if defined(MODULE)
+# define NS921X_FIM_NUMBERS_PARAM(number) \
+ static int number = -1; \
+ module_param_named(fims, number, int, 0644);
+#else
+# define NS921X_FIM_NUMBERS_PARAM(number) \
+ static int number = FIM_NR_PICS;
+#endif
+
+/* Call the function for checking the FIM module parameter */
+#if defined(MODULE)
+inline int fim_check_numbers_param(int number) \
+{ \
+ if (number < 0 || number > FIM_NR_PICS) \
+ return -1; \
+ else \
+ return 0; \
+}
+inline int fim_check_device_id(int number, uint id) { \
+ int ret; \
+ if (id < 0) \
+ ret = 1; \
+ else if (number == FIM_NR_PICS && id < number) \
+ ret = 0; \
+ else if (number < FIM_NR_PICS && id == number) \
+ ret = 0; \
+ else \
+ ret = 1; \
+ return ret; \
+}
+#else
+# define fim_check_numbers_param(number) (0)
+# define fim_check_device_id(number, id) (id < 0 || id >= number)
+#endif
+
+/* These are the functions of the FIM-API */
+int fim_register_driver(struct fim_driver *driver);
+int fim_unregister_driver(struct fim_driver *driver);
+int fim_send_interrupt2(struct fim_driver *driver, unsigned int code);
+int fim_get_exp_reg(struct fim_driver *driver, int nr, unsigned int *value);
+int fim_enable_irq(struct fim_driver *driver);
+int fim_disable_irq(struct fim_driver *driver);
+int fim_send_buffer(struct fim_driver *driver, const struct fim_buffer_t *bufdesc);
+int fim_tx_buffers_room(struct fim_driver *driver);
+int fim_tx_buffers_level(struct fim_driver *driver);
+int fim_send_reset(struct fim_driver *driver);
+int fim_send_start(struct fim_driver *driver);
+int fim_send_stop(struct fim_driver *driver);
+void fim_flush_rx(struct fim_driver *driver);
+void fim_flush_tx(struct fim_driver *driver);
+struct fim_buffer_t *fim_alloc_buffer(struct fim_driver *driver, int length,
+ unsigned int gfp_flags);
+void fim_free_buffer(struct fim_driver *driver, struct fim_buffer_t *buffer);
+void fim_set_ctrl_reg(struct fim_driver *driver, int reg, unsigned int val);
+void fim_set_exp_reg(struct fim_driver *driver, int reg, unsigned int val);
+int fim_get_ctrl_reg(struct fim_driver *driver, int reg, unsigned int *val);
+int fim_get_stat_reg(struct fim_driver *driver, int reg, unsigned int *val);
+struct pic_t *fim_request_pic(int picnr);
+void fim_free_pic(struct pic_t *pic);
+void fim_print_fifo_status(struct fim_driver *driver);
+int fim_number_pics(void);
+int fim_download_firmware(struct fim_driver *driver);
+int fim_is_running(struct fim_driver *driver);
+
+int fim_dma_stop(struct fim_driver *fim);
+int fim_dma_start(struct fim_driver *fim, struct fim_dma_cfg_t *cfg);
+
+#endif /* ifndef _NS921X_FIM_CORE_H */
+
+
+
diff --git a/arch/arm/mach-ns9xxx/include/mach/fim-uncompress.h b/arch/arm/mach-ns9xxx/include/mach/fim-uncompress.h
new file mode 100644
index 000000000000..0f77d72bbc5d
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/fim-uncompress.h
@@ -0,0 +1,93 @@
+/* -*- linux-c -*-
+ *
+ * arch/arm/mach-ns9xxx/include/mach/fim-uncompress.h
+ *
+ * Copyright (C) 2009 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * !Authors: Hector Palacios, Luis Galdos
+ * !Desc:
+ * !References:
+ */
+
+#ifndef __FIM_UNCROMPRESS_H
+#define __FIM_UNCROMPRESS_H
+
+#include <asm/io.h>
+
+#define NS921X_FIM0 __REG(0x90000000)
+#define NS921X_FIM1 __REG(0x90008000)
+
+#define FIM_SERIAL_DATA_BITS (8)
+
+#define NS92XX_FIM_CTRL0_REG (0x10)
+#define NS92XX_FIM_EXP0_REG (0x50)
+#define NS92XX_FIM_CTRL_REG(i) (NS92XX_FIM_CTRL0_REG + 4*i)
+#define NS92XX_FIM_EXP_REG(i) (NS92XX_FIM_EXP0_REG + 4*i)
+
+#define NS92XX_FIM_REG_BASE_PA (0x90001000)
+#define NS92XX_FIM_REG_BASE_PA (0x90001000)
+#define NS92XX_FIM_REG_OFFSET (0x8000)
+#define FIM_REG_ADDR(x) (NS92XX_FIM_REG_BASE_PA + \
+ (x * NS92XX_FIM_REG_OFFSET))
+#define NS921X_FIM_ENABLED(base) (__raw_readl((base) + 0x1000) \
+ & (1 << 31))
+#define NS92XX_FIM_GEN_CTRL_REG (0x00)
+#define NS92XX_FIM_GEN_CTRL_INTTOPIC (0x00007f00)
+#define NS92XX_FIM_GEN_CTRL_INTACKRD (0x00000080)
+#define NS92XX_FIM_INT_MASK(code) (code<<8)
+
+#define FIM_SERIAL_INT_INSERT_CHAR (0x01)
+
+static int fim_send_interrupt(int pic_num, unsigned int code)
+{
+ unsigned int stopcnt;
+ u32 status;
+
+ code = NS92XX_FIM_INT_MASK(code);
+ status = readl(FIM_REG_ADDR(pic_num) + NS92XX_FIM_GEN_CTRL_REG);
+ writel(status | code, FIM_REG_ADDR(pic_num) + NS92XX_FIM_GEN_CTRL_REG);
+
+ /* This loop is perhaps problematic, exit with a timeout */
+ stopcnt = 0xFFFF;
+ do {
+ status = readl(FIM_REG_ADDR(pic_num) + NS92XX_FIM_GEN_CTRL_REG);
+ stopcnt--;
+ } while (!(status & NS92XX_FIM_GEN_CTRL_INTACKRD) && stopcnt);
+
+ if (!stopcnt) {
+ return 1;
+ }
+
+ /* Reset the interrupt bits for the PIC acknowledge */
+ status &= ~NS92XX_FIM_GEN_CTRL_INTTOPIC;
+ writel(status, FIM_REG_ADDR(pic_num) + NS92XX_FIM_GEN_CTRL_REG);
+
+ stopcnt = 0xFFFF;
+ do {
+ status = readl(FIM_REG_ADDR(pic_num) + NS92XX_FIM_GEN_CTRL_REG);
+ stopcnt--;
+ } while ((status & NS92XX_FIM_GEN_CTRL_INTACKRD) && stopcnt);
+
+ if (!stopcnt) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void fim_set_ctrl_reg(int pic_num, int reg, unsigned int val)
+{
+ writel(val, FIM_REG_ADDR(pic_num) + NS92XX_FIM_CTRL_REG(reg));
+}
+
+static int fim_get_exp_reg(int pic_num, int nr)
+{
+ return readl(FIM_REG_ADDR(pic_num) + NS92XX_FIM_EXP_REG(nr));
+}
+
+#endif /* __FIM_UNCROMPRESS_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/gpio.h b/arch/arm/mach-ns9xxx/include/mach/gpio.h
index 5eb349032579..40e246dabdcc 100644
--- a/arch/arm/mach-ns9xxx/include/mach/gpio.h
+++ b/arch/arm/mach-ns9xxx/include/mach/gpio.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-ns9xxx/include/mach/gpio.h
*
- * Copyright (C) 2007 by Digi International Inc.
+ * Copyright (C) 2007,2008 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
@@ -11,21 +11,457 @@
#ifndef __ASM_ARCH_GPIO_H
#define __ASM_ARCH_GPIO_H
+#include <linux/spinlock.h>
#include <asm/errno.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/processor.h>
-int gpio_request(unsigned gpio, const char *label);
+#include <mach/regs-io-ns921x.h>
+#include <mach/regs-bbu.h>
+
+
+/* Macros for configuring the GPIO-functions */
+#if defined(CONFIG_PROCESSOR_NS9210) || defined(CONFIG_PROCESSOR_NS9215)
+# define NS921X_GPIO_FUNC_0 (0x00)
+# define NS921X_GPIO_FUNC_1 (0x01)
+# define NS921X_GPIO_FUNC_2 (0x02)
+# define NS921X_GPIO_FUNC_3 (0x03)
+# define NS921X_GPIO_FUNC_4 (0x04)
+
+# define NS921X_GPIO_FUNC_GPIO NS921X_GPIO_FUNC_3
+
+# define NS921X_GPIO_INPUT (0x00)
+# define NS921X_GPIO_OUTPUT (0x01)
+
+# define NS921X_GPIO_INVERT (0x01)
+# define NS921X_GPIO_DONT_INVERT (0x00)
+
+# define NS921X_GPIO_ENABLE_PULLUP (0x00)
+# define NS921X_GPIO_DISABLE_PULLUP (0x01)
+#endif
+
+/* Macros for configuring the GPIO-functions */
+#if defined(CONFIG_PROCESSOR_NS9360)
+# define NS9360_GPIO_FUNC_0 (0x00)
+# define NS9360_GPIO_FUNC_1 (0x01)
+# define NS9360_GPIO_FUNC_2 (0x02)
+# define NS9360_GPIO_FUNC_3 (0x03)
+# define NS9360_GPIO_FUNC_4 (0x04)
+
+# define NS9360_GPIO_FUNC_GPIO NS9360_GPIO_FUNC_3
+
+# define NS9360_GPIO_INPUT (0x00)
+# define NS9360_GPIO_OUTPUT (0x01)
+
+# define NS9360_GPIO_INVERT (0x01)
+# define NS9360_GPIO_DONT_INVERT (0x00)
+#endif
+
+
+struct gpio_to_irq_map {
+ unsigned gpio;
+ unsigned irq;
+ int func;
+};
+
+#define NS9XXX_NUM_GPIO 0
+
+#if defined(CONFIG_PROCESSOR_NS9210)
+# define NS9XXX_NUM_GPIO_NS9210 108
+# if NS9XXX_NUM_GPIO < NS9XXX_NUM_GPIO_NS9210
+# undef NS9XXX_NUM_GPIO
+# define NS9XXX_NUM_GPIO NS9XXX_NUM_GPIO_NS9210
+# endif
+static inline int gpio_issocgpio_ns9210(unsigned gpio)
+{
+ return gpio < NS9XXX_NUM_GPIO_NS9210 && !(gpio >= 50 && gpio < 105);
+}
+#endif
+
+#if defined(CONFIG_PROCESSOR_NS9215)
+# define NS9XXX_NUM_GPIO_NS9215 108
+# if NS9XXX_NUM_GPIO < NS9XXX_NUM_GPIO_NS9215
+# undef NS9XXX_NUM_GPIO
+# define NS9XXX_NUM_GPIO NS9XXX_NUM_GPIO_NS9215
+# endif
+static inline int gpio_issocgpio_ns9215(unsigned gpio)
+{
+ return gpio < NS9XXX_NUM_GPIO_NS9215;
+}
+#endif
+
+static const inline struct gpio_to_irq_map *gpio_get_map(unsigned gpio,
+ const struct gpio_to_irq_map map[], size_t array_size)
+{
+ /* TODO: check if a binary search yields some performance advantage */
+ int i;
+
+ for (i = 0; i < array_size; ++i) {
+ if (map[i].gpio == gpio)
+ return &map[i];
+ }
+
+ return NULL;
+}
+
+#if defined(CONFIG_PROCESSOR_NS921X)
+const struct gpio_to_irq_map *gpio_get_map_ns921x(unsigned gpio) __attribute__((const));
+
+static inline void gpio_configure_ns921x_unlocked(unsigned gpio,
+ int dir, int inv, int func, int dispullup)
+{
+ void __iomem *conf = NS921X_IO_GPIOCONFx(gpio / 4);
+ u32 confval;
+
+ confval = __raw_readl(conf);
+ REGSETIM_IDX(confval, NS921X_IO_GPIOCONFx, DIR, gpio & 3, dir);
+ REGSETIM_IDX(confval, NS921X_IO_GPIOCONFx, INV, gpio & 3, inv);
+ REGSETIM_IDX(confval, NS921X_IO_GPIOCONFx, FUNC, gpio & 3, func);
+ if (gpio != 9 && gpio != 12 && (gpio < 102 || gpio > 105))
+ REGSETIM_IDX(confval, NS921X_IO_GPIOCONFx, PUEN, gpio & 3, dispullup);
+ else {
+ if (dispullup)
+ pr_warning("cannot disable pullup for gpio %u\n", gpio);
+
+ REGSETIM_IDX(confval, NS921X_IO_GPIOCONFx, PUEN, gpio & 3, 0);
+ }
+
+ __raw_writel(confval, conf);
+}
+
+static inline void gpio_configure_ns921x(unsigned gpio,
+ int dir, int inv, int func, int dispullup)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ gpio_configure_ns921x_unlocked(gpio, dir, inv, func, dispullup);
+
+ local_irq_restore(flags);
+}
+
+static inline int gpio_get_value_ns921x(unsigned gpio)
+{
+ void __iomem *stat = NS921X_IO_GPIOSTATx(gpio / 32);
+
+ return (__raw_readl(stat) >> (gpio & 31)) & 1;
+}
+
+static inline void gpio_set_value_ns921x_unlocked(unsigned gpio, int value)
+{
+ void __iomem *ctrl = NS921X_IO_GPIOCTRLx(gpio / 32);
+ u32 ctrlval;
+
+ ctrlval = __raw_readl(ctrl);
+
+ if (value)
+ ctrlval |= 1 << (gpio & 31);
+ else
+ ctrlval &= ~(1 << (gpio & 31));
+
+ __raw_writel(ctrlval, ctrl);
+}
+
+static inline int gpio_direction_input_ns921x_unlocked(unsigned gpio)
+{
+ gpio_configure_ns921x_unlocked(gpio, 0, 0, 3, 0);
+ return 0;
+}
+
+static inline int gpio_direction_irqinput_ns921x_unlocked(unsigned gpio)
+{
+ const struct gpio_to_irq_map *map = gpio_get_map_ns921x(gpio);
+
+ if (map) {
+ gpio_configure_ns921x_unlocked(gpio, 0, 0, map->func, 0);
+ return 0;
+ } else
+ return gpio_direction_input_ns921x_unlocked(gpio);
+}
+
+static inline int gpio_direction_output_ns921x_unlocked(unsigned gpio,
+ int value)
+{
+ gpio_set_value_ns921x_unlocked(gpio, value);
+ gpio_configure_ns921x_unlocked(gpio, 1, 0, 3, 0);
+ return 0;
+}
+
+#endif /* if defined(CONFIG_PROCESSOR_NS921X) */
+
+#if defined(CONFIG_PROCESSOR_NS9360)
+# define NS9XXX_NUM_GPIO_NS9360 73
+# if NS9XXX_NUM_GPIO < NS9XXX_NUM_GPIO_NS9360
+# undef NS9XXX_NUM_GPIO
+# define NS9XXX_NUM_GPIO NS9XXX_NUM_GPIO_NS9360
+# endif
+static inline void __iomem *gpio_ns9360_gstataddr(unsigned gpio)
+{
+ if (gpio < 32)
+ return NS9360_BBU_GSTAT1;
+ else if (gpio < 64)
+ return NS9360_BBU_GSTAT2;
+ else
+ return NS9360_BBU_GSTAT3;
+}
+
+static inline void __iomem *gpio_ns9360_gctrladdr(unsigned gpio)
+{
+ if (gpio < 32)
+ return NS9360_BBU_GCTRL1;
+ else if (gpio < 64)
+ return NS9360_BBU_GCTRL2;
+ else
+ return NS9360_BBU_GCTRL3;
+}
+
+static inline void __iomem *gpio_ns9360_gconfaddr(unsigned gpio)
+{
+ if (gpio < 56)
+ return NS9360_BBU_GCONFb1(gpio / 8);
+ else
+ /* this could be optimised away on
+ * ns9750 only builds, but it isn't ...
+ */
+ return NS9360_BBU_GCONFb2((gpio - 56) / 8);
+}
+
+static inline int gpio_issocgpio_ns9360(unsigned gpio)
+{
+ return gpio <= 72;
+}
+
+const struct gpio_to_irq_map *gpio_get_map_ns9360(unsigned gpio) __attribute__((const));
+
+static inline void gpio_configure_ns9360_unlocked(unsigned gpio,
+ int dir, int inv, int func)
+{
+ void __iomem *conf = gpio_ns9360_gconfaddr(gpio);
+ u32 confval;
+
+ confval = __raw_readl(conf);
+ REGSETIM_IDX(confval, NS9360_BBU_GCONFx, DIR, gpio & 7, dir);
+ REGSETIM_IDX(confval, NS9360_BBU_GCONFx, INV, gpio & 7, inv);
+ REGSETIM_IDX(confval, NS9360_BBU_GCONFx, FUNC, gpio & 7, func);
+ __raw_writel(confval, conf);
+}
+
+static inline void gpio_configure_ns9360(unsigned gpio,
+ int dir, int inv, int func)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ gpio_configure_ns9360_unlocked(gpio, dir, inv, func);
+
+ local_irq_restore(flags);
+}
+
+static inline int gpio_get_value_ns9360(unsigned gpio)
+{
+ void __iomem *stat = gpio_ns9360_gstataddr(gpio);
+
+ return (__raw_readl(stat) >> (gpio & 31)) & 1;
+}
+
+static inline void gpio_set_value_ns9360_unlocked(unsigned gpio, int value)
+{
+ void __iomem *ctrl = gpio_ns9360_gctrladdr(gpio);
+ u32 ctrlval;
+
+ ctrlval = __raw_readl(ctrl);
+
+ if (value)
+ ctrlval |= 1 << (gpio & 31);
+ else
+ ctrlval &= ~(1 << (gpio & 31));
+
+ __raw_writel(ctrlval, ctrl);
+}
+
+static inline int gpio_direction_input_ns9360_unlocked(unsigned gpio)
+{
+ gpio_configure_ns9360_unlocked(gpio, 0, 0, 3);
+ return 0;
+}
+
+static inline int gpio_direction_irqinput_ns9360_unlocked(unsigned gpio)
+{
+ const struct gpio_to_irq_map *map = gpio_get_map_ns9360(gpio);
+ if (map) {
+ gpio_configure_ns9360_unlocked(gpio, 0, 0, map->func);
+ return 0;
+ } else
+ return gpio_direction_input_ns9360_unlocked(gpio);
+}
+
+static inline int gpio_direction_output_ns9360_unlocked(unsigned gpio,
+ int value)
+{
+ gpio_set_value_ns9360_unlocked(gpio, value);
+ gpio_configure_ns9360_unlocked(gpio, 1, 0, 3);
+ return 0;
+}
+
+#endif /* if defined(CONFIG_PROCESSOR_NS9360) */
+
+static inline int gpio_issocgpio(unsigned gpio)
+{
+#if defined(CONFIG_PROCESSOR_NS9210)
+ if (processor_is_ns9210())
+ return gpio_issocgpio_ns9210(gpio);
+ else
+#endif
+#if defined(CONFIG_PROCESSOR_NS9215)
+ if (processor_is_ns9215())
+ return gpio_issocgpio_ns9215(gpio);
+ else
+#endif
+#if defined(CONFIG_PROCESSOR_NS9360)
+ if (processor_is_ns9360())
+ return gpio_issocgpio_ns9360(gpio);
+ else
+#endif
+ BUG();
+
+ BUG();
+
+ return 0;
+}
+
+#if defined(CONFIG_GPIOLIB)
+
+#include <asm-generic/gpio.h>
+
+static inline int gpio_get_value(unsigned gpio)
+{
+ return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ return __gpio_set_value(gpio, value);
+}
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+ return __gpio_cansleep(gpio);
+}
+
+#else /* if defined(CONFIG_GPIOLIB) */
+
+extern spinlock_t gpio_lock;
+
+int gpio_request(unsigned gpio, const char *label);
void gpio_free(unsigned gpio);
-int ns9xxx_gpio_configure(unsigned gpio, int inv, int func);
+static inline int gpio_get_value(unsigned gpio)
+{
+#if defined(CONFIG_PROCESSOR_NS921X)
+ if (processor_is_ns921x())
+ return gpio_get_value_ns921x(gpio);
+ else
+#endif
+#if defined(CONFIG_PROCESSOR_NS9360)
+ if (processor_is_ns9360())
+ return gpio_get_value_ns9360(gpio);
+ else
+#endif
+ BUG();
+}
+
+static inline void gpio_set_value_unlocked(unsigned gpio, int value)
+{
+#if defined(CONFIG_PROCESSOR_NS921X)
+ if (processor_is_ns921x())
+ gpio_set_value_ns921x_unlocked(gpio, value);
+ else
+#endif
+#if defined(CONFIG_PROCESSOR_NS9360)
+ if (processor_is_ns9360())
+ gpio_set_value_ns9360_unlocked(gpio, value);
+ else
+#endif
+ BUG();
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+ unsigned long flags;
+
+ BUG_ON(!gpio_issocgpio(gpio));
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+ gpio_set_value_unlocked(gpio, value);
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+}
+
+static inline int gpio_direction_input(unsigned gpio)
+{
+ if (likely(gpio_issocgpio(gpio))) {
+ int ret = -EINVAL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&gpio_lock, flags);
+
+#if defined(CONFIG_PROCESSOR_NS921X)
+ if (processor_is_ns921x())
+ ret = gpio_direction_irqinput_ns921x_unlocked(gpio);
+ else
+#endif
+#if defined(CONFIG_PROCESSOR_NS9360)
+ if (processor_is_ns9360())
+ ret = gpio_direction_irqinput_ns9360_unlocked(gpio);
+ else
+#endif
+ BUG();
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
-int gpio_direction_input(unsigned gpio);
+ return ret;
+ } else
+ return -EINVAL;
+}
+
+static inline int gpio_direction_output(unsigned gpio, int value)
+{
+ if (likely(gpio_issocgpio(gpio))) {
+ int ret = -EINVAL;
+ unsigned long flags;
-int gpio_direction_output(unsigned gpio, int value);
+ spin_lock_irqsave(&gpio_lock, flags);
-int gpio_get_value(unsigned gpio);
+#if defined(CONFIG_PROCESSOR_NS921X)
+ if (processor_is_ns921x())
+ ret = gpio_direction_output_ns921x_unlocked(gpio,
+ value);
+ else
+#endif
+#if defined(CONFIG_PROCESSOR_NS9360)
+ if (processor_is_ns9360())
+ ret = gpio_direction_output_ns9360_unlocked(gpio,
+ value);
+ else
+#endif
+ BUG();
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+
+ return ret;
+ } else
+ return -EINVAL;
+}
+
+#include <asm-generic/gpio.h>
+
+#endif /* if defined(CONFIG_GPIOLIB) / else */
-void gpio_set_value(unsigned gpio, int value);
/*
* ns9xxx can use gpio pins to trigger an irq, but it's not generic
@@ -33,6 +469,23 @@ void gpio_set_value(unsigned gpio, int value);
*/
static inline int gpio_to_irq(unsigned gpio)
{
+#if defined(CONFIG_PROCESSOR_NS921X)
+ if (processor_is_ns921x()) {
+ const struct gpio_to_irq_map *map = gpio_get_map_ns921x(gpio);
+
+ if (map)
+ return map->irq;
+ }
+#endif
+#if defined(CONFIG_PROCESSOR_NS9360)
+ if (processor_is_ns9360()) {
+ const struct gpio_to_irq_map *map = gpio_get_map_ns9360(gpio);
+
+ if (map)
+ return map->irq;
+ }
+#endif
+
return -EINVAL;
}
@@ -41,7 +494,4 @@ static inline int irq_to_gpio(unsigned irq)
return -EINVAL;
}
-/* get the cansleep() stubs */
-#include <asm-generic/gpio.h>
-
#endif /* ifndef __ASM_ARCH_GPIO_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/hardware.h b/arch/arm/mach-ns9xxx/include/mach/hardware.h
index 6dbb2030f563..46299b18433e 100644
--- a/arch/arm/mach-ns9xxx/include/mach/hardware.h
+++ b/arch/arm/mach-ns9xxx/include/mach/hardware.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-ns9xxx/include/mach/hardware.h
*
- * Copyright (C) 2006 by Digi International Inc.
+ * Copyright (C) 2006-2008 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
@@ -30,7 +30,9 @@
#define __REGSHIFT(mask) ((mask) & (-(mask)))
#define __REGBIT(bit) ((u32)1 << (bit))
+#define __REGBIT_SHIFT(bit, shift) ((u32)1 << ((bit) + (shift)))
#define __REGBITS(hbit, lbit) ((((u32)1 << ((hbit) - (lbit) + 1)) - 1) << (lbit))
+#define __REGBITS_SHIFT(hbit, lbit, shift) __REGBITS((hbit) + (shift), (lbit) + (shift))
#define __REGVAL(mask, value) (((value) * __REGSHIFT(mask)) & (mask))
#ifndef __ASSEMBLY__
@@ -66,13 +68,13 @@
__REGGET(var, reg ## _ ## field) / __REGSHIFT(reg ## _ ## field)
# define REGGETIM_IDX(var, reg, field, idx) \
- __REGGET(var, reg ## _ ## field((idx))) / \
+ __REGGET(var, reg ## _ ## field((idx))) / \
__REGSHIFT(reg ## _ ## field((idx)))
#else
# define __REG(x) io_p2v(x)
-# define __REG2(x, y) io_p2v((x) + 4 * (y))
+# define __REG2(x, y) io_p2v((x) + (y))
#endif
diff --git a/arch/arm/mach-ns9xxx/include/mach/irqs.h b/arch/arm/mach-ns9xxx/include/mach/irqs.h
index 13483949e210..f72bd08e5de9 100644
--- a/arch/arm/mach-ns9xxx/include/mach/irqs.h
+++ b/arch/arm/mach-ns9xxx/include/mach/irqs.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-ns9xxx/include/mach/irqs.h
*
- * Copyright (C) 2006,2007 by Digi International Inc.
+ * Copyright (C) 2006-2008 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
@@ -11,14 +11,48 @@
#ifndef __ASM_ARCH_IRQS_H
#define __ASM_ARCH_IRQS_H
-/* NetSilicon 9360 */
+/* Digi ns921x */
#define IRQ_NS9XXX_WATCHDOG 0
#define IRQ_NS9XXX_AHBBUSERR 1
-#define IRQ_NS9360_BBUSAGG 2
-/* irq 3 is reserved for NS9360 */
+#define IRQ_NS921X_EXTDMA 2
+#define IRQ_NS921X_CPUWAKE 3
#define IRQ_NS9XXX_ETHRX 4
#define IRQ_NS9XXX_ETHTX 5
-#define IRQ_NS9XXX_ETHPHY 6
+#define IRQ_NS9XXX_ETHPHY 6 /* reserved for ns9210 */
+#define IRQ_NS921X_UARTA 7
+#define IRQ_NS921X_UARTB 8
+#define IRQ_NS921X_UARTC 9
+#define IRQ_NS921X_UARTD 10
+#define IRQ_NS921X_SPI 11
+#define IRQ_NS921X_PIC0 12
+#define IRQ_NS921X_PIC1 13
+#define IRQ_NS9215_ADC 14
+#define IRQ_NS9215_EPL 15
+#define IRQ_NS921X_I2C 16
+#define IRQ_NS9215_RTC 17
+#define IRQ_NS921X_TIMER0 18
+#define IRQ_NS921X_TIMER1 19
+#define IRQ_NS921X_TIMER2 20
+#define IRQ_NS921X_TIMER3 21
+#define IRQ_NS921X_TIMER4 22
+#define IRQ_NS921X_TIMER5 23
+#define IRQ_NS921X_TIMER6 24
+#define IRQ_NS921X_TIMER7 25
+#define IRQ_NS921X_TIMER8 26
+#define IRQ_NS921X_TIMER9 27
+#define IRQ_NS9XXX_EXT0 28
+#define IRQ_NS9XXX_EXT1 29
+#define IRQ_NS9XXX_EXT2 30
+#define IRQ_NS9XXX_EXT3 31
+
+/* NetSilicon 9360 */
+/* IRQ_NS9XXX_WATCHDOG 0 */
+/* IRQ_NS9XXX_AHBBUSERR 1 */
+#define IRQ_NS9360_BBUSAGG 2
+/* irq 3 is reserved for NS9360 */
+/* IRQ_NS9XXX_ETHRX 3 */
+/* IRQ_NS9XXX_ETHTX 4 */
+/* IRQ_NS9XXX_ETHPHY 5 */
#define IRQ_NS9360_LCD 7
#define IRQ_NS9360_SERBRX 8
#define IRQ_NS9360_SERBTX 9
@@ -40,37 +74,39 @@
#define IRQ_NS9360_USBHOST 25
#define IRQ_NS9360_USBDEVICE 26
#define IRQ_NS9360_IEEE1284 27
-#define IRQ_NS9XXX_EXT0 28
-#define IRQ_NS9XXX_EXT1 29
-#define IRQ_NS9XXX_EXT2 30
-#define IRQ_NS9XXX_EXT3 31
+/* IRQ_NS9XXX_EXT0 28 */
+/* IRQ_NS9XXX_EXT1 29 */
+/* IRQ_NS9XXX_EXT2 30 */
+/* IRQ_NS9XXX_EXT3 31 */
+
+#define IRQ_NS9360_BBUS(irq) (32 + irq)
-#define BBUS_IRQ(irq) (32 + irq)
+#define IRQ_NS9360_BBUS_DMA IRQ_NS9360_BBUS(0)
+#define IRQ_NS9360_BBUS_SERBRX IRQ_NS9360_BBUS(2)
+#define IRQ_NS9360_BBUS_SERBTX IRQ_NS9360_BBUS(3)
+#define IRQ_NS9360_BBUS_SERARX IRQ_NS9360_BBUS(4)
+#define IRQ_NS9360_BBUS_SERATX IRQ_NS9360_BBUS(5)
+#define IRQ_NS9360_BBUS_SERCRX IRQ_NS9360_BBUS(6)
+#define IRQ_NS9360_BBUS_SERCTX IRQ_NS9360_BBUS(7)
+#define IRQ_NS9360_BBUS_SERDRX IRQ_NS9360_BBUS(8)
+#define IRQ_NS9360_BBUS_SERDTX IRQ_NS9360_BBUS(9)
+#define IRQ_NS9360_BBUS_I2C IRQ_NS9360_BBUS(10)
+#define IRQ_NS9360_BBUS_1284 IRQ_NS9360_BBUS(11)
+#define IRQ_NS9360_BBUS_UTIL IRQ_NS9360_BBUS(12)
+#define IRQ_NS9360_BBUS_RTC IRQ_NS9360_BBUS(13)
+#define IRQ_NS9360_BBUS_USBHST IRQ_NS9360_BBUS(14)
+#define IRQ_NS9360_BBUS_USBDEV IRQ_NS9360_BBUS(15)
+#define IRQ_NS9360_BBUS_AHBDMA1 IRQ_NS9360_BBUS(24)
+#define IRQ_NS9360_BBUS_AHBDMA2 IRQ_NS9360_BBUS(25)
-#define IRQ_BBUS_DMA BBUS_IRQ(0)
-#define IRQ_BBUS_SERBRX BBUS_IRQ(2)
-#define IRQ_BBUS_SERBTX BBUS_IRQ(3)
-#define IRQ_BBUS_SERARX BBUS_IRQ(4)
-#define IRQ_BBUS_SERATX BBUS_IRQ(5)
-#define IRQ_BBUS_SERCRX BBUS_IRQ(6)
-#define IRQ_BBUS_SERCTX BBUS_IRQ(7)
-#define IRQ_BBUS_SERDRX BBUS_IRQ(8)
-#define IRQ_BBUS_SERDTX BBUS_IRQ(9)
-#define IRQ_BBUS_I2C BBUS_IRQ(10)
-#define IRQ_BBUS_1284 BBUS_IRQ(11)
-#define IRQ_BBUS_UTIL BBUS_IRQ(12)
-#define IRQ_BBUS_RTC BBUS_IRQ(13)
-#define IRQ_BBUS_USBHST BBUS_IRQ(14)
-#define IRQ_BBUS_USBDEV BBUS_IRQ(15)
-#define IRQ_BBUS_AHBDMA1 BBUS_IRQ(24)
-#define IRQ_BBUS_AHBDMA2 BBUS_IRQ(25)
+#define IRQ_NS9360_BBUDMA(irq) (58 + irq)
/*
* these Interrupts are specific for the a9m9750dev board.
* They are generated by an FPGA that interrupts the CPU on
* IRQ_NS9360_EXT2
*/
-#define FPGA_IRQ(irq) (64 + irq)
+#define FPGA_IRQ(irq) (74 + irq)
#define IRQ_FPGA_UARTA FPGA_IRQ(0)
#define IRQ_FPGA_UARTB FPGA_IRQ(1)
@@ -81,6 +117,6 @@
#define IRQ_FPGA_CAN0 FPGA_IRQ(6)
#define IRQ_FPGA_CAN1 FPGA_IRQ(7)
-#define NR_IRQS 72
+#define NR_IRQS 82
#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/module.h b/arch/arm/mach-ns9xxx/include/mach/module.h
index f851a6b7da6c..6c497bf87084 100644
--- a/arch/arm/mach-ns9xxx/include/mach/module.h
+++ b/arch/arm/mach-ns9xxx/include/mach/module.h
@@ -31,6 +31,11 @@
|| machine_is_cc9p9215js() \
)
+#define module_is_ccw9p9215() (0 \
+ || machine_is_ccw9p9215() \
+ || machine_is_ccw9p9215js() \
+ )
+
#define module_is_cc9p9360() (0 \
|| machine_is_a9m9360() \
|| machine_is_cc9p9360dev() \
@@ -49,6 +54,11 @@
|| machine_is_ccw9c() \
)
+#define module_is_cme9210() (0 \
+ || machine_is_cme9210() \
+ || machine_is_cme9210js() \
+ )
+
#define module_is_inc20otter() (0 \
|| machine_is_inc20otter() \
)
diff --git a/arch/arm/mach-ns9xxx/include/mach/ns921x-serial.h b/arch/arm/mach-ns9xxx/include/mach/ns921x-serial.h
new file mode 100644
index 000000000000..e879492fe10a
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/ns921x-serial.h
@@ -0,0 +1,22 @@
+/*
+ * include/linux/ns9360.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef __NS921X_SERIAL_H__
+#define __NS921X_SERIAL_H__
+
+
+struct ns921x_uart_data {
+ unsigned int gpios[8];
+ unsigned int nr_gpios;
+ unsigned int rtsen; /* RTS for 485 transceiver control */
+};
+
+#endif
diff --git a/arch/arm/mach-ns9xxx/include/mach/ns9360fb.h b/arch/arm/mach-ns9xxx/include/mach/ns9360fb.h
new file mode 100644
index 000000000000..cacb56c17997
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/ns9360fb.h
@@ -0,0 +1,26 @@
+#ifndef __NS9360FB_H__
+#define __NS9360FB_H__
+
+
+struct ns9360fb_display {
+
+ /* Display name */
+ char *display_name;
+
+ unsigned height;
+ unsigned width;
+ unsigned clock;
+
+ u32 timing[4];
+ u32 control;
+
+ void (*display_power_enable)(int);
+};
+
+struct ns9360fb_pdata {
+ unsigned num_displays; /* number of defined displays */
+ struct ns9360fb_display *displays; /* attached diplays info */
+ struct ns9360fb_display *display; /* attached diplays info */
+};
+
+#endif
diff --git a/arch/arm/mach-ns9xxx/include/mach/ns9xxx-pwm.h b/arch/arm/mach-ns9xxx/include/mach/ns9xxx-pwm.h
new file mode 100644
index 000000000000..b48527482cd3
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/ns9xxx-pwm.h
@@ -0,0 +1,146 @@
+/*
+ * drivers/pwm/ns9xxx-pwm.h
+ *
+ * Copyright (C) 2009 Digi International 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __NS9XXX_PWM_HEADER_H
+#define __NS9XXX_PWM_HEADER_H
+
+/* Maximal number of available channels */
+#define NS9XXX_PWM_CHANNEL_MAX 10
+
+/* This is the data for the PWM channels */
+struct ns9xxx_pwm_channel {
+ int timer;
+ int gpio;
+
+ /* Additional channel configuration variables ... */
+};
+
+/* */
+struct ns9xxx_pwm_pdata {
+ unsigned int number_channels;
+ struct ns9xxx_pwm_channel *channels;
+};
+
+
+
+
+#define NS921X_TMC_T0E (1 << 0) /* Timer enable */
+#define NS921X_TMC_T1E (1 << 1)
+#define NS921X_TMC_T2E (1 << 2)
+#define NS921X_TMC_T3E (1 << 3)
+#define NS921X_TMC_T4E (1 << 4)
+#define NS921X_TMC_T5E (1 << 5)
+#define NS921X_TMC_T6E (1 << 6)
+#define NS921X_TMC_T7E (1 << 7)
+#define NS921X_TMC_T8E (1 << 8)
+#define NS921X_TMC_T9E (1 << 9)
+#define NS921X_TMC_T6HSE (1 << 10) /* High step enable */
+#define NS921X_TMC_T6LSE (1 << 11) /* Low step enable */
+#define NS921X_TMC_T6RSE (1 << 12) /* Reload step enable */
+#define NS921X_TMC_T7HSE (1 << 13)
+#define NS921X_TMC_T7LSE (1 << 14)
+#define NS921X_TMC_T7RSE (1 << 15)
+#define NS921X_TMC_T8HSE (1 << 16)
+#define NS921X_TMC_T8LSE (1 << 17)
+#define NS921X_TMC_T8RSE (1 << 18)
+#define NS921X_TMC_T9HSE (1 << 19)
+#define NS921X_TMC_T9LSE (1 << 20)
+#define NS921X_TMC_T9RSE (1 << 21)
+
+#define NS921X_TCR_RELOADEN (1 << 0) /* Reload enable */
+#define NS921X_TCR_BITTIMER (1 << 1) /* 32 or 16 bit timer */
+#define NS921X_TCR_UPDOWN (1 << 2) /* Up/Down select */
+#define NS921X_TCR_INTSEL (1 << 3) /* Interrupt select */
+
+#define NS921X_TCR_TMODE(x) ((x) & (0x3 << 4)) /* Timer mode */
+#define NS921X_TCR_TMODE_MASK (0x3 << 4)
+#define NS921X_TCR_TMODE_INT (0 << 4)
+#define NS921X_TCR_TMODE_EXTLOW (1 << 4)
+#define NS921X_TCR_TMODE_EXTHIGH (2 << 4)
+/* @TODO: Complete the remaining macros */
+//#define NS921X_TCR_TMODE (2 << 4) /* Timer mode */
+
+#define NS921X_TCR_TCLKSEL (0xf << 6) /* Timer clock set */
+#define NS921X_TCR_TCLKSEL_MASK (0xf << 6)
+#define NS921X_TCR_TCLKSEL_AHB (0x1 << 6)
+#define NS921X_TCR_INTCLR (1 << 10) /* Interrupt clear */
+#define NS921X_TCR_DEBUGMODE (1 << 11) /* Debug mode */
+#define NS921X_TCR_CAPCOMP (7 << 12) /* Capture and compare mode functions */
+#define NS921X_TCR_TE (1 << 15) /* Timer enable */
+#define NS921X_TCR_TMODE2 (3 << 16) /* Timer mode 2 */
+#define NS921X_TCR_TMODE2_PWM (1 << 16) /* Timer mode 2 */
+
+#define NS921X_TCR_RELOADMODE2 (1 << 18) /* Reload mode */
+
+#define NS921X_THIGHREG (32 << 0) /* PWM output toggles high when timer counter reaches this value */
+#define NS921X_TLOWREG (32 << 0) /* PWM toggles low when counter reaches this value */
+
+#define NS921X_HISTEP_DIR (1 << 31) /* High step direction */
+#define NS921X_HISTEP (15 << 16) /* High step */
+#define NS921X_LOWSTEP_DIR (1 << 15) /* Low step direction */
+#define NS921X_LOWSTEP (15 << 0) /* Low step */
+
+#define NS921X_RELOADSTEPDIR (1 << 15) /* Reload step direction */
+#define NS921X_RELOADSTEP (15 << 0) /* Reload step */
+
+#define NS921X_TIMECOMP (16 << 16) /* Timer compare register or timer reload bits 31:16 count register */
+#define NS921X_TIMERELOADBITS (16 << 0) /* Timer reload bits 15:00 count register */
+
+#define NS921X_TIMERCAP (16 << 16) /* Timer capture register or timer read bits 31:16 register */
+#define NS921X_TIMERREAD (16 << 0) /* Timer read bits 15:00 register */
+
+
+
+#if 0
+struct pwm_channel {
+ void __iomem *regs;
+ unsigned index;
+ unsigned long mck;
+};
+
+extern int pwm_channel_alloc(int index, struct pwm_channel *ch);
+extern int pwm_channel_free(struct pwm_channel *ch);
+
+extern int pwm_clk_alloc(unsigned prescale, unsigned div);
+extern void pwm_clk_free(unsigned clk);
+
+extern int __pwm_channel_onoff(struct pwm_channel *ch, int enabled);
+
+#define pwm_channel_enable(ch) __pwm_channel_onoff((ch), 1)
+#define pwm_channel_disable(ch) __pwm_channel_onoff((ch), 0)
+
+/* periodic interrupts, mostly for CUPD changes to period or cycle */
+extern int pwm_channel_handler(struct pwm_channel *ch,
+ void (*handler)(struct pwm_channel *ch));
+
+static inline void
+pwm_channel_writel(struct pwm_channel *pwmc, unsigned offset, u32 val)
+{
+ __raw_writel(val, pwmc->regs + offset);
+}
+
+static inline u32 pwm_channel_readl(struct pwm_channel *pwmc, unsigned offset)
+{
+ return __raw_readl(pwmc->regs + offset);
+}
+
+#endif /* __LINUX_NS9XXX_PWM_H */
+
+#endif /* __NS9XXX_PWM_HEADER_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/processor.h b/arch/arm/mach-ns9xxx/include/mach/processor.h
index 9f77f746a386..a36ce171b4e3 100644
--- a/arch/arm/mach-ns9xxx/include/mach/processor.h
+++ b/arch/arm/mach-ns9xxx/include/mach/processor.h
@@ -16,12 +16,14 @@
#define processor_is_ns9210() (0 \
|| module_is_cc7ucamry() \
|| module_is_cc9p9210() \
+ || module_is_cme9210() \
|| module_is_inc20otter() \
|| module_is_otter() \
)
#define processor_is_ns9215() (0 \
|| module_is_cc9p9215() \
+ || module_is_ccw9p9215() \
)
#define processor_is_ns9360() (0 \
diff --git a/arch/arm/mach-ns9xxx/include/mach/regs-bbu.h b/arch/arm/mach-ns9xxx/include/mach/regs-bbu.h
index af227c058fb9..564498990063 100644
--- a/arch/arm/mach-ns9xxx/include/mach/regs-bbu.h
+++ b/arch/arm/mach-ns9xxx/include/mach/regs-bbu.h
@@ -8,38 +8,51 @@
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
-#ifndef __ASM_ARCH_REGSBBU_H
-#define __ASM_ARCH_REGSBBU_H
+#ifndef __ASM_ARCH_REGS_BBU_H
+#define __ASM_ARCH_REGS_BBU_H
#include <mach/hardware.h>
/* BBus Utility */
+#define NS9360_BBU_MSR __REG(0x90600000)
+
/* GPIO Configuration Registers block 1 */
/* NOTE: the HRM starts counting at 1 for the GPIO registers, here the start is
- * at 0 for each block. That is, BBU_GCONFb1(0) is GPIO Configuration Register
- * #1, BBU_GCONFb2(0) is GPIO Configuration Register #8. */
-#define BBU_GCONFb1(x) __REG2(0x90600010, (x))
-#define BBU_GCONFb2(x) __REG2(0x90600100, (x))
-
-#define BBU_GCONFx_DIR(m) __REGBIT(3 + (((m) & 7) << 2))
-#define BBU_GCONFx_DIR_INPUT(m) __REGVAL(BBU_GCONFx_DIR(m), 0)
-#define BBU_GCONFx_DIR_OUTPUT(m) __REGVAL(BBU_GCONFx_DIR(m), 1)
-#define BBU_GCONFx_INV(m) __REGBIT(2 + (((m) & 7) << 2))
-#define BBU_GCONFx_INV_NO(m) __REGVAL(BBU_GCONFx_INV(m), 0)
-#define BBU_GCONFx_INV_YES(m) __REGVAL(BBU_GCONFx_INV(m), 1)
-#define BBU_GCONFx_FUNC(m) __REGBITS(1 + (((m) & 7) << 2), ((m) & 7) << 2)
-#define BBU_GCONFx_FUNC_0(m) __REGVAL(BBU_GCONFx_FUNC(m), 0)
-#define BBU_GCONFx_FUNC_1(m) __REGVAL(BBU_GCONFx_FUNC(m), 1)
-#define BBU_GCONFx_FUNC_2(m) __REGVAL(BBU_GCONFx_FUNC(m), 2)
-#define BBU_GCONFx_FUNC_3(m) __REGVAL(BBU_GCONFx_FUNC(m), 3)
-
-#define BBU_GCTRL1 __REG(0x90600030)
-#define BBU_GCTRL2 __REG(0x90600034)
-#define BBU_GCTRL3 __REG(0x90600120)
-
-#define BBU_GSTAT1 __REG(0x90600040)
-#define BBU_GSTAT2 __REG(0x90600044)
-#define BBU_GSTAT3 __REG(0x90600130)
-
-#endif /* ifndef __ASM_ARCH_REGSBBU_H */
+ * at 0 for each block. That is, NS9360_BBU_GCONFb1(0) is GPIO Configuration
+ * Register #1, NS9360_BBU_GCONFb2(0) is GPIO Configuration Register #8. */
+#define NS9360_BBU_GCONFb1(x) __REG2(0x90600010, (x))
+#define NS9360_BBU_GCONFb2(x) __REG2(0x90600100, (x))
+
+#define __NS9360_BBU_GCONFx_SHIFT(m) (((m) & 7) << 2)
+
+#define NS9360_BBU_GCONFx_DIR(m) __REGBIT_SHIFT(3, __NS9360_BBU_GCONFx_SHIFT(m))
+#define NS9360_BBU_GCONFx_DIR_INPUT(m) __REGVAL(NS9360_BBU_GCONFx_DIR(m), 0)
+#define NS9360_BBU_GCONFx_DIR_OUTPUT(m) __REGVAL(NS9360_BBU_GCONFx_DIR(m), 1)
+#define NS9360_BBU_GCONFx_INV(m) __REGBIT_SHIFT(2, __NS9360_BBU_GCONFx_SHIFT(m))
+#define NS9360_BBU_GCONFx_INV_NO(m) __REGVAL(NS9360_BBU_GCONFx_INV(m), 0)
+#define NS9360_BBU_GCONFx_INV_YES(m) __REGVAL(NS9360_BBU_GCONFx_INV(m), 1)
+#define NS9360_BBU_GCONFx_FUNC(m) __REGBITS_SHIFT(1, 0, __NS9360_BBU_GCONFx_SHIFT(m))
+#define NS9360_BBU_GCONFx_FUNC_0(m) __REGVAL(NS9360_BBU_GCONFx_FUNC(m), 0)
+#define NS9360_BBU_GCONFx_FUNC_1(m) __REGVAL(NS9360_BBU_GCONFx_FUNC(m), 1)
+#define NS9360_BBU_GCONFx_FUNC_2(m) __REGVAL(NS9360_BBU_GCONFx_FUNC(m), 2)
+#define NS9360_BBU_GCONFx_FUNC_3(m) __REGVAL(NS9360_BBU_GCONFx_FUNC(m), 3)
+
+#define NS9360_BBU_GCTRL1 __REG(0x90600030)
+#define NS9360_BBU_GCTRL2 __REG(0x90600034)
+#define NS9360_BBU_GCTRL3 __REG(0x90600120)
+
+#define NS9360_BBU_GSTAT1 __REG(0x90600040)
+#define NS9360_BBU_GSTAT2 __REG(0x90600044)
+#define NS9360_BBU_GSTAT3 __REG(0x90600130)
+
+#define NS9360_BBUS_USB __REG(0x90600070)
+
+#define NS9360_BBUS_DMA_ISTAT __REG(0x90600060)
+#define NS9360_BBUS_DMA_IEN __REG(0x90600064)
+
+#define NS9360_BBUS_ISTAT __REG(0xa0401000)
+#define NS9360_BBUS_IEN __REG(0xa0401004)
+#define NS9360_BBUS_IEN_GLBL (1 << 31)
+
+#endif /* ifndef __ASM_ARCH_REGS_BBU_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/regs-io-ns921x.h b/arch/arm/mach-ns9xxx/include/mach/regs-io-ns921x.h
new file mode 100644
index 000000000000..948a273a9621
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/regs-io-ns921x.h
@@ -0,0 +1,41 @@
+/*
+ * arch/arm/mach-ns9xxx/include/mach/regs-io-ns921x.h
+ *
+ * Copyright (C) 2007-2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSIONS921X_H
+#define __ASM_ARCH_REGSIONS921X_H
+
+#include <mach/hardware.h>
+
+#define __NS921X_IO_GPIOCONF_SHIFT(m) (((m) & 3) << 3)
+
+/* I/O Control Module */
+
+/* NOTE: the first GPIO has number #0, this is different from NS9360 which
+ * starts at #1 */
+
+/* GPIO Configuration Register */
+#define NS921X_IO_GPIOCONFx(x) __REG2(0xa0902000, (x))
+
+#define NS921X_IO_GPIOCONFx_FUNC(m) __REGBITS_SHIFT(5, 3, __NS921X_IO_GPIOCONF_SHIFT(m))
+#define NS921X_IO_GPIOCONFx_DIR(m) __REGBIT(2 + __NS921X_IO_GPIOCONF_SHIFT(m))
+#define NS921X_IO_GPIOCONFx_DIR_IN(m) __REGVAL(NS921X_IO_GPIOCONF_DIR(m), 0)
+#define NS921X_IO_GPIOCONFx_DIR_OUT(m) __REGVAL(NS921X_IO_GPIOCONF_DIR(m), 1)
+#define NS921X_IO_GPIOCONFx_INV(m) __REGBIT(1 + __NS921X_IO_GPIOCONF_SHIFT(m))
+#define NS921X_IO_GPIOCONFx_INV_OFF(m) __REGVAL(NS921X_IO_GPIOCONF_INV(m), 0)
+#define NS921X_IO_GPIOCONFx_INV_ON(m) __REGVAL(NS921X_IO_GPIOCONF_INV(m), 1)
+#define NS921X_IO_GPIOCONFx_PUEN(m) __REGBIT(__NS921X_IO_GPIOCONF_SHIFT(m))
+#define NS921X_IO_GPIOCONFx_PUEN_EN(m) __REGVAL(NS921X_IO_GPIOCONF_PUEN(m), 0)
+#define NS921X_IO_GPIOCONFx_PUEN_DIS(m) __REGVAL(NS921X_IO_GPIOCONF_PUEN(m), 1)
+
+#define NS921X_IO_GPIOCTRLx(x) __REG2(0xa090206c, (x))
+
+#define NS921X_IO_GPIOSTATx(x) __REG2(0xa090207c, (x))
+
+#endif /* ifndef __ASM_ARCH_REGSSYSNS921X_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/regs-iohub-ns921x.h b/arch/arm/mach-ns9xxx/include/mach/regs-iohub-ns921x.h
new file mode 100644
index 000000000000..8b274bb8bcd8
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/regs-iohub-ns921x.h
@@ -0,0 +1,133 @@
+/*
+ * arch/arm/mach-ns9xxx/include/mach/regs-sys-ns921x.h
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * !Revision: $Revision: 1.0 $
+ * !Author: Luis Galdos
+ * !Desc:
+ * !References:
+ */
+
+#ifndef __ASM_ARCH_REGSIOHUB_NS921X_H
+#define __ASM_ARCH_REGSIOHUB_NS921X_H
+
+#include <mach/hardware.h>
+#include <mach/regs-sys-common.h>
+
+#define IOHUB_REG_BASE_PA (0x90000000)
+#define IOHUB_REG_BASE_VA io_p2v(IOHUB_REG_BASE_PA)
+#define IOHUB_REG_OFFSET (0x8000)
+#define IOHUB_FIM0_BASE_PA IOHUB_REG_BASE_PA
+#define IOHUB_FIM1_BASE_PA (IOHUB_REG_BASE_PA + IOHUB_REG_OFFSET)
+#define IOHUB_FIM0_BASE_VA io_p2v(IOHUB_FIM0_BASE_PA)
+#define IOHUB_FIM1_BASE_VA io_p2v(IOHUB_FIM1_BASE_PA)
+
+/* Register offsets for the IOHUB-components */
+#define IOHUB_IFS_REG (0x00)
+
+#define IOHUB_RX_DMA_CTRL_REG (0x04)
+#define IOHUB_RX_DMA_BUFPTR_REG (0x08)
+#define IOHUB_RX_DMA_ICTRL_REG (0x0C)
+#define IOHUB_RX_DIR_REG (0x10)
+#define IOHUB_RX_DIR_FIFO_REG (0x14)
+#define IOHUB_TX_DMA_CTRL_REG (0x18)
+#define IOHUB_TX_DMA_BUFPTR_REG (0x1C)
+#define IOHUB_TX_ICTRL_REG (0x20)
+#define IOHUB_TX_FIFO_REG (0x28)
+#define IOHUB_TX_DIR_REG (0x2C)
+
+/* DMA RX control bits */
+#define IOHUB_RX_DMA_CTRL_CE (1<<31)
+#define IOHUB_RX_DMA_CTRL_CA (1<<30)
+#define IOHUB_RX_DMA_CTRL_FLEXIO (1<<29)
+#define IOHUB_RX_DMA_CTRL_DIRECT (1<<28)
+#define IOHUB_RX_DMA_CTRL_STATE (0xFC00)
+#define IOHUB_RX_DMA_CTRL_INDEX (0x03FF)
+
+
+/* DMA TX control bits */
+#define IOHUB_TX_DMA_CTRL_CE (1<<31)
+#define IOHUB_TX_DMA_CTRL_CA (1<<30)
+#define IOHUB_TX_DMA_CTRL_FLEXIO (1<<29)
+#define IOHUB_TX_DMA_CTRL_DIRECT (1<<28)
+#define IOHUB_TX_DMA_CTRL_STATE (0xFC00)
+#define IOHUB_TX_DMA_CTRL_INDEXEN (1<<27)
+#define IOHUB_TX_DMA_CTRL_INDEX(i) (i & 0x03FF)
+
+
+
+/* Interrupt and FIFO status register */
+#define IOHUB_IFS_RXNCIP (1<<31)
+#define IOHUB_IFS_RXECIP (1<<30)
+#define IOHUB_IFS_RXNRIP (1<<29)
+#define IOHUB_IFS_RXCAIP (1<<28)
+#define IOHUB_IFS_TXNCIP (1<<24)
+#define IOHUB_IFS_TXECIP (1<<23)
+#define IOHUB_IFS_TXNRIP (1<<22)
+#define IOHUB_IFS_TXCAIP (1<<21)
+#define IOHUB_IFS_TXFUFIP (1<<20)
+#define IOHUB_IFS_TXFSRIP (1<<19)
+#define IOHUB_IFS_MODIP (1<<18)
+#define IOHUB_IFS_DMA_TX (IOHUB_IFS_TXNCIP | \
+ IOHUB_IFS_TXNRIP | \
+ IOHUB_IFS_TXECIP | \
+ IOHUB_IFS_TXCAIP)
+#define IOHUB_IFS_DMA_RX (IOHUB_IFS_RXNCIP | \
+ IOHUB_IFS_RXNRIP | \
+ IOHUB_IFS_RXECIP | \
+ IOHUB_IFS_RXCAIP)
+
+/* Interrupt configuration register */
+#define IOHUB_ICTRL_RXTHRS(val) (val<<28)
+#define IOHUB_ICTRL_RXFOFIE (1<<26)
+#define IOHUB_ICTRL_RXFSRIE (1<<25)
+#define IOHUB_ICTRL_RXNCIE (1<<24)
+#define IOHUB_ICTRL_RXECIE (1<<23)
+#define IOHUB_ICTRL_RXNRIE (1<<22)
+#define IOHUB_ICTRL_RXCAIE (1<<21)
+#define IOHUB_ICTRL_RXPCIE (1<<20)
+#define IOHUB_ICTRL_WSTAT (1<<19)
+#define IOHUB_ICTRL_ISTAT (1<<18)
+#define IOHUB_ICTRL_LSTAT (1<<17)
+#define IOHUB_ICTRL_FSTAT (1<<16)
+#define IOHUB_ICTRL_BLENSTAT (0xFF)
+#define IOHUB_ICTRL_RXALLE (IOHUB_ICTRL_RXFOFIE | \
+ IOHUB_ICTRL_RXFSRIE | \
+ IOHUB_ICTRL_RXNCIE | \
+ IOHUB_ICTRL_RXECIE | \
+ IOHUB_ICTRL_RXNRIE | \
+ IOHUB_ICTRL_RXCAIE | \
+ IOHUB_ICTRL_RXPCIE)
+
+
+#define IOHUB_ICTRL_TXTHRS(val) (val<<28)
+#define IOHUB_ICTRL_TXFUFIE (1<<26)
+#define IOHUB_ICTRL_TXFSRIE (1<<25)
+#define IOHUB_ICTRL_TXNCIE (1<<24)
+#define IOHUB_ICTRL_TXECIE (1<<23)
+#define IOHUB_ICTRL_TXNRIE (1<<22)
+#define IOHUB_ICTRL_TXCAIE (1<<21)
+#define IOHUB_ICTRL_WSTAT (1<<19)
+#define IOHUB_ICTRL_ISTAT (1<<18)
+#define IOHUB_ICTRL_LSTAT (1<<17)
+#define IOHUB_ICTRL_FSTAT (1<<16)
+#define IOHUB_ICTRL_BLENSTAT (0xFF)
+#define IOHUB_ICTRL_TXALLE (IOHUB_ICTRL_TXFUFIE | \
+ IOHUB_ICTRL_TXFSRIE | \
+ IOHUB_ICTRL_TXNCIE | \
+ IOHUB_ICTRL_TXECIE | \
+ IOHUB_ICTRL_TXNRIE | \
+ IOHUB_ICTRL_TXCAIE)
+
+
+
+#endif /* ifndef __ASM_ARCH_REGSIOHUB_NS921X_H */
+
+
+
diff --git a/arch/arm/mach-ns9xxx/include/mach/regs-lcd-ns9360.h b/arch/arm/mach-ns9xxx/include/mach/regs-lcd-ns9360.h
new file mode 100644
index 000000000000..7beabc4729bc
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/regs-lcd-ns9360.h
@@ -0,0 +1,88 @@
+/*
+ * arch/arm/mach-ns9xxx/include/mach/regs-lcd-ns9360.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_REGSLCDNS9360_H
+#define __ASM_ARCH_REGSLCDNS9360_H
+
+#define LCD_TIMING0 0x00
+#define LCD_TIMING0_HBP(x) (((x) & 0xFF) << 24)
+#define LCD_TIMING0_HFP(x) (((x) & 0xFF) << 16)
+#define LCD_TIMING0_HSW(x) (((x) & 0xFF) << 8)
+#define LCD_TIMING0_PPL(x) (((x) & 0x3F) << 2)
+
+#define LCD_TIMING1 0x04
+#define LCD_TIMING1_VBP(x) (((x) & 0xFF) << 24)
+#define LCD_TIMING1_VFP(x) (((x) & 0xFF) << 16)
+#define LCD_TIMING1_VSW(x) (((x) & 0x3F) << 10)
+#define LCD_TIMING1_LPP(x) (((x) & 0x3FF))
+
+#define LCD_TIMING2 0x08
+#define LCD_TIMING2_BCD (1 << 26)
+#define LCD_TIMING2_CPL(x) (((x) & 0x3FF) << 16)
+#define LCD_TIMING2_IOE (1 << 14)
+#define LCD_TIMING2_IPC (1 << 13)
+#define LCD_TIMING2_IHS (1 << 12)
+#define LCD_TIMING2_IVS (1 << 11)
+#define LCD_TIMING2_ACB(x) (((x) & 0x1F) << 6)
+#define LCD_TIMING2_PCD(x) (((x) & 0x1F))
+
+#define LCD_TIMING3 0x0c
+#define LCD_TIMING3_LEE (1 << 16)
+#define LCD_TIMING3_LED(x) (((x) & 0x7F))
+
+#define LCD_UPBASE 0x10
+#define LCD_UPBASE_V(x) (((x) & 0x3FFFFFFF)<<2)
+
+#define LCD_LPBASE 0x14
+#define LCD_PBASE_V(x) (((x) & 0x3FFFFFFF)<<2)
+
+#define LCD_IRENABLE 0x18
+#define LCD_IRENABLE_MBERR (1 << 3)
+#define LCD_IRENABLE_VCOMP (1 << 2)
+#define LCD_IRENABLE_LNBU (1 << 1)
+
+#define LCD_CONTROL 0x1c
+#define LCD_CONTROL_WATERMARK (1 << 16)
+#define LCD_CONTROL_VCOMP_MA (3 << 12)
+#define LCD_CONTROL_VCOMP_VS (0 << 12)
+#define LCD_CONTROL_VCOMP_BP (1 << 12)
+#define LCD_CONTROL_VCOMP_AV (2 << 12)
+#define LCD_CONTROL_VCOMP_FP (3 << 12)
+#define LCD_CONTROL_PWR (1 << 11)
+#define LCD_CONTROL_BEPO (1 << 10)
+#define LCD_CONTROL_BEBO (1 << 9)
+#define LCD_CONTROL_BGR (1 << 8)
+#define LCD_CONTROL_DUAL (1 << 7)
+#define LCD_CONTROL_MONO8 (1 << 6)
+#define LCD_CONTROL_TFT (1 << 5)
+#define LCD_CONTROL_BW (1 << 4)
+#define LCD_CONTROL_BPP_MA (7 << 1)
+#define LCD_CONTROL_BPP_1 (0 << 1)
+#define LCD_CONTROL_BPP_2 (1 << 1)
+#define LCD_CONTROL_BPP_4 (2 << 1)
+#define LCD_CONTROL_BPP_8 (3 << 1)
+#define LCD_CONTROL_BPP_16 (4 << 1)
+#define LCD_CONTROL_EN (1 << 0)
+
+#define LCD_STATUS 0x20
+#define LCD_STATUS_MBERROR (4 << 1)
+#define LCD_STATUS_VCOMP (3 << 1)
+#define LCD_STATUS_LNBU (2 << 1)
+
+#define LCD_INTR 0x24
+#define LCD_INTR_MBERROR (4 << 1)
+#define LCD_INTR_VCOMP (3 << 1)
+#define LCD_INTR_LNBUINTR (2 << 1)
+
+#define LCD_UPCURRENT 0x28
+#define LCD_LPCURRENT 0x2c
+
+#endif
diff --git a/arch/arm/mach-ns9xxx/include/mach/regs-sys-common.h b/arch/arm/mach-ns9xxx/include/mach/regs-sys-common.h
index 14f91dfd5736..3041d3f6f44a 100644
--- a/arch/arm/mach-ns9xxx/include/mach/regs-sys-common.h
+++ b/arch/arm/mach-ns9xxx/include/mach/regs-sys-common.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-ns9xxx/include/mach/regs-sys-common.h
*
- * Copyright (C) 2007 by Digi International Inc.
+ * Copyright (C) 2007,2008 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,6 +18,12 @@
/* Interrupt Configuration registers */
#define SYS_IC(x) __REG2(0xa0900144, (x))
+#define __SYS_IC_FIELDNUM(i) (3 - ((i) & 3))
+#define __SYS_IC_SHIFT(i) (((i) & 3) << 3)
+#define SYS_IC_IE(i) __REGBIT(7 + __SYS_IC_SHIFT(i))
+#define SYS_IC_IE_EN(i) __REGVAL(SYS_IC_IE(i), 1)
+#define SYS_IC_IE_DIS(i) __REGVAL(SYS_IC_IE(i), 0)
+#define SYS_IC_ISD(i) __REGBITS_SHIFT(4, 0, __SYS_IC_SHIFT(i))
/* ISRADDR */
#define SYS_ISRADDR __REG(0xa0900164)
@@ -28,4 +34,43 @@
/* Interrupt Status Raw */
#define SYS_ISR __REG(0xa090016c)
+/* Active Interrupt Level ID Status register */
+#define SYS_AILID __REG(0xa090018c)
+
+/* System Memory Chip Select x Dynamic Memory Base */
+#define SYS_SMCSDMB(x) __REG2(0xa09001d0, (x) << 1)
+
+/* System Memory Chip Select x Dynamic Memory Mask */
+#define SYS_SMCSDMM(x) __REG2(0xa09001d4, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Base */
+#define SYS_SMCSSMB(x) __REG2(0xa09001f0, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Base: Chip select x base */
+#define SYS_SMCSSMB_CSxB __REGBITS(31, 12)
+
+/* System Memory Chip Select x Static Memory Mask */
+#define SYS_SMCSSMM(x) __REG2(0xa09001f4, (x) << 1)
+
+/* System Memory Chip Select x Static Memory Mask: Chip select x mask */
+#define SYS_SMCSSMM_CSxM __REGBITS(31, 12)
+
+/* System Memory Chip Select x Static Memory Mask: Chip select x enable */
+#define SYS_SMCSSMM_CSEx __REGBIT(0)
+#define SYS_SMCSSMM_CSEx_DIS __REGVAL(SYS_SMCSSMM_CSEx, 0)
+#define SYS_SMCSSMM_CSEx_EN __REGVAL(SYS_SMCSSMM_CSEx, 1)
+
+/* General purpose, user-defined ID register */
+#define SYS_GENID __REG(0xa0900210)
+
+
+#define SYS_EIxCTRL(i) __REG2(0xa0900214, (i))
+#define SYS_EIxCTRL_CLEAR __REGBIT(2)
+#define SYS_EIxCTRL_PLTY __REGBIT(1)
+#define SYS_EIxCTRL_PLTY_HIGH __REGVAL(SYS_EIxCTRL_PLTY, 0)
+#define SYS_EIxCTRL_PLTY_LOW __REGVAL(SYS_EIxCTRL_PLTY, 1)
+#define SYS_EIxCTRL_TYPE __REGBIT(0)
+#define SYS_EIxCTRL_TYPE_LEVEL __REGVAL(SYS_EIxCTRL_TYPE, 0)
+#define SYS_EIxCTRL_TYPE_EDGE __REGVAL(SYS_EIxCTRL_TYPE, 1)
+
#endif /* ifndef __ASM_ARCH_REGSSYSCOMMON_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/regs-sys-ns921x.h b/arch/arm/mach-ns9xxx/include/mach/regs-sys-ns921x.h
new file mode 100644
index 000000000000..a8e4410806c6
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/regs-sys-ns921x.h
@@ -0,0 +1,154 @@
+/*
+ * arch/arm/mach-ns9xxx/include/mach/regs-sys-ns921x.h
+ *
+ * Copyright (C) 2007,2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __ASM_ARCH_REGSSYSNS921X_H
+#define __ASM_ARCH_REGSSYSNS921X_H
+
+#include <mach/hardware.h>
+#include <mach/regs-sys-common.h>
+
+/* System Control Module */
+
+/* Timer Master Control */
+#define SYS_TMC __REG(0xa0900024)
+#define SYS_TMC_T9RSE __REGBIT(21)
+#define SYS_TMC_T9LSE __REGBIT(20)
+#define SYS_TMC_T9HSE __REGBIT(19)
+#define SYS_TMC_T8RSE __REGBIT(18)
+#define SYS_TMC_T8LSE __REGBIT(17)
+#define SYS_TMC_T8HSE __REGBIT(16)
+#define SYS_TMC_T7RSE __REGBIT(15)
+#define SYS_TMC_T7LSE __REGBIT(14)
+#define SYS_TMC_T7HSE __REGBIT(13)
+#define SYS_TMC_T6RSE __REGBIT(12)
+#define SYS_TMC_T6LSE __REGBIT(11)
+#define SYS_TMC_T6HSE __REGBIT(10)
+#define SYS_TMC_T9E __REGBIT(9)
+#define SYS_TMC_T8E __REGBIT(8)
+#define SYS_TMC_T7E __REGBIT(7)
+#define SYS_TMC_T6E __REGBIT(6)
+#define SYS_TMC_T5E __REGBIT(5)
+#define SYS_TMC_T4E __REGBIT(4)
+#define SYS_TMC_T3E __REGBIT(3)
+#define SYS_TMC_T2E __REGBIT(2)
+#define SYS_TMC_T1E __REGBIT(1)
+#define SYS_TMC_T0E __REGBIT(0)
+
+/* Timer x Reload Count and Compare register */
+#define SYS_TRCC(x) __REG2(0xa0900028, (x))
+
+/* Timer x Read and Capture register */
+#define SYS_TRC(x) __REG2(0xa0900050, (x))
+
+/* Interrupt Vector Address Register Level x */
+#define SYS_IVA(x) __REG2(0xa09000c4, (x))
+
+/* Clock Configuration register */
+#define SYS_CLOCK __REG(0xa090017c)
+#define SYS_CLOCK_CSC __REGBITS(31, 29)
+#define SYS_CLOCK_CSSEL __REGBIT(25)
+#define SYS_CLOCK_EXTDMA __REGBIT(14)
+#define SYS_CLOCK_RTC __REGBIT(12)
+#define SYS_CLOCK_I2C __REGBIT(11)
+#define SYS_CLOCK_AES __REGBIT(9)
+#define SYS_CLOCK_ADC __REGBIT(8)
+#define SYS_CLOCK_SPI __REGBIT(5)
+#define SYS_CLOCK_UARTx(i) __REGBIT(1 + (i))
+#define SYS_CLOCK_UARTD SYS_CLOCK_UARTx(3)
+#define SYS_CLOCK_UARTC SYS_CLOCK_UARTx(2)
+#define SYS_CLOCK_UARTB SYS_CLOCK_UARTx(1)
+#define SYS_CLOCK_UARTA SYS_CLOCK_UARTx(0)
+#define SYS_CLOCK_ETH __REGBIT(0)
+
+#define SYS_RESET __REG(0xa0900180)
+
+/* PLL Configuration register */
+#define SYS_PLL __REG(0xa0900188)
+#define SYS_PLL_NF __REGBITS(16, 8)
+#define SYS_PLL_BP __REGBIT(7)
+#define SYS_PLL_OD __REGBITS(6, 5)
+#define SYS_PLL_NR __REGBITS(4, 0)
+
+/* Timer x Control register */
+#define SYS_TC(x) __REG2(0xa0900190, (x))
+#define SYS_TCx_RELMODE __REGBIT(18)
+#define SYS_TCx_RELMODE_FULL __REGVAL(SYS_TCx_RELMODE, 0)
+#define SYS_TCx_RELMODE_HALF __REGVAL(SYS_TCx_RELMODE, 1)
+#define SYS_TCx_MODE2 __REGBITS(17, 16)
+#define SYS_TCx_MODE2_00 __REGVAL(SYS_TCx_MODE2, 0)
+#define SYS_TCx_MODE2_01 __REGVAL(SYS_TCx_MODE2, 1)
+#define SYS_TCx_MODE2_10 __REGVAL(SYS_TCx_MODE2, 2)
+#define SYS_TCx_MODE2_11 __REGVAL(SYS_TCx_MODE2, 3)
+#define SYS_TCx_TE __REGBIT(15)
+#define SYS_TCx_TE_DIS __REGVAL(SYS_TCx_TE, 0)
+#define SYS_TCx_TE_EN __REGVAL(SYS_TCx_TE, 1)
+#define SYS_TCx_CAPCOMP __REGBITS(14,12)
+#define SYS_TCx_CAPCOMP_000 __REGVAL(SYS_TCx_CAPCOMP, 0)
+#define SYS_TCx_DEBUG __REGBIT(11)
+#define SYS_TCx_DEBUG_CONT __REGVAL(SYS_TCx_DEBUG, 0)
+#define SYS_TCx_DEBUG_STOP __REGVAL(SYS_TCx_DEBUG, 1)
+#define SYS_TCx_INTCLR __REGBIT(10)
+#define SYS_TCx_TCS __REGBITS(9, 6)
+#define SYS_TCx_TCS_2AHB __REGVAL(SYS_TCx_TCS, 0)
+#define SYS_TCx_TCS_AHB __REGVAL(SYS_TCx_TCS, 1)
+#define SYS_TCx_MODE __REGBITS(5, 4)
+#define SYS_TCx_MODE_INTERNAL __REGVAL(SYS_TCx_MODE, 0)
+#define SYS_TCx_MODE_CONCA __REGVAL(SYS_TCx_MODE, 3)
+#define SYS_TCx_INTSEL __REGBIT(3)
+#define SYS_TCx_INTSEL_DIS __REGVAL(SYS_TCx_INTSEL, 0)
+#define SYS_TCx_INTSEL_EN __REGVAL(SYS_TCx_INTSEL, 1)
+#define SYS_TCx_UPDOWN __REGBIT(2)
+#define SYS_TCx_UPDOWN_UP __REGVAL(SYS_TCx_UPDOWN, 0)
+#define SYS_TCx_UPDOWN_DOWN __REGVAL(SYS_TCx_UPDOWN, 1)
+#define SYS_TCx_BITTIMER __REGBIT(1)
+#define SYS_TCx_BITTIMER_16 __REGVAL(SYS_TCx_BITTIMER, 0)
+#define SYS_TCx_BITTIMER_32 __REGVAL(SYS_TCx_BITTIMER, 1)
+#define SYS_TCx_RELENBL __REGBIT(0)
+#define SYS_TCx_RELENBL_DIS __REGVAL(SYS_TCx_RELENBL, 0)
+#define SYS_TCx_RELENBL_EN __REGVAL(SYS_TCx_RELENBL, 1)
+
+/* Timer Registers */
+#define SYS_THR(x) __REG2(0xa0900078, (x)) /* Timer 6-9 High Registers */
+#define SYS_TLR(x) __REG2(0xa0900088, (x)) /* Timer 6-9 Low Registers */
+#define SYS_THLSR(x) __REG2(0xa0900098, (x)) /* Timer 6-9 High Low Step Register */
+#define SYS_TRELSR(x) __REG2(0xa09000a8, (x)) /* Timer 6-9 Reload Step Register */
+#define SYS_TRELCCR(x) __REG2(0xa0900028, (x)) /* Timer 0-9 Reload Count and Compare Register */
+#define SYS_TRCR(x) __REG2(0xa0900050, (x)) /* Timer 0-9 Read and Capture Register */
+
+/* */
+#define SYS_RTCMC __REG(0xa0900224)
+#define SYS_RTCMC_SS __REGBIT(4)
+#define SYS_RTCMC_RIS __REGBIT(3)
+#define SYS_RTCMC_MIS __REGBIT(2)
+#define SYS_RTCMC_MODE __REGBIT(1)
+#define SYS_RTCMC_MODE_STANDBY __REGVAL(SYS_RTCMC_MODE, 0)
+#define SYS_RTCMC_MODE_NORMAL __REGVAL(SYS_RTCMC_MODE, 1)
+#define SYS_RTCMC_RIC __REGBIT(0)
+
+/* */
+#define SYS_POWER __REG(0xa0900228)
+#define SYS_POWER_SLFRFSH __REGBIT(21)
+#define SYS_POWER_INTCLR __REGBIT(20)
+#define SYS_POWER_EXTIRQx(i) __REGBIT(16 + (i))
+#define SYS_POWER_EXTIRQ3 SYS_POWER_EXTIRQx(3)
+#define SYS_POWER_EXTIRQ2 SYS_POWER_EXTIRQx(2)
+#define SYS_POWER_EXTIRQ1 SYS_POWER_EXTIRQx(1)
+#define SYS_POWER_EXTIRQ0 SYS_POWER_EXTIRQx(0)
+#define SYS_POWER_RTC SYS_CLOCK_RTC
+#define SYS_POWER_I2C SYS_CLOCK_I2C
+#define SYS_POWER_SPI SYS_CLOCK_SPI
+#define SYS_POWER_UARTx(i) SYS_CLOCK_UARTx(i)
+#define SYS_POWER_UARTD SYS_POWER_UARTx(3)
+#define SYS_POWER_UARTC SYS_POWER_UARTx(2)
+#define SYS_POWER_UARTB SYS_POWER_UARTx(1)
+#define SYS_POWER_UARTA SYS_POWER_UARTx(0)
+#define SYS_POWER_ETH SYS_CLOCK_ETH
+
+#endif /* ifndef __ASM_ARCH_REGSSYSNS921X_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/regs-sys-ns9360.h b/arch/arm/mach-ns9xxx/include/mach/regs-sys-ns9360.h
index 8ff254d9901c..30236e6fbc49 100644
--- a/arch/arm/mach-ns9xxx/include/mach/regs-sys-ns9360.h
+++ b/arch/arm/mach-ns9xxx/include/mach/regs-sys-ns9360.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-ns9xxx/include/mach/regs-sys-ns9360.h
*
- * Copyright (C) 2006,2007 by Digi International Inc.
+ * Copyright (C) 2006-2008 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
@@ -30,6 +30,12 @@
/* Timer Interrupt Status register */
#define SYS_TIS __REG(0xa0900170)
+#define SYS_CLOCK __REG(0xa090017c)
+#define SYS_CLOCK_LPCSEXT __REGBIT(9)
+
+#define SYS_RESET __REG(0xa0900180)
+#define SYS_RESET_LCDC __REGBIT(5)
+
/* PLL Configuration register */
#define SYS_PLL __REG(0xa0900188)
@@ -100,32 +106,6 @@
#define SYS_TCx_REN_DIS __REGVAL(SYS_TCx_REN, 0)
#define SYS_TCx_REN_EN __REGVAL(SYS_TCx_REN, 1)
-/* System Memory Chip Select x Dynamic Memory Base */
-#define SYS_SMCSDMB(x) __REG2(0xa09001d0, (x) << 1)
-
-/* System Memory Chip Select x Dynamic Memory Mask */
-#define SYS_SMCSDMM(x) __REG2(0xa09001d4, (x) << 1)
-
-/* System Memory Chip Select x Static Memory Base */
-#define SYS_SMCSSMB(x) __REG2(0xa09001f0, (x) << 1)
-
-/* System Memory Chip Select x Static Memory Base: Chip select x base */
-#define SYS_SMCSSMB_CSxB __REGBITS(31, 12)
-
-/* System Memory Chip Select x Static Memory Mask */
-#define SYS_SMCSSMM(x) __REG2(0xa09001f4, (x) << 1)
-
-/* System Memory Chip Select x Static Memory Mask: Chip select x mask */
-#define SYS_SMCSSMM_CSxM __REGBITS(31, 12)
-
-/* System Memory Chip Select x Static Memory Mask: Chip select x enable */
-#define SYS_SMCSSMM_CSEx __REGBIT(0)
-#define SYS_SMCSSMM_CSEx_DIS __REGVAL(SYS_SMCSSMM_CSEx, 0)
-#define SYS_SMCSSMM_CSEx_EN __REGVAL(SYS_SMCSSMM_CSEx, 1)
-
-/* General purpose, user-defined ID register */
-#define SYS_GENID __REG(0xa0900210)
-
/* External Interrupt x Control register */
#define SYS_EIC(x) __REG2(0xa0900214, (x))
@@ -145,4 +125,7 @@
#define SYS_EIC_LVEDG_LEVEL __REGVAL(SYS_EIC_LVEDG, 0)
#define SYS_EIC_LVEDG_EDGE __REGVAL(SYS_EIC_LVEDG, 1)
+/* RTC Clock Control register */
+#define SYS_RTCCC __REG(0xa0900224)
+
#endif /* ifndef __ASM_ARCH_REGSSYSNS9360_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/spi.h b/arch/arm/mach-ns9xxx/include/mach/spi.h
new file mode 100644
index 000000000000..801d01b838d6
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/include/mach/spi.h
@@ -0,0 +1,28 @@
+/*
+ * arch/arm/mach-ns9xxx/include/mach/spi.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+*/
+#ifndef __ASM_ARCH_SPI_H
+#define __ASM_ARCH_SPI_H
+
+#define SPI_MOSI_GPIO_OFFSET 0
+#define SPI_MISO_GPIO_OFFSET 1
+#define SPI_CLK_GPIO_OFFSET 2
+#define SPI_EN_GPIO_OFFSET 3
+
+
+#define SPI_MAX_GPIO 10
+
+struct spi_ns9xxx_data {
+ char gpios[SPI_MAX_GPIO];
+ char gpio_funcs[SPI_MAX_GPIO];
+ char nr_gpios;
+};
+
+#endif /* ifndef __ASM_ARCH_SPI_H */
diff --git a/arch/arm/mach-ns9xxx/include/mach/system.h b/arch/arm/mach-ns9xxx/include/mach/system.h
index e2068c57415f..e4ae479dc5b2 100644
--- a/arch/arm/mach-ns9xxx/include/mach/system.h
+++ b/arch/arm/mach-ns9xxx/include/mach/system.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-ns9xxx/include/mach/system.h
*
- * Copyright (C) 2006,2007 by Digi International Inc.
+ * Copyright (C) 2006-2008 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
@@ -13,15 +13,32 @@
#include <asm/proc-fns.h>
#include <mach/processor.h>
-#include <mach/processor-ns9360.h>
static inline void arch_idle(void)
{
- cpu_do_idle();
+ /*
+ * When a Camry (i.e. ns921x) executes
+ *
+ * mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
+ *
+ * the CPU is stopped, so are all timers. This is not something I want
+ * to handle. As the "wait for interrupt" instruction is part of
+ * cpu_arm926_do_idle, it's not called for it.
+ */
+ if (!processor_is_ns921x())
+ cpu_do_idle();
}
+void ns921x_reset(char);
+void ns9360_reset(char);
+
static inline void arch_reset(char mode)
{
+#ifdef CONFIG_PROCESSOR_NS921X
+ if (processor_is_ns921x())
+ ns921x_reset(mode);
+ else
+#endif
#ifdef CONFIG_PROCESSOR_NS9360
if (processor_is_ns9360())
ns9360_reset(mode);
diff --git a/arch/arm/mach-ns9xxx/include/mach/timex.h b/arch/arm/mach-ns9xxx/include/mach/timex.h
index 734a8d8bd578..e901b4e10610 100644
--- a/arch/arm/mach-ns9xxx/include/mach/timex.h
+++ b/arch/arm/mach-ns9xxx/include/mach/timex.h
@@ -12,7 +12,7 @@
#define __ASM_ARCH_TIMEX_H
/*
- * value for CLOCK_TICK_RATE stolen from arch/arm/mach-s3c2410/include/mach/timex.h.
+ * value for CLOCK_TICK_RATE stolen from include/asm-arm/arch-s3c2410/timex.h.
* See there for an explanation.
*/
#define CLOCK_TICK_RATE 12000000
diff --git a/arch/arm/mach-ns9xxx/include/mach/uncompress.h b/arch/arm/mach-ns9xxx/include/mach/uncompress.h
index 1b12d324b087..fc9b0a424230 100644
--- a/arch/arm/mach-ns9xxx/include/mach/uncompress.h
+++ b/arch/arm/mach-ns9xxx/include/mach/uncompress.h
@@ -11,15 +11,21 @@
#ifndef __ASM_ARCH_UNCOMPRESS_H
#define __ASM_ARCH_UNCOMPRESS_H
-#include <linux/io.h>
-
-#define __REG(x) ((void __iomem __force *)(x))
+#include <asm/io.h>
+#define __REG(x) ((void __iomem __force *)(x))
static void putc_dummy(char c, void __iomem *base)
{
/* nothing */
}
+#if defined(CONFIG_PROCESSOR_NS9360)
+# define NS9360_UARTA __REG(0x90200040)
+# define NS9360_UARTB __REG(0x90200000)
+# define NS9360_UARTC __REG(0x90300000)
+# define NS9360_UARTD __REG(0x90300040)
+# define NS9360_UART_ENABLED(base) \
+ (__raw_readl(NS9360_UARTA) & (1 << 31))
static void putc_ns9360(char c, void __iomem *base)
{
static int t = 0x10000;
@@ -34,22 +40,16 @@ static void putc_ns9360(char c, void __iomem *base)
}
} while (t);
}
-
-static void putc_a9m9750dev(char c, void __iomem *base)
-{
- static int t = 0x10000;
- do {
- if (t)
- --t;
-
- if (__raw_readb(base + 5) & (1 << 5)) {
- __raw_writeb(c, base);
- t = 0x10000;
- break;
- }
- } while (t);
-
-}
+#endif
+
+#if defined(CONFIG_PROCESSOR_NS921X)
+# define NS921XSYS_CLOCK __REG(0xa090017c)
+# define NS921X_UARTA __REG(0x90010000)
+# define NS921X_UARTB __REG(0x90018000)
+# define NS921X_UARTC __REG(0x90020000)
+# define NS921X_UARTD __REG(0x90028000)
+# define NS921X_UART_ENABLED(base) \
+ (__raw_readl((base) + 0x1000) & (1 << 29))
static void putc_ns921x(char c, void __iomem *base)
{
@@ -66,79 +66,96 @@ static void putc_ns921x(char c, void __iomem *base)
} while (t);
}
-#define MSCS __REG(0xA0900184)
+#include "fim-uncompress.h"
-#define NS9360_UARTA __REG(0x90200040)
-#define NS9360_UARTB __REG(0x90200000)
-#define NS9360_UARTC __REG(0x90300000)
-#define NS9360_UARTD __REG(0x90300040)
+static void putc_ns921x_fim(char ch, void __iomem *base)
+{
+ unsigned int status;
+ unsigned short data = 1;
+ int pic = 0;
-#define NS9360_UART_ENABLED(base) \
- (__raw_readl(NS9360_UARTA) & (1 << 31))
+ if ('\n' == ch)
+ ch = '\r';
-#define A9M9750DEV_UARTA __REG(0x40000000)
+ data = (data << FIM_SERIAL_DATA_BITS) | (ch & ((1 << FIM_SERIAL_DATA_BITS) - 1));
-#define NS921XSYS_CLOCK __REG(0xa090017c)
-#define NS921X_UARTA __REG(0x90010000)
-#define NS921X_UARTB __REG(0x90018000)
-#define NS921X_UARTC __REG(0x90020000)
-#define NS921X_UARTD __REG(0x90028000)
+ /* Check if the PIC is tasked with another send-char request */
+ do {
+ status = fim_get_exp_reg(pic, 0);
+ } while (status & FIM_SERIAL_INT_INSERT_CHAR);
-#define NS921X_UART_ENABLED(base) \
- (__raw_readl((base) + 0x1000) & (1 << 29))
+ /* And send the char using the interrupt function */
+ fim_set_ctrl_reg(pic, 0, data & 0xFF);
+ fim_set_ctrl_reg(pic, 1, (data >> 8) & 0xFF);
+ fim_send_interrupt(pic, FIM_SERIAL_INT_INSERT_CHAR);
+}
+#endif
static void autodetect(void (**putc)(char, void __iomem *), void __iomem **base)
{
- if (((__raw_readl(MSCS) >> 16) & 0xfe) == 0x00) {
- /* ns9360 or ns9750 */
- if (NS9360_UART_ENABLED(NS9360_UARTA)) {
- *putc = putc_ns9360;
- *base = NS9360_UARTA;
- return;
- } else if (NS9360_UART_ENABLED(NS9360_UARTB)) {
- *putc = putc_ns9360;
- *base = NS9360_UARTB;
- return;
- } else if (NS9360_UART_ENABLED(NS9360_UARTC)) {
- *putc = putc_ns9360;
- *base = NS9360_UARTC;
- return;
- } else if (NS9360_UART_ENABLED(NS9360_UARTD)) {
- *putc = putc_ns9360;
- *base = NS9360_UARTD;
- return;
- } else if (__raw_readl(__REG(0xa09001f4)) == 0xfffff001) {
- *putc = putc_a9m9750dev;
- *base = A9M9750DEV_UARTA;
- return;
- }
- } else if (((__raw_readl(MSCS) >> 16) & 0xfe) == 0x02) {
- /* ns921x */
- u32 clock = __raw_readl(NS921XSYS_CLOCK);
-
- if ((clock & (1 << 1)) &&
- NS921X_UART_ENABLED(NS921X_UARTA)) {
- *putc = putc_ns921x;
- *base = NS921X_UARTA;
- return;
- } else if ((clock & (1 << 2)) &&
- NS921X_UART_ENABLED(NS921X_UARTB)) {
- *putc = putc_ns921x;
- *base = NS921X_UARTB;
- return;
- } else if ((clock & (1 << 3)) &&
- NS921X_UART_ENABLED(NS921X_UARTC)) {
- *putc = putc_ns921x;
- *base = NS921X_UARTC;
- return;
- } else if ((clock & (1 << 4)) &&
- NS921X_UART_ENABLED(NS921X_UARTD)) {
- *putc = putc_ns921x;
- *base = NS921X_UARTD;
- return;
- }
+#if defined(CONFIG_PROCESSOR_NS9360)
+ /* ns9360 */
+ if (NS9360_UART_ENABLED(NS9360_UARTA)) {
+ *putc = putc_ns9360;
+ *base = NS9360_UARTA;
+ return;
+ } else if (NS9360_UART_ENABLED(NS9360_UARTB)) {
+ *putc = putc_ns9360;
+ *base = NS9360_UARTB;
+ return;
+ } else if (NS9360_UART_ENABLED(NS9360_UARTC)) {
+ *putc = putc_ns9360;
+ *base = NS9360_UARTC;
+ return;
+ } else if (NS9360_UART_ENABLED(NS9360_UARTD)) {
+ *putc = putc_ns9360;
+ *base = NS9360_UARTD;
+ return;
}
-
+#elif defined(CONFIG_PROCESSOR_NS921X)
+ /* ns921x */
+ u32 clock = __raw_readl(NS921XSYS_CLOCK);
+
+ if ((clock & (1 << 1)) &&
+ NS921X_UART_ENABLED(NS921X_UARTA)) {
+ *putc = putc_ns921x;
+ *base = NS921X_UARTA;
+ return;
+ } else if ((clock & (1 << 2)) &&
+ NS921X_UART_ENABLED(NS921X_UARTB)) {
+ *putc = putc_ns921x;
+ *base = NS921X_UARTB;
+ return;
+ } else if ((clock & (1 << 3)) &&
+ NS921X_UART_ENABLED(NS921X_UARTC)) {
+ *putc = putc_ns921x;
+ *base = NS921X_UARTC;
+ return;
+ } else if ((clock & (1 << 4)) &&
+ NS921X_UART_ENABLED(NS921X_UARTD)) {
+ *putc = putc_ns921x;
+ *base = NS921X_UARTD;
+ return;
+ }
+# if defined(CONFIG_SERIAL_FIM_CONSOLE)
+ /* None of the standard UARTs is enabled. Try with the FIMs */
+# if defined(CONFIG_FIM_ZERO_SERIAL_SELECTED) && !defined(CONFIG_FIM_ONE_SERIAL_SELECTED)
+ /* Try with UART on FIM0 */
+ else if (NS921X_FIM_ENABLED(NS921X_FIM0)) {
+ *putc = putc_ns921x_fim;
+ *base = NS921X_FIM0;
+ return;
+ }
+# elif !defined(CONFIG_FIM_ZERO_SERIAL_SELECTED) && defined(CONFIG_FIM_ONE_SERIAL_SELECTED)
+ /* Try with UART on FIM1 */
+ else if (NS921X_FIM_ENABLED(NS921X_FIM1)) {
+ *putc = putc_ns921x_fim;
+ *base = NS921X_FIM1;
+ return;
+ }
+# endif /* FIM_x */
+# endif /* SERIAL_FIM_CONSOLE */
+#endif /* PROCESSOR_x */
*putc = putc_dummy;
}
@@ -147,7 +164,7 @@ void __iomem *base;
static void putc(char c)
{
- myputc(c, base);
+ myputc(c, base);
}
static void arch_decomp_setup(void)
diff --git a/arch/arm/mach-ns9xxx/irq-ns921x.c b/arch/arm/mach-ns9xxx/irq-ns921x.c
new file mode 100644
index 000000000000..1937d574a0e3
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/irq-ns921x.c
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-ns9xxx/irq-ns921x.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/errno.h>
+#include <linux/kernel.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <mach/regs-sys-ns921x.h>
+
+#include "processor-ns921x.h"
+
+static const u32 ns921x_irq2powermask[] = {
+ [IRQ_NS9XXX_ETHRX] = SYS_POWER_ETH,
+ [IRQ_NS921X_UARTA] = SYS_POWER_UARTA,
+ [IRQ_NS921X_UARTB] = SYS_POWER_UARTB,
+ [IRQ_NS921X_UARTC] = SYS_POWER_UARTC,
+ [IRQ_NS921X_UARTD] = SYS_POWER_UARTD,
+ [IRQ_NS921X_SPI] = SYS_POWER_SPI,
+ [IRQ_NS921X_I2C] = SYS_POWER_I2C,
+ [IRQ_NS9215_RTC] = SYS_POWER_RTC,
+ [IRQ_NS9XXX_EXT0] = SYS_POWER_EXTIRQ0,
+ [IRQ_NS9XXX_EXT1] = SYS_POWER_EXTIRQ1,
+ [IRQ_NS9XXX_EXT2] = SYS_POWER_EXTIRQ2,
+ [IRQ_NS9XXX_EXT3] = SYS_POWER_EXTIRQ3,
+};
+
+int ns921x_set_wake_irq(unsigned int irq, unsigned int on)
+{
+ unsigned long flags;
+ u32 power;
+
+ if (irq > ARRAY_SIZE(ns921x_irq2powermask) ||
+ !ns921x_irq2powermask[irq])
+ return -ENOENT;
+
+ local_irq_save(flags);
+
+ power = __raw_readl(SYS_POWER);
+
+ if (on)
+ power |= ns921x_irq2powermask[irq];
+ else
+ power &= ~ns921x_irq2powermask[irq];
+
+ __raw_writel(power, SYS_POWER);
+
+ local_irq_restore(flags);
+
+ return 0;
+}
diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c
index 22e0eb6e9ec4..e678f53cca61 100644
--- a/arch/arm/mach-ns9xxx/irq.c
+++ b/arch/arm/mach-ns9xxx/irq.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-ns9xxx/irq.c
*
- * Copyright (C) 2006,2007 by Digi International Inc.
+ * Copyright (C) 2006-2008 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
@@ -10,30 +10,105 @@
*/
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
-#include <linux/io.h>
+#include <asm/io.h>
#include <asm/mach/irq.h>
+#include <asm/mach-types.h>
+#include <mach/regs-bbu.h>
#include <mach/regs-sys-common.h>
#include <mach/irqs.h>
#include <mach/board.h>
+#include <mach/processor.h>
-#include "generic.h"
+#include "processor-ns921x.h"
+#include "irq.h"
-/* simple interrupt prio table: prio(x) < prio(y) <=> x < y */
-#define irq2prio(i) (i)
-#define prio2irq(p) (p)
+static unsigned prio2irq(unsigned prio)
+{
+ u32 ic = __raw_readl(SYS_IC(prio / 4));
+ return REGGETIM_IDX(ic, SYS_IC, ISD, __SYS_IC_FIELDNUM(prio));
+}
+
+static unsigned irq2prio_map[32];
+
+static unsigned irq2prio(unsigned irq)
+{
+ unsigned cachedprio = irq2prio_map[irq];
+ int timeout;
+
+ if (likely(irq == prio2irq(cachedprio)))
+ return cachedprio;
+
+ for (timeout = 32; timeout; --timeout) {
+ static unsigned i;
+ unsigned iirq;
+
+ i = (i + 1) % 32;
+
+ iirq = prio2irq(i);
+
+ irq2prio_map[iirq] = i;
+
+ pr_debug("%s: update %u -> %u\n", __func__, iirq, i);
+
+ if (iirq == irq)
+ return i;
+ }
+
+ BUG();
+
+ return 0; /* not reached, clean compiler warning */
+}
+
+#define prio2irq_init(p) (p)
static void ns9xxx_mask_irq(unsigned int irq)
{
- /* XXX: better use cpp symbols */
int prio = irq2prio(irq);
u32 ic = __raw_readl(SYS_IC(prio / 4));
- ic &= ~(1 << (7 + 8 * (3 - (prio & 3))));
+ REGSET_IDX(ic, SYS_IC, IE, __SYS_IC_FIELDNUM(prio), DIS);
__raw_writel(ic, SYS_IC(prio / 4));
}
+int ns9xxx_is_enabled_irq(unsigned int irq)
+{
+ int prio = irq2prio(irq);
+ u32 ic, en_bit_mask;
+
+ en_bit_mask = 0x80 << ((3 - (prio & 3)) * 8);
+ ic = __raw_readl(SYS_IC(prio / 4));
+
+ return ic & en_bit_mask;
+}
+EXPORT_SYMBOL(ns9xxx_is_enabled_irq);
+
+static void ns9xxx_disable_irq(unsigned int irq)
+{
+ struct irq_desc *desc = irq_desc + irq;
+
+ ns9xxx_mask_irq(irq);
+ desc->status &= IRQ_MASKED;
+}
+
static void ns9xxx_ack_irq(unsigned int irq)
{
- __raw_writel(0, SYS_ISRADDR);
+ if (irq >= IRQ_NS9XXX_EXT0) {
+ u32 eixctl;
+
+ BUG_ON((unsigned)(irq - IRQ_NS9XXX_EXT0) > 4);
+
+ eixctl = __raw_readl(SYS_EIxCTRL(irq - IRQ_NS9XXX_EXT0));
+
+ if (REGGET(eixctl, SYS_EIxCTRL, TYPE) ==
+ SYS_EIxCTRL_TYPE_EDGE) {
+ REGSETIM(eixctl, SYS_EIxCTRL, CLEAR, 1);
+ __raw_writel(eixctl,
+ SYS_EIxCTRL(irq - IRQ_NS9XXX_EXT0));
+
+ REGSETIM(eixctl, SYS_EIxCTRL, CLEAR, 0);
+ __raw_writel(eixctl,
+ SYS_EIxCTRL(irq - IRQ_NS9XXX_EXT0));
+ }
+ }
}
static void ns9xxx_maskack_irq(unsigned int irq)
@@ -44,23 +119,175 @@ static void ns9xxx_maskack_irq(unsigned int irq)
static void ns9xxx_unmask_irq(unsigned int irq)
{
- /* XXX: better use cpp symbols */
int prio = irq2prio(irq);
u32 ic = __raw_readl(SYS_IC(prio / 4));
- ic |= 1 << (7 + 8 * (3 - (prio & 3)));
+ REGSET_IDX(ic, SYS_IC, IE, __SYS_IC_FIELDNUM(prio), EN);
__raw_writel(ic, SYS_IC(prio / 4));
}
+static void ns9xxx_eoi_irq(unsigned int irq)
+{
+ __raw_writel(irq2prio(irq), SYS_ISRADDR);
+}
+
+static int ns9xxx_set_type_irq(unsigned int irq, unsigned int flow_type)
+{
+ void __iomem *regeixctrl = SYS_EIxCTRL(irq - IRQ_NS9XXX_EXT0);
+ u32 eixctrl = 0;
+
+ REGSETIM(eixctrl, SYS_EIxCTRL, CLEAR, 1);
+
+ if (irq < IRQ_NS9XXX_EXT0 || irq > IRQ_NS9XXX_EXT3)
+ return -EINVAL;
+
+ switch (flow_type) {
+ case IRQF_TRIGGER_HIGH:
+ REGSET(eixctrl, SYS_EIxCTRL, PLTY, HIGH);
+ REGSET(eixctrl, SYS_EIxCTRL, TYPE, LEVEL);
+ break;
+
+ case IRQF_TRIGGER_LOW:
+ REGSET(eixctrl, SYS_EIxCTRL, PLTY, LOW);
+ REGSET(eixctrl, SYS_EIxCTRL, TYPE, LEVEL);
+ break;
+
+ case IRQF_TRIGGER_RISING:
+ REGSET(eixctrl, SYS_EIxCTRL, PLTY, HIGH);
+ REGSET(eixctrl, SYS_EIxCTRL, TYPE, EDGE);
+ break;
+
+ case IRQF_TRIGGER_FALLING:
+ REGSET(eixctrl, SYS_EIxCTRL, PLTY, LOW);
+ REGSET(eixctrl, SYS_EIxCTRL, TYPE, EDGE);
+ break;
+
+ default:
+ pr_warning("%s: cannot configure for flow type %u\n",
+ __func__, flow_type);
+ return -ENODEV;
+ }
+
+ __raw_writel(eixctrl, regeixctrl);
+ REGSETIM(eixctrl, SYS_EIxCTRL, CLEAR, 0);
+ __raw_writel(eixctrl, regeixctrl);
+
+ return 0;
+}
+
+static int ns9xxx_set_wake_irq(unsigned int irq, unsigned int on)
+{
+#if defined(CONFIG_PROCESSOR_NS921X)
+ if (processor_is_ns921x())
+ return ns921x_set_wake_irq(irq, on);
+#endif
+
+ return -EINVAL;
+}
+
static struct irq_chip ns9xxx_chip = {
+ .name = "ns9xxx",
+ .disable = ns9xxx_disable_irq,
.ack = ns9xxx_ack_irq,
.mask = ns9xxx_mask_irq,
.mask_ack = ns9xxx_maskack_irq,
.unmask = ns9xxx_unmask_irq,
+ .eoi = ns9xxx_eoi_irq,
+ .set_type = ns9xxx_set_type_irq,
+ .set_wake = ns9xxx_set_wake_irq,
+};
+
+#if defined(CONFIG_PROCESSOR_NS9360)
+static void ns9360_mask_bbus_irq(unsigned int irq)
+{
+ u32 ier = __raw_readl(NS9360_BBUS_IEN);
+ ier &= ~(1 << (irq - IRQ_NS9360_BBUS(0)));
+ __raw_writel(ier, NS9360_BBUS_IEN);
+}
+
+static void ns9360_unmask_bbus_irq(unsigned int irq)
+{
+ u32 ier = __raw_readl(NS9360_BBUS_IEN);
+ ier |= 1 << (irq - IRQ_NS9360_BBUS(0));
+ __raw_writel(ier, NS9360_BBUS_IEN);
+}
+
+static void ns9360_demux_bbus_irq(unsigned int irq, struct irq_desc *desc)
+{
+ unsigned bbus_irq_plus1;
+ u32 stat = __raw_readl(NS9360_BBUS_ISTAT);
+
+ while ((bbus_irq_plus1 = fls(stat))) {
+ unsigned bbus_irq = bbus_irq_plus1 - 1;
+ stat &= ~(1 << bbus_irq);
+
+ desc_handle_irq(IRQ_NS9360_BBUS(bbus_irq),
+ irq_desc + IRQ_NS9360_BBUS(bbus_irq));
+ }
+
+ /* unmask parent irq */
+ desc->chip->unmask(irq);
+ desc->chip->eoi(irq);
+}
+
+static struct irq_chip ns9360_bbus_chip = {
+ .name = "ns9xxx_bbus",
+ .ack = ns9360_mask_bbus_irq,
+ .mask = ns9360_mask_bbus_irq,
+ .mask_ack = ns9360_mask_bbus_irq,
+ .unmask = ns9360_unmask_bbus_irq,
+};
+
+static void ns9360_mask_bbus_dma_irq(unsigned int irq)
+{
+ u32 ien = __raw_readl(NS9360_BBUS_DMA_IEN);
+ ien &= ~(1 << (irq - IRQ_NS9360_BBUDMA(0)));
+ __raw_writel(ien, NS9360_BBUS_DMA_IEN);
+}
+
+static void ns9360_unmask_bbus_dma_irq( unsigned int irq )
+{
+ u32 ien = __raw_readl(NS9360_BBUS_DMA_IEN);
+ ien |= 1 << (irq - IRQ_NS9360_BBUDMA(0));
+ __raw_writel(ien, NS9360_BBUS_DMA_IEN);
+}
+
+static void ns9360_demux_bbus_dma_irq(unsigned int irq, struct irq_desc *desc)
+{
+ unsigned dma_irq_plus1;
+ u32 stat = __raw_readl(NS9360_BBUS_DMA_ISTAT);
+
+ /* mask parent irq */
+ desc->chip->mask_ack(irq);
+
+ while ((dma_irq_plus1 = fls(stat))) {
+ unsigned dma_irq = dma_irq_plus1 - 1;
+ stat &= ~(1 << dma_irq);
+
+ desc_handle_irq(IRQ_NS9360_BBUDMA(dma_irq),
+ irq_desc + IRQ_NS9360_BBUDMA(dma_irq));
+ }
+
+ /* unmask parent */
+ desc->chip->unmask(irq);
+}
+
+static struct irq_chip ns9360_bbus_dma_chip = {
+ .name = "ns9xxx_bbus_dma",
+ .ack = ns9360_mask_bbus_dma_irq,
+ .mask = ns9360_mask_bbus_dma_irq,
+ .mask_ack = ns9360_mask_bbus_dma_irq,
+ .unmask = ns9360_unmask_bbus_dma_irq,
};
+#endif /* if defined(CONFIG_PROCESSOR_NS9360) */
+
+extern int noirqdebug;
-#if 0
-#define handle_irq handle_level_irq
-#else
+/* this is similar to handle_fasteoi_irq. The differences are:
+ * - handle_prio_irq calls desc->chip->ack at the beginning;
+ * - handle_prio_irq disables an irq directly after handle_IRQ_event to work
+ * around the bug in the ns9xxx' irq priority encoder;
+ * - currently some debug code;
+ */
static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
{
unsigned int cpu = smp_processor_id();
@@ -69,24 +296,29 @@ static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
spin_lock(&desc->lock);
- BUG_ON(desc->status & IRQ_INPROGRESS);
+ desc->chip->ack(irq);
+
+ if (unlikely(desc->status & IRQ_INPROGRESS)) {
+ desc->status |= IRQ_PENDING;
+ goto out_unlock;
+ }
desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
kstat_cpu(cpu).irqs[irq]++;
action = desc->action;
- if (unlikely(!action || (desc->status & IRQ_DISABLED)))
+ if (unlikely(!action || (desc->status & IRQ_DISABLED))) {
+ desc->status |= IRQ_PENDING;
goto out_mask;
+ }
desc->status |= IRQ_INPROGRESS;
+ desc->status &= ~IRQ_PENDING;
spin_unlock(&desc->lock);
action_ret = handle_IRQ_event(irq, action);
-
- /* XXX: There is no direct way to access noirqdebug, so check
- * unconditionally for spurious irqs...
- * Maybe this function should go to kernel/irq/chip.c? */
- note_interrupt(irq, desc, action_ret);
+ if (!noirqdebug)
+ note_interrupt(irq, desc, action_ret);
spin_lock(&desc->lock);
desc->status &= ~IRQ_INPROGRESS;
@@ -95,32 +327,62 @@ static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
out_mask:
desc->chip->mask(irq);
- /* ack unconditionally to unmask lower prio irqs */
- desc->chip->ack(irq);
+ desc->chip->eoi(irq);
+out_unlock:
spin_unlock(&desc->lock);
}
-#define handle_irq handle_prio_irq
-#endif
void __init ns9xxx_init_irq(void)
{
int i;
/* disable all IRQs */
- for (i = 0; i < 8; ++i)
- __raw_writel(prio2irq(4 * i) << 24 |
- prio2irq(4 * i + 1) << 16 |
- prio2irq(4 * i + 2) << 8 |
- prio2irq(4 * i + 3),
- SYS_IC(i));
+ for (i = 0; i < 8; ++i) {
+ u32 ic = 0;
+
+ REGSETIM_IDX(ic, SYS_IC, ISD, __SYS_IC_FIELDNUM(0),
+ prio2irq_init(4 * i));
+ REGSETIM_IDX(ic, SYS_IC, ISD, __SYS_IC_FIELDNUM(1),
+ prio2irq_init(4 * i + 1));
+ REGSETIM_IDX(ic, SYS_IC, ISD, __SYS_IC_FIELDNUM(2),
+ prio2irq_init(4 * i + 2));
+ REGSETIM_IDX(ic, SYS_IC, ISD, __SYS_IC_FIELDNUM(3),
+ prio2irq_init(4 * i + 3));
+
+ __raw_writel(ic, SYS_IC(i));
+ }
for (i = 0; i < 32; ++i)
__raw_writel(prio2irq(i), SYS_IVA(i));
for (i = 0; i <= 31; ++i) {
set_irq_chip(i, &ns9xxx_chip);
- set_irq_handler(i, handle_irq);
+ set_irq_handler(i, handle_prio_irq);
set_irq_flags(i, IRQF_VALID);
}
+
+#ifdef CONFIG_PROCESSOR_NS9360
+ if (processor_is_ns9360()) {
+ /* set up the BBUS interrupt handlers */
+ __raw_writel(NS9360_BBUS_IEN_GLBL, NS9360_BBUS_IEN);
+ for (i = IRQ_NS9360_BBUS(0); i <= IRQ_NS9360_BBUS(25); i++) {
+ set_irq_chip(i, &ns9360_bbus_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+ set_irq_chained_handler(IRQ_NS9360_BBUSAGG,
+ ns9360_demux_bbus_irq);
+
+ /* set up the BBUS DMA interrupt handlers */
+ __raw_writel(0, NS9360_BBUS_DMA_IEN);
+ for (i = IRQ_NS9360_BBUDMA(0); i <= IRQ_NS9360_BBUDMA(15); i++) {
+ set_irq_chip(i, &ns9360_bbus_dma_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+ set_irq_chained_handler(IRQ_NS9360_BBUS_DMA,
+ ns9360_demux_bbus_dma_irq);
+ }
+#endif
}
diff --git a/arch/arm/mach-ns9xxx/irq.h b/arch/arm/mach-ns9xxx/irq.h
new file mode 100644
index 000000000000..81f4487a8cd2
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/irq.h
@@ -0,0 +1,16 @@
+/*
+ * arch/arm/mach-ns9xxx/irq.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/time.h>
+#include <asm/mach/time.h>
+#include <linux/init.h>
+
+void __init ns9xxx_init_irq(void);
diff --git a/arch/arm/mach-ns9xxx/leds.c b/arch/arm/mach-ns9xxx/leds.c
new file mode 100644
index 000000000000..99414dce0437
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/leds.c
@@ -0,0 +1,64 @@
+/*
+ * arch/arm/mach-ns9xxx/leds.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/kernel.h>
+#include <linux/gpio.h>
+
+#include <asm/leds.h>
+
+#include <mach/module.h>
+
+static void cc9p9215_leds_event(led_event_t evt)
+{
+ switch(evt) {
+ case led_idle_start:
+ gpio_set_value(89, 1);
+ break;
+ case led_idle_end:
+ gpio_set_value(89, 0);
+ break;
+ case led_green_on:
+ if (module_is_ccw9p9215())
+ gpio_set_value(88, 0);
+ break;
+ case led_green_off:
+ if (module_is_ccw9p9215())
+ gpio_set_value(88, 1);
+ break;
+ default:
+ break;
+ }
+}
+
+static int __init ns9xxx_init_leds(void)
+{
+ int ret;
+
+ if (!module_is_cc9p9215() && !module_is_ccw9p9215())
+ return -ENODEV;
+
+ ret = gpio_request(89, "idle led");
+ if (ret)
+ return ret;
+
+ if (module_is_ccw9p9215()) {
+ ret = gpio_request(88, "wifi led");
+ if (ret)
+ return ret;
+ /* switch the led, just in case it were on */
+ gpio_set_value(88, 1);
+ }
+
+ leds_event = cc9p9215_leds_event;
+
+ return 0;
+}
+device_initcall(ns9xxx_init_leds);
diff --git a/arch/arm/mach-ns9xxx/mach-cc7ucamry.c b/arch/arm/mach-ns9xxx/mach-cc7ucamry.c
new file mode 100644
index 000000000000..741cc8974d7b
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-cc7ucamry.c
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cc7ucamry.c
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "irq.h"
+#include "processor-ns921x.h"
+
+MACHINE_START(CC7UCAMRY, "ConnectCore 7U Camry")
+ .map_io = ns921x_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = ns921x_init_machine,
+ .timer = &ns921x_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/mach-cc9c.c b/arch/arm/mach-ns9xxx/mach-cc9c.c
new file mode 100644
index 000000000000..08561d0441b6
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-cc9c.c
@@ -0,0 +1,176 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cc9c.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "irq.h"
+#include "processor-ns9360.h"
+#include "ns9360_devices.h"
+#include "ccx9c_devices.h"
+
+/* I2C devices */
+#if defined(CONFIG_GPIO_PCA953X) || defined(CONFIG_GPIO_PCA953X_MODULE)
+static struct pca953x_platform_data pca9554_data = {
+ .gpio_base = 108,
+};
+#endif
+
+static struct i2c_board_info i2c_devices[] __initdata = {
+#if defined(CONFIG_GPIO_PCA953X) || defined(CONFIG_GPIO_PCA953X_MODULE)
+ {
+ I2C_BOARD_INFO("pca9554", 0x20),
+ .platform_data = &pca9554_data,
+ },
+#endif
+};
+
+#ifdef CONFIG_CCX9C_TOUCH
+static int touch_pendown_state(void)
+{
+ return gpio_get_value(18) ? 0 : 1;
+}
+
+static struct ads7846_platform_data ccx9c_touch_data = {
+ .model = 7843,
+ .get_pendown_state = touch_pendown_state,
+ .x_min = 100,
+ .y_min = 100,
+ .x_max = 4000,
+ .y_max = 4000,
+ .rotate = 180,
+ .buflen = 20,
+ .skip_samples = 0,
+};
+
+void __init ccx9c_add_device_touch(void)
+{
+ if (gpio_request(18, "ads7846"))
+ return;
+
+ gpio_configure_ns9360(18, 0, 0, 2);
+}
+
+#define CCX9C_SPI_TOUCH \
+ { \
+ .modalias = "ads7846", \
+ .max_speed_hz = 200000, \
+ .irq = IRQ_NS9XXX_EXT3, \
+ .bus_num = 0, \
+ .chip_select = 0, \
+ .platform_data = &ccx9c_touch_data, \
+ },
+
+#else
+#define CCX9C_SPI_TOUCH
+void __init ccx9c_add_device_touch(void) {}
+#endif
+
+static struct spi_board_info spi_devices[] __initdata = {
+ CCX9C_SPI_TOUCH
+ /* Add here other SPI devices, if any... */
+};
+
+static void __init mach_cc9cjs_init_machine(void)
+{
+ /* register several system clocks */
+ ns9360_init_machine();
+
+ /* UARTs */
+#if defined(CONFIG_CCX9C_SERIAL_PORTA_RXTX)
+ ns9xxx_add_device_ccx9c_uarta_rxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTA_CTSRTSRXTX)
+ ns9xxx_add_device_ccx9c_uarta_ctsrtsrxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTA_FULL)
+ ns9xxx_add_device_ccx9c_uarta_full();
+#endif
+#if defined(CONFIG_CCX9C_SERIAL_PORTB_RXTX)
+ ns9xxx_add_device_ccx9c_uartb_rxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTB_CTSRTSRXTX)
+ ns9xxx_add_device_ccx9c_uartb_ctsrtsrxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTB_FULL)
+ ns9xxx_add_device_ccx9c_uartb_full();
+#endif
+#if defined(CONFIG_CCX9C_SERIAL_PORTC_RXTX)
+ ns9xxx_add_device_ccx9c_uartc_rxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTC_CTSRTSRXTX)
+ ns9xxx_add_device_ccx9c_uartc_ctsrtsrxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTC_FULL)
+ ns9xxx_add_device_ccx9c_uartc_full();
+#endif
+#if defined(CONFIG_CCX9C_SERIAL_PORTD_RXTX)
+ ns9xxx_add_device_ccx9c_uartd_rxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTD_CTSRTSRXTX)
+ ns9xxx_add_device_ccx9c_uartd_ctsrtsrxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTD_FULL)
+ ns9xxx_add_device_ccx9c_uartd_full();
+#endif
+
+ /* SPI */
+#if defined(CONFIG_CCX9C_SPI_PORTA)
+ ns9xxx_add_device_ccx9c_spi_porta();
+#endif
+#if defined(CONFIG_CCX9C_SPI_PORTB)
+ ns9xxx_add_device_ccx9c_spi_portb();
+#endif
+#if defined(CONFIG_CCX9C_SPI_PORTC)
+ ns9xxx_add_device_ccx9c_spi_portc();
+#endif
+#if defined(CONFIG_CCX9C_SPI_PORTD)
+ ns9xxx_add_device_ccx9c_spi_portd();
+#endif
+
+ /* Ethernet */
+ ns9xxx_add_device_ccx9c_eth();
+
+ /* NAND flash */
+ ns9xxx_add_device_ccx9c_nand();
+
+ /* Watchdog timer */
+ ns9xxx_add_device_ns9360_wdt();
+
+ /* USB host */
+ ns9xxx_add_device_ns9360_usbh();
+
+ /* I2C controller */
+ ns9xxx_add_device_ccx9c_i2c();
+
+ /* I2C devices */
+ i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
+
+ /* Framebuffer */
+#if defined(CONFIG_CCX9C_FB)
+ ns9xxx_add_device_ccx9c_fb(23);
+#endif
+
+ /* Touchscreen */
+ ccx9c_add_device_touch();
+
+ /* SPI devices */
+ spi_register_board_info(spi_devices, ARRAY_SIZE(spi_devices));
+
+ /* RTC */
+ ns9xxx_add_device_ns9360_rtc();
+}
+
+MACHINE_START(CC9C, "ConnectCore 9C")
+ .map_io = ns9360_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = mach_cc9cjs_init_machine,
+ .timer = &ns9360_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9215.c b/arch/arm/mach-ns9xxx/mach-cc9p9215.c
new file mode 100644
index 000000000000..6e223e70078c
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-cc9p9215.c
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cc9p9215.c
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "irq.h"
+#include "processor-ns921x.h"
+
+MACHINE_START(CC9P9215, "ConnectCore 9P 9215")
+ .map_io = ns921x_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = ns921x_init_machine,
+ .timer = &ns921x_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9215js.c b/arch/arm/mach-ns9xxx/mach-cc9p9215js.c
new file mode 100644
index 000000000000..96f8220f0eec
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-cc9p9215js.c
@@ -0,0 +1,192 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cc9p9215.c
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "irq.h"
+#include "processor-ns921x.h"
+#include "ns921x_devices.h"
+#include "ns9215_devices.h"
+#include "cc9p9215_devices.h"
+
+/* I2C devices */
+#if defined(CONFIG_GPIO_PCA953X) || defined(CONFIG_GPIO_PCA953X_MODULE)
+static struct pca953x_platform_data pca9554_data = {
+ .gpio_base = 108,
+};
+#endif
+
+static struct i2c_board_info i2c_devices[] __initdata = {
+#if defined(CONFIG_GPIO_PCA953X) || defined(CONFIG_GPIO_PCA953X_MODULE)
+ {
+ I2C_BOARD_INFO("pca9554", 0x20),
+ .platform_data = &pca9554_data,
+ },
+#endif
+};
+
+#ifdef CONFIG_CC9P9215JS_TOUCH
+static int touch_pendown_state(void)
+{
+ return gpio_get_value(101) ? 0 : 1;
+}
+
+static struct ads7846_platform_data cc9p9215js_touch_data = {
+ .model = 7843,
+ .get_pendown_state = touch_pendown_state,
+ .x_min = 100,
+ .y_min = 100,
+ .x_max = 4000,
+ .y_max = 4000,
+ .rotate = 180,
+ .buflen = 20,
+ .skip_samples = 0,
+};
+
+void __init cc9p9215js_add_device_touch(void)
+{
+ if (gpio_request(101, "ads7846"))
+ return;
+ gpio_configure_ns921x(101, 0, 0, 2, 0);
+}
+
+#define CC9P9215JS_TOUCH \
+ { \
+ .modalias = "ads7846", \
+ .max_speed_hz = 300000, \
+ .irq = IRQ_NS9XXX_EXT3, \
+ .bus_num = 1, \
+ .chip_select = 0, \
+ .platform_data = &cc9p9215js_touch_data, \
+ },
+
+#else
+#define CC9P9215JS_TOUCH
+void __init cc9p9215js_add_device_touch(void) {}
+#endif
+
+/* SPI devices */
+static struct spi_board_info spi_devices[] __initdata = {
+ CC9P9215JS_TOUCH
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 10000000,
+ .bus_num = 1,
+ .chip_select = 0,
+ },
+#endif
+};
+
+static void __init mach_cc9p9215js_init_machine(void)
+{
+ /* register several system clocks */
+ ns921x_init_machine();
+
+ /* UARTs */
+#if defined(CONFIG_CC9P9215JS_SERIAL_PORTA_RXTX)
+ ns9xxx_add_device_cc9p9215_uarta_rxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTA_CTSRTSRXTX) || \
+ defined(CONFIG_CC9P9215JS_SERIAL_PORTA_RXTX485)
+ ns9xxx_add_device_cc9p9215_uarta_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTA_FULL)
+ ns9xxx_add_device_cc9p9215_uarta_full();
+#endif
+#if defined(CONFIG_CC9P9215JS_SERIAL_PORTB_RXTX)
+ ns9xxx_add_device_cc9p9215_uartb_rxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTB_CTSRTSRXTX) || \
+ defined(CONFIG_CC9P9215JS_SERIAL_PORTB_RXTX485)
+ ns9xxx_add_device_cc9p9215_uartb_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTB_FULL)
+ ns9xxx_add_device_cc9p9215_uartb_full();
+#endif
+#if defined(CONFIG_CC9P9215JS_SERIAL_PORTC_RXTX)
+ ns9xxx_add_device_cc9p9215_uartc_rxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTC_CTSRTSRXTX) || \
+ defined(CONFIG_CC9P9215JS_SERIAL_PORTC_RXTX485)
+ ns9xxx_add_device_cc9p9215_uartc_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTC_FULL)
+ ns9xxx_add_device_cc9p9215_uartc_full();
+#endif
+#if defined(CONFIG_CC9P9215JS_SERIAL_PORTD_RXTX)
+ ns9xxx_add_device_cc9p9215_uartd_rxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTD_CTSRTSRXTX) || \
+ defined(CONFIG_CC9P9215JS_SERIAL_PORTD_RXTX485)
+ ns9xxx_add_device_cc9p9215_uartd_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTD_FULL)
+ ns9xxx_add_device_cc9p9215_uartd_full();
+#endif
+
+ /* Ethernet */
+ ns9xxx_add_device_cc9p9215_eth();
+
+ /* SPI */
+#ifdef CONFIG_CC9P9215JS_SPI
+ ns9xxx_add_device_cc9p9215_spi();
+#endif
+
+ /* SPI devices */
+ spi_register_board_info(spi_devices, ARRAY_SIZE(spi_devices));
+
+ /* Watchdog timer */
+ ns9xxx_add_device_ns921x_wdt();
+
+ /* NOR Flash */
+ ns9xxx_add_device_cc9p9215_flash();
+
+ /* I2C controller */
+ ns9xxx_add_device_cc9p9215_i2c();
+
+ /* I2C devices */
+ i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
+
+ /* Leds */
+ ns9xxx_add_device_ns9215_leds();
+
+ /* Analog Digital Converter */
+ ns9xxx_add_device_ns9215_adc();
+
+ /* AES HW Encryption module */
+#if defined(CONFIG_CRYPTO_DEV_NS921X_AES) || \
+ defined(CONFIG_CRYPTO_DEV_NS921X_AES_MODULE)
+ ns9xxx_add_device_ns921x_aes();
+#endif
+
+ /* Real Time Clock */
+ ns9xxx_add_device_ns9215_rtc();
+
+ /* GPIO 4 is used as wake up gpio */
+ (void)ns921x_extgpio_pm_wakeup_init(4);
+
+ /* Init the FIM devices */
+ ns9xxx_add_device_ns921x_fims();
+
+ /* Video */
+ ns9xxx_add_device_cc9p9215_edt_diplay();
+
+ /* Touchscreen */
+ cc9p9215js_add_device_touch();
+}
+
+MACHINE_START(CC9P9215JS, "ConnectCore 9P 9215 on a JSCC9P9215 Devboard")
+ .map_io = ns921x_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = mach_cc9p9215js_init_machine,
+ .timer = &ns921x_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360js.c b/arch/arm/mach-ns9xxx/mach-cc9p9360js.c
index 729f68da4293..cebf99f49a84 100644
--- a/arch/arm/mach-ns9xxx/mach-cc9p9360js.c
+++ b/arch/arm/mach-ns9xxx/mach-cc9p9360js.c
@@ -1,28 +1,201 @@
/*
* arch/arm/mach-ns9xxx/mach-cc9p9360js.c
*
- * Copyright (C) 2006,2007 by Digi International Inc.
+ * Copyright (C) 2008 by Digi International Inc.
* All rights reserved.
*
* 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/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
+#include <mach/irqs.h>
+
+#include "irq.h"
+#include "processor-ns9360.h"
+#include "ns9360_devices.h"
+#include "cc9p9360_devices.h"
+
+/* I2C devices */
+#if defined(CONFIG_GPIO_PCA953X) || defined(CONFIG_GPIO_PCA953X_MODULE)
+static struct pca953x_platform_data pca9554_data = {
+ .gpio_base = 108,
+};
+#endif
+
+static struct i2c_board_info i2c_devices[] __initdata = {
+#if defined(CONFIG_GPIO_PCA953X) || defined(CONFIG_GPIO_PCA953X_MODULE)
+ {
+ I2C_BOARD_INFO("pca9554", 0x20),
+ .platform_data = &pca9554_data,
+ },
+#endif
+#if defined(CONFIG_RTC_DRV_DS1307) || defined(CONFIG_RTC_DRV_DS1307_MODULE)
+ {
+ I2C_BOARD_INFO("ds1337", 0x68),
+#if defined(CONFIG_EXTERNAL_RTC_ALARM)
+ .irq = IRQ_NS9XXX_EXT0,
+#endif
+ },
+#endif
+};
+
+#ifdef CONFIG_CC9P9360JS_TOUCH
+static int touch_pendown_state(void)
+{
+ return gpio_get_value(69) ? 0 : 1;
+}
+
+static struct ads7846_platform_data cc9p9360js_touch_data = {
+ .model = 7843,
+ .get_pendown_state = touch_pendown_state,
+ .x_min = 100,
+ .y_min = 100,
+ .x_max = 4000,
+ .y_max = 4000,
+ .rotate = 180,
+ .buflen = 20,
+ .skip_samples = 0,
+};
+
+void __init cc9p9360js_add_device_touch(void)
+{
+ if (gpio_request(69, "ads7846"))
+ return;
+
+ gpio_configure_ns9360(69, 0, 0, 2);
+}
+
+#define CC9P9360JS_TOUCH \
+ { \
+ .modalias = "ads7846", \
+ .max_speed_hz = 200000, \
+ .irq = IRQ_NS9XXX_EXT1, \
+ .bus_num = 0, \
+ .chip_select = 0, \
+ .platform_data = &cc9p9360js_touch_data, \
+ },
+
+#else
+#define CC9P9360JS_TOUCH
+void __init cc9p9360js_add_device_touch(void) {}
+#endif
-#include <mach/processor-ns9360.h>
+static struct spi_board_info spi_devices[] __initdata = {
+ CC9P9360JS_TOUCH
+ /* Add here other SPI devices, if any... */
+};
-#include "board-jscc9p9360.h"
-#include "generic.h"
+#if defined(CONFIG_EXTERNAL_RTC_ALARM)
+void __init cc9p9360js_external_rtc_alarm(void)
+{
+ /* Request and configure GPIO */
+ if (gpio_request(13, "ds1337"))
+ return;
+ gpio_configure_ns9360(13, 0, 0, 1);
+ /* Configure interrupt */
+ set_irq_type( IRQ_NS9XXX_EXT0, IRQF_TRIGGER_FALLING );
+}
+#endif
static void __init mach_cc9p9360js_init_machine(void)
{
- ns9xxx_init_machine();
- board_jscc9p9360_init_machine();
+ /* register several system clocks */
+ ns9360_init_machine();
+
+ /* UARTs */
+#if defined(CONFIG_CC9P9360JS_SERIAL_PORTA_RXTX)
+ ns9xxx_add_device_cc9p9360_uarta_rxtx();
+#elif defined(CONFIG_CC9P9360JS_SERIAL_PORTA_CTSRTSRXTX)
+ ns9xxx_add_device_cc9p9360_uarta_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9360JS_SERIAL_PORTA_FULL)
+ ns9xxx_add_device_cc9p9360_uarta_full();
+#endif
+#if defined(CONFIG_CC9P9360JS_SERIAL_PORTB_RXTX)
+ ns9xxx_add_device_cc9p9360_uartb_rxtx();
+#elif defined(CONFIG_CC9P9360JS_SERIAL_PORTB_CTSRTSRXTX)
+ ns9xxx_add_device_cc9p9360_uartb_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9360JS_SERIAL_PORTB_FULL)
+ ns9xxx_add_device_cc9p9360_uartb_full();
+#endif
+#if defined(CONFIG_CC9P9360JS_SERIAL_PORTC_RXTX)
+ ns9xxx_add_device_cc9p9360_uartc_rxtx();
+#elif defined(CONFIG_CC9P9360JS_SERIAL_PORTC_CTSRTSRXTX)
+ ns9xxx_add_device_cc9p9360_uartc_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9360JS_SERIAL_PORTC_FULL)
+ ns9xxx_add_device_cc9p9360_uartc_full();
+#endif
+#if defined(CONFIG_CC9P9360JS_SERIAL_PORTD_RXTX)
+ ns9xxx_add_device_cc9p9360_uartd_rxtx();
+#elif defined(CONFIG_CC9P9360JS_SERIAL_PORTD_CTSRTSRXTX)
+ ns9xxx_add_device_cc9p9360_uartd_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9360JS_SERIAL_PORTD_FULL)
+ ns9xxx_add_device_cc9p9360_uartd_full();
+#endif
+
+ /* SPI */
+#if defined(CONFIG_CC9P9360JS_SPI_PORTA)
+ ns9xxx_add_device_cc9p9360_spi_porta();
+#endif
+#if defined(CONFIG_CC9P9360JS_SPI_PORTB)
+ ns9xxx_add_device_cc9p9360_spi_portb();
+#endif
+#if defined(CONFIG_CC9P9360JS_SPI_PORTC)
+ ns9xxx_add_device_cc9p9360_spi_portc();
+#endif
+#if defined(CONFIG_CC9P9360JS_SPI_PORTD)
+ ns9xxx_add_device_cc9p9360_spi_portd();
+#endif
+
+ /* Ethernet */
+ ns9xxx_add_device_cc9p9360_eth();
+
+ /* NAND flash */
+ ns9xxx_add_device_cc9p9360_nand();
+
+ /* Watchdog timer */
+ ns9xxx_add_device_ns9360_wdt();
+
+ /* USB host */
+ ns9xxx_add_device_ns9360_usbh();
+
+ /* I2C controller */
+ ns9xxx_add_device_cc9p9360_i2c();
+
+ /* I2C devices */
+ i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
+
+ /* Framebuffer */
+#if defined(CONFIG_CC9P9360JS_FB)
+ ns9xxx_add_device_cc9p9360_fb(18);
+#endif
+
+ /* Touchscreen */
+ cc9p9360js_add_device_touch();
+
+ /* SPI devices */
+ spi_register_board_info(spi_devices, ARRAY_SIZE(spi_devices));
+
+ /* RTC (internal) */
+ ns9xxx_add_device_ns9360_rtc();
+
+ /* RTC (external) */
+#if defined(CONFIG_EXTERNAL_RTC_ALARM)
+ cc9p9360js_external_rtc_alarm();
+#endif
}
-MACHINE_START(CC9P9360JS, "Digi ConnectCore 9P 9360 on an JSCC9P9360 Devboard")
+MACHINE_START(CC9P9360JS, "ConnectCore 9P 9360 on a JSCC9P9360 Devboard")
.map_io = ns9360_map_io,
.init_irq = ns9xxx_init_irq,
.init_machine = mach_cc9p9360js_init_machine,
diff --git a/arch/arm/mach-ns9xxx/mach-ccw9c.c b/arch/arm/mach-ns9xxx/mach-ccw9c.c
new file mode 100644
index 000000000000..3bb098c92b1e
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-ccw9c.c
@@ -0,0 +1,176 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-ccw9c.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/gpio.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "irq.h"
+#include "processor-ns9360.h"
+#include "ns9360_devices.h"
+#include "ccx9c_devices.h"
+
+/* I2C devices */
+#if defined(CONFIG_GPIO_PCA953X) || defined(CONFIG_GPIO_PCA953X_MODULE)
+static struct pca953x_platform_data pca9554_data = {
+ .gpio_base = 108,
+};
+#endif
+
+static struct i2c_board_info i2c_devices[] __initdata = {
+#if defined(CONFIG_GPIO_PCA953X) || defined(CONFIG_GPIO_PCA953X_MODULE)
+ {
+ I2C_BOARD_INFO("pca9554", 0x20),
+ .platform_data = &pca9554_data,
+ },
+#endif
+};
+
+#ifdef CONFIG_CCX9C_TOUCH
+static int touch_pendown_state(void)
+{
+ return gpio_get_value(18) ? 0 : 1;
+}
+
+static struct ads7846_platform_data ccx9c_touch_data = {
+ .model = 7843,
+ .get_pendown_state = touch_pendown_state,
+ .x_min = 100,
+ .y_min = 100,
+ .x_max = 4000,
+ .y_max = 4000,
+ .rotate = 180,
+ .buflen = 20,
+ .skip_samples = 0,
+};
+
+void __init ccx9c_add_device_touch(void)
+{
+ if (gpio_request(18, "ads7846"))
+ return;
+
+ gpio_configure_ns9360(18, 0, 0, 2);
+}
+
+#define CCX9C_SPI_TOUCH \
+ { \
+ .modalias = "ads7846", \
+ .max_speed_hz = 200000, \
+ .irq = IRQ_NS9XXX_EXT3, \
+ .bus_num = 0, \
+ .chip_select = 0, \
+ .platform_data = &ccx9c_touch_data, \
+ },
+
+#else
+#define CCX9C_SPI_TOUCH
+void __init ccx9c_add_device_touch(void) {}
+#endif
+
+static struct spi_board_info spi_devices[] __initdata = {
+ CCX9C_SPI_TOUCH
+ /* Add here other SPI devices, if any... */
+};
+
+static void __init mach_ccw9cjs_init_machine(void)
+{
+ /* register several system clocks */
+ ns9360_init_machine();
+
+ /* UARTs */
+#if defined(CONFIG_CCX9C_SERIAL_PORTA_RXTX)
+ ns9xxx_add_device_ccx9c_uarta_rxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTA_CTSRTSRXTX)
+ ns9xxx_add_device_ccx9c_uarta_ctsrtsrxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTA_FULL)
+ ns9xxx_add_device_ccx9c_uarta_full();
+#endif
+#if defined(CONFIG_CCX9C_SERIAL_PORTB_RXTX)
+ ns9xxx_add_device_ccx9c_uartb_rxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTB_CTSRTSRXTX)
+ ns9xxx_add_device_ccx9c_uartb_ctsrtsrxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTB_FULL)
+ ns9xxx_add_device_ccx9c_uartb_full();
+#endif
+#if defined(CONFIG_CCX9C_SERIAL_PORTC_RXTX)
+ ns9xxx_add_device_ccx9c_uartc_rxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTC_CTSRTSRXTX)
+ ns9xxx_add_device_ccx9c_uartc_ctsrtsrxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTC_FULL)
+ ns9xxx_add_device_ccx9c_uartc_full();
+#endif
+#if defined(CONFIG_CCX9C_SERIAL_PORTD_RXTX)
+ ns9xxx_add_device_ccx9c_uartd_rxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTD_CTSRTSRXTX)
+ ns9xxx_add_device_ccx9c_uartd_ctsrtsrxtx();
+#elif defined(CONFIG_CCX9C_SERIAL_PORTD_FULL)
+ ns9xxx_add_device_ccx9c_uartd_full();
+#endif
+
+ /* SPI */
+#if defined(CONFIG_CCX9C_SPI_PORTA)
+ ns9xxx_add_device_ccx9c_spi_porta();
+#endif
+#if defined(CONFIG_CCX9C_SPI_PORTB)
+ ns9xxx_add_device_ccx9c_spi_portb();
+#endif
+#if defined(CONFIG_CCX9C_SPI_PORTC)
+ ns9xxx_add_device_ccx9c_spi_portc();
+#endif
+#if defined(CONFIG_CCX9C_SPI_PORTD)
+ ns9xxx_add_device_ccx9c_spi_portd();
+#endif
+
+ /* Ethernet */
+ ns9xxx_add_device_ccx9c_eth();
+
+ /* NAND flash */
+ ns9xxx_add_device_ccx9c_nand();
+
+ /* Watchdog timer */
+ ns9xxx_add_device_ns9360_wdt();
+
+ /* USB host */
+ ns9xxx_add_device_ns9360_usbh();
+
+ /* I2C controller */
+ ns9xxx_add_device_ccx9c_i2c();
+
+ /* I2C devices */
+ i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
+
+ /* Framebuffer */
+#if defined(CONFIG_CCX9C_FB)
+ ns9xxx_add_device_ccx9c_fb(23);
+#endif
+
+ /* Touchscreen */
+ ccx9c_add_device_touch();
+
+ /* SPI devices */
+ spi_register_board_info(spi_devices, ARRAY_SIZE(spi_devices));
+
+ /* RTC */
+ ns9xxx_add_device_ns9360_rtc();
+}
+
+MACHINE_START(CCW9C, "ConnectCore Wi-9C")
+ .map_io = ns9360_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = mach_ccw9cjs_init_machine,
+ .timer = &ns9360_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/mach-ccw9p9215.c b/arch/arm/mach-ns9xxx/mach-ccw9p9215.c
new file mode 100644
index 000000000000..db86575a120e
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-ccw9p9215.c
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cc9p9215.c
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "irq.h"
+#include "processor-ns921x.h"
+
+MACHINE_START(CCW9P9215, "ConnectCore Wi-9P 9215")
+ .map_io = ns921x_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = ns921x_init_machine,
+ .timer = &ns921x_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/mach-ccw9p9215js.c b/arch/arm/mach-ns9xxx/mach-ccw9p9215js.c
new file mode 100644
index 000000000000..4a5ddcb33dd8
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-ccw9p9215js.c
@@ -0,0 +1,242 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cc9p9215.c
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/i2c.h>
+#include <linux/i2c/pca953x.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
+#include <linux/gpio.h>
+#include <linux/crc32.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+#include <asm/leds.h>
+
+#include "irq.h"
+#include "pipermain.h"
+#include "processor-ns921x.h"
+#include "ns921x_devices.h"
+#include "ns9215_devices.h"
+#include "cc9p9215_devices.h"
+#include "ccw9p9215_devices.h"
+
+
+/* I2C devices */
+#if defined(CONFIG_GPIO_PCA953X) || defined(CONFIG_GPIO_PCA953X_MODULE)
+static struct pca953x_platform_data pca9554_data = {
+ .gpio_base = 108,
+};
+#endif
+
+static struct i2c_board_info i2c_devices[] __initdata = {
+#if defined(CONFIG_GPIO_PCA953X) || defined(CONFIG_GPIO_PCA953X_MODULE)
+ {
+ I2C_BOARD_INFO("pca9554", 0x20),
+ .platform_data = &pca9554_data,
+ },
+#endif
+};
+
+#ifdef CONFIG_CC9P9215JS_TOUCH
+static int touch_pendown_state(void)
+{
+ return gpio_get_value(101) ? 0 : 1;
+}
+
+static struct ads7846_platform_data cc9p9215js_touch_data = {
+ .model = 7843,
+ .get_pendown_state = touch_pendown_state,
+ .x_min = 100,
+ .y_min = 100,
+ .x_max = 4000,
+ .y_max = 4000,
+ .rotate = 180,
+ .buflen = 20,
+ .skip_samples = 0,
+};
+
+void __init cc9p9215js_add_device_touch(void)
+{
+ if (gpio_request(101, "ads7846"))
+ return;
+ gpio_configure_ns921x(101, 0, 0, 2, 0);
+}
+
+#define CC9P9215JS_TOUCH \
+ { \
+ .modalias = "ads7846", \
+ .max_speed_hz = 300000, \
+ .irq = IRQ_NS9XXX_EXT3, \
+ .bus_num = 1, \
+ .chip_select = 0, \
+ .platform_data = &cc9p9215js_touch_data, \
+ },
+
+#else
+#define CC9P9215JS_TOUCH
+void __init cc9p9215js_add_device_touch(void) {}
+#endif
+
+/* SPI devices */
+static struct spi_board_info spi_devices[] __initdata = {
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 10000000,
+ .bus_num = 1,
+ .chip_select = 0,
+ },
+#endif
+ CC9P9215JS_TOUCH
+};
+
+
+#if defined(CONFIG_DIGI_PIPER_WIFI)
+static struct piper_pdata ccw9p9215_piper_pdata = {
+ .rst_gpio = 92,
+ .irq_gpio = 104,
+ .i2c_adapter_num = 0,
+};
+
+static void __init ccw9p9215js_fixup(struct machine_desc *desc,
+ struct tag *tags, char **cmdline,
+ struct meminfo *mi)
+{
+ unsigned char *mac = phys_to_virt(desc->boot_params) + 0xf00;
+ wcd_data_t *pwcal;
+ u32 crc;
+
+ /* 8 bytes after the mac address, its located the calibration data */
+ pwcal = (wcd_data_t *)(mac + 8);
+ memcpy(&ccw9p9215_piper_pdata.macaddr[0], mac, 6);
+
+ if (!strncmp(pwcal->header.magic_string, WCD_MAGIC,
+ sizeof(pwcal->header.magic_string))) {
+ /* check version */
+ if (((pwcal->header.ver_major >= '1') && (pwcal->header.ver_major <= '9')) &&
+ ((pwcal->header.ver_minor >= '0') && (pwcal->header.ver_minor <= '9'))) {
+ crc = ~crc32_le(~0, (unsigned char const *)pwcal->cal_curves_bg,
+ pwcal->header.wcd_len);
+ if (crc == pwcal->header.wcd_crc) {
+ memcpy(&ccw9p9215_piper_pdata.wcd, pwcal, sizeof(wcd_data_t));
+ return;
+ }
+ }
+ }
+
+ memset(&ccw9p9215_piper_pdata.wcd, 0, sizeof(wcd_data_t));
+}
+#endif
+
+static void __init mach_ccw9p9215js_init_machine(void)
+{
+ /* register several system clocks */
+ ns921x_init_machine();
+
+ /* UARTs */
+#if defined(CONFIG_CC9P9215JS_SERIAL_PORTA_RXTX)
+ ns9xxx_add_device_cc9p9215_uarta_rxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTA_CTSRTSRXTX) || \
+ defined(CONFIG_CC9P9215JS_SERIAL_PORTA_RXTX485)
+ ns9xxx_add_device_cc9p9215_uarta_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTA_FULL)
+ ns9xxx_add_device_cc9p9215_uarta_full();
+#endif
+#if defined(CONFIG_CC9P9215JS_SERIAL_PORTB_RXTX)
+ ns9xxx_add_device_cc9p9215_uartb_rxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTB_CTSRTSRXTX) || \
+ defined(CONFIG_CC9P9215JS_SERIAL_PORTB_RXTX485)
+ ns9xxx_add_device_cc9p9215_uartb_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTB_FULL)
+ ns9xxx_add_device_cc9p9215_uartb_full();
+#endif
+#if defined(CONFIG_CC9P9215JS_SERIAL_PORTC_RXTX)
+ ns9xxx_add_device_cc9p9215_uartc_rxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTC_CTSRTSRXTX) || \
+ defined(CONFIG_CC9P9215JS_SERIAL_PORTC_RXTX485)
+ ns9xxx_add_device_cc9p9215_uartc_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTC_FULL)
+ ns9xxx_add_device_cc9p9215_uartc_full();
+#endif
+#if defined(CONFIG_CC9P9215JS_SERIAL_PORTD_RXTX)
+ ns9xxx_add_device_cc9p9215_uartd_rxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTD_CTSRTSRXTX) || \
+ defined(CONFIG_CC9P9215JS_SERIAL_PORTD_RXTX485)
+ ns9xxx_add_device_cc9p9215_uartd_ctsrtsrxtx();
+#elif defined(CONFIG_CC9P9215JS_SERIAL_PORTD_FULL)
+ ns9xxx_add_device_cc9p9215_uartd_full();
+#endif
+
+ /* Ethernet */
+ ns9xxx_add_device_cc9p9215_eth();
+
+ /* 802.11 */
+#if defined(CONFIG_DIGI_PIPER_WIFI)
+ ns9xxx_add_device_ccw9p9215_wifi(&ccw9p9215_piper_pdata);
+#endif
+
+ /* SPI */
+#ifdef CONFIG_CC9P9215JS_SPI
+ ns9xxx_add_device_cc9p9215_spi();
+#endif
+
+ /* SPI devices */
+ spi_register_board_info(spi_devices, ARRAY_SIZE(spi_devices));
+
+ /* Watchdog timer */
+ ns9xxx_add_device_ns921x_wdt();
+
+ /* NOR Flash */
+ ns9xxx_add_device_cc9p9215_flash();
+
+ /* I2C controller */
+ ns9xxx_add_device_cc9p9215_i2c();
+
+ /* I2C devices */
+ i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
+
+ /* Leds */
+ ns9xxx_add_device_ns9215_leds();
+
+ /* Analog Digital Converter */
+ ns9xxx_add_device_ns9215_adc();
+
+ /* AES HW Encryption module */
+#if defined(CONFIG_CRYPTO_DEV_NS921X_AES) || \
+ defined(CONFIG_CRYPTO_DEV_NS921X_AES_MODULE)
+ ns9xxx_add_device_ns921x_aes();
+#endif
+
+ /* Real Time Clock */
+ ns9xxx_add_device_ns9215_rtc();
+
+ /* GPIO 4 is used as wake up gpio */
+ (void)ns921x_extgpio_pm_wakeup_init(4);
+
+ /* Init the FIM devices */
+ ns9xxx_add_device_ns921x_fims();
+
+ /* Video */
+ ns9xxx_add_device_cc9p9215_edt_diplay();
+
+ /* Touchscreen */
+ cc9p9215js_add_device_touch();
+}
+MACHINE_START(CCW9P9215JS, "ConnectCore Wi-9P 9215 on a JSCCW9P9215 Devboard")
+ .map_io = ns921x_map_io,
+ .init_irq = ns9xxx_init_irq,
+#if defined(CONFIG_DIGI_PIPER_WIFI)
+ .fixup = ccw9p9215js_fixup,
+#endif
+ .init_machine = mach_ccw9p9215js_init_machine,
+ .timer = &ns921x_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/mach-cme9210.c b/arch/arm/mach-ns9xxx/mach-cme9210.c
new file mode 100644
index 000000000000..29f71ce0acf1
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-cme9210.c
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cme9210.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "irq.h"
+#include "processor-ns921x.h"
+
+MACHINE_START(CME9210JS, "Digi Connect ME 9210")
+ .map_io = ns921x_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = ns921x_init_machine,
+ .timer = &ns921x_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/mach-cme9210js.c b/arch/arm/mach-ns9xxx/mach-cme9210js.c
new file mode 100644
index 000000000000..23853f86a778
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-cme9210js.c
@@ -0,0 +1,109 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-cme9210js.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/spi/spi.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "irq.h"
+#include "processor-ns921x.h"
+#include "ns921x_devices.h"
+#include "cme9210_devices.h"
+
+/* SPI devices */
+static struct spi_board_info spi_devices[] __initdata = {
+#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
+ {
+ .modalias = "spidev",
+ .max_speed_hz = 10000000,
+ .bus_num = 1,
+ .chip_select = 0,
+ },
+#endif
+};
+
+/* I2C devices */
+/* Array to add I2C devices
+static struct i2c_board_info i2c_devices[] __initdata = {
+ {
+ I2C_BOARD_INFO("device_name", address),
+ },
+};
+*/
+
+static void __init mach_cme9210js_init_machine(void)
+{
+ /* register several system clocks */
+ ns921x_init_machine();
+
+ /* UART */
+#if defined(CONFIG_CME9210JS_SERIAL_PORTA_RXTX)
+ ns9xxx_add_device_cme9210_uarta_rxtx();
+#elif defined(CONFIG_CME9210JS_SERIAL_PORTA_CTSRTSRXTX) || \
+ defined(CONFIG_CME9210JS_SERIAL_PORTA_RXTX485)
+ ns9xxx_add_device_cme9210_uarta_ctsrtsrxtx();
+#elif defined(CONFIG_CME9210JS_SERIAL_PORTA_FULL)
+ ns9xxx_add_device_cme9210_uarta_full();
+#endif
+#if defined(CONFIG_CME9210JS_SERIAL_PORTC_RXTX)
+ ns9xxx_add_device_cme9210_uartc_rxtx();
+#endif
+
+ /* Ethernet */
+ /* Adjust the netdev_max_backlog to a lower value. A big queue
+ * of incoming packets in the kernel can exhaust the kernel memory
+ * and trigger the OOM killer. This value can be tuned later in
+ * user space throught proc fs and with sysctl */
+ netdev_max_backlog = 300;
+ ns9xxx_add_device_cme9210_eth();
+
+ /* Watchdog timer */
+ ns9xxx_add_device_ns921x_wdt();
+
+ /* NOR Flash */
+ ns9xxx_add_device_cme9210_flash();
+
+ /* SPI */
+#ifdef CONFIG_CME9210JS_SPI
+ ns9xxx_add_device_cme9210_spi();
+#endif
+
+ /* SPI devices */
+ spi_register_board_info(spi_devices, ARRAY_SIZE(spi_devices));
+
+ /* I2C controller */
+ ns9xxx_add_device_cme9210_i2c();
+
+ /* I2C devices */
+ /*
+ i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
+ */
+
+ /* Init the FIM devices */
+ ns9xxx_add_device_ns921x_fims();
+
+ /* AES HW Encryption module */
+#if defined(CONFIG_CRYPTO_DEV_NS921X_AES) || \
+ defined(CONFIG_CRYPTO_DEV_NS921X_AES_MODULE)
+ ns9xxx_add_device_ns921x_aes();
+#endif
+}
+
+MACHINE_START(CME9210JS, "Digi Connect ME 9210 on Devboard")
+ .map_io = ns921x_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = mach_cme9210js_init_machine,
+ .timer = &ns921x_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/mach-inc20otter.c b/arch/arm/mach-ns9xxx/mach-inc20otter.c
new file mode 100644
index 000000000000..477553fe4411
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-inc20otter.c
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-inc20otter.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "irq.h"
+#include "processor-ns921x.h"
+
+MACHINE_START(INC20OTTER, "Inc20-Otter")
+ .map_io = ns921x_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = ns921x_init_machine,
+ .timer = &ns921x_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/mach-otter.c b/arch/arm/mach-ns9xxx/mach-otter.c
new file mode 100644
index 000000000000..5ab5cf13e0d2
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/mach-otter.c
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/mach-ns9xxx/mach-otter.c
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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 <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "irq.h"
+#include "processor-ns921x.h"
+
+MACHINE_START(OTTER, "Otter")
+ .map_io = ns921x_map_io,
+ .init_irq = ns9xxx_init_irq,
+ .init_machine = ns921x_init_machine,
+ .timer = &ns921x_timer,
+ .boot_params = 0x100,
+MACHINE_END
diff --git a/arch/arm/mach-ns9xxx/ns9215_devices.c b/arch/arm/mach-ns9xxx/ns9215_devices.c
new file mode 100644
index 000000000000..0a6f473b68f1
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/ns9215_devices.c
@@ -0,0 +1,299 @@
+/*
+ * arch/arm/mach-ns9xxx/ns9215_devices.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#include <mach/ns9xxx-pwm.h>
+#include <linux/leds.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+#include <linux/pwm-led.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-sys-ns921x.h>
+
+#include "clock.h"
+#include "processor-ns921x.h"
+
+#if defined(CONFIG_ARCH_NS9XXX)
+static struct led_info ns9xxx_leds_pdata_info = {
+ .name = "leds-pwm",
+ .default_trigger = "ledtrig-dim",
+ .flags = 0,
+};
+
+static struct pwm_channel_config ns9xxx_leds_pdata_config = {
+ .duty_ns = 0,
+ .period_ns = 0,
+
+};
+
+static struct pwm_led_platform_data ns9xxx_leds_pdata = {
+ .bus_id = "ns9xxx_pwmc.0",
+ .chan = 0,
+ .led_info = &ns9xxx_leds_pdata_info,
+ .config = &ns9xxx_leds_pdata_config,
+};
+
+static struct platform_device ns9xxx_device_ns9215_leds = {
+ .name = "leds-pwm",
+ .id = 0,
+ .dev = {
+ .platform_data = &ns9xxx_leds_pdata,
+ }
+};
+
+static struct ns9xxx_pwm_channel ns9215_pwm_channels[] = {
+ [0] = {
+ .timer = 6,
+ .gpio = 5,
+ },
+ [1] = {
+ .timer = 7,
+ .gpio = 7,
+ },
+ [2] = {
+ .timer = 8,
+ .gpio = 8,
+ },
+ [3] = {
+ .timer = 9,
+ .gpio = 13,
+ }
+};
+
+
+/* This structure will be initialized in the init function (see below) */
+static struct ns9xxx_pwm_pdata ns9215_pwm_pdata;
+
+
+static struct platform_device ns9xxx_device_ns9215_pwm = {
+ .name = "ns9xxx_pwmc",
+ .id = 0,
+ .dev = {
+ .platform_data = &ns9215_pwm_pdata,
+ }
+};
+
+void __init ns9xxx_add_device_ns9215_leds(void)
+{
+ platform_device_register(&ns9xxx_device_ns9215_leds);
+
+#if 1 /* Enabled PWM by the user configuration */
+ ns9215_pwm_pdata.channels = ns9215_pwm_channels;
+ ns9215_pwm_pdata.number_channels = ARRAY_SIZE(ns9215_pwm_channels);
+ platform_device_register(&ns9xxx_device_ns9215_pwm);
+#endif
+
+}
+#else
+void __init ns9xxx_add_device_ns9215_leds(void) {}
+#endif
+
+#if defined(CONFIG_ADC_NS9215) || defined(CONFIG_ADC_NS9215_MODULE)
+static struct ns921x_sysclk adc_clk = {
+ .clk = {
+ .name = "adc-ns9215",
+ .id = -1,
+ .owner = THIS_MODULE,
+ },
+ .mask = SYS_CLOCK_ADC,
+};
+
+static struct resource adc_resources[] = {
+ {
+ .start = 0x90039000,
+ .end = 0x90039027,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ns9xxx_device_ns9215_adc = {
+ .name = "adc-ns9215",
+ .id = -1,
+ .resource = adc_resources,
+ .num_resources = ARRAY_SIZE(adc_resources),
+};
+
+void __init ns9xxx_add_device_ns9215_adc(void)
+{
+ if (clk_register(&adc_clk.clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns9215_adc);
+}
+#else
+void __init ns9xxx_add_device_ns9215_adc(void) {}
+#endif
+
+#if defined(CONFIG_RTC_DRV_NS9XXX) || defined(CONFIG_RTC_DRV_NS9XXX_MODULE)
+static irqreturn_t ns9xxx_plat_rtc_irq(int irq, void *data)
+{
+ u32 sysrtcmc = __raw_readl(SYS_RTCMC);
+
+ if (sysrtcmc & SYS_RTCMC_RIS) {
+ REGSETIM(sysrtcmc, SYS_RTCMC, RIC, 1);
+ __raw_writel(sysrtcmc, SYS_RTCMC);
+ REGSETIM(sysrtcmc, SYS_RTCMC, RIC, 0);
+ __raw_writel(sysrtcmc, SYS_RTCMC);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static inline int wait_for_clkrdy(void)
+{
+ u32 sysrtcmc;
+ unsigned int timeout = 0x20;
+
+wait:
+ sysrtcmc = __raw_readl(SYS_RTCMC);
+ if (!(sysrtcmc & SYS_RTCMC_RIS)) {
+ if (unlikely(!--timeout))
+ return -ETIMEDOUT;
+ udelay(1);
+ goto wait;
+ }
+ pr_debug("%s: SYS_RTCMC = 0x%x\n", __func__, sysrtcmc);
+
+ REGSETIM(sysrtcmc, SYS_RTCMC, RIC, 1);
+ __raw_writel(sysrtcmc, SYS_RTCMC);
+ REGSETIM(sysrtcmc, SYS_RTCMC, RIC, 0);
+ __raw_writel(sysrtcmc, SYS_RTCMC);
+
+ return sysrtcmc & SYS_RTCMC_SS ? 0 : -EIO;
+}
+
+static int ns9215_rtc_endisable(struct clk *clk, int enable)
+{
+ u32 sysrtcmc = __raw_readl(SYS_RTCMC);
+
+ pr_debug("%s: enable=%d, SYS_RTCMC=%08x\n", __func__, enable, sysrtcmc);
+
+ if (enable && (sysrtcmc & (SYS_RTCMC_SS | SYS_RTCMC_MODE)) ==
+ SYS_RTCMC_SS) {
+ /* the clock was disabled but is still active */
+
+ unsigned int timeout = 0x20;
+
+ pr_debug("%s: wait until disabled clock becomes inactive\n",
+ __func__);
+wait:
+ sysrtcmc = __raw_readl(SYS_RTCMC);
+ if (sysrtcmc & SYS_RTCMC_SS) {
+ if (unlikely(!--timeout))
+ return -ETIMEDOUT;
+ udelay(1);
+ goto wait;
+ }
+ }
+
+ if (enable && (sysrtcmc & SYS_RTCMC_SS)) {
+ pr_debug("%s: RTC clock already on\n", __func__);
+ return 0;
+ }
+
+ if (enable) {
+ int ret;
+
+ /* disable rtc irq because the irq is acked in wait_for_clkrdy
+ * and this might stuck the irq controller. (It doesn't like an
+ * irq to become active and then inactive before it is serviced.
+ *
+ * Not acking doesn't do the trick. Then the following might
+ * happen in an endless loop:
+ * - clk_enable + clk_disable with irqs off. This makes
+ * IRQ_NS9215_RTC pending.
+ * - reenable irqs
+ * - service IRQ_NS9215_RTC
+ * - platform handler runs and acks irq.
+ * - driver handler enables clk, sees that there is nothing to
+ * do, and disables clk again. All this with IRQ_NS9215_RTC
+ * being masked.
+ */
+ disable_irq(IRQ_NS9215_RTC);
+
+ __raw_writel(SYS_RTCMC_MODE_NORMAL, SYS_RTCMC);
+
+ ret = wait_for_clkrdy();
+
+ enable_irq(IRQ_NS9215_RTC);
+
+ return ret;
+ } else {
+ __raw_writel(SYS_RTCMC_MODE_STANDBY, SYS_RTCMC);
+ sysrtcmc = __raw_readl(SYS_RTCMC);
+ pr_debug("%s: disable done, SYS_RTCMC=%08x\n",
+ __func__, sysrtcmc);
+
+ return 0;
+ }
+}
+
+static struct ns921x_sysclk rtc_pm_clk = {
+ .clk = {
+ .name = "rtc-ns9xxx-pm",
+ .id = -1,
+ .owner = THIS_MODULE,
+ .endisable = ns921x_endisable_sysclock,
+ },
+ .mask = SYS_CLOCK_RTC,
+ };
+
+static struct clk rtc_clk = {
+ .name = "rtc-ns9xxx",
+ .id = 0,
+ .owner = THIS_MODULE,
+ .endisable = ns9215_rtc_endisable,
+};
+
+static struct resource rtc_resources[] = {
+ {
+ .start = 0x90060000,
+ .end = 0x900600ff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS9215_RTC,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device ns9xxx_device_ns9215_rtc = {
+ .name = "rtc-ns9xxx",
+ .id = 0,
+ .resource = rtc_resources,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+};
+
+void __init ns9xxx_add_device_ns9215_rtc(void)
+{
+ if (clk_register(&rtc_pm_clk.clk))
+ return;
+
+ rtc_clk.parent = &rtc_pm_clk.clk;
+ if (clk_register(&rtc_clk))
+ return;
+
+ if (request_irq(IRQ_NS9215_RTC, ns9xxx_plat_rtc_irq, IRQF_SHARED,
+ "plat-rtc-ns9xxx", ns9xxx_plat_rtc_irq))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns9215_rtc);
+}
+#else
+void __init ns9xxx_add_device_ns9215_rtc(void) {}
+#endif
diff --git a/arch/arm/mach-ns9xxx/ns9215_devices.h b/arch/arm/mach-ns9xxx/ns9215_devices.h
new file mode 100644
index 000000000000..065c270b9350
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/ns9215_devices.h
@@ -0,0 +1,14 @@
+/*
+ * arch/arm/mach-ns9xxx/ns9215_devices.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+void __init ns9xxx_add_device_ns9215_leds(void);
+void __init ns9xxx_add_device_ns9215_adc(void);
+void __init ns9xxx_add_device_ns9215_rtc(void);
diff --git a/arch/arm/mach-ns9xxx/ns921x_devices.c b/arch/arm/mach-ns9xxx/ns921x_devices.c
new file mode 100644
index 000000000000..1814cb95782d
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/ns921x_devices.c
@@ -0,0 +1,798 @@
+/*
+ * arch/arm/mach-ns9xxx/ns921x_devices.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/ns9xxx-eth.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/regs-sys-ns921x.h>
+#include <mach/ns921x-serial.h>
+#include <mach/fim-ns921x.h>
+#include <mach/gpio.h>
+
+#include "clock.h"
+#include "ns921x_devices.h"
+#include "processor-ns921x.h"
+
+/* Watchdog timer */
+#if defined(CONFIG_NS9XXX_WATCHDOG) || defined(CONFIG_NS9XXX_WATCHDOG_MODULE)
+static struct clk wdt_clk = {
+ .name = "ns9xxx-wdt",
+ .id = -1,
+ .owner = THIS_MODULE,
+};
+
+static struct resource wdt_resources[] = {
+ {
+ .start = 0xa0900174,
+ .end = 0xa0900177,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ns9xxx_device_ns921x_wdt = {
+ .name = "ns9xxx-wdt",
+ .id = -1,
+ .resource = wdt_resources,
+ .num_resources = ARRAY_SIZE(wdt_resources),
+};
+
+void __init ns9xxx_add_device_ns921x_wdt(void)
+{
+ wdt_clk.parent = clk_get(NULL, "cpuclock");
+ if (IS_ERR(wdt_clk.parent))
+ return;
+
+ if (clk_register(&wdt_clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns921x_wdt);
+}
+#else
+void __init ns9xxx_add_device_ns921x_wdt(void) {}
+#endif
+
+/* Ethernet */
+#if defined(CONFIG_NS9XXX_ETH) || defined(CONFIG_NS9XXX_ETH_MODULE)
+int __init eth_register_gpios(int gpio[], int func[], int dir[], int num)
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ if (gpio_request(gpio[i], "ns9xxx-eth"))
+ goto err;
+ gpio_configure_ns921x(gpio[i], dir[i], 0, func[i], 0);
+ }
+
+ return 0;
+err:
+ for (; i >= 0; i--)
+ gpio_free(gpio[i]);
+
+ return -EBUSY;
+}
+
+static struct ns921x_sysclk eth_clk = {
+ .clk = {
+ .name = "ns9xxx-eth",
+ .id = -1,
+ .owner = THIS_MODULE,
+ .endisable = ns921x_endisable_sysclock,
+ },
+ .mask = SYS_CLOCK_ETH,
+};
+
+static struct plat_ns9xxx_eth ns9xxx_device_ns921x_eth_data = {
+ .irqrx = IRQ_NS9XXX_ETHRX,
+ .irqtx = IRQ_NS9XXX_ETHTX,
+#ifdef CONFIG_GPIO_ETH_ACTIVITY_LED
+ .activityled = 14,
+#endif
+};
+
+static struct resource eth_resources[] = {
+ {
+ .start = 0xa0600000,
+ .end = 0xa06027ff,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device ns9xxx_device_ns921x_eth = {
+ .name = "ns9xxx-eth",
+ .id = -1,
+ .resource = eth_resources,
+ .num_resources = ARRAY_SIZE(eth_resources),
+ .dev = {
+ .platform_data = &ns9xxx_device_ns921x_eth_data,
+ },
+};
+
+void __init ns9xxx_add_device_ns921x_eth(struct clk *phyclk, u32 phy_mask,
+ int gpio[], int func[], int dir[], int num)
+{
+ if (eth_register_gpios(gpio, func, dir, num))
+ return;
+
+ eth_clk.clk.parent = phyclk;
+ ns9xxx_device_ns921x_eth_data.phy_mask = phy_mask;
+
+ if (clk_register(&eth_clk.clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns921x_eth);
+}
+#else
+void __init ns9xxx_add_device_ns921x_eth(struct clk *phyclk, u32 phy_mask,
+ int gpio[], int func[], int dir[], int num) {}
+#endif
+
+/* I2C controller */
+#if defined(CONFIG_I2C_NS9XXX) || defined(CONFIG_I2C_NS9XXX_MODULE)
+static struct ns921x_sysclk i2c_clk = {
+ .clk = {
+ .name = "i2c-ns9xxx",
+ .id = -1,
+ .owner = THIS_MODULE,
+ .endisable = ns921x_endisable_sysclock,
+ },
+ .mask = SYS_CLOCK_I2C,
+};
+
+static struct resource i2c_resources[] = {
+ {
+ .start = 0x90050000,
+ .end = 0x9005000f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS921X_I2C,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ns9xxx_device_ns921x_i2c = {
+ .name = "i2c-ns9xxx",
+ .id = -1,
+ .resource = i2c_resources,
+ .num_resources = ARRAY_SIZE(i2c_resources),
+};
+
+void __init ns9xxx_add_device_ns921x_i2c(struct plat_ns9xxx_i2c *i2c_data)
+{
+ i2c_clk.clk.parent = clk_get(NULL, "systemclock");
+ if (IS_ERR(i2c_clk.clk.parent))
+ return;
+
+ if (clk_register(&i2c_clk.clk))
+ return;
+
+ ns9xxx_device_ns921x_i2c.dev.platform_data = i2c_data;
+ platform_device_register(&ns9xxx_device_ns921x_i2c);
+}
+#else
+void __init ns9xxx_add_device_ns921x_i2c(struct plat_ns9xxx_i2c *i2c_data) {}
+#endif
+
+/* UARTs */
+#if defined(CONFIG_SERIAL_NS921X) || defined(CONFIG_SERIAL_NS921X_MODULE)
+static struct ns921x_sysclk uarta_clk = {
+ .clk = {
+ .name = "ns921x-serial",
+ .id = 0,
+ .owner = THIS_MODULE,
+ .rate = NS921X_REFCLOCK,
+ .endisable = ns921x_endisable_sysclock,
+ },
+ .mask = SYS_CLOCK_UARTA,
+};
+
+static struct ns921x_sysclk uartb_clk = {
+ .clk = {
+ .name = "ns921x-serial",
+ .id = 1,
+ .owner = THIS_MODULE,
+ .rate = NS921X_REFCLOCK,
+ .endisable = ns921x_endisable_sysclock,
+ },
+ .mask = SYS_CLOCK_UARTB,
+};
+
+static struct ns921x_sysclk uartc_clk = {
+ .clk = {
+ .name = "ns921x-serial",
+ .id = 2,
+ .owner = THIS_MODULE,
+ .rate = NS921X_REFCLOCK,
+ .endisable = ns921x_endisable_sysclock,
+ },
+ .mask = SYS_CLOCK_UARTC,
+};
+
+static struct ns921x_sysclk uartd_clk = {
+ .clk = {
+ .name = "ns921x-serial",
+ .id = 3,
+ .owner = THIS_MODULE,
+ .rate = NS921X_REFCLOCK,
+ .endisable = ns921x_endisable_sysclock,
+ },
+ .mask = SYS_CLOCK_UARTD,
+};
+
+static struct resource uarta_resources[] = {
+ {
+ .start = 0x90010000,
+ .end = 0x90017fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS921X_UARTA,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource uartb_resources[] = {
+ {
+ .start = 0x90018000,
+ .end = 0x9001ffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS921X_UARTB,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource uartc_resources[] = {
+ {
+ .start = 0x90020000,
+ .end = 0x90027fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS921X_UARTC,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource uartd_resources[] = {
+ {
+ .start = 0x90028000,
+ .end = 0x9002ffff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS921X_UARTD,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct ns921x_uart_data uarta_data;
+static struct ns921x_uart_data uartb_data;
+static struct ns921x_uart_data uartc_data;
+static struct ns921x_uart_data uartd_data;
+
+static struct platform_device ns9xxx_device_ns921x_uarta = {
+ .name = "ns921x-serial",
+ .id = 0,
+ .dev = {
+ .platform_data = &uarta_data,
+ },
+ .resource = uarta_resources,
+ .num_resources = ARRAY_SIZE(uarta_resources),
+};
+
+static struct platform_device ns9xxx_device_ns921x_uartb = {
+ .name = "ns921x-serial",
+ .id = 1,
+ .dev = {
+ .platform_data = &uartb_data,
+ },
+ .resource = uartb_resources,
+ .num_resources = ARRAY_SIZE(uartb_resources),
+};
+
+static struct platform_device ns9xxx_device_ns921x_uartc = {
+ .name = "ns921x-serial",
+ .id = 2,
+ .dev = {
+ .platform_data = &uartc_data,
+ },
+ .resource = uartc_resources,
+ .num_resources = ARRAY_SIZE(uartc_resources),
+};
+
+static struct platform_device ns9xxx_device_ns921x_uartd = {
+ .name = "ns921x-serial",
+ .id = 3,
+ .dev = {
+ .platform_data = &uartd_data,
+ },
+ .resource = uartd_resources,
+ .num_resources = ARRAY_SIZE(uartd_resources),
+};
+
+int __init uart_register_gpios(int gpio_start,
+ int gpio_nr,
+ int func,
+ struct ns921x_uart_data *data)
+{
+ int i;
+ int gpio[] = { 3, 7, 1, 5, 0, 2, 4, 6 };
+
+ for (i = 0; i < gpio_nr; i++) {
+ if (i!=2 || !data->rtsen) /* Skip request of CTS line */
+ {
+ if (gpio_request(gpio_start + gpio[i], "ns921x-serial"))
+ goto err;
+#ifdef CONFIG_NS921X_SERIAL_RTS_AS_GPIO
+ if (i==3) /* RTS needs to be used as gpio to allow using AFE */
+ gpio_configure_ns921x(gpio_start + gpio[i], 0, 0, 3, 0);
+ else
+#endif
+ gpio_configure_ns921x(gpio_start + gpio[i], 0, 0, func, 0);
+ }
+ data->gpios[i] = gpio_start + gpio[i];
+ }
+
+ return 0;
+err:
+ for (; i >= 0; i--)
+ gpio_free(gpio_start + gpio[i]);
+
+ return -EBUSY;
+}
+
+void __init ns9xxx_add_device_ns921x_uarta(int gpio_start,
+ int gpio_nr, int func)
+{
+ uarta_data.nr_gpios = gpio_nr;
+#if defined(CONFIG_CC9P9215JS_SERIAL_PORTA_RXTX485) || \
+ defined(CONFIG_CME9210JS_SERIAL_PORTA_RXTX485)
+ uarta_data.rtsen = 1;
+#else
+ uarta_data.rtsen = 0;
+#endif
+ if (uart_register_gpios(gpio_start, gpio_nr, func, &uarta_data))
+ return;
+
+ if (clk_register(&uarta_clk.clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns921x_uarta);
+}
+
+void __init ns9xxx_add_device_ns921x_uartb(int gpio_start,
+ int gpio_nr, int func)
+{
+ uartb_data.nr_gpios = gpio_nr;
+#ifdef CONFIG_CC9P9215JS_SERIAL_PORTB_RXTX485
+ uartb_data.rtsen = 1;
+#else
+ uartb_data.rtsen = 0;
+#endif
+
+ if (uart_register_gpios(gpio_start, gpio_nr, func, &uartb_data))
+ return;
+
+ if (clk_register(&uartb_clk.clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns921x_uartb);
+}
+
+void __init ns9xxx_add_device_ns921x_uartc(int gpio_start,
+ int gpio_nr, int func)
+{
+ uartc_data.nr_gpios = gpio_nr;
+#ifdef CONFIG_CC9P9215JS_SERIAL_PORTC_RXTX485
+ uartc_data.rtsen = 1;
+#else
+ uartc_data.rtsen = 0;
+#endif
+
+ if (uart_register_gpios(gpio_start, gpio_nr, func, &uartc_data))
+ return;
+
+ if (clk_register(&uartc_clk.clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns921x_uartc);
+}
+
+void __init ns9xxx_add_device_ns921x_uartd(int gpio_start,
+ int gpio_nr, int func)
+{
+ uartd_data.nr_gpios = gpio_nr;
+#ifdef CONFIG_CC9P9215JS_SERIAL_PORTD_RXTX485
+ uartd_data.rtsen = 1;
+#else
+ uartd_data.rtsen = 0;
+#endif
+
+ if (uart_register_gpios(gpio_start, gpio_nr, func, &uartd_data))
+ return;
+
+ if (clk_register(&uartd_clk.clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns921x_uartd);
+}
+#else
+void __init ns9xxx_add_device_ns921x_uarta(int gpio_start,
+ int gpio_nr, int func) {}
+void __init ns9xxx_add_device_ns921x_uartb(int gpio_start,
+ int gpio_nr, int func) {}
+void __init ns9xxx_add_device_ns921x_uartc(int gpio_start,
+ int gpio_nr, int func) {}
+void __init ns9xxx_add_device_ns921x_uartd(int gpio_start,
+ int gpio_nr, int func) {}
+#endif
+
+/* Flash */
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP)
+static struct resource flash_resources[] = {
+ {
+ .start = 0x50000000,
+ .end = 0x5fffffff,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ns9xxx_device_ns921x_flash = {
+ .name = "physmap-flash",
+ .id = 0,
+ .resource = flash_resources,
+ .num_resources = ARRAY_SIZE(flash_resources),
+};
+
+void __init ns9xxx_add_device_ns921x_flash(
+ struct physmap_flash_data *flash_data)
+{
+
+ ns9xxx_device_ns921x_flash.dev.platform_data = flash_data;
+ platform_device_register(&ns9xxx_device_ns921x_flash);
+}
+#else
+void __init ns9xxx_add_device_ns921x_flash(
+ struct physmap_flash_data *flash_data) {}
+#endif
+
+/* SPI port */
+#if defined(CONFIG_SPI_NS921X) || defined(CONFIG_SPI_NS921X_MODULE)
+int __init spi_register_gpios(struct spi_ns9xxx_data *data)
+{
+ int i;
+
+ for (i = 0; i < data->nr_gpios; i++) {
+ if (gpio_request(data->gpios[i], "spi_ns921x"))
+ goto err;
+ gpio_configure_ns921x(data->gpios[i],
+ 0,
+ 0,
+ data->gpio_funcs[i],
+ 0 );
+ }
+
+ return 0;
+err:
+ for (; i >= 0; i--)
+ gpio_free(data->gpios[i]);
+
+ return -EBUSY;
+}
+
+static struct ns921x_sysclk spi_clk = {
+ .clk = {
+ .name = "spi_ns921x",
+ .id = 1,
+ .owner = THIS_MODULE,
+ .endisable = ns921x_endisable_sysclock,
+ },
+ .mask = SYS_CLOCK_SPI,
+};
+
+static struct resource spi_resources[] = {
+ {
+ .start = 0x90030000,
+ .end = 0x90037fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS921X_SPI,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 spi_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ns9xxx_device_ns921x_spi = {
+ .name = "spi_ns921x",
+ .id = 1,
+ .resource = spi_resources,
+ .num_resources = ARRAY_SIZE(spi_resources),
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init ns9xxx_add_device_ns921x_spi(struct spi_ns9xxx_data *data)
+{
+ if (spi_register_gpios(data))
+ return;
+
+ spi_clk.clk.parent = clk_get(NULL, "systemclock");
+ if (IS_ERR(spi_clk.clk.parent))
+ return;
+
+ if (clk_register(&spi_clk.clk))
+ return;
+
+ ns9xxx_device_ns921x_spi.dev.platform_data = data;
+ platform_device_register(&ns9xxx_device_ns921x_spi);
+}
+#else
+void __init ns9xxx_add_device_ns921x_spi(struct spi_ns9xxx_data *data) {}
+#endif
+
+/* AES HW Encryption module */
+#if defined(CONFIG_CRYPTO_DEV_NS921X_AES) || \
+ defined(CONFIG_CRYPTO_DEV_NS921X_AES_MODULE)
+static struct ns921x_sysclk aes_clk = {
+ .clk = {
+ .name = "ns921x-aes",
+ .id = -1,
+ .owner = THIS_MODULE,
+ .endisable = ns921x_endisable_sysclock,
+ },
+ .mask = SYS_CLOCK_AES,
+};
+
+static struct resource aes_resources[] = {
+ {
+ .start = 0xa0800000,
+ .end = 0xa080000f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS921X_EXTDMA,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 aes_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ns9xxx_device_ns921x_aes = {
+ .name = "ns921x-aes",
+ .id = 1,
+ .resource = aes_resources,
+ .num_resources = ARRAY_SIZE(aes_resources),
+ .dev = {
+ .dma_mask = &aes_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init ns9xxx_add_device_ns921x_aes(void)
+{
+ aes_clk.clk.parent = clk_get(NULL, "dmaclock");
+ if (IS_ERR(aes_clk.clk.parent))
+ return;
+
+ if (clk_register(&aes_clk.clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns921x_aes);
+}
+#else
+void __init ns9xxx_add_device_ns921x_aes(void);
+#endif
+
+
+#if defined(CONFIG_PM)
+static irqreturn_t ns921x_ack_extirq(int irq, void *dev_id)
+{
+ u32 eixctl;
+
+ BUG_ON((unsigned)(irq - IRQ_NS9XXX_EXT0) > 4);
+
+ eixctl = __raw_readl(SYS_EIxCTRL(irq - IRQ_NS9XXX_EXT0));
+
+ /* ack ext irq */
+ REGSETIM(eixctl, SYS_EIxCTRL, CLEAR, 1);
+ __raw_writel(eixctl, SYS_EIxCTRL(irq - IRQ_NS9XXX_EXT0));
+ REGSETIM(eixctl, SYS_EIxCTRL, CLEAR, 0);
+ __raw_writel(eixctl, SYS_EIxCTRL(irq - IRQ_NS9XXX_EXT0));
+
+ return IRQ_HANDLED;
+}
+
+int __init ns921x_extgpio_pm_wakeup_init(unsigned int gpio)
+{
+ int ret;
+ const struct gpio_to_irq_map *map;
+
+ map = gpio_get_map_ns921x(gpio);
+ if (!map) {
+ pr_debug("%s: selected gpio %d not irq capable\n", __func__, gpio);
+ return -EINVAL;
+ }
+
+ ret = gpio_request(gpio, "cpuwake");
+ if (ret) {
+ pr_debug("%s: err_gpio_request -> %d\n", __func__, ret);
+ goto err_gpio_request;
+ }
+
+ gpio_configure_ns921x(gpio, 0, 0, map->func, 0);
+
+ ret = request_irq(map->irq, ns921x_ack_extirq, IRQF_TRIGGER_FALLING,
+ "extwakeirq", NULL);
+ if (ret) {
+ pr_debug("%s: err_request_irq_extwakeirq %d -> %d\n", __func__, map->irq, ret);
+ goto err_irq_request;
+ }
+
+ ret = enable_irq_wake(map->irq);
+ if (ret) {
+ pr_debug("%s: err_enable_irq_extwakeirq %d -> %d\n", __func__, map->irq, ret);
+ goto err_enable_wake;
+ }
+ return 0;
+
+err_enable_wake:
+ free_irq(map->irq, NULL);
+err_irq_request:
+ gpio_free(gpio);
+err_gpio_request:
+ return ret;
+}
+#else /* CONFIG_PM */
+int __init ns921x_extgpio_pm_wakeup_init(unsigned int gpio)
+{
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+#if defined(CONFIG_FIM_ZERO_SDIO)
+void __init ns9xxx_add_device_ns921x_fim_sdio0(void)
+{
+ extern struct platform_device ns921x_fim_sdio0;
+ platform_device_register(&ns921x_fim_sdio0);
+}
+#else
+void __init ns9xxx_add_device_ns921x_fim_sdio0(void) {}
+#endif
+
+#if defined(CONFIG_FIM_ONE_SDIO)
+void __init ns9xxx_add_device_ns921x_fim_sdio1(void)
+{
+ extern struct platform_device ns921x_fim_sdio1;
+ platform_device_register(&ns921x_fim_sdio1);
+}
+#else
+void __init ns9xxx_add_device_ns921x_fim_sdio1(void) {}
+#endif
+
+
+#if defined(CONFIG_FIM_ZERO_SERIAL)
+void __init ns9xxx_add_device_ns921x_fim_serial0(void)
+{
+ extern struct platform_device ns921x_fim_serial0;
+ platform_device_register(&ns921x_fim_serial0);
+}
+#else
+void __init ns9xxx_add_device_ns921x_fim_serial0(void) {}
+#endif /* CONFIG_FIM_SERIAL */
+
+#if defined(CONFIG_FIM_ONE_SERIAL)
+void __init ns9xxx_add_device_ns921x_fim_serial1(void)
+{
+ extern struct platform_device ns921x_fim_serial1;
+ platform_device_register(&ns921x_fim_serial1);
+}
+#else
+void __init ns9xxx_add_device_ns921x_fim_serial1(void) {}
+#endif /* CONFIG_FIM_SERIAL */
+
+#if defined(CONFIG_FIM_ZERO_CAN)
+void __init ns9xxx_add_device_ns921x_fim_can0(void)
+{
+ extern struct platform_device ns921x_fim_can0;
+ platform_device_register(&ns921x_fim_can0);
+}
+#else
+void __init ns9xxx_add_device_ns921x_fim_can0(void) {}
+#endif
+
+#if defined(CONFIG_FIM_ONE_CAN)
+void __init ns9xxx_add_device_ns921x_fim_can1(void)
+{
+ extern struct platform_device ns921x_fim_can1;
+ platform_device_register(&ns921x_fim_can1);
+}
+#else
+void __init ns9xxx_add_device_ns921x_fim_can1(void) {}
+#endif
+
+#if defined(CONFIG_FIM_ZERO_W1)
+static void __init ns9xxx_add_device_ns921x_fim0_w1(void)
+{
+ extern struct platform_device ns921x_fim0_w1;
+ platform_device_register(&ns921x_fim0_w1);
+}
+#else
+static inline void __init ns9xxx_add_device_ns921x_fim0_w1(void) { }
+#endif
+
+#if defined(CONFIG_FIM_ONE_W1)
+static void __init ns9xxx_add_device_ns921x_fim1_w1(void)
+{
+ extern struct platform_device ns921x_fim1_w1;
+ platform_device_register(&ns921x_fim1_w1);
+}
+#else
+static inline void __init ns9xxx_add_device_ns921x_fim1_w1(void) { }
+#endif
+
+#if defined(CONFIG_FIM_ZERO_USB)
+void __init ns9xxx_add_device_ns921x_fim_usb0(void)
+{
+ extern struct platform_device ns921x_fim_usb0;
+ platform_device_register(&ns921x_fim_usb0);
+}
+#else
+static inline void __init ns9xxx_add_device_ns921x_fim_usb0(void) {}
+#endif
+
+#if defined(CONFIG_FIM_ONE_USB)
+void __init ns9xxx_add_device_ns921x_fim_usb1(void)
+{
+ extern struct platform_device ns921x_fim_usb1;
+ platform_device_register(&ns921x_fim_usb1);
+}
+#else
+static inline void __init ns9xxx_add_device_ns921x_fim_usb1(void) {}
+#endif
+
+#if defined(CONFIG_FIM_CORE) || defined(CONFIG_FIM_MODULES)
+void __init ns9xxx_add_device_ns921x_fims(void)
+{
+ /*
+ * By the CME9210s with the CAN-support the GPIOs 2 and 23 are inter-connected.
+ * This is just problematic when these modules should use the FIM-serial
+ * interface, then the GPIO23 is not configured as input GPIO after the resets.
+ * IMPORTANT: The below code will disappear in one of the next U-Boot releases
+ * with the FIMs-support.
+ * (Luis Galdos)
+ */
+#if defined(CONFIG_FIM_CORE) && \
+ (defined(CONFIG_MACH_CME9210) || defined(CONFIG_MACH_CME9210JS))
+ gpio_direction_input_ns921x_unlocked(23);
+#endif
+
+ /* FIM 0 */
+ ns9xxx_add_device_ns921x_fim_serial0();
+ ns9xxx_add_device_ns921x_fim_sdio0();
+ ns9xxx_add_device_ns921x_fim_can0();
+ ns9xxx_add_device_ns921x_fim0_w1();
+ ns9xxx_add_device_ns921x_fim_usb0();
+
+ /* FIM 1 */
+ ns9xxx_add_device_ns921x_fim_serial1();
+ ns9xxx_add_device_ns921x_fim_sdio1();
+ ns9xxx_add_device_ns921x_fim_can1();
+ ns9xxx_add_device_ns921x_fim1_w1();
+ ns9xxx_add_device_ns921x_fim_usb1();
+}
+#else
+void __init ns9xxx_add_device_ns921x_fims(void) {}
+#endif /* CONFIG_FIM_CORE */
+
diff --git a/arch/arm/mach-ns9xxx/ns921x_devices.h b/arch/arm/mach-ns9xxx/ns921x_devices.h
new file mode 100644
index 000000000000..d1e7e7153cdf
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/ns921x_devices.h
@@ -0,0 +1,37 @@
+/*
+ * arch/arm/mach-ns9xxx/ns921x_devices.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/clk.h>
+#include <linux/i2c-ns9xxx.h>
+#include <linux/init.h>
+#include <linux/mtd/physmap.h>
+#include <mach/spi.h>
+
+#include "clock.h"
+
+void __init ns9xxx_add_device_ns921x_wdt(void);
+void __init ns9xxx_add_device_ns921x_eth(struct clk *phyclk, u32 phy_mask,
+ int gpio[], int func[], int dir[], int num);
+void __init ns9xxx_add_device_ns921x_i2c(struct plat_ns9xxx_i2c *);
+void __init ns9xxx_add_device_ns921x_uarta(int gpio_start,
+ int gpio_nr, int func);
+void __init ns9xxx_add_device_ns921x_uartb(int gpio_start,
+ int gpio_nr, int func);
+void __init ns9xxx_add_device_ns921x_uartc(int gpio_start,
+ int gpio_nr, int func);
+void __init ns9xxx_add_device_ns921x_uartd(int gpio_start,
+ int gpio_nr, int func);
+void __init ns9xxx_add_device_ns921x_flash(
+ struct physmap_flash_data *flash_data);
+void __init ns9xxx_add_device_ns921x_spi(struct spi_ns9xxx_data *data);
+int __init ns921x_extgpio_pm_wakeup_init(unsigned int gpio);
+void __init ns9xxx_add_device_ns921x_fims(void);
+void __init ns9xxx_add_device_ns921x_aes(void);
diff --git a/arch/arm/mach-ns9xxx/ns9360_devices.c b/arch/arm/mach-ns9xxx/ns9360_devices.c
new file mode 100644
index 000000000000..63d2d1205c0c
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/ns9360_devices.c
@@ -0,0 +1,813 @@
+/*
+ * arch/arm/mach-ns9xxx/ns9360_devices.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+#include <linux/ns9xxx-eth.h>
+#include <linux/platform_device.h>
+
+#include <mach/regs-lcd-ns9360.h>
+#include <mach/regs-sys-ns9360.h>
+#include <mach/gpio.h>
+#include <mach/ns9360fb.h>
+#include <mach/display/displays.h>
+
+#include "clock.h"
+#include "ns9360_devices.h"
+
+
+/* USB host */
+#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+static int usbh_endisable(struct clk *clk, int enable)
+{
+ if (enable) {
+ u32 mrst = __raw_readl(NS9360_BBU_MSR);
+ mrst |= 1 << 11;
+ __raw_writel(mrst, NS9360_BBU_MSR);
+
+ __raw_writel(0 << 2, NS9360_BBUS_USB);
+
+ mrst = __raw_readl(NS9360_BBU_MSR);
+ mrst &= ~(1 << 11);
+ __raw_writel(mrst, NS9360_BBU_MSR);
+ }
+
+ return 0;
+}
+
+static struct clk usbh_clk = {
+ .name = "ns9360-ohci",
+ .id = -1,
+ .owner = THIS_MODULE,
+ .endisable = usbh_endisable,
+};
+
+static u64 ohci_dmamask = DMA_BIT_MASK(32);
+static struct resource usbh_resources[] = {
+ {
+ .start = 0x90801000,
+ .end = 0x90801fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0x90800000,
+ .end = 0x90800fff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS9360_USBHOST,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ns9xxx_device_ns9360_usbh = {
+ .name = "ns9360-ohci",
+ .id = -1,
+ .resource = usbh_resources,
+ .num_resources = ARRAY_SIZE(usbh_resources),
+ .dev = {
+ .dma_mask = &ohci_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init ns9xxx_add_device_ns9360_usbh(void)
+{
+ if (clk_register(&usbh_clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns9360_usbh);
+}
+#else
+void __init ns9xxx_add_device_ns9360_usbh(void) {}
+#endif
+
+/* Watchdog timer */
+#if defined(CONFIG_NS9XXX_WATCHDOG) || defined(CONFIG_NS9XXX_WATCHDOG_MODULE)
+static struct clk wdt_clk = {
+ .name = "ns9xxx-wdt",
+ .id = -1,
+ .owner = THIS_MODULE,
+};
+
+static struct resource wdt_resources[] = {
+ {
+ .start = 0xa0900174,
+ .end = 0xa0900177,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ns9xxx_device_ns9360_wdt = {
+ .name = "ns9xxx-wdt",
+ .id = -1,
+ .resource = wdt_resources,
+ .num_resources = ARRAY_SIZE(wdt_resources),
+};
+
+void __init ns9xxx_add_device_ns9360_wdt(void)
+{
+ wdt_clk.parent = clk_get(NULL, "cpuclock");
+ if (IS_ERR(wdt_clk.parent))
+ return;
+
+ if (clk_register(&wdt_clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns9360_wdt);
+}
+#else
+void __init ns9xxx_add_device_ns9360_wdt(void) {}
+#endif
+
+/* RTC */
+#if defined(CONFIG_RTC_DRV_NS9XXX) || defined(CONFIG_RTC_DRV_NS9XXX_MODULE)
+static struct clk rtc_clk = {
+ .name = "rtc-ns9xxx",
+ .id = -1,
+ .owner = THIS_MODULE,
+};
+
+static struct resource rtc_resources[] = {
+ {
+ .start = 0x90700000,
+ .end = 0x907000ff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS9360_RTC,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device ns9xxx_device_ns9360_rtc = {
+ .name = "rtc-ns9xxx",
+ .id = 0,
+ .resource = rtc_resources,
+ .num_resources = ARRAY_SIZE(rtc_resources),
+};
+
+void __init ns9xxx_add_device_ns9360_rtc(void)
+{
+ struct clk *sysclk = clk_get(NULL, "systemclock");
+ if (IS_ERR(sysclk))
+ return;
+
+ __raw_writel(clk_get_rate(sysclk) / 200, SYS_RTCCC);
+ clk_put(sysclk);
+
+ if (clk_register(&rtc_clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns9360_rtc);
+}
+#else
+void __init ns9xxx_add_device_ns9360_rtc(void) {}
+#endif
+
+/* Ethernet */
+#if defined(CONFIG_NS9XXX_ETH) || defined(CONFIG_NS9XXX_ETH_MODULE)
+int __init eth_register_gpios(int gpio[], int gpio_nr, int func)
+{
+ int i;
+
+ for (i = 0; i < gpio_nr; i++) {
+ if (gpio_request(gpio[i], "ns9xxx-eth"))
+ goto err;
+ gpio_configure_ns9360(gpio[i], 0, 0, func);
+ }
+
+ return 0;
+err:
+ for (; i >= 0; i--)
+ gpio_free(gpio[i]);
+
+ return -EBUSY;
+}
+
+static struct clk eth_clk = {
+ .name = "ns9xxx-eth",
+ .id = -1,
+ .owner = THIS_MODULE,
+};
+
+static struct plat_ns9xxx_eth ns9xxx_device_ns9360_eth_data = {
+ .irqrx = IRQ_NS9XXX_ETHRX,
+ .irqtx = IRQ_NS9XXX_ETHTX,
+};
+
+static struct resource eth_resources[] = {
+ {
+ .start = 0xa0600000,
+ .end = 0xa06027ff,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device ns9xxx_device_ns9360_eth = {
+ .name = "ns9xxx-eth",
+ .id = -1,
+ .resource = eth_resources,
+ .num_resources = ARRAY_SIZE(eth_resources),
+ .dev = {
+ .platform_data = &ns9xxx_device_ns9360_eth_data,
+ },
+};
+
+void __init ns9xxx_add_device_ns9360_eth(int gpio[], int gpio_nr, int func, u32 phy_mask)
+{
+ if (eth_register_gpios(gpio, gpio_nr, func))
+ return;
+
+ if (clk_register(&eth_clk))
+ return;
+
+ ns9xxx_device_ns9360_eth_data.phy_mask = phy_mask;
+
+ platform_device_register(&ns9xxx_device_ns9360_eth);
+}
+#else
+void __init ns9xxx_add_device_ns9360_eth(int gpio[], int gpio_nr, int func, u32 phy_mask) {}
+#endif
+
+/* UARTs */
+#if defined(CONFIG_SERIAL_NS9360) || defined(CONFIG_SERIAL_NS9360_MODULE)
+static struct clk uarta_clk = {
+ .name = "ns9360-serial",
+ .id = 1,
+ .owner = THIS_MODULE,
+};
+
+static struct clk uartb_clk = {
+ .name = "ns9360-serial",
+ .id = 0,
+ .owner = THIS_MODULE,
+};
+
+static struct clk uartc_clk = {
+ .name = "ns9360-serial",
+ .id = 2,
+ .owner = THIS_MODULE,
+};
+
+static struct clk uartd_clk = {
+ .name = "ns9360-serial",
+ .id = 3,
+ .owner = THIS_MODULE,
+};
+
+static struct resource uarta_resources[] = {
+ {
+ .start = 0x90200040,
+ .end = 0x9020007f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS9360_SERARX,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource uartb_resources[] = {
+ {
+ .start = 0x90200000,
+ .end = 0x9020003f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS9360_SERBRX,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource uartc_resources[] = {
+ {
+ .start = 0x90300000,
+ .end = 0x9030003f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS9360_SERCRX,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct resource uartd_resources[] = {
+ {
+ .start = 0x90300040,
+ .end = 0x9030007f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS9360_BBUS_SERDRX,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device ns9xxx_device_ns9360_uarta = {
+ .name = "ns9360-serial",
+ .id = 1,
+ .resource = uarta_resources,
+ .num_resources = ARRAY_SIZE(uarta_resources),
+};
+
+static struct platform_device ns9xxx_device_ns9360_uartb = {
+ .name = "ns9360-serial",
+ .id = 0,
+ .resource = uartb_resources,
+ .num_resources = ARRAY_SIZE(uartb_resources),
+};
+
+static struct platform_device ns9xxx_device_ns9360_uartc = {
+ .name = "ns9360-serial",
+ .id = 2,
+ .resource = uartc_resources,
+ .num_resources = ARRAY_SIZE(uartc_resources),
+};
+
+static struct platform_device ns9xxx_device_ns9360_uartd = {
+ .name = "ns9360-serial",
+ .id = 3,
+ .resource = uartd_resources,
+ .num_resources = ARRAY_SIZE(uartd_resources),
+};
+
+int __init uart_register_gpios(int gpio[], int gpio_nr, int func)
+{
+ int i;
+
+ for (i = 0; i < gpio_nr; i++) {
+ if (gpio_request(gpio[i], "ns9360-serial"))
+ goto err;
+ gpio_configure_ns9360(gpio[i], 0, 0, func);
+ }
+
+ return 0;
+err:
+ for (; i >= 0; i--)
+ gpio_free(gpio[i]);
+
+ return -EBUSY;
+}
+
+void __init ns9xxx_add_device_ns9360_uarta(int gpio[], int gpio_nr, int func)
+{
+ if (uart_register_gpios(gpio, gpio_nr, func))
+ return;
+
+ uarta_clk.parent = clk_get(NULL, "bbusclock");
+ if (IS_ERR(uarta_clk.parent))
+ return;
+
+ if (clk_register(&uarta_clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns9360_uarta);
+}
+
+void __init ns9xxx_add_device_ns9360_uartb(int gpio[], int gpio_nr, int func)
+{
+ if (uart_register_gpios(gpio, gpio_nr, func))
+ return;
+
+ uartb_clk.parent = clk_get(NULL, "bbusclock");
+ if (IS_ERR(uartb_clk.parent))
+ return;
+
+ if (clk_register(&uartb_clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns9360_uartb);
+}
+
+void __init ns9xxx_add_device_ns9360_uartc(int gpio[], int gpio_nr, int func)
+{
+ if (uart_register_gpios(gpio, gpio_nr, func))
+ return;
+
+ uartc_clk.parent = clk_get(NULL, "bbusclock");
+ if (IS_ERR(uartc_clk.parent))
+ return;
+
+ if (clk_register(&uartc_clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns9360_uartc);
+}
+
+void __init ns9xxx_add_device_ns9360_uartd(int gpio[], int gpio_nr, int func)
+{
+ if (uart_register_gpios(gpio, gpio_nr, func))
+ return;
+
+ uartd_clk.parent = clk_get(NULL, "bbusclock");
+ if (IS_ERR(uartd_clk.parent))
+ return;
+
+ if (clk_register(&uartd_clk))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns9360_uartd);
+}
+#else
+void __init ns9xxx_add_device_ns9360_uarta(int gpio[], int gpio_nr, int func) {}
+void __init ns9xxx_add_device_ns9360_uartb(int gpio[], int gpio_nr, int func) {}
+void __init ns9xxx_add_device_ns9360_uartc(int gpio[], int gpio_nr, int func) {}
+void __init ns9xxx_add_device_ns9360_uartd(int gpio[], int gpio_nr, int func) {}
+#endif
+
+/* NAND flash */
+#if defined(CONFIG_MTD_NAND_CCX9X) || defined(CONFIG_MTD_NAND_CCX9X_MODULE)
+static struct resource nand_resources[] = {
+ {
+ .start = 0x50000000,
+ .end = 0x5fffffff,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static struct platform_device ns9xxx_device_ns9360_nand = {
+ .name = "ccx9x_nand",
+ .id = -1,
+ .resource = nand_resources,
+ .num_resources = ARRAY_SIZE(nand_resources),
+};
+
+void __init ns9xxx_add_device_ns9360_nand(struct ccx9x_nand_info *nand_data)
+{
+ ns9xxx_device_ns9360_nand.dev.platform_data = nand_data;
+ platform_device_register(&ns9xxx_device_ns9360_nand);
+}
+#else
+void __init ns9xxx_add_device_ns9360_nand(struct ccx9x_nand_info *nand_data) {}
+#endif
+
+/* I2C controller */
+#if defined(CONFIG_I2C_NS9XXX) || defined(CONFIG_I2C_NS9XXX_MODULE)
+static struct clk i2c_clk = {
+ .name = "i2c-ns9xxx",
+ .id = -1,
+ .owner = THIS_MODULE,
+};
+
+static struct resource i2c_resources[] = {
+ {
+ .start = 0x90500000,
+ .end = 0x9050000f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = IRQ_NS9360_I2C,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device ns9xxx_device_ns9360_i2c = {
+ .name = "i2c-ns9xxx",
+ .id = -1,
+ .resource = i2c_resources,
+ .num_resources = ARRAY_SIZE(i2c_resources),
+};
+
+void __init ns9xxx_add_device_ns9360_i2c(struct plat_ns9xxx_i2c *i2c_data)
+{
+ i2c_clk.parent = clk_get(NULL, "systemclock");
+ if (IS_ERR(i2c_clk.parent))
+ return;
+
+ if (clk_register(&i2c_clk))
+ return;
+
+ ns9xxx_device_ns9360_i2c.dev.platform_data = i2c_data;
+ platform_device_register(&ns9xxx_device_ns9360_i2c);
+}
+#else
+void __init ns9xxx_add_device_ns9360_i2c(struct plat_ns9xxx_i2c *i2c_data) {}
+#endif
+
+/* Framebuffer controller */
+#if (defined(CONFIG_FB_NS9360) || defined(CONFIG_FB_NS9360_MODULE)) && !defined(NS9XXX_NODISPLAY)
+int __init fb_register_gpios(int gpio[], int gpio_nr, int func[], int power)
+{
+ int i;
+
+ for (i = 0; i < gpio_nr; i++) {
+ if (gpio_request(gpio[i], "ns9360fb"))
+ goto err;
+ gpio_configure_ns9360(gpio[i], 0, 0, func[i]);
+ }
+
+ if (gpio_request(power, "ns9360fb")) {
+ i--;
+ goto err;
+ }
+ gpio_direction_output(power, 0);
+
+ return 0;
+err:
+ for (; i >= 0; i--)
+ gpio_free(gpio[i]);
+
+ return -EBUSY;
+}
+
+static int fb_endisable(struct clk *clk, int enable)
+{
+ /* Currently, nothing to do */
+ return 0;
+}
+
+static struct clk fb_clk = {
+ .name = "ns9360fb",
+ .id = -1,
+ .owner = THIS_MODULE,
+ .endisable = fb_endisable,
+
+};
+static struct ns9360fb_pdata ns9xxx_device_ns9360_fb_data = {
+ .displays = display_list,
+ .num_displays = ARRAY_SIZE(display_list),
+};
+
+static struct resource fb_resources[] = {
+ {
+ .start = 0xa0800000,
+ .end = 0xa080002f,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ns9xxx_device_ns9360_fb = {
+ .name = "ns9360fb",
+ .id = -1,
+ .resource = fb_resources,
+ .num_resources = ARRAY_SIZE(fb_resources),
+ .dev = {
+ .platform_data = &ns9xxx_device_ns9360_fb_data,
+ },
+};
+
+void __init ns9xxx_add_device_ns9360_fb(int gpio[], int gpio_nr,
+ int func[], int power)
+{
+ fb_clk.parent = clk_get(NULL, "ahbclock");
+ if (IS_ERR(fb_clk.parent))
+ return;
+
+ if (clk_register(&fb_clk))
+ return;
+
+ if (fb_register_gpios(gpio, gpio_nr, func, power))
+ return;
+
+ platform_device_register(&ns9xxx_device_ns9360_fb);
+}
+#else
+void __init ns9xxx_add_device_ns9360_fb(int gpio[], int gpio_nr,
+ int func[], int power) {}
+#endif
+
+#if defined(CONFIG_SPI_NS9360) || defined(CONFIG_SPI_NS9360_MODULE)
+int __init spi_register_gpios(struct spi_ns9xxx_data *data)
+{
+ int i;
+
+ for (i = 0; i < data->nr_gpios; i++) {
+ if (gpio_request(data->gpios[i], "spi_ns9360"))
+ goto err;
+ gpio_configure_ns9360( data->gpios[i],
+ 0,
+ 0,
+ data->gpio_funcs[i] );
+ }
+
+ return 0;
+err:
+ for (; i >= 0; i--)
+ gpio_free(data->gpios[i]);
+
+ return -EBUSY;
+}
+
+static struct clk spi_porta_clk = {
+ .name = "spi_ns9360",
+ .id = 1,
+ .owner = THIS_MODULE,
+};
+
+static struct clk spi_portb_clk = {
+ .name = "spi_ns9360",
+ .id = 0,
+ .owner = THIS_MODULE,
+};
+
+static struct clk spi_portc_clk = {
+ .name = "spi_ns9360",
+ .id = 2,
+ .owner = THIS_MODULE,
+};
+
+static struct clk spi_portd_clk = {
+ .name = "spi_ns9360",
+ .id = 3,
+ .owner = THIS_MODULE,
+};
+
+static struct resource spi_porta_resources[] = {
+ {
+ .start = 0x90200040,
+ .end = 0x9020007f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0x90000040,
+ .end = 0x9000007f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 60,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = 61,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource spi_portb_resources[] = {
+ {
+ .start = 0x90200000,
+ .end = 0x9020003f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0x90000000,
+ .end = 0x9000003f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 58,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = 59,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource spi_portc_resources[] = {
+ {
+ .start = 0x90300000,
+ .end = 0x9020003f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0x90000080,
+ .end = 0x900000bf,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 62,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = 63,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct resource spi_portd_resources[] = {
+ {
+ .start = 0x90300040,
+ .end = 0x9030007f,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 0x900000c0,
+ .end = 0x900000ff,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = 64,
+ .flags = IORESOURCE_IRQ,
+ }, {
+ .start = 65,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 spi_dmamask = DMA_BIT_MASK(32);
+
+static struct platform_device ns9xxx_device_ns9360_spi_porta = {
+ .name = "spi_ns9360",
+ .id = 1,
+ .resource = spi_porta_resources,
+ .num_resources = ARRAY_SIZE(spi_porta_resources),
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+static struct platform_device ns9xxx_device_ns9360_spi_portb = {
+ .name = "spi_ns9360",
+ .id = 0,
+ .resource = spi_portb_resources,
+ .num_resources = ARRAY_SIZE(spi_portb_resources),
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+static struct platform_device ns9xxx_device_ns9360_spi_portc = {
+ .name = "spi_ns9360",
+ .id = 2,
+ .resource = spi_portc_resources,
+ .num_resources = ARRAY_SIZE(spi_portc_resources),
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+static struct platform_device ns9xxx_device_ns9360_spi_portd = {
+ .name = "spi_ns9360",
+ .id = 3,
+ .resource = spi_portd_resources,
+ .num_resources = ARRAY_SIZE(spi_portd_resources),
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+void __init ns9xxx_add_device_ns9360_spi_porta(struct spi_ns9xxx_data *data)
+{
+ if (spi_register_gpios(data))
+ return;
+
+ spi_porta_clk.parent = clk_get(NULL, "bbusclock");
+ if (IS_ERR(spi_porta_clk.parent))
+ return;
+
+ if (clk_register(&spi_porta_clk))
+ return;
+
+ /* Set platform data */
+ ns9xxx_device_ns9360_spi_porta.dev.platform_data = data;
+
+ platform_device_register(&ns9xxx_device_ns9360_spi_porta);
+}
+
+void __init ns9xxx_add_device_ns9360_spi_portb( struct spi_ns9xxx_data *data )
+{
+ if (spi_register_gpios(data))
+ return;
+
+ spi_portb_clk.parent = clk_get(NULL, "bbusclock");
+ if (IS_ERR(spi_portb_clk.parent))
+ return;
+
+ if (clk_register(&spi_portb_clk))
+ return;
+
+ /* Set platform data */
+ ns9xxx_device_ns9360_spi_portb.dev.platform_data = data;
+
+ platform_device_register(&ns9xxx_device_ns9360_spi_portb);
+}
+
+
+void __init ns9xxx_add_device_ns9360_spi_portc(struct spi_ns9xxx_data *data)
+{
+ if (spi_register_gpios(data))
+ return;
+
+ spi_portc_clk.parent = clk_get(NULL, "bbusclock");
+ if (IS_ERR(spi_portc_clk.parent))
+ return;
+
+ if (clk_register(&spi_portc_clk))
+ return;
+
+ /* Set platform data */
+ ns9xxx_device_ns9360_spi_portc.dev.platform_data = data;
+
+ platform_device_register(&ns9xxx_device_ns9360_spi_portc);
+}
+
+void __init ns9xxx_add_device_ns9360_spi_portd(struct spi_ns9xxx_data *data)
+{
+ if (spi_register_gpios(data))
+ return;
+
+ spi_portd_clk.parent = clk_get(NULL, "bbusclock");
+ if (IS_ERR(spi_portd_clk.parent))
+ return;
+
+ if (clk_register(&spi_portd_clk))
+ return;
+
+ /* Set platform data */
+ ns9xxx_device_ns9360_spi_portd.dev.platform_data = data;
+
+ platform_device_register(&ns9xxx_device_ns9360_spi_portd);
+}
+#else
+void __init ns9xxx_add_device_ns9360_spi_porta(struct spi_ns9xxx_data *data) {}
+void __init ns9xxx_add_device_ns9360_spi_portb(struct spi_ns9xxx_data *data) {}
+void __init ns9xxx_add_device_ns9360_spi_portc(struct spi_ns9xxx_data *data) {}
+void __init ns9xxx_add_device_ns9360_spi_portd(struct spi_ns9xxx_data *data) {}
+#endif
diff --git a/arch/arm/mach-ns9xxx/ns9360_devices.h b/arch/arm/mach-ns9xxx/ns9360_devices.h
new file mode 100644
index 000000000000..1994532aa3a1
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/ns9360_devices.h
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-ns9xxx/ns9360_devices.h
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/i2c-ns9xxx.h>
+#include <linux/init.h>
+#include <linux/mtd/ccx9x_nand.h>
+#include <mach/spi.h>
+
+void __init ns9xxx_add_device_ns9360_usbh(void);
+void __init ns9xxx_add_device_ns9360_wdt(void);
+void __init ns9xxx_add_device_ns9360_rtc(void);
+void __init ns9xxx_add_device_ns9360_eth(int gpio[], int gpio_nr, int func, u32 phy_mask);
+void __init ns9xxx_add_device_ns9360_uarta(int gpio[], int gpio_nr, int func);
+void __init ns9xxx_add_device_ns9360_uartb(int gpio[], int gpio_nr, int func);
+void __init ns9xxx_add_device_ns9360_uartc(int gpio[], int gpio_nr, int func);
+void __init ns9xxx_add_device_ns9360_uartd(int gpio[], int gpio_nr, int func);
+void __init ns9xxx_add_device_ns9360_nand(struct ccx9x_nand_info *);
+void __init ns9xxx_add_device_ns9360_i2c(struct plat_ns9xxx_i2c *);
+void __init ns9xxx_add_device_ns9360_fb(int gpio[], int gpio_nr,
+ int func[], int power);
+void __init ns9xxx_add_device_ns9360_spi_porta(struct spi_ns9xxx_data *data);
+void __init ns9xxx_add_device_ns9360_spi_portb(struct spi_ns9xxx_data *data);
+void __init ns9xxx_add_device_ns9360_spi_portc(struct spi_ns9xxx_data *data);
+void __init ns9xxx_add_device_ns9360_spi_portd(struct spi_ns9xxx_data *data);
diff --git a/arch/arm/mach-ns9xxx/pm-ns921x.c b/arch/arm/mach-ns9xxx/pm-ns921x.c
new file mode 100644
index 000000000000..5ecd5bb5b1bf
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/pm-ns921x.c
@@ -0,0 +1,173 @@
+/*
+ * arch/arm/mach-ns9xxx/pm-ns921x.c
+ *
+ * Copyright (C) 2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/gpio.h>
+
+#include <asm/io.h>
+#include <asm/leds.h>
+
+#include <mach/processor.h>
+#include <mach/regs-sys-ns921x.h>
+#include <mach/irqs.h>
+
+#include "processor-ns921x.h"
+
+#define NS921X_PM_ENET (1 << 0)
+#define NS921X_PM_UART (0xf << 1)
+#define NS921X_PM_SPI (1 << 5)
+#define NS921X_PM_I2C (1 << 11)
+#define NS921X_PM_RTC (1 << 12)
+#define NS921X_PM_I2C (1 << 11)
+#define NS921X_PM_EXT0 (1 << 16)
+#define NS921X_PM_EXT1 (1 << 17)
+#define NS921X_PM_EXT2 (1 << 18)
+#define NS921X_PM_EXT3 (1 << 19)
+#define NS921X_PM_ALL_WK 0xf183f
+
+#if defined(DEBUG)
+#define REGMAP(reg) { .name = #reg, .addr = reg, }
+static const struct {
+ const char *name;
+ void __iomem *addr;
+} regmap[] = {
+ REGMAP(SYS_ISA),
+ REGMAP(SYS_ISR),
+ REGMAP(SYS_CLOCK),
+ REGMAP(SYS_POWER),
+};
+
+static void dump_regs(void)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(regmap); ++i)
+ pr_debug("%s = 0x%08x\n", regmap[i].name,
+ __raw_readl(regmap[i].addr));
+}
+#else
+#define dump_regs() ((void)0)
+#endif
+
+static irqreturn_t ns921x_cpuwake_irq(int irq, void *dev_id)
+{
+ u32 power = __raw_readl(SYS_POWER);
+
+ /* ack wake irq */
+ __raw_writel(power | SYS_POWER_INTCLR, SYS_POWER);
+ __raw_writel(power, SYS_POWER);
+
+ return IRQ_HANDLED;
+}
+
+static int ns921x_pm_prepare(void)
+{
+ int ret;
+
+ ret = request_irq(IRQ_NS921X_CPUWAKE, ns921x_cpuwake_irq, 0, "cpuwake",
+ NULL);
+ if (ret) {
+ pr_debug("%s: err_%s -> %d\n",
+ __func__, "request_irq_cpuwake", ret);
+ }
+
+ return ret;
+}
+
+extern int ns9xxx_is_enabled_irq(unsigned int irq);
+
+static int ns921x_pm_enter(suspend_state_t state)
+{
+ u32 power = __raw_readl(SYS_POWER) | SYS_POWER_SLFRFSH;
+
+ /* ack any possible wake up irq before going to sleep... */
+ __raw_writel(power | SYS_POWER_INTCLR, SYS_POWER);
+ __raw_writel(power, SYS_POWER);
+
+ power &= NS921X_PM_ALL_WK;
+ if (!power)
+ goto pm_enter_err;
+
+ /* Verify that, if only one source is enabled that at least
+ * that irq is enabled */
+ if (!(power & ~NS921X_PM_ENET)) {
+ if (!ns9xxx_is_enabled_irq(IRQ_NS9XXX_ETHRX))
+ goto pm_enter_err;
+ }
+
+ if (!(power & ~NS921X_PM_UART)) {
+ if (!ns9xxx_is_enabled_irq(IRQ_NS921X_UARTA) |
+ !ns9xxx_is_enabled_irq(IRQ_NS921X_UARTB) |
+ !ns9xxx_is_enabled_irq(IRQ_NS921X_UARTC) |
+ !ns9xxx_is_enabled_irq(IRQ_NS921X_UARTD))
+ goto pm_enter_err;
+ }
+
+ if (!(power & ~NS921X_PM_RTC)) {
+ if (!ns9xxx_is_enabled_irq(IRQ_NS9215_RTC))
+ goto pm_enter_err;
+ }
+
+ if (!(power & ~NS921X_PM_EXT0)) {
+ if (!ns9xxx_is_enabled_irq(IRQ_NS9XXX_EXT0))
+ goto pm_enter_err;
+ }
+
+ if (!(power & ~NS921X_PM_EXT1)) {
+ if (!ns9xxx_is_enabled_irq(IRQ_NS9XXX_EXT1))
+ goto pm_enter_err;
+ }
+
+ if (!(power & ~NS921X_PM_EXT2)) {
+ if (!ns9xxx_is_enabled_irq(IRQ_NS9XXX_EXT2))
+ goto pm_enter_err;
+ }
+
+ if (!(power & ~NS921X_PM_EXT3)) {
+ if (!ns9xxx_is_enabled_irq(IRQ_NS9XXX_EXT3))
+ goto pm_enter_err;
+ }
+
+ leds_event(led_idle_start);
+ asm volatile("mcr p15, 0, %0, c7, c0, 4" : : "r" (0));
+ leds_event(led_idle_end);
+
+ return 0;
+
+pm_enter_err:
+ pr_warning("No wakeup source or interface disabled, not going to sleep (0x%08x)\n",
+ __raw_readl(SYS_POWER));
+ return -EDEADLK;
+
+}
+
+static void ns921x_pm_finish(void)
+{
+ free_irq(IRQ_NS921X_CPUWAKE, NULL);
+}
+
+static struct platform_suspend_ops ns921x_pm_ops = {
+ .valid = suspend_valid_only_mem,
+ .prepare = ns921x_pm_prepare,
+ .enter = ns921x_pm_enter,
+ .finish = ns921x_pm_finish,
+};
+
+static int __init ns921x_pm_init(void)
+{
+ if (!processor_is_ns921x())
+ return -ENODEV;
+
+ suspend_set_ops(&ns921x_pm_ops);
+ return 0;
+}
+arch_initcall(ns921x_pm_init);
diff --git a/arch/arm/mach-ns9xxx/processor-ns921x.c b/arch/arm/mach-ns9xxx/processor-ns921x.c
new file mode 100644
index 000000000000..cc0a49ccbc87
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/processor-ns921x.c
@@ -0,0 +1,379 @@
+/*
+ * arch/arm/mach-ns9xxx/processor-ns921x.c
+ *
+ * Copyright (C) 2007,2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/cpufreq.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include <asm/page.h>
+#include <asm/mach/map.h>
+
+#include <mach/regs-mem.h>
+#include <mach/regs-sys-ns921x.h>
+
+#include "clock.h"
+
+#include "processor-ns921x.h"
+#include "gpiolib-ns921x.h"
+
+void ns921x_reset(char mode)
+{
+ unsigned long pll = __raw_readl(SYS_PLL);
+ __raw_writel(pll, SYS_PLL);
+}
+
+#define DIVMASK(mask) ((mask) & (-(mask)))
+#define MASKVALUE(value, mask) (((value) & (mask)) / DIVMASK(mask))
+
+unsigned long ns921x_systemclock(void)
+{
+ unsigned long pll = __raw_readl(SYS_PLL);
+ unsigned pll_nr = MASKVALUE(pll, SYS_PLL_NR);
+ unsigned pll_nf = MASKVALUE(pll, SYS_PLL_NF);
+ unsigned pll_od = MASKVALUE(pll, SYS_PLL_OD);
+
+ return NS921X_REFCLOCK / (pll_nr + 1) * (pll_nf + 1) / (pll_od + 1);
+}
+static unsigned long ns921x_get_systemclock_rate(struct clk *clk)
+{
+ return ns921x_systemclock();
+}
+
+static inline unsigned long ahbclock(u32 clock)
+{
+ return ns921x_systemclock() >> (MASKVALUE(clock, SYS_CLOCK_CSC) + 2);
+}
+
+unsigned long ns921x_ahbclock(void)
+{
+ unsigned long clock = __raw_readl(SYS_CLOCK);
+ return ahbclock(clock);
+}
+
+static unsigned long ns921x_get_ahbclock_rate(struct clk *clk)
+{
+ return ns921x_ahbclock();
+}
+
+static inline unsigned long cpuclock(u32 clock)
+{
+ return ahbclock(clock) << MASKVALUE(clock, SYS_CLOCK_CSSEL);
+}
+
+static unsigned long ns921x_cpuclock(void)
+{
+ unsigned long clock = __raw_readl(SYS_CLOCK);
+ return cpuclock(clock);
+}
+
+static unsigned long ns921x_get_cpuclock_rate(struct clk *clk)
+{
+ return ns921x_cpuclock();
+}
+
+#if defined(CONFIG_CPU_FREQ)
+static inline int ns921x_freq2clock(unsigned int freq /* [kHz] */,
+ u32 cssel)
+{
+ /* valid range for CSC = [0...4] */
+ int i, found = 0;
+
+ BUG_ON(cssel && (cssel != SYS_CLOCK_CSSEL));
+ pr_debug("%s: freq = %u\n", __func__, freq);
+
+ for (i = 4; i >= 0; --i) {
+ u32 clock = i << 29 | cssel;
+ found = cpuclock(clock) >= 1000UL * freq;
+ if (found)
+ break;
+ }
+ if (!found) {
+ pr_debug("%s(%u, 0x%x) failed\n", __func__, freq, cssel);
+ BUG();
+ }
+
+ return i << 29 | cssel;
+}
+
+/* refresh_timer hold the value of the MEM_DMRT register for full speed
+ * operation (SYS_CLOCK_SYS = 0b000)
+ */
+static u32 refresh_timer;
+
+static int ns921x_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ unsigned int freq;
+ u32 cssel = 0;
+
+ pr_debug("%s\n", __func__);
+ /* This is an UP machine */
+ if (policy->cpu)
+ return -EINVAL;
+
+ if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
+ cssel = SYS_CLOCK_CSSEL;
+
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+
+ /* XXX: make sure there is at least one frequency within the policy */
+ freq = cpuclock(ns921x_freq2clock(policy->min, cssel)) / 1000;
+ if (freq > policy->max)
+ policy->max = freq;
+
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+
+ pr_debug("/%s\n", __func__);
+ return 0;
+}
+
+static inline void update_refresh_timer(u32 clock)
+{
+ u32 rt = (refresh_timer >> (clock >> 29));
+
+ if (unlikely(!rt)) {
+ pr_warning("Cannot adapt the Dynamic Memory Refresh Timer: "
+ "clock=0x%08x, rftimer=0x%08x",
+ clock, refresh_timer);
+ rt = 1;
+ } else {
+ if (unlikely(rt > 0x7ff))
+ rt = 0x7ff;
+ pr_debug("%s: MEM_DMRT <- 0x%08x\n", __func__, rt);
+ }
+ __raw_writel(rt, MEM_DMRT);
+}
+
+static int ns921x_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct cpufreq_freqs freqs;
+ unsigned long flags;
+ u32 cssel = 0;
+ u32 clock;
+
+ pr_debug("%s\n", __func__);
+ if (policy->policy == CPUFREQ_POLICY_PERFORMANCE)
+ cssel = SYS_CLOCK_CSSEL;
+
+ clock = ns921x_freq2clock(target_freq, cssel);
+
+ pr_debug("%s: targetfreq = %u, relation = %u, new clock = %lx\n",
+ __func__, target_freq, relation, (unsigned long)clock);
+
+ if (relation == CPUFREQ_RELATION_H &&
+ cpuclock(clock) / 1000 != target_freq) {
+ clock += 1 << 29;
+ BUG_ON((clock >> 29) > 4);
+ }
+
+ freqs.cpu = policy->cpu;
+ freqs.old = policy->cur;
+
+ freqs.new = cpuclock(clock) / 1000;
+
+ pr_debug("%s: new = %u kHz, CLOCK=%lx\n", __func__, freqs.new,
+ (unsigned long)clock);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ local_irq_save(flags);
+
+ if (freqs.old > freqs.new)
+ update_refresh_timer(clock);
+
+ clock |= __raw_readl(SYS_CLOCK) & ~(SYS_CLOCK_CSC | SYS_CLOCK_CSSEL);
+
+ pr_debug("%s: SYS_CLOCK <- %x (%lu)\n", __func__, clock, cpuclock(clock));
+ __raw_writel(clock, SYS_CLOCK);
+
+ if (freqs.old < freqs.new)
+ update_refresh_timer(clock);
+
+ local_irq_restore(flags);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ pr_debug("/%s\n", __func__);
+
+ return 0;
+}
+
+static unsigned int ns921x_cpufreq_get(unsigned int cpu)
+{
+ BUG_ON(cpu);
+
+ return ns921x_cpuclock() / 1000;
+}
+
+static int ns921x_cpufreq_init(struct cpufreq_policy *policy)
+{
+ u32 clock = __raw_readl(SYS_CLOCK);
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
+ policy->cpuinfo.min_freq = cpuclock(4 << 29 | SYS_CLOCK_CSSEL) / 1000;
+ policy->cpuinfo.max_freq = cpuclock(SYS_CLOCK_CSSEL) / 1000;
+ policy->cpuinfo.transition_latency = 1; /* XXX ??? */
+ policy->cur = ns921x_cpufreq_get(0);
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+
+ refresh_timer = __raw_readl(MEM_DMRT) << (clock >> 29);
+
+ pr_info("ns921x CPU frequency change support initialized\n");
+ pr_debug("%s: cur = %u, min = %d, max = %d\n", __func__, policy->cur,
+ policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+
+ return 0;
+}
+
+static struct cpufreq_driver ns921x_cpufreq_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = ns921x_cpufreq_verify,
+ .target = ns921x_cpufreq_target,
+ .get = ns921x_cpufreq_get,
+ .init = ns921x_cpufreq_init,
+ .name = "ns921x",
+};
+#endif
+
+static struct map_desc ns921x_io_desc[] __initdata = {
+ { /* Memory Controller */
+ .virtual = io_p2v(0xa0700000),
+ .pfn = __phys_to_pfn(0xa0700000),
+ .length = 0x27c,
+ .type = MT_DEVICE,
+ },
+ { /* External DMA Module */
+ .virtual = io_p2v(0xa0800000),
+ .pfn = __phys_to_pfn(0xa0800000),
+ .length = 0x20,
+ .type = MT_DEVICE,
+ },
+ { /* System Control Module */
+ .virtual = io_p2v(0xa0900000),
+ .pfn = __phys_to_pfn(0xa0900000),
+ .length = 0x1000,
+ .type = MT_DEVICE,
+ },
+ { /* I/O Control Module */
+ .virtual = io_p2v(0xa0902000),
+ .pfn = __phys_to_pfn(0xa0902000),
+ .length = 0x90,
+ .type = MT_DEVICE,
+ },
+};
+
+void __init ns921x_map_io(void)
+{
+ iotable_init(ns921x_io_desc, ARRAY_SIZE(ns921x_io_desc));
+}
+
+static inline void ns921x_setclock(u32 mask, u32 value)
+{
+ u32 oldclock = __raw_readl(SYS_CLOCK), clock;
+
+ BUG_ON(value & ~mask);
+
+ clock = (oldclock & ~mask) | value;
+
+ __raw_writel(clock, SYS_CLOCK);
+}
+
+static inline void ns921x_setreset(u32 mask, u32 value)
+{
+ u32 oldreset = __raw_readl(SYS_RESET), reset;
+
+ BUG_ON(value & ~mask);
+
+ reset = (oldreset & ~mask) | value;
+
+ if (reset != oldreset)
+ __raw_writel(reset, SYS_RESET);
+}
+
+int ns921x_endisable_sysclock(struct clk *clk, int enable)
+{
+ struct ns921x_sysclk *sysclk =
+ container_of(clk, struct ns921x_sysclk, clk);
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if (enable) {
+ ns921x_setreset(sysclk->mask, sysclk->mask);
+ ns921x_setclock(sysclk->mask, sysclk->mask);
+ } else {
+ ns921x_setclock(sysclk->mask, 0);
+#if defined(CONFIG_RESET_DISABLED_MODULES)
+ ns921x_setreset(sysclk->mask, 0);
+#endif
+ }
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+void ns921x_init_machine(void)
+{
+ /* register system, ahb and cpu clocks */
+ struct clk *clk = kzalloc(3 * sizeof(*clk), GFP_KERNEL);
+ struct ns921x_sysclk *dmaclk;
+ int ret, i;
+
+ if (!clk) {
+ pr_warning("%s: could not register system clocks\n", __func__);
+ return;
+ }
+
+ clk[0].name = "systemclock";
+ clk[0].get_rate = ns921x_get_systemclock_rate;
+
+ clk[1].name = "ahbclock";
+ clk[1].get_rate = ns921x_get_ahbclock_rate;
+
+ clk[2].name = "cpuclock";
+ clk[2].get_rate = ns921x_get_cpuclock_rate;
+
+ for (i = 0; i < 3; ++i) {
+ clk[i].id = -1;
+ ret = clk_register(&clk[i]);
+ if (ret)
+ pr_warning("%s: could not register %s\n",
+ __func__, clk[i].name);
+ }
+
+ dmaclk = kzalloc(sizeof(*dmaclk), GFP_KERNEL);
+ if (!dmaclk) {
+ pr_warning("%s: could not register dma clock\n", __func__);
+ return;
+ }
+
+ dmaclk->clk.name = "dmaclock";
+ dmaclk->clk.id = -1;
+ dmaclk->clk.endisable = ns921x_endisable_sysclock;
+ dmaclk->clk.owner = THIS_MODULE;
+ dmaclk->mask = 1 << 14;
+
+ ret = clk_register(&dmaclk->clk);
+ if (ret)
+ pr_warning("%s: could not register dma clock\n", __func__);
+
+#if defined(CONFIG_CPU_FREQ)
+ cpufreq_register_driver(&ns921x_cpufreq_driver);
+#endif
+
+ /* add system GPIOs */
+ ns921x_gpio_init();
+}
diff --git a/arch/arm/mach-ns9xxx/processor-ns921x.h b/arch/arm/mach-ns9xxx/processor-ns921x.h
new file mode 100644
index 000000000000..a5c91a63c911
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/processor-ns921x.h
@@ -0,0 +1,44 @@
+/*
+ * arch/arm/mach-ns9xxx/processor-ns921x.h
+ *
+ * Copyright (C) 2007,2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __NS9XXX_PROCESSOR_NS921X_H
+#define __NS9XXX_PROCESSOR_NS921X_H
+#include <linux/init.h>
+
+#include "clock.h"
+
+#define NS921X_REFCLOCK 29491200
+
+void ns921x_reset(char mode);
+
+unsigned long ns921x_systemclock(void) __attribute__((const));
+
+unsigned long ns921x_ahbclock(void) __attribute__((const));
+
+void __init ns921x_map_io(void);
+
+extern struct sys_timer ns921x_timer;
+
+struct ns921x_sysclk {
+ struct clk clk;
+ u32 mask;
+};
+/*
+ * only use ns921x_endisable_sysclock as callback for struct ns921x_sysclk's
+ * because there is no additional locking to serialize access to SYS_CLOCK.
+ */
+int ns921x_endisable_sysclock(struct clk *clk, int enable);
+
+void __init ns921x_init_machine(void);
+
+/* irq-ns921x.c */
+int ns921x_set_wake_irq(unsigned int irq, unsigned int on);
+
+#endif /* ifndef __NS9XXX_PROCESSOR_NS921X_H */
diff --git a/arch/arm/mach-ns9xxx/processor-ns9360.c b/arch/arm/mach-ns9xxx/processor-ns9360.c
index abee8338735d..ca9475ed1b62 100644
--- a/arch/arm/mach-ns9xxx/processor-ns9360.c
+++ b/arch/arm/mach-ns9xxx/processor-ns9360.c
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-ns9xxx/processor-ns9360.c
*
- * Copyright (C) 2007 by Digi International Inc.
+ * Copyright (C) 2007,2008 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,9 +14,14 @@
#include <asm/page.h>
#include <asm/mach/map.h>
-#include <mach/processor-ns9360.h>
+
#include <mach/regs-sys-ns9360.h>
+#include "clock.h"
+
+#include "processor-ns9360.h"
+#include "gpiolib-ns9360.h"
+
void ns9360_reset(char mode)
{
u32 reg;
@@ -34,6 +39,36 @@ unsigned long ns9360_systemclock(void)
>> REGGETIM(pll, SYS_PLL, FS);
}
+unsigned long ns9360_cpuclock(void)
+{
+ return ns9360_systemclock() / 2;
+}
+
+unsigned long ns9360_ahbclock(void)
+{
+ return ns9360_systemclock() / 4;
+}
+
+static unsigned long ns9360_get_systemclock_rate(struct clk *clk)
+{
+ return ns9360_systemclock();
+}
+
+static unsigned long ns9360_get_bbusclock_rate(struct clk *clk)
+{
+ return ns9360_systemclock() / 8;
+}
+
+static unsigned long ns9360_get_cpuclock_rate(struct clk *clk)
+{
+ return ns9360_cpuclock();
+}
+
+static unsigned long ns9360_get_ahbclock_rate(struct clk *clk)
+{
+ return ns9360_ahbclock();
+}
+
static struct map_desc ns9360_io_desc[] __initdata = {
{ /* BBus */
.virtual = io_p2v(0x90000000),
@@ -52,3 +87,39 @@ void __init ns9360_map_io(void)
{
iotable_init(ns9360_io_desc, ARRAY_SIZE(ns9360_io_desc));
}
+
+void ns9360_init_machine(void)
+{
+ /* register system, bbus and cpu clocks */
+ struct clk *clk = kzalloc(4 * sizeof(*clk), GFP_KERNEL);
+ int ret, i;
+
+ if (!clk) {
+ pr_warning("%s: could not register system clocks\n", __func__);
+ return;
+ }
+
+ clk[0].name = "systemclock";
+ clk[0].get_rate = ns9360_get_systemclock_rate;
+
+ clk[1].name = "bbusclock";
+ clk[1].get_rate = ns9360_get_bbusclock_rate;
+
+ clk[2].name = "cpuclock";
+ clk[2].get_rate = ns9360_get_cpuclock_rate;
+
+ clk[3].name = "ahbclock";
+ clk[3].get_rate = ns9360_get_ahbclock_rate;
+
+ for (i = 0; i < 4; ++i) {
+ clk[i].id = -1;
+ ret = clk_register(&clk[i]);
+ if (ret)
+ pr_warning("%s: could not register %s\n",
+ __func__, clk[i].name);
+
+ }
+
+ /* add system GPIOs */
+ ns9360_gpio_init();
+}
diff --git a/arch/arm/mach-ns9xxx/processor-ns9360.h b/arch/arm/mach-ns9xxx/processor-ns9360.h
new file mode 100644
index 000000000000..7fbb79e0cbb1
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/processor-ns9360.h
@@ -0,0 +1,30 @@
+/*
+ * arch/arm/mach-ns9xxx/processor-ns9360.h
+ *
+ * Copyright (C) 2007,2008 by Digi International Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+#ifndef __NS9XXX_PROCESSOR_NS9360_H
+#define __NS9XXX_PROCESSOR_NS9360_H
+
+#include <linux/init.h>
+
+#include "clock.h"
+
+void ns9360_reset(char mode);
+
+unsigned long ns9360_systemclock(void) __attribute__((const));
+
+unsigned long ns9360_cpuclock(void) __attribute__((const));
+
+void __init ns9360_map_io(void);
+
+extern struct sys_timer ns9360_timer;
+
+void __init ns9360_init_machine(void);
+
+#endif /* ifndef __NS9XXX_PROCESSOR_NS9360_H */
diff --git a/arch/arm/mach-ns9xxx/time-ns921x.c b/arch/arm/mach-ns9xxx/time-ns921x.c
new file mode 100644
index 000000000000..5e5d54608e00
--- /dev/null
+++ b/arch/arm/mach-ns9xxx/time-ns921x.c
@@ -0,0 +1,195 @@
+/*
+ * arch/arm/mach-ns9xxx/time-ns921x.c
+ *
+ * Copyright (C) 2007 by Digi International Inc.
+ * All rights reserved.
+ *
+ * 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/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/stringify.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+
+#include <mach/regs-sys-ns921x.h>
+#include <mach/irqs.h>
+
+#include "irq.h"
+#include "processor-ns921x.h"
+
+#define TIMER_CLOCKSOURCE 0
+#define TIMER_CLOCKEVENT 1
+static u32 latch;
+
+static cycle_t ns921x_clocksource_read(void)
+{
+ return __raw_readl(SYS_TRC(TIMER_CLOCKSOURCE));
+}
+
+static struct clocksource ns921x_clocksource = {
+ .name = "ns921x-timer" __stringify(TIMER_CLOCKSOURCE),
+ .rating = 300,
+ .read = ns921x_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 20,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void ns921x_clockevent_setmode(enum clock_event_mode mode,
+ struct clock_event_device *clk)
+{
+ u32 oldtc, tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+ oldtc = tc;
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ __raw_writel(latch, SYS_TRCC(TIMER_CLOCKEVENT));
+ REGSET(tc, SYS_TCx, RELENBL, EN);
+ REGSET(tc, SYS_TCx, INTSEL, EN);
+ REGSET(tc, SYS_TCx, TE, EN);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ REGSET(tc, SYS_TCx, RELENBL, DIS);
+ REGSET(tc, SYS_TCx, INTSEL, EN);
+ REGSET(tc, SYS_TCx, TE, DIS);
+ break;
+
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ default:
+ REGSET(tc, SYS_TCx, TE, DIS);
+ break;
+ }
+
+ /* ack an possibly pending irq
+ * This might stuck the irq priority encoder, but only until the next
+ * timer irq ... */
+ if (REGGET(tc, SYS_TCx, TE) == SYS_TCx_TE_DIS &&
+ REGGET(oldtc, SYS_TCx, TE) == SYS_TCx_TE_EN) {
+ REGSETIM(tc, SYS_TCx, INTCLR, 1);
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+ REGSETIM(tc, SYS_TCx, INTCLR, 0);
+ }
+
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+}
+
+static int ns921x_clockevent_setnextevent(unsigned long evt,
+ struct clock_event_device *clk)
+{
+ u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+
+ if (REGGET(tc, SYS_TCx, TE)) {
+ REGSET(tc, SYS_TCx, TE, DIS);
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+ }
+
+ REGSET(tc, SYS_TCx, TE, EN);
+
+ __raw_writel(evt, SYS_TRCC(TIMER_CLOCKEVENT));
+
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+
+ return 0;
+}
+
+static struct clock_event_device ns921x_clockevent_device = {
+ .name = "ns921x-timer" __stringify(TIMER_CLOCKEVENT),
+ .shift = 20,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = ns921x_clockevent_setmode,
+ .set_next_event = ns921x_clockevent_setnextevent,
+};
+
+static irqreturn_t ns921x_clockevent_handler(int irq, void *dev_id)
+{
+ int timerno = irq - IRQ_NS921X_TIMER0;
+ u32 tc;
+
+ struct clock_event_device *evt = &ns921x_clockevent_device;
+
+ /* clear irq */
+ tc = __raw_readl(SYS_TC(timerno));
+ if (REGGET(tc, SYS_TCx, RELENBL) == SYS_TCx_RELENBL_DIS) {
+ REGSET(tc, SYS_TCx, TE, DIS);
+ __raw_writel(tc, SYS_TC(timerno));
+ }
+ REGSETIM(tc, SYS_TCx, INTCLR, 1);
+ __raw_writel(tc, SYS_TC(timerno));
+ REGSETIM(tc, SYS_TCx, INTCLR, 0);
+ __raw_writel(tc, SYS_TC(timerno));
+
+ evt->event_handler(evt);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction ns921x_clockevent_action = {
+ .name = "ns921x-timer" __stringify(TIMER_CLOCKEVENT),
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+ .handler = ns921x_clockevent_handler,
+};
+
+static void __init ns921x_timer_init(void)
+{
+ int tc;
+
+ tc = __raw_readl(SYS_TC(TIMER_CLOCKSOURCE));
+ if (REGGET(tc, SYS_TCx, TE)) {
+ REGSET(tc, SYS_TCx, TE, DIS);
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
+ }
+
+ __raw_writel(0, SYS_TRC(TIMER_CLOCKSOURCE));
+
+ REGSET(tc, SYS_TCx, TE, EN);
+ REGSET(tc, SYS_TCx, DEBUG, STOP);
+ REGSET(tc, SYS_TCx, TCS, 2AHB);
+ REGSET(tc, SYS_TCx, MODE, INTERNAL);
+ REGSET(tc, SYS_TCx, INTSEL, DIS);
+ REGSET(tc, SYS_TCx, UPDOWN, UP);
+ REGSET(tc, SYS_TCx, BITTIMER, 32);
+ REGSET(tc, SYS_TCx, RELENBL, EN);
+
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
+
+ ns921x_clocksource.mult = clocksource_hz2mult(ns921x_ahbclock() * 2,
+ ns921x_clocksource.shift);
+
+ clocksource_register(&ns921x_clocksource);
+
+ latch = SH_DIV(ns921x_ahbclock() * 2, HZ, 0);
+
+ tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT));
+ REGSET(tc, SYS_TCx, TE, DIS);
+ REGSET(tc, SYS_TCx, DEBUG, STOP);
+ REGSET(tc, SYS_TCx, TCS, 2AHB);
+ REGSET(tc, SYS_TCx, MODE, INTERNAL);
+ REGSET(tc, SYS_TCx, INTSEL, DIS);
+ REGSET(tc, SYS_TCx, UPDOWN, DOWN);
+ REGSET(tc, SYS_TCx, BITTIMER, 32);
+ REGSET(tc, SYS_TCx, RELENBL, EN);
+ __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT));
+
+ ns921x_clockevent_device.mult = div_sc(ns921x_ahbclock() * 2,
+ NSEC_PER_SEC, ns921x_clockevent_device.shift);
+ ns921x_clockevent_device.max_delta_ns =
+ clockevent_delta2ns(-1, &ns921x_clockevent_device);
+ ns921x_clockevent_device.min_delta_ns =
+ clockevent_delta2ns(1, &ns921x_clockevent_device);
+
+ ns921x_clockevent_device.cpumask = cpumask_of_cpu(0);
+ clockevents_register_device(&ns921x_clockevent_device);
+
+ setup_irq(IRQ_NS921X_TIMER0 + TIMER_CLOCKEVENT,
+ &ns921x_clockevent_action);
+}
+
+struct sys_timer ns921x_timer = {
+ .init = ns921x_timer_init,
+};
diff --git a/arch/arm/mach-ns9xxx/time-ns9360.c b/arch/arm/mach-ns9xxx/time-ns9360.c
index a63424d083d9..553617eba15a 100644
--- a/arch/arm/mach-ns9xxx/time-ns9360.c
+++ b/arch/arm/mach-ns9xxx/time-ns9360.c
@@ -15,11 +15,12 @@
#include <linux/clocksource.h>
#include <linux/clockchips.h>
-#include <mach/processor-ns9360.h>
#include <mach/regs-sys-ns9360.h>
#include <mach/irqs.h>
#include <mach/system.h>
-#include "generic.h"
+
+#include "irq.h"
+#include "processor-ns9360.h"
#define TIMER_CLOCKSOURCE 0
#define TIMER_CLOCKEVENT 1