diff options
author | Jesper Nilsson <jesper@jni.nu> | 2018-03-11 13:05:23 +0300 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2018-03-16 12:56:05 +0300 |
commit | c690eddc2f3b44b24520f4a77cc3a4c9bde7d571 (patch) | |
tree | b7ba2caa6ebb2e36a529f9bf7182c9e0a73d53c4 /arch/cris/arch-v10/drivers | |
parent | bb9d812643d8a121df7d614a2b9c60193a92deb0 (diff) | |
download | linux-c690eddc2f3b44b24520f4a77cc3a4c9bde7d571.tar.xz |
CRIS: Drop support for the CRIS port
The port was added back in 2000 so it's no longer even a good source
of inspiration for newer ports (if it ever was)
The last SoC (ARTPEC-3) with a CRIS main CPU was launched in 2008.
Coupled with time and working developer board hardware being
in low supply, it's time to drop the port from Linux.
So long and thanks for all the fish!
Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/cris/arch-v10/drivers')
-rw-r--r-- | arch/cris/arch-v10/drivers/Kconfig | 561 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/Makefile | 11 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/axisflashmap.c | 413 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/eeprom.c | 852 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/gpio.c | 857 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/i2c.c | 699 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/i2c.h | 18 | ||||
-rw-r--r-- | arch/cris/arch-v10/drivers/sync_serial.c | 1463 |
8 files changed, 0 insertions, 4874 deletions
diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig deleted file mode 100644 index 8792af63c049..000000000000 --- a/arch/cris/arch-v10/drivers/Kconfig +++ /dev/null @@ -1,561 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -if ETRAX_ARCH_V10 - -config ETRAX_ETHERNET - bool "Ethernet support" - depends on ETRAX_ARCH_V10 && NETDEVICES - select MII - help - This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet - controller. - -config ETRAX_SERIAL - bool "Serial-port support" - depends on ETRAX_ARCH_V10 - help - Enables the ETRAX 100 serial driver for ser0 (ttyS0) - You probably want this enabled. - -config ETRAX_SERIAL_FAST_TIMER - bool "Use fast timers for serial DMA flush (experimental)" - depends on ETRAX_SERIAL - help - Select this to have the serial DMAs flushed at a higher rate than - normally, possible by using the fast timer API, the timeout is - approx. 4 character times. - If unsure, say N. - -config ETRAX_SERIAL_FLUSH_DMA_FAST - bool "Fast serial port DMA flush" - depends on ETRAX_SERIAL && !ETRAX_SERIAL_FAST_TIMER - help - Select this to have the serial DMAs flushed at a higher rate than - normally possible through a fast timer interrupt (currently at - 15360 Hz). - If unsure, say N. - -config ETRAX_SERIAL_RX_TIMEOUT_TICKS - int "Receive flush timeout (ticks) " - depends on ETRAX_SERIAL && !ETRAX_SERIAL_FAST_TIMER && !ETRAX_SERIAL_FLUSH_DMA_FAST - default "5" - help - Number of timer ticks between flush of receive fifo (1 tick = 10ms). - Try 0-3 for low latency applications. Approx 5 for high load - applications (e.g. PPP). Maybe this should be more adaptive some - day... - -config ETRAX_SERIAL_PORT0 - bool "Serial port 0 enabled" - depends on ETRAX_SERIAL - help - Enables the ETRAX 100 serial driver for ser0 (ttyS0) - Normally you want this on, unless you use external DMA 1 that uses - the same DMA channels. - -choice - prompt "Ser0 DTR, RI, DSR and CD assignment" - depends on ETRAX_SERIAL_PORT0 - default ETRAX_SER0_DTR_RI_DSR_CD_ON_NONE - -config ETRAX_SER0_DTR_RI_DSR_CD_ON_NONE - bool "No_DTR_RI_DSR_CD" - -config ETRAX_SER0_DTR_RI_DSR_CD_ON_PA - bool "DTR_RI_DSR_CD_on_PA" - -config ETRAX_SER0_DTR_RI_DSR_CD_ON_PB - bool "DTR_RI_DSR_CD_on_PB" - help - Enables the status and control signals DTR, RI, DSR and CD on PB for - ser0. - -config ETRAX_SER0_DTR_RI_DSR_CD_MIXED - bool "DTR_RI_DSR_CD_mixed_on_PA_and_PB" - -endchoice - -config ETRAX_SER0_DTR_ON_PA_BIT - int "Ser0 DTR on PA bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT0 - default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED - default "4" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER0_RI_ON_PA_BIT - int "Ser0 RI on PA bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT0 - default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED - default "5" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER0_DSR_ON_PA_BIT - int "Ser0 DSR on PA bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT0 - default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED - default "6" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER0_CD_ON_PA_BIT - int "Ser0 CD on PA bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT0 - default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED - default "7" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PA || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER0_DTR_ON_PB_BIT - int "Ser0 DTR on PB bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT0 - default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED - default "4" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PB port to carry the DTR signal for serial - port 0. - -config ETRAX_SER0_RI_ON_PB_BIT - int "Ser0 RI on PB bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT0 - default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED - default "5" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PB port to carry the RI signal for serial - port 0. - -config ETRAX_SER0_DSR_ON_PB_BIT - int "Ser0 DSR on PB bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT0 - default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED - default "6" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PB port to carry the DSR signal for serial - port 0. - -config ETRAX_SER0_CD_ON_PB_BIT - int "Ser0 CD on PB bit (-1 = not used)" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT0 - default "-1" if !ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER0_DTR_RI_DSR_CD_MIXED - default "7" if ETRAX_SER0_DTR_RI_DSR_CD_ON_PB || ETRAX_SER0_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PB port to carry the CD signal for serial - port 0. - -config ETRAX_SERIAL_PORT1 - bool "Serial port 1 enabled" - depends on ETRAX_SERIAL - help - Enables the ETRAX 100 serial driver for ser1 (ttyS1). - -choice - prompt "Ser1 DTR, RI, DSR and CD assignment" - depends on ETRAX_SERIAL_PORT1 - default ETRAX_SER1_DTR_RI_DSR_CD_ON_NONE - -config ETRAX_SER1_DTR_RI_DSR_CD_ON_NONE - bool "No_DTR_RI_DSR_CD" - -config ETRAX_SER1_DTR_RI_DSR_CD_ON_PA - bool "DTR_RI_DSR_CD_on_PA" - -config ETRAX_SER1_DTR_RI_DSR_CD_ON_PB - bool "DTR_RI_DSR_CD_on_PB" - help - Enables the status and control signals DTR, RI, DSR and CD on PB for - ser1. - -config ETRAX_SER1_DTR_RI_DSR_CD_MIXED - bool "DTR_RI_DSR_CD_mixed_on_PA_and_PB" - -endchoice - -config ETRAX_SER1_DTR_ON_PA_BIT - int "Ser1 DTR on PA bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT1 - default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED - default "4" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER1_RI_ON_PA_BIT - int "Ser1 RI on PA bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT1 - default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED - default "5" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER1_DSR_ON_PA_BIT - int "Ser1 DSR on PA bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT1 - default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED - default "6" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER1_CD_ON_PA_BIT - int "Ser1 CD on PA bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT1 - default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED - default "7" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PA || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER1_DTR_ON_PB_BIT - int "Ser1 DTR on PB bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT1 - default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED - default "4" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PB port to carry the DTR signal for serial - port 1. - -config ETRAX_SER1_RI_ON_PB_BIT - int "Ser1 RI on PB bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT1 - default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED - default "5" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PB port to carry the RI signal for serial - port 1. - -config ETRAX_SER1_DSR_ON_PB_BIT - int "Ser1 DSR on PB bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT1 - default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED - default "6" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PB port to carry the DSR signal for serial - port 1. - -config ETRAX_SER1_CD_ON_PB_BIT - int "Ser1 CD on PB bit (-1 = not used)" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT1 - default "-1" if !ETRAX_SER1_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER1_DTR_RI_DSR_CD_MIXED - default "7" if ETRAX_SER1_DTR_RI_DSR_CD_ON_PB || ETRAX_SER1_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PB port to carry the CD signal for serial - port 1. - -comment "Make sure you do not have the same PB bits more than once!" - depends on ETRAX_SERIAL && ETRAX_SER0_DTR_RI_DSR_CD_ON_PB && ETRAX_SER1_DTR_RI_DSR_CD_ON_PB - -config ETRAX_SERIAL_PORT2 - bool "Serial port 2 enabled" - depends on ETRAX_SERIAL - help - Enables the ETRAX 100 serial driver for ser2 (ttyS2). - -choice - prompt "Ser2 DTR, RI, DSR and CD assignment" - depends on ETRAX_SERIAL_PORT2 - default ETRAX_SER2_DTR_RI_DSR_CD_ON_NONE - -config ETRAX_SER2_DTR_RI_DSR_CD_ON_NONE - bool "No_DTR_RI_DSR_CD" - -config ETRAX_SER2_DTR_RI_DSR_CD_ON_PA - bool "DTR_RI_DSR_CD_on_PA" - help - Enables the status and control signals DTR, RI, DSR and CD on PA for - ser2. - -config ETRAX_SER2_DTR_RI_DSR_CD_ON_PB - bool "DTR_RI_DSR_CD_on_PB" - -config ETRAX_SER2_DTR_RI_DSR_CD_MIXED - bool "DTR_RI_DSR_CD_mixed_on_PA_and_PB" - -endchoice - -config ETRAX_SER2_DTR_ON_PA_BIT - int "Ser2 DTR on PA bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT2 - default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED - default "4" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PA port to carry the DTR signal for serial - port 2. - -config ETRAX_SER2_RI_ON_PA_BIT - int "Ser2 RI on PA bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT2 - default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED - default "5" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PA port to carry the RI signal for serial - port 2. - -config ETRAX_SER2_DSR_ON_PA_BIT - int "Ser2 DSR on PA bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT2 - default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED - default "6" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PA port to carry the DTR signal for serial - port 2. - -config ETRAX_SER2_CD_ON_PA_BIT - int "Ser2 CD on PA bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT2 - default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PA && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED - default "7" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PA || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - help - Specify the pin of the PA port to carry the CD signal for serial - port 2. - -config ETRAX_SER2_DTR_ON_PB_BIT - int "Ser2 DTR on PB bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT2 - default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED - default "4" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER2_RI_ON_PB_BIT - int "Ser2 RI on PB bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT2 - default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED - default "5" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER2_DSR_ON_PB_BIT - int "Ser2 DSR on PB bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT2 - default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED - default "6" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - -config ETRAX_SER2_CD_ON_PB_BIT - int "Ser2 CD on PB bit (-1 = not used)" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT2 - default "-1" if !ETRAX_SER2_DTR_RI_DSR_CD_ON_PB && !ETRAX_SER2_DTR_RI_DSR_CD_MIXED - default "7" if ETRAX_SER2_DTR_RI_DSR_CD_ON_PB || ETRAX_SER2_DTR_RI_DSR_CD_MIXED - -config ETRAX_SERIAL_PORT3 - bool "Serial port 3 enabled" - depends on ETRAX_SERIAL - help - Enables the ETRAX 100 serial driver for ser3 (ttyS3). - -choice - prompt "Ser3 DTR, RI, DSR and CD assignment" - depends on ETRAX_SERIAL_PORT3 - default ETRAX_SER3_DTR_RI_DSR_CD_ON_NONE - -config ETRAX_SER3_DTR_RI_DSR_CD_ON_NONE - bool "No_DTR_RI_DSR_CD" - -config ETRAX_SER3_DTR_RI_DSR_CD_ON_PA - bool "DTR_RI_DSR_CD_on_PA" - -config ETRAX_SER3_DTR_RI_DSR_CD_ON_PB - bool "DTR_RI_DSR_CD_on_PB" - -config ETRAX_SER3_DTR_RI_DSR_CD_MIXED - bool "DTR_RI_DSR_CD_mixed_on_PA_and_PB" - -endchoice - -config ETRAX_SER3_DTR_ON_PA_BIT - int "Ser3 DTR on PA bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PA || ETRAX_SER3_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT3 - default "-1" - -config ETRAX_SER3_RI_ON_PA_BIT - int "Ser3 RI on PA bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PA || ETRAX_SER3_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT3 - default "-1" - -config ETRAX_SER3_DSR_ON_PA_BIT - int "Ser3 DSR on PA bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PA || ETRAX_SER3_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT3 - default "-1" - -config ETRAX_SER3_CD_ON_PA_BIT - int "Ser3 CD on PA bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PA || ETRAX_SER3_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT3 - default "-1" - -config ETRAX_SER3_DTR_ON_PB_BIT - int "Ser3 DTR on PB bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PB || ETRAX_SER3_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT3 - default "-1" - -config ETRAX_SER3_RI_ON_PB_BIT - int "Ser3 RI on PB bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PB || ETRAX_SER3_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT3 - default "-1" - -config ETRAX_SER3_DSR_ON_PB_BIT - int "Ser3 DSR on PB bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PB || ETRAX_SER3_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT3 - default "-1" - -config ETRAX_SER3_CD_ON_PB_BIT - int "Ser3 CD on PB bit (-1 = not used)" if ETRAX_SER3_DTR_RI_DSR_CD_ON_PB || ETRAX_SER3_DTR_RI_DSR_CD_MIXED - depends on ETRAX_SERIAL_PORT3 - default "-1" - -config ETRAX_RS485 - bool "RS-485 support" - depends on ETRAX_SERIAL - help - Enables support for RS-485 serial communication. For a primer on - RS-485, see <http://en.wikipedia.org/wiki/Rs485> - -config ETRAX_RS485_ON_PA - bool "RS-485 mode on PA" - depends on ETRAX_RS485 - help - Control Driver Output Enable on RS485 transceiver using a pin on PA - port: - Axis 2400/2401 uses PA 3. - -config ETRAX_RS485_ON_PA_BIT - int "RS-485 mode on PA bit" - depends on ETRAX_RS485_ON_PA - default "3" - help - Control Driver Output Enable on RS485 transceiver using a this bit - on PA port. - -config ETRAX_RS485_DISABLE_RECEIVER - bool "Disable serial receiver" - depends on ETRAX_RS485 - help - It's necessary to disable the serial receiver to avoid serial - loopback. Not all products are able to do this in software only. - Axis 2400/2401 must disable receiver. - -config ETRAX_USB_HOST - bool "USB host" - select USB - help - This option enables the host functionality of the ETRAX 100LX - built-in USB controller. In host mode the controller is designed - for CTRL and BULK traffic only, INTR traffic may work as well - however (depending on the requirements of timeliness). - -config ETRAX_PTABLE_SECTOR - int "Byte-offset of partition table sector" - depends on ETRAX_AXISFLASHMAP - default "65536" - help - Byte-offset of the partition table in the first flash chip. - The default value is 64kB and should not be changed unless - you know exactly what you are doing. The only valid reason - for changing this is when the flash block size is bigger - than 64kB (e.g. when using two parallel 16 bit flashes). - -config ETRAX_I2C - bool "I2C support" - depends on ETRAX_ARCH_V10 - help - Enables an I2C driver on ETRAX100. - EXAMPLE usage: - i2c_arg = I2C_WRITEARG(STA013_WRITE_ADDR, reg, val); - ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_WRITEREG), i2c_arg); - i2c_arg = I2C_READARG(STA013_READ_ADDR, reg); - val = ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_READREG), i2c_arg); - -# this is true for most products since PB-I2C seems to be somewhat -# flawed.. -config ETRAX_I2C_USES_PB_NOT_PB_I2C - bool "I2C uses PB not PB-I2C" - depends on ETRAX_I2C - help - Select whether to use the special I2C mode in the PB I/O register or - not. This option needs to be selected in order to use some drivers - that access the I2C I/O pins directly instead of going through the - I2C driver, like the DS1302 realtime-clock driver. If you are - uncertain, choose Y here. - -config ETRAX_I2C_DATA_PORT - int "I2C SDA bit number" - depends on ETRAX_I2C_USES_PB_NOT_PB_I2C - default "0" - help - Selects the pin on Port B where the data pin is connected - -config ETRAX_I2C_CLK_PORT - int "I2C SCL bit number" - depends on ETRAX_I2C_USES_PB_NOT_PB_I2C - default "1" - help - Select the pin on Port B where the clock pin is connected - -config ETRAX_I2C_EEPROM - bool "I2C EEPROM (non-volatile RAM) support" - depends on ETRAX_I2C - help - Enables I2C EEPROM (non-volatile RAM) on PB0 and PB1 using the I2C - driver. Select size option: Probed, 2k, 8k, 16k. - (Probing works for 2k and 8k but not that well for 16k) - -choice - prompt "EEPROM size" - depends on ETRAX_I2C_EEPROM - default ETRAX_I2C_EEPROM_PROBE - -config ETRAX_I2C_EEPROM_PROBE - bool "Probed" - help - Specifies size or auto probe of the EEPROM size. - Options: Probed, 2k, 8k, 16k. - (Probing works for 2k and 8k but not that well for 16k) - -config ETRAX_I2C_EEPROM_2KB - bool "2kB" - help - Use a 2kB EEPROM. - -config ETRAX_I2C_EEPROM_8KB - bool "8kB" - help - Use a 8kB EEPROM. - -config ETRAX_I2C_EEPROM_16KB - bool "16kB" - help - Use a 16kB EEPROM. - -endchoice - -config ETRAX_GPIO - bool "GPIO support" - depends on ETRAX_ARCH_V10 - ---help--- - Enables the ETRAX general port device (major 120, minors 0 and 1). - You can use this driver to access the general port bits. It supports - these ioctl's: - #include <linux/etraxgpio.h> - fd = open("/dev/gpioa", O_RDWR); // or /dev/gpiob - ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), bits_to_set); - ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), bits_to_clear); - val = ioctl(fd, _IO(ETRAXGPIO_IOCTYPE, IO_READBITS), NULL); - Remember that you need to setup the port directions appropriately in - the General configuration. - -config ETRAX_PA_CHANGEABLE_DIR - hex "PA user changeable dir mask" - depends on ETRAX_GPIO - default "00" - help - This is a bitmask with information of what bits in PA that a user - can change direction on using ioctl's. - Bit set = changeable. - You probably want 00 here. - -config ETRAX_PA_CHANGEABLE_BITS - hex "PA user changeable bits mask" - depends on ETRAX_GPIO - default "FF" - help - This is a bitmask with information of what bits in PA that a user - can change the value on using ioctl's. - Bit set = changeable. - You probably want 00 here. - -config ETRAX_PB_CHANGEABLE_DIR - hex "PB user changeable dir mask" - depends on ETRAX_GPIO - default "00" - help - This is a bitmask with information of what bits in PB that a user - can change direction on using ioctl's. - Bit set = changeable. - You probably want 00 here. - -config ETRAX_PB_CHANGEABLE_BITS - hex "PB user changeable bits mask" - depends on ETRAX_GPIO - default "FF" - help - This is a bitmask with information of what bits in PB that a user - can change the value on using ioctl's. - Bit set = changeable. - You probably want 00 here. - -endif diff --git a/arch/cris/arch-v10/drivers/Makefile b/arch/cris/arch-v10/drivers/Makefile deleted file mode 100644 index d5549dca81bf..000000000000 --- a/arch/cris/arch-v10/drivers/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for Etrax-specific drivers -# - -obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o -obj-$(CONFIG_ETRAX_I2C) += i2c.o -obj-$(CONFIG_ETRAX_I2C_EEPROM) += eeprom.o -obj-$(CONFIG_ETRAX_GPIO) += gpio.o -obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL) += sync_serial.o - diff --git a/arch/cris/arch-v10/drivers/axisflashmap.c b/arch/cris/arch-v10/drivers/axisflashmap.c deleted file mode 100644 index 28292da49664..000000000000 --- a/arch/cris/arch-v10/drivers/axisflashmap.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Physical mapping layer for MTD using the Axis partitiontable format - * - * Copyright (c) 2001, 2002 Axis Communications AB - * - * This file is under the GPL. - * - * First partition is always sector 0 regardless of if we find a partitiontable - * or not. In the start of the next sector, there can be a partitiontable that - * tells us what other partitions to define. If there isn't, we use a default - * partition split defined below. - * - */ - -#include <linux/module.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> - -#include <linux/mtd/concat.h> -#include <linux/mtd/map.h> -#include <linux/mtd/mtd.h> -#include <linux/mtd/mtdram.h> -#include <linux/mtd/partitions.h> - -#include <asm/axisflashmap.h> -#include <asm/mmu.h> -#include <arch/sv_addr_ag.h> - -#ifdef CONFIG_CRIS_LOW_MAP -#define FLASH_UNCACHED_ADDR KSEG_8 -#define FLASH_CACHED_ADDR KSEG_5 -#else -#define FLASH_UNCACHED_ADDR KSEG_E -#define FLASH_CACHED_ADDR KSEG_F -#endif - -#if CONFIG_ETRAX_FLASH_BUSWIDTH==1 -#define flash_data __u8 -#elif CONFIG_ETRAX_FLASH_BUSWIDTH==2 -#define flash_data __u16 -#elif CONFIG_ETRAX_FLASH_BUSWIDTH==4 -#define flash_data __u32 -#endif - -/* From head.S */ -extern unsigned long romfs_start, romfs_length, romfs_in_flash; - -/* The master mtd for the entire flash. */ -struct mtd_info* axisflash_mtd = NULL; - -/* Map driver functions. */ - -static map_word flash_read(struct map_info *map, unsigned long ofs) -{ - map_word tmp; - tmp.x[0] = *(flash_data *)(map->map_priv_1 + ofs); - return tmp; -} - -static void flash_copy_from(struct map_info *map, void *to, - unsigned long from, ssize_t len) -{ - memcpy(to, (void *)(map->map_priv_1 + from), len); -} - -static void flash_write(struct map_info *map, map_word d, unsigned long adr) -{ - *(flash_data *)(map->map_priv_1 + adr) = (flash_data)d.x[0]; -} - -/* - * The map for chip select e0. - * - * We run into tricky coherence situations if we mix cached with uncached - * accesses to we only use the uncached version here. - * - * The size field is the total size where the flash chips may be mapped on the - * chip select. MTD probes should find all devices there and it does not matter - * if there are unmapped gaps or aliases (mirrors of flash devices). The MTD - * probes will ignore them. - * - * The start address in map_priv_1 is in virtual memory so we cannot use - * MEM_CSE0_START but must rely on that FLASH_UNCACHED_ADDR is the start - * address of cse0. - */ -static struct map_info map_cse0 = { - .name = "cse0", - .size = MEM_CSE0_SIZE, - .bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH, - .read = flash_read, - .copy_from = flash_copy_from, - .write = flash_write, - .map_priv_1 = FLASH_UNCACHED_ADDR -}; - -/* - * The map for chip select e1. - * - * If there was a gap between cse0 and cse1, map_priv_1 would get the wrong - * address, but there isn't. - */ -static struct map_info map_cse1 = { - .name = "cse1", - .size = MEM_CSE1_SIZE, - .bankwidth = CONFIG_ETRAX_FLASH_BUSWIDTH, - .read = flash_read, - .copy_from = flash_copy_from, - .write = flash_write, - .map_priv_1 = FLASH_UNCACHED_ADDR + MEM_CSE0_SIZE -}; - -/* If no partition-table was found, we use this default-set. */ -#define MAX_PARTITIONS 7 -#define NUM_DEFAULT_PARTITIONS 3 - -/* - * Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the - * size of one flash block and "filesystem"-partition needs 5 blocks to be able - * to use JFFS. - */ -static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = { - { - .name = "boot firmware", - .size = CONFIG_ETRAX_PTABLE_SECTOR, - .offset = 0 - }, - { - .name = "kernel", - .size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR), - .offset = CONFIG_ETRAX_PTABLE_SECTOR - }, - { - .name = "filesystem", - .size = 5 * CONFIG_ETRAX_PTABLE_SECTOR, - .offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR) - } -}; - -/* Initialize the ones normally used. */ -static struct mtd_partition axis_partitions[MAX_PARTITIONS] = { - { - .name = "part0", - .size = CONFIG_ETRAX_PTABLE_SECTOR, - .offset = 0 - }, - { - .name = "part1", - .size = 0, - .offset = 0 - }, - { - .name = "part2", - .size = 0, - .offset = 0 - }, - { - .name = "part3", - .size = 0, - .offset = 0 - }, - { - .name = "part4", - .size = 0, - .offset = 0 - }, - { - .name = "part5", - .size = 0, - .offset = 0 - }, - { - .name = "part6", - .size = 0, - .offset = 0 - }, -}; - -/* - * Probe a chip select for AMD-compatible (JEDEC) or CFI-compatible flash - * chips in that order (because the amd_flash-driver is faster). - */ -static struct mtd_info *probe_cs(struct map_info *map_cs) -{ - struct mtd_info *mtd_cs = NULL; - - printk(KERN_INFO - "%s: Probing a 0x%08lx bytes large window at 0x%08lx.\n", - map_cs->name, map_cs->size, map_cs->map_priv_1); - -#ifdef CONFIG_MTD_CFI - mtd_cs = do_map_probe("cfi_probe", map_cs); -#endif -#ifdef CONFIG_MTD_JEDECPROBE - if (!mtd_cs) - mtd_cs = do_map_probe("jedec_probe", map_cs); -#endif - - return mtd_cs; -} - -/* - * Probe each chip select individually for flash chips. If there are chips on - * both cse0 and cse1, the mtd_info structs will be concatenated to one struct - * so that MTD partitions can cross chip boundaries. - * - * The only known restriction to how you can mount your chips is that each - * chip select must hold similar flash chips. But you need external hardware - * to do that anyway and you can put totally different chips on cse0 and cse1 - * so it isn't really much of a restriction. - */ -static struct mtd_info *flash_probe(void) -{ - struct mtd_info *mtd_cse0; - struct mtd_info *mtd_cse1; - struct mtd_info *mtd_cse; - - mtd_cse0 = probe_cs(&map_cse0); - mtd_cse1 = probe_cs(&map_cse1); - - if (!mtd_cse0 && !mtd_cse1) { - /* No chip found. */ - return NULL; - } - - if (mtd_cse0 && mtd_cse1) { - struct mtd_info *mtds[] = { mtd_cse0, mtd_cse1 }; - - /* Since the concatenation layer adds a small overhead we - * could try to figure out if the chips in cse0 and cse1 are - * identical and reprobe the whole cse0+cse1 window. But since - * flash chips are slow, the overhead is relatively small. - * So we use the MTD concatenation layer instead of further - * complicating the probing procedure. - */ - mtd_cse = mtd_concat_create(mtds, ARRAY_SIZE(mtds), - "cse0+cse1"); - if (!mtd_cse) { - printk(KERN_ERR "%s and %s: Concatenation failed!\n", - map_cse0.name, map_cse1.name); - - /* The best we can do now is to only use what we found - * at cse0. - */ - mtd_cse = mtd_cse0; - map_destroy(mtd_cse1); - } - } else { - mtd_cse = mtd_cse0? mtd_cse0 : mtd_cse1; - } - - return mtd_cse; -} - -/* - * Probe the flash chip(s) and, if it succeeds, read the partition-table - * and register the partitions with MTD. - */ -static int __init init_axis_flash(void) -{ - struct mtd_info *mymtd; - int err = 0; - int pidx = 0; - struct partitiontable_head *ptable_head = NULL; - struct partitiontable_entry *ptable; - int use_default_ptable = 1; /* Until proven otherwise. */ - const char pmsg[] = " /dev/flash%d at 0x%08x, size 0x%08x\n"; - - if (!(mymtd = flash_probe())) { - /* There's no reason to use this module if no flash chip can - * be identified. Make sure that's understood. - */ - printk(KERN_INFO "axisflashmap: Found no flash chip.\n"); - } else { - printk(KERN_INFO "%s: 0x%08x bytes of flash memory.\n", - mymtd->name, mymtd->size); - axisflash_mtd = mymtd; - } - - if (mymtd) { - mymtd->owner = THIS_MODULE; - ptable_head = (struct partitiontable_head *)(FLASH_CACHED_ADDR + - CONFIG_ETRAX_PTABLE_SECTOR + - PARTITION_TABLE_OFFSET); - } - pidx++; /* First partition is always set to the default. */ - - if (ptable_head && (ptable_head->magic == PARTITION_TABLE_MAGIC) - && (ptable_head->size < - (MAX_PARTITIONS * sizeof(struct partitiontable_entry) + - PARTITIONTABLE_END_MARKER_SIZE)) - && (*(unsigned long*)((void*)ptable_head + sizeof(*ptable_head) + - ptable_head->size - - PARTITIONTABLE_END_MARKER_SIZE) - == PARTITIONTABLE_END_MARKER)) { - /* Looks like a start, sane length and end of a - * partition table, lets check csum etc. - */ - int ptable_ok = 0; - struct partitiontable_entry *max_addr = - (struct partitiontable_entry *) - ((unsigned long)ptable_head + sizeof(*ptable_head) + - ptable_head->size); - unsigned long offset = CONFIG_ETRAX_PTABLE_SECTOR; - unsigned char *p; - unsigned long csum = 0; - - ptable = (struct partitiontable_entry *) - ((unsigned long)ptable_head + sizeof(*ptable_head)); - - /* Lets be PARANOID, and check the checksum. */ - p = (unsigned char*) ptable; - - while (p <= (unsigned char*)max_addr) { - csum += *p++; - csum += *p++; - csum += *p++; - csum += *p++; - } - ptable_ok = (csum == ptable_head->checksum); - - /* Read the entries and use/show the info. */ - printk(KERN_INFO " Found a%s partition table at 0x%p-0x%p.\n", - (ptable_ok ? " valid" : "n invalid"), ptable_head, - max_addr); - - /* We have found a working bootblock. Now read the - * partition table. Scan the table. It ends when - * there is 0xffffffff, that is, empty flash. - */ - while (ptable_ok - && ptable->offset != 0xffffffff - && ptable < max_addr - && pidx < MAX_PARTITIONS) { - - axis_partitions[pidx].offset = offset + ptable->offset; - axis_partitions[pidx].size = ptable->size; - - printk(pmsg, pidx, axis_partitions[pidx].offset, - axis_partitions[pidx].size); - pidx++; - ptable++; - } - use_default_ptable = !ptable_ok; - } - - if (romfs_in_flash) { - /* Add an overlapping device for the root partition (romfs). */ - - axis_partitions[pidx].name = "romfs"; - axis_partitions[pidx].size = romfs_length; - axis_partitions[pidx].offset = romfs_start - FLASH_CACHED_ADDR; - axis_partitions[pidx].mask_flags |= MTD_WRITEABLE; - - printk(KERN_INFO - " Adding readonly flash partition for romfs image:\n"); - printk(pmsg, pidx, axis_partitions[pidx].offset, - axis_partitions[pidx].size); - pidx++; - } - - if (mymtd) { - if (use_default_ptable) { - printk(KERN_INFO " Using default partition table.\n"); - err = mtd_device_register(mymtd, - axis_default_partitions, - NUM_DEFAULT_PARTITIONS); - } else { - err = mtd_device_register(mymtd, axis_partitions, - pidx); - } - - if (err) - panic("axisflashmap could not add MTD partitions!\n"); - } - - if (!romfs_in_flash) { - /* Create an RAM device for the root partition (romfs). */ - -#if !defined(CONFIG_MTD_MTDRAM) || (CONFIG_MTDRAM_TOTAL_SIZE != 0) - /* No use trying to boot this kernel from RAM. Panic! */ - printk(KERN_EMERG "axisflashmap: Cannot create an MTD RAM " - "device due to kernel (mis)configuration!\n"); - panic("This kernel cannot boot from RAM!\n"); -#else - struct mtd_info *mtd_ram; - - mtd_ram = kmalloc(sizeof(struct mtd_info), GFP_KERNEL); - if (!mtd_ram) - panic("axisflashmap couldn't allocate memory for " - "mtd_info!\n"); - - printk(KERN_INFO " Adding RAM partition for romfs image:\n"); - printk(pmsg, pidx, (unsigned)romfs_start, - (unsigned)romfs_length); - - err = mtdram_init_device(mtd_ram, - (void *)romfs_start, - romfs_length, - "romfs"); - if (err) - panic("axisflashmap could not initialize MTD RAM " - "device!\n"); -#endif - } - return err; -} - -/* This adds the above to the kernels init-call chain. */ -module_init(init_axis_flash); - -EXPORT_SYMBOL(axisflash_mtd); diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c deleted file mode 100644 index 2d312c8a4dd5..000000000000 --- a/arch/cris/arch-v10/drivers/eeprom.c +++ /dev/null @@ -1,852 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/*!***************************************************************************** -*! -*! Implements an interface for i2c compatible eeproms to run under Linux. -*! Supports 2k, 8k(?) and 16k. Uses adaptive timing adjustments by -*! Johan.Adolfsson@axis.com -*! -*! Probing results: -*! 8k or not is detected (the assumes 2k or 16k) -*! 2k or 16k detected using test reads and writes. -*! -*!------------------------------------------------------------------------ -*! HISTORY -*! -*! DATE NAME CHANGES -*! ---- ---- ------- -*! Aug 28 1999 Edgar Iglesias Initial Version -*! Aug 31 1999 Edgar Iglesias Allow simultaneous users. -*! Sep 03 1999 Edgar Iglesias Updated probe. -*! Sep 03 1999 Edgar Iglesias Added bail-out stuff if we get interrupted -*! in the spin-lock. -*! -*! (c) 1999 Axis Communications AB, Lund, Sweden -*!*****************************************************************************/ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/fs.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/uaccess.h> -#include "i2c.h" - -#define D(x) - -/* If we should use adaptive timing or not: */ -/* #define EEPROM_ADAPTIVE_TIMING */ - -#define EEPROM_MAJOR_NR 122 /* use a LOCAL/EXPERIMENTAL major for now */ -#define EEPROM_MINOR_NR 0 - -/* Empirical sane initial value of the delay, the value will be adapted to - * what the chip needs when using EEPROM_ADAPTIVE_TIMING. - */ -#define INITIAL_WRITEDELAY_US 4000 -#define MAX_WRITEDELAY_US 10000 /* 10 ms according to spec for 2KB EEPROM */ - -/* This one defines how many times to try when eeprom fails. */ -#define EEPROM_RETRIES 10 - -#define EEPROM_2KB (2 * 1024) -/*#define EEPROM_4KB (4 * 1024)*/ /* Exists but not used in Axis products */ -#define EEPROM_8KB (8 * 1024 - 1 ) /* Last byte has write protection bit */ -#define EEPROM_16KB (16 * 1024) - -#define i2c_delay(x) udelay(x) - -/* - * This structure describes the attached eeprom chip. - * The values are probed for. - */ - -struct eeprom_type -{ - unsigned long size; - unsigned long sequential_write_pagesize; - unsigned char select_cmd; - unsigned long usec_delay_writecycles; /* Min time between write cycles - (up to 10ms for some models) */ - unsigned long usec_delay_step; /* For adaptive algorithm */ - int adapt_state; /* 1 = To high , 0 = Even, -1 = To low */ - - /* this one is to keep the read/write operations atomic */ - struct mutex lock; - int retry_cnt_addr; /* Used to keep track of number of retries for - adaptive timing adjustments */ - int retry_cnt_read; -}; - -static int eeprom_open(struct inode * inode, struct file * file); -static loff_t eeprom_lseek(struct file * file, loff_t offset, int orig); -static ssize_t eeprom_read(struct file * file, char * buf, size_t count, - loff_t *off); -static ssize_t eeprom_write(struct file * file, const char * buf, size_t count, - loff_t *off); -static int eeprom_close(struct inode * inode, struct file * file); - -static int eeprom_address(unsigned long addr); -static int read_from_eeprom(char * buf, int count); -static int eeprom_write_buf(loff_t addr, const char * buf, int count); -static int eeprom_read_buf(loff_t addr, char * buf, int count); - -static void eeprom_disable_write_protect(void); - - -static const char eeprom_name[] = "eeprom"; - -/* chip description */ -static struct eeprom_type eeprom; - -/* This is the exported file-operations structure for this device. */ -const struct file_operations eeprom_fops = -{ - .llseek = eeprom_lseek, - .read = eeprom_read, - .write = eeprom_write, - .open = eeprom_open, - .release = eeprom_close -}; - -/* eeprom init call. Probes for different eeprom models. */ - -int __init eeprom_init(void) -{ - mutex_init(&eeprom.lock); - -#ifdef CONFIG_ETRAX_I2C_EEPROM_PROBE -#define EETEXT "Found" -#else -#define EETEXT "Assuming" -#endif - if (register_chrdev(EEPROM_MAJOR_NR, eeprom_name, &eeprom_fops)) - { - printk(KERN_INFO "%s: unable to get major %d for eeprom device\n", - eeprom_name, EEPROM_MAJOR_NR); - return -1; - } - - printk("EEPROM char device v0.3, (c) 2000 Axis Communications AB\n"); - - /* - * Note: Most of this probing method was taken from the printserver (5470e) - * codebase. It did not contain a way of finding the 16kB chips - * (M24128 or variants). The method used here might not work - * for all models. If you encounter problems the easiest way - * is probably to define your model within #ifdef's, and hard- - * code it. - */ - - eeprom.size = 0; - eeprom.usec_delay_writecycles = INITIAL_WRITEDELAY_US; - eeprom.usec_delay_step = 128; - eeprom.adapt_state = 0; - -#ifdef CONFIG_ETRAX_I2C_EEPROM_PROBE - i2c_start(); - i2c_outbyte(0x80); - if(!i2c_getack()) - { - /* It's not 8k.. */ - int success = 0; - unsigned char buf_2k_start[16]; - - /* Im not sure this will work... :) */ - /* assume 2kB, if failure go for 16kB */ - /* Test with 16kB settings.. */ - /* If it's a 2kB EEPROM and we address it outside it's range - * it will mirror the address space: - * 1. We read two locations (that are mirrored), - * if the content differs * it's a 16kB EEPROM. - * 2. if it doesn't differ - write different value to one of the locations, - * check the other - if content still is the same it's a 2k EEPROM, - * restore original data. - */ -#define LOC1 8 -#define LOC2 (0x1fb) /*1fb, 3ed, 5df, 7d1 */ - - /* 2k settings */ - i2c_stop(); - eeprom.size = EEPROM_2KB; - eeprom.select_cmd = 0xA0; - eeprom.sequential_write_pagesize = 16; - if( eeprom_read_buf( 0, buf_2k_start, 16 ) == 16 ) - { - D(printk("2k start: '%16.16s'\n", buf_2k_start)); - } - else - { - printk(KERN_INFO "%s: Failed to read in 2k mode!\n", eeprom_name); - } - - /* 16k settings */ - eeprom.size = EEPROM_16KB; - eeprom.select_cmd = 0xA0; - eeprom.sequential_write_pagesize = 64; - - { - unsigned char loc1[4], loc2[4], tmp[4]; - if( eeprom_read_buf(LOC2, loc2, 4) == 4) - { - if( eeprom_read_buf(LOC1, loc1, 4) == 4) - { - D(printk("0 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n", - LOC1, loc1, LOC2, loc2)); -#if 0 - if (memcmp(loc1, loc2, 4) != 0 ) - { - /* It's 16k */ - printk(KERN_INFO "%s: 16k detected in step 1\n", eeprom_name); - eeprom.size = EEPROM_16KB; - success = 1; - } - else -#endif - { - /* Do step 2 check */ - /* Invert value */ - loc1[0] = ~loc1[0]; - if (eeprom_write_buf(LOC1, loc1, 1) == 1) - { - /* If 2k EEPROM this write will actually write 10 bytes - * from pos 0 - */ - D(printk("1 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n", - LOC1, loc1, LOC2, loc2)); - if( eeprom_read_buf(LOC1, tmp, 4) == 4) - { - D(printk("2 loc1: (%i) '%4.4s' tmp '%4.4s'\n", - LOC1, loc1, tmp)); - if (memcmp(loc1, tmp, 4) != 0 ) - { - printk(KERN_INFO "%s: read and write differs! Not 16kB\n", - eeprom_name); - loc1[0] = ~loc1[0]; - - if (eeprom_write_buf(LOC1, loc1, 1) == 1) - { - success = 1; - } - else - { - printk(KERN_INFO "%s: Restore 2k failed during probe," - " EEPROM might be corrupt!\n", eeprom_name); - - } - i2c_stop(); - /* Go to 2k mode and write original data */ - eeprom.size = EEPROM_2KB; - eeprom.select_cmd = 0xA0; - eeprom.sequential_write_pagesize = 16; - if( eeprom_write_buf(0, buf_2k_start, 16) == 16) - { - } - else - { - printk(KERN_INFO "%s: Failed to write back 2k start!\n", - eeprom_name); - } - - eeprom.size = EEPROM_2KB; - } - } - - if(!success) - { - if( eeprom_read_buf(LOC2, loc2, 1) == 1) - { - D(printk("0 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n", - LOC1, loc1, LOC2, loc2)); - if (memcmp(loc1, loc2, 4) == 0 ) - { - /* Data the same, must be mirrored -> 2k */ - /* Restore data */ - printk(KERN_INFO "%s: 2k detected in step 2\n", eeprom_name); - loc1[0] = ~loc1[0]; - if (eeprom_write_buf(LOC1, loc1, 1) == 1) - { - success = 1; - } - else - { - printk(KERN_INFO "%s: Restore 2k failed during probe," - " EEPROM might be corrupt!\n", eeprom_name); - - } - - eeprom.size = EEPROM_2KB; - } - else - { - printk(KERN_INFO "%s: 16k detected in step 2\n", - eeprom_name); - loc1[0] = ~loc1[0]; - /* Data differs, assume 16k */ - /* Restore data */ - if (eeprom_write_buf(LOC1, loc1, 1) == 1) - { - success = 1; - } - else - { - printk(KERN_INFO "%s: Restore 16k failed during probe," - " EEPROM might be corrupt!\n", eeprom_name); - } - - eeprom.size = EEPROM_16KB; - } - } - } - } - } /* read LOC1 */ - } /* address LOC1 */ - if (!success) - { - printk(KERN_INFO "%s: Probing failed!, using 2KB!\n", eeprom_name); - eeprom.size = EEPROM_2KB; - } - } /* read */ - } - } - else - { - i2c_outbyte(0x00); - if(!i2c_getack()) - { - /* No 8k */ - eeprom.size = EEPROM_2KB; - } - else - { - i2c_start(); - i2c_outbyte(0x81); - if (!i2c_getack()) - { - eeprom.size = EEPROM_2KB; - } - else - { - /* It's a 8kB */ - i2c_inbyte(); - eeprom.size = EEPROM_8KB; - } - } - } - i2c_stop(); -#elif defined(CONFIG_ETRAX_I2C_EEPROM_16KB) - eeprom.size = EEPROM_16KB; -#elif defined(CONFIG_ETRAX_I2C_EEPROM_8KB) - eeprom.size = EEPROM_8KB; -#elif defined(CONFIG_ETRAX_I2C_EEPROM_2KB) - eeprom.size = EEPROM_2KB; -#endif - - switch(eeprom.size) - { - case (EEPROM_2KB): - printk("%s: " EETEXT " i2c compatible 2kB eeprom.\n", eeprom_name); - eeprom.sequential_write_pagesize = 16; - eeprom.select_cmd = 0xA0; - break; - case (EEPROM_8KB): - printk("%s: " EETEXT " i2c compatible 8kB eeprom.\n", eeprom_name); - eeprom.sequential_write_pagesize = 16; - eeprom.select_cmd = 0x80; - break; - case (EEPROM_16KB): - printk("%s: " EETEXT " i2c compatible 16kB eeprom.\n", eeprom_name); - eeprom.sequential_write_pagesize = 64; - eeprom.select_cmd = 0xA0; - break; - default: - eeprom.size = 0; - printk("%s: Did not find a supported eeprom\n", eeprom_name); - break; - } - - - - eeprom_disable_write_protect(); - - return 0; -} - -/* Opens the device. */ -static int eeprom_open(struct inode * inode, struct file * file) -{ - if(iminor(inode) != EEPROM_MINOR_NR) - return -ENXIO; - if(imajor(inode) != EEPROM_MAJOR_NR) - return -ENXIO; - - if( eeprom.size > 0 ) - { - /* OK */ - return 0; - } - - /* No EEprom found */ - return -EFAULT; -} - -/* Changes the current file position. */ - -static loff_t eeprom_lseek(struct file * file, loff_t offset, int orig) -{ -/* - * orig 0: position from beginning of eeprom - * orig 1: relative from current position - * orig 2: position from last eeprom address - */ - - switch (orig) - { - case 0: - file->f_pos = offset; - break; - case 1: - file->f_pos += offset; - break; - case 2: - file->f_pos = eeprom.size - offset; - break; - default: - return -EINVAL; - } - - /* truncate position */ - if (file->f_pos < 0) - { - file->f_pos = 0; - return(-EOVERFLOW); - } - - if (file->f_pos >= eeprom.size) - { - file->f_pos = eeprom.size - 1; - return(-EOVERFLOW); - } - - return ( file->f_pos ); -} - -/* Reads data from eeprom. */ - -static int eeprom_read_buf(loff_t addr, char * buf, int count) -{ - return eeprom_read(NULL, buf, count, &addr); -} - - - -/* Reads data from eeprom. */ - -static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t *off) -{ - int read=0; - unsigned long p = *off; - - unsigned char page; - - if(p >= eeprom.size) /* Address i 0 - (size-1) */ - { - return -EFAULT; - } - - if (mutex_lock_interruptible(&eeprom.lock)) - return -EINTR; - - page = (unsigned char) (p >> 8); - - if(!eeprom_address(p)) - { - printk(KERN_INFO "%s: Read failed to address the eeprom: " - "0x%08X (%i) page: %i\n", eeprom_name, (int)p, (int)p, page); - i2c_stop(); - - /* don't forget to wake them up */ - mutex_unlock(&eeprom.lock); - return -EFAULT; - } - - if( (p + count) > eeprom.size) - { - /* truncate count */ - count = eeprom.size - p; - } - - /* stop dummy write op and initiate the read op */ - i2c_start(); - - /* special case for small eeproms */ - if(eeprom.size < EEPROM_16KB) - { - i2c_outbyte( eeprom.select_cmd | 1 | (page << 1) ); - } - - /* go on with the actual read */ - read = read_from_eeprom( buf, count); - - if(read > 0) - { - *off += read; - } - - mutex_unlock(&eeprom.lock); - return read; -} - -/* Writes data to eeprom. */ - -static int eeprom_write_buf(loff_t addr, const char * buf, int count) -{ - return eeprom_write(NULL, buf, count, &addr); -} - - -/* Writes data to eeprom. */ - -static ssize_t eeprom_write(struct file * file, const char * buf, size_t count, - loff_t *off) -{ - int i, written, restart=1; - unsigned long p; - - if (!access_ok(VERIFY_READ, buf, count)) - { - return -EFAULT; - } - - /* bail out if we get interrupted */ - if (mutex_lock_interruptible(&eeprom.lock)) - return -EINTR; - for(i = 0; (i < EEPROM_RETRIES) && (restart > 0); i++) - { - restart = 0; - written = 0; - p = *off; - - - while( (written < count) && (p < eeprom.size)) - { - /* address the eeprom */ - if(!eeprom_address(p)) - { - printk(KERN_INFO "%s: Write failed to address the eeprom: " - "0x%08X (%i) \n", eeprom_name, (int)p, (int)p); - i2c_stop(); - - /* don't forget to wake them up */ - mutex_unlock(&eeprom.lock); - return -EFAULT; - } -#ifdef EEPROM_ADAPTIVE_TIMING - /* Adaptive algorithm to adjust timing */ - if (eeprom.retry_cnt_addr > 0) - { - /* To Low now */ - D(printk(">D=%i d=%i\n", - eeprom.usec_delay_writecycles, eeprom.usec_delay_step)); - - if (eeprom.usec_delay_step < 4) - { - eeprom.usec_delay_step++; - eeprom.usec_delay_writecycles += eeprom.usec_delay_step; - } - else - { - - if (eeprom.adapt_state > 0) - { - /* To Low before */ - eeprom.usec_delay_step *= 2; - if (eeprom.usec_delay_step > 2) - { - eeprom.usec_delay_step--; - } - eeprom.usec_delay_writecycles += eeprom.usec_delay_step; - } - else if (eeprom.adapt_state < 0) - { - /* To High before (toggle dir) */ - eeprom.usec_delay_writecycles += eeprom.usec_delay_step; - if (eeprom.usec_delay_step > 1) - { - eeprom.usec_delay_step /= 2; - eeprom.usec_delay_step--; - } - } - } - - eeprom.adapt_state = 1; - } - else - { - /* To High (or good) now */ - D(printk("<D=%i d=%i\n", - eeprom.usec_delay_writecycles, eeprom.usec_delay_step)); - - if (eeprom.adapt_state < 0) - { - /* To High before */ - if (eeprom.usec_delay_step > 1) - { - eeprom.usec_delay_step *= 2; - eeprom.usec_delay_step--; - - if (eeprom.usec_delay_writecycles > eeprom.usec_delay_step) - { - eeprom.usec_delay_writecycles -= eeprom.usec_delay_step; - } - } - } - else if (eeprom.adapt_state > 0) - { - /* To Low before (toggle dir) */ - if (eeprom.usec_delay_writecycles > eeprom.usec_delay_step) - { - eeprom.usec_delay_writecycles -= eeprom.usec_delay_step; - } - if (eeprom.usec_delay_step > 1) - { - eeprom.usec_delay_step /= 2; - eeprom.usec_delay_step--; - } - - eeprom.adapt_state = -1; - } - - if (eeprom.adapt_state > -100) - { - eeprom.adapt_state--; - } - else - { - /* Restart adaption */ - D(printk("#Restart\n")); - eeprom.usec_delay_step++; - } - } -#endif /* EEPROM_ADAPTIVE_TIMING */ - /* write until we hit a page boundary or count */ - do - { - i2c_outbyte(buf[written]); - if(!i2c_getack()) - { - restart=1; - printk(KERN_INFO "%s: write error, retrying. %d\n", eeprom_name, i); - i2c_stop(); - break; - } - written++; - p++; - } while( written < count && ( p % eeprom.sequential_write_pagesize )); - - /* end write cycle */ - i2c_stop(); - i2c_delay(eeprom.usec_delay_writecycles); - } /* while */ - } /* for */ - - mutex_unlock(&eeprom.lock); - if (written == 0 && p >= eeprom.size){ - return -ENOSPC; - } - *off = p; - return written; -} - -/* Closes the device. */ - -static int eeprom_close(struct inode * inode, struct file * file) -{ - /* do nothing for now */ - return 0; -} - -/* Sets the current address of the eeprom. */ - -static int eeprom_address(unsigned long addr) -{ - int i; - unsigned char page, offset; - - page = (unsigned char) (addr >> 8); - offset = (unsigned char) addr; - - for(i = 0; i < EEPROM_RETRIES; i++) - { - /* start a dummy write for addressing */ - i2c_start(); - - if(eeprom.size == EEPROM_16KB) - { - i2c_outbyte( eeprom.select_cmd ); - i2c_getack(); - i2c_outbyte(page); - } - else - { - i2c_outbyte( eeprom.select_cmd | (page << 1) ); - } - if(!i2c_getack()) - { - /* retry */ - i2c_stop(); - /* Must have a delay here.. 500 works, >50, 100->works 5th time*/ - i2c_delay(MAX_WRITEDELAY_US / EEPROM_RETRIES * i); - /* The chip needs up to 10 ms from write stop to next start */ - - } - else - { - i2c_outbyte(offset); - - if(!i2c_getack()) - { - /* retry */ - i2c_stop(); - } - else - break; - } - } - - - eeprom.retry_cnt_addr = i; - D(printk("%i\n", eeprom.retry_cnt_addr)); - if(eeprom.retry_cnt_addr == EEPROM_RETRIES) - { - /* failed */ - return 0; - } - return 1; -} - -/* Reads from current address. */ - -static int read_from_eeprom(char * buf, int count) -{ - int i, read=0; - - for(i = 0; i < EEPROM_RETRIES; i++) - { - if(eeprom.size == EEPROM_16KB) - { - i2c_outbyte( eeprom.select_cmd | 1 ); - } - - if(i2c_getack()) - { - break; - } - } - - if(i == EEPROM_RETRIES) - { - printk(KERN_INFO "%s: failed to read from eeprom\n", eeprom_name); - i2c_stop(); - - return -EFAULT; - } - - while( (read < count)) - { - if (put_user(i2c_inbyte(), &buf[read++])) - { - i2c_stop(); - - return -EFAULT; - } - - /* - * make sure we don't ack last byte or you will get very strange - * results! - */ - if(read < count) - { - i2c_sendack(); - } - } - - /* stop the operation */ - i2c_stop(); - - return read; -} - -/* Disables write protection if applicable. */ - -#define DBP_SAVE(x) -#define ax_printf printk -static void eeprom_disable_write_protect(void) -{ - /* Disable write protect */ - if (eeprom.size == EEPROM_8KB) - { - /* Step 1 Set WEL = 1 (write 00000010 to address 1FFFh */ - i2c_start(); - i2c_outbyte(0xbe); - if(!i2c_getack()) - { - DBP_SAVE(ax_printf("Get ack returns false\n")); - } - i2c_outbyte(0xFF); - if(!i2c_getack()) - { - DBP_SAVE(ax_printf("Get ack returns false 2\n")); - } - i2c_outbyte(0x02); - if(!i2c_getack()) - { - DBP_SAVE(ax_printf("Get ack returns false 3\n")); - } - i2c_stop(); - - i2c_delay(1000); - - /* Step 2 Set RWEL = 1 (write 00000110 to address 1FFFh */ - i2c_start(); - i2c_outbyte(0xbe); - if(!i2c_getack()) - { - DBP_SAVE(ax_printf("Get ack returns false 55\n")); - } - i2c_outbyte(0xFF); - if(!i2c_getack()) - { - DBP_SAVE(ax_printf("Get ack returns false 52\n")); - } - i2c_outbyte(0x06); - if(!i2c_getack()) - { - DBP_SAVE(ax_printf("Get ack returns false 53\n")); - } - i2c_stop(); - - /* Step 3 Set BP1, BP0, and/or WPEN bits (write 00000110 to address 1FFFh */ - i2c_start(); - i2c_outbyte(0xbe); - if(!i2c_getack()) - { - DBP_SAVE(ax_printf("Get ack returns false 56\n")); - } - i2c_outbyte(0xFF); - if(!i2c_getack()) - { - DBP_SAVE(ax_printf("Get ack returns false 57\n")); - } - i2c_outbyte(0x06); - if(!i2c_getack()) - { - DBP_SAVE(ax_printf("Get ack returns false 58\n")); - } - i2c_stop(); - - /* Write protect disabled */ - } -} -device_initcall(eeprom_init); diff --git a/arch/cris/arch-v10/drivers/gpio.c b/arch/cris/arch-v10/drivers/gpio.c deleted file mode 100644 index cd0e05d89d42..000000000000 --- a/arch/cris/arch-v10/drivers/gpio.c +++ /dev/null @@ -1,857 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Etrax general port I/O device - * - * Copyright (c) 1999-2007 Axis Communications AB - * - * Authors: Bjorn Wesen (initial version) - * Ola Knutsson (LED handling) - * Johan Adolfsson (read/set directions, write, port G) - */ - - -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/poll.h> -#include <linux/init.h> -#include <linux/interrupt.h> - -#include <asm/etraxgpio.h> -#include <arch/svinto.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <arch/io_interface_mux.h> - -#define GPIO_MAJOR 120 /* experimental MAJOR number */ - -#define D(x) - -#if 0 -static int dp_cnt; -#define DP(x) do { dp_cnt++; if (dp_cnt % 1000 == 0) x; }while(0) -#else -#define DP(x) -#endif - -static char gpio_name[] = "etrax gpio"; - -#if 0 -static wait_queue_head_t *gpio_wq; -#endif - -static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -static ssize_t gpio_write(struct file *file, const char __user *buf, - size_t count, loff_t *off); -static int gpio_open(struct inode *inode, struct file *filp); -static int gpio_release(struct inode *inode, struct file *filp); -static __poll_t gpio_poll(struct file *filp, struct poll_table_struct *wait); - -/* private data per open() of this driver */ - -struct gpio_private { - struct gpio_private *next; - /* These fields are for PA and PB only */ - volatile unsigned char *port, *shadow; - volatile unsigned char *dir, *dir_shadow; - unsigned char changeable_dir; - unsigned char changeable_bits; - unsigned char clk_mask; - unsigned char data_mask; - unsigned char write_msb; - unsigned char pad1, pad2, pad3; - /* These fields are generic */ - unsigned long highalarm, lowalarm; - wait_queue_head_t alarm_wq; - int minor; -}; - -/* linked list of alarms to check for */ - -static struct gpio_private *alarmlist; - -static int gpio_some_alarms; /* Set if someone uses alarm */ -static unsigned long gpio_pa_irq_enabled_mask; - -static DEFINE_SPINLOCK(gpio_lock); /* Protect directions etc */ - -/* Port A and B use 8 bit access, but Port G is 32 bit */ -#define NUM_PORTS (GPIO_MINOR_B+1) - -static volatile unsigned char *ports[NUM_PORTS] = { - R_PORT_PA_DATA, - R_PORT_PB_DATA, -}; -static volatile unsigned char *shads[NUM_PORTS] = { - &port_pa_data_shadow, - &port_pb_data_shadow -}; - -/* What direction bits that are user changeable 1=changeable*/ -#ifndef CONFIG_ETRAX_PA_CHANGEABLE_DIR -#define CONFIG_ETRAX_PA_CHANGEABLE_DIR 0x00 -#endif -#ifndef CONFIG_ETRAX_PB_CHANGEABLE_DIR -#define CONFIG_ETRAX_PB_CHANGEABLE_DIR 0x00 -#endif - -#ifndef CONFIG_ETRAX_PA_CHANGEABLE_BITS -#define CONFIG_ETRAX_PA_CHANGEABLE_BITS 0xFF -#endif -#ifndef CONFIG_ETRAX_PB_CHANGEABLE_BITS -#define CONFIG_ETRAX_PB_CHANGEABLE_BITS 0xFF -#endif - - -static unsigned char changeable_dir[NUM_PORTS] = { - CONFIG_ETRAX_PA_CHANGEABLE_DIR, - CONFIG_ETRAX_PB_CHANGEABLE_DIR -}; -static unsigned char changeable_bits[NUM_PORTS] = { - CONFIG_ETRAX_PA_CHANGEABLE_BITS, - CONFIG_ETRAX_PB_CHANGEABLE_BITS -}; - -static volatile unsigned char *dir[NUM_PORTS] = { - R_PORT_PA_DIR, - R_PORT_PB_DIR -}; - -static volatile unsigned char *dir_shadow[NUM_PORTS] = { - &port_pa_dir_shadow, - &port_pb_dir_shadow -}; - -/* All bits in port g that can change dir. */ -static const unsigned long int changeable_dir_g_mask = 0x01FFFF01; - -/* Port G is 32 bit, handle it special, some bits are both inputs - and outputs at the same time, only some of the bits can change direction - and some of them in groups of 8 bit. */ -static unsigned long changeable_dir_g; -static unsigned long dir_g_in_bits; -static unsigned long dir_g_out_bits; -static unsigned long dir_g_shadow; /* 1=output */ - -#define USE_PORTS(priv) ((priv)->minor <= GPIO_MINOR_B) - - -static __poll_t gpio_poll(struct file *file, poll_table *wait) -{ - __poll_t mask = 0; - struct gpio_private *priv = file->private_data; - unsigned long data; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - poll_wait(file, &priv->alarm_wq, wait); - if (priv->minor == GPIO_MINOR_A) { - unsigned long tmp; - data = *R_PORT_PA_DATA; - /* PA has support for high level interrupt - - * lets activate for those low and with highalarm set - */ - tmp = ~data & priv->highalarm & 0xFF; - tmp = (tmp << R_IRQ_MASK1_SET__pa0__BITNR); - - gpio_pa_irq_enabled_mask |= tmp; - *R_IRQ_MASK1_SET = tmp; - } else if (priv->minor == GPIO_MINOR_B) - data = *R_PORT_PB_DATA; - else if (priv->minor == GPIO_MINOR_G) - data = *R_PORT_G_DATA; - else { - mask = 0; - goto out; - } - - if ((data & priv->highalarm) || - (~data & priv->lowalarm)) { - mask = EPOLLIN|EPOLLRDNORM; - } - -out: - spin_unlock_irqrestore(&gpio_lock, flags); - DP(printk("gpio_poll ready: mask 0x%08X\n", mask)); - - return mask; -} - -int etrax_gpio_wake_up_check(void) -{ - struct gpio_private *priv; - unsigned long data = 0; - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - priv = alarmlist; - while (priv) { - if (USE_PORTS(priv)) - data = *priv->port; - else if (priv->minor == GPIO_MINOR_G) - data = *R_PORT_G_DATA; - - if ((data & priv->highalarm) || - (~data & priv->lowalarm)) { - DP(printk("etrax_gpio_wake_up_check %i\n",priv->minor)); - wake_up_interruptible(&priv->alarm_wq); - ret = 1; - } - priv = priv->next; - } - spin_unlock_irqrestore(&gpio_lock, flags); - return ret; -} - -static irqreturn_t -gpio_poll_timer_interrupt(int irq, void *dev_id) -{ - if (gpio_some_alarms) { - etrax_gpio_wake_up_check(); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -static irqreturn_t -gpio_interrupt(int irq, void *dev_id) -{ - unsigned long tmp; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - /* Find what PA interrupts are active */ - tmp = (*R_IRQ_READ1); - - /* Find those that we have enabled */ - tmp &= gpio_pa_irq_enabled_mask; - - /* Clear them.. */ - *R_IRQ_MASK1_CLR = tmp; - gpio_pa_irq_enabled_mask &= ~tmp; - - spin_unlock_irqrestore(&gpio_lock, flags); - - if (gpio_some_alarms) - return IRQ_RETVAL(etrax_gpio_wake_up_check()); - - return IRQ_NONE; -} - -static void gpio_write_bit(struct gpio_private *priv, - unsigned char data, int bit) -{ - *priv->port = *priv->shadow &= ~(priv->clk_mask); - if (data & 1 << bit) - *priv->port = *priv->shadow |= priv->data_mask; - else - *priv->port = *priv->shadow &= ~(priv->data_mask); - - /* For FPGA: min 5.0ns (DCC) before CCLK high */ - *priv->port = *priv->shadow |= priv->clk_mask; -} - -static void gpio_write_byte(struct gpio_private *priv, unsigned char data) -{ - int i; - - if (priv->write_msb) - for (i = 7; i >= 0; i--) - gpio_write_bit(priv, data, i); - else - for (i = 0; i <= 7; i++) - gpio_write_bit(priv, data, i); -} - -static ssize_t gpio_write(struct file *file, const char __user *buf, - size_t count, loff_t *off) -{ - struct gpio_private *priv = file->private_data; - unsigned long flags; - ssize_t retval = count; - - if (priv->minor != GPIO_MINOR_A && priv->minor != GPIO_MINOR_B) - return -EFAULT; - - if (!access_ok(VERIFY_READ, buf, count)) - return -EFAULT; - - spin_lock_irqsave(&gpio_lock, flags); - - /* It must have been configured using the IO_CFG_WRITE_MODE */ - /* Perhaps a better error code? */ - if (priv->clk_mask == 0 || priv->data_mask == 0) { - retval = -EPERM; - goto out; - } - - D(printk(KERN_DEBUG "gpio_write: %02X to data 0x%02X " - "clk 0x%02X msb: %i\n", - count, priv->data_mask, priv->clk_mask, priv->write_msb)); - - while (count--) - gpio_write_byte(priv, *buf++); - -out: - spin_unlock_irqrestore(&gpio_lock, flags); - return retval; -} - - - -static int -gpio_open(struct inode *inode, struct file *filp) -{ - struct gpio_private *priv; - int p = iminor(inode); - unsigned long flags; - - if (p > GPIO_MINOR_LAST) - return -EINVAL; - - priv = kzalloc(sizeof(struct gpio_private), GFP_KERNEL); - - if (!priv) - return -ENOMEM; - - priv->minor = p; - - /* initialize the io/alarm struct */ - - if (USE_PORTS(priv)) { /* A and B */ - priv->port = ports[p]; - priv->shadow = shads[p]; - priv->dir = dir[p]; - priv->dir_shadow = dir_shadow[p]; - priv->changeable_dir = changeable_dir[p]; - priv->changeable_bits = changeable_bits[p]; - } else { - priv->port = NULL; - priv->shadow = NULL; - priv->dir = NULL; - priv->dir_shadow = NULL; - priv->changeable_dir = 0; - priv->changeable_bits = 0; - } - - priv->highalarm = 0; - priv->lowalarm = 0; - priv->clk_mask = 0; - priv->data_mask = 0; - init_waitqueue_head(&priv->alarm_wq); - - filp->private_data = priv; - - /* link it into our alarmlist */ - spin_lock_irqsave(&gpio_lock, flags); - priv->next = alarmlist; - alarmlist = priv; - spin_unlock_irqrestore(&gpio_lock, flags); - - return 0; -} - -static int -gpio_release(struct inode *inode, struct file *filp) -{ - struct gpio_private *p; - struct gpio_private *todel; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - p = alarmlist; - todel = filp->private_data; - - /* unlink from alarmlist and free the private structure */ - - if (p == todel) { - alarmlist = todel->next; - } else { - while (p->next != todel) - p = p->next; - p->next = todel->next; - } - - kfree(todel); - /* Check if there are still any alarms set */ - p = alarmlist; - while (p) { - if (p->highalarm | p->lowalarm) { - gpio_some_alarms = 1; - goto out; - } - p = p->next; - } - gpio_some_alarms = 0; -out: - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} - -/* Main device API. ioctl's to read/set/clear bits, as well as to - * set alarms to wait for using a subsequent select(). - */ -inline unsigned long setget_input(struct gpio_private *priv, unsigned long arg) -{ - /* Set direction 0=unchanged 1=input, - * return mask with 1=input */ - if (USE_PORTS(priv)) { - *priv->dir = *priv->dir_shadow &= - ~((unsigned char)arg & priv->changeable_dir); - return ~(*priv->dir_shadow) & 0xFF; /* Only 8 bits */ - } - - if (priv->minor != GPIO_MINOR_G) - return 0; - - /* We must fiddle with R_GEN_CONFIG to change dir */ - if (((arg & dir_g_in_bits) != arg) && - (arg & changeable_dir_g)) { - arg &= changeable_dir_g; - /* Clear bits in genconfig to set to input */ - if (arg & (1<<0)) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, g0dir); - dir_g_in_bits |= (1<<0); - dir_g_out_bits &= ~(1<<0); - } - if ((arg & 0x0000FF00) == 0x0000FF00) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, g8_15dir); - dir_g_in_bits |= 0x0000FF00; - dir_g_out_bits &= ~0x0000FF00; - } - if ((arg & 0x00FF0000) == 0x00FF0000) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, g16_23dir); - dir_g_in_bits |= 0x00FF0000; - dir_g_out_bits &= ~0x00FF0000; - } - if (arg & (1<<24)) { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, g24dir); - dir_g_in_bits |= (1<<24); - dir_g_out_bits &= ~(1<<24); - } - D(printk(KERN_DEBUG "gpio: SETINPUT on port G set " - "genconfig to 0x%08lX " - "in_bits: 0x%08lX " - "out_bits: 0x%08lX\n", - (unsigned long)genconfig_shadow, - dir_g_in_bits, dir_g_out_bits)); - *R_GEN_CONFIG = genconfig_shadow; - /* Must be a >120 ns delay before writing this again */ - - } - return dir_g_in_bits; -} /* setget_input */ - -inline unsigned long setget_output(struct gpio_private *priv, unsigned long arg) -{ - if (USE_PORTS(priv)) { - *priv->dir = *priv->dir_shadow |= - ((unsigned char)arg & priv->changeable_dir); - return *priv->dir_shadow; - } - if (priv->minor != GPIO_MINOR_G) - return 0; - - /* We must fiddle with R_GEN_CONFIG to change dir */ - if (((arg & dir_g_out_bits) != arg) && - (arg & changeable_dir_g)) { - /* Set bits in genconfig to set to output */ - if (arg & (1<<0)) { - genconfig_shadow |= IO_MASK(R_GEN_CONFIG, g0dir); - dir_g_out_bits |= (1<<0); - dir_g_in_bits &= ~(1<<0); - } - if ((arg & 0x0000FF00) == 0x0000FF00) { - genconfig_shadow |= IO_MASK(R_GEN_CONFIG, g8_15dir); - dir_g_out_bits |= 0x0000FF00; - dir_g_in_bits &= ~0x0000FF00; - } - if ((arg & 0x00FF0000) == 0x00FF0000) { - genconfig_shadow |= IO_MASK(R_GEN_CONFIG, g16_23dir); - dir_g_out_bits |= 0x00FF0000; - dir_g_in_bits &= ~0x00FF0000; - } - if (arg & (1<<24)) { - genconfig_shadow |= IO_MASK(R_GEN_CONFIG, g24dir); - dir_g_out_bits |= (1<<24); - dir_g_in_bits &= ~(1<<24); - } - D(printk(KERN_INFO "gpio: SETOUTPUT on port G set " - "genconfig to 0x%08lX " - "in_bits: 0x%08lX " - "out_bits: 0x%08lX\n", - (unsigned long)genconfig_shadow, - dir_g_in_bits, dir_g_out_bits)); - *R_GEN_CONFIG = genconfig_shadow; - /* Must be a >120 ns delay before writing this again */ - } - return dir_g_out_bits & 0x7FFFFFFF; -} /* setget_output */ - -static int -gpio_leds_ioctl(unsigned int cmd, unsigned long arg); - -static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - unsigned long flags; - unsigned long val; - int ret = 0; - - struct gpio_private *priv = file->private_data; - if (_IOC_TYPE(cmd) != ETRAXGPIO_IOCTYPE) - return -EINVAL; - - switch (_IOC_NR(cmd)) { - case IO_READBITS: /* Use IO_READ_INBITS and IO_READ_OUTBITS instead */ - // read the port - spin_lock_irqsave(&gpio_lock, flags); - if (USE_PORTS(priv)) { - ret = *priv->port; - } else if (priv->minor == GPIO_MINOR_G) { - ret = (*R_PORT_G_DATA) & 0x7FFFFFFF; - } - spin_unlock_irqrestore(&gpio_lock, flags); - - break; - case IO_SETBITS: - // set changeable bits with a 1 in arg - spin_lock_irqsave(&gpio_lock, flags); - - if (USE_PORTS(priv)) { - *priv->port = *priv->shadow |= - ((unsigned char)arg & priv->changeable_bits); - } else if (priv->minor == GPIO_MINOR_G) { - *R_PORT_G_DATA = port_g_data_shadow |= (arg & dir_g_out_bits); - } - spin_unlock_irqrestore(&gpio_lock, flags); - - break; - case IO_CLRBITS: - // clear changeable bits with a 1 in arg - spin_lock_irqsave(&gpio_lock, flags); - if (USE_PORTS(priv)) { - *priv->port = *priv->shadow &= - ~((unsigned char)arg & priv->changeable_bits); - } else if (priv->minor == GPIO_MINOR_G) { - *R_PORT_G_DATA = port_g_data_shadow &= ~((unsigned long)arg & dir_g_out_bits); - } - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_HIGHALARM: - // set alarm when bits with 1 in arg go high - spin_lock_irqsave(&gpio_lock, flags); - priv->highalarm |= arg; - gpio_some_alarms = 1; - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_LOWALARM: - // set alarm when bits with 1 in arg go low - spin_lock_irqsave(&gpio_lock, flags); - priv->lowalarm |= arg; - gpio_some_alarms = 1; - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_CLRALARM: - /* clear alarm for bits with 1 in arg */ - spin_lock_irqsave(&gpio_lock, flags); - priv->highalarm &= ~arg; - priv->lowalarm &= ~arg; - { - /* Must update gpio_some_alarms */ - struct gpio_private *p = alarmlist; - int some_alarms; - p = alarmlist; - some_alarms = 0; - while (p) { - if (p->highalarm | p->lowalarm) { - some_alarms = 1; - break; - } - p = p->next; - } - gpio_some_alarms = some_alarms; - } - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_READDIR: /* Use IO_SETGET_INPUT/OUTPUT instead! */ - /* Read direction 0=input 1=output */ - spin_lock_irqsave(&gpio_lock, flags); - if (USE_PORTS(priv)) { - ret = *priv->dir_shadow; - } else if (priv->minor == GPIO_MINOR_G) { - /* Note: Some bits are both in and out, - * Those that are dual is set here as well. - */ - ret = (dir_g_shadow | dir_g_out_bits) & 0x7FFFFFFF; - } - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_SETINPUT: /* Use IO_SETGET_INPUT instead! */ - /* Set direction 0=unchanged 1=input, - * return mask with 1=input - */ - spin_lock_irqsave(&gpio_lock, flags); - ret = setget_input(priv, arg) & 0x7FFFFFFF; - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_SETOUTPUT: /* Use IO_SETGET_OUTPUT instead! */ - /* Set direction 0=unchanged 1=output, - * return mask with 1=output - */ - spin_lock_irqsave(&gpio_lock, flags); - ret = setget_output(priv, arg) & 0x7FFFFFFF; - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_SHUTDOWN: - spin_lock_irqsave(&gpio_lock, flags); - SOFT_SHUTDOWN(); - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_GET_PWR_BT: - spin_lock_irqsave(&gpio_lock, flags); -#if defined (CONFIG_ETRAX_SOFT_SHUTDOWN) - ret = (*R_PORT_G_DATA & ( 1 << CONFIG_ETRAX_POWERBUTTON_BIT)); -#else - ret = 0; -#endif - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_CFG_WRITE_MODE: - spin_lock_irqsave(&gpio_lock, flags); - priv->clk_mask = arg & 0xFF; - priv->data_mask = (arg >> 8) & 0xFF; - priv->write_msb = (arg >> 16) & 0x01; - /* Check if we're allowed to change the bits and - * the direction is correct - */ - if (!((priv->clk_mask & priv->changeable_bits) && - (priv->data_mask & priv->changeable_bits) && - (priv->clk_mask & *priv->dir_shadow) && - (priv->data_mask & *priv->dir_shadow))) - { - priv->clk_mask = 0; - priv->data_mask = 0; - ret = -EPERM; - } - spin_unlock_irqrestore(&gpio_lock, flags); - break; - case IO_READ_INBITS: - /* *arg is result of reading the input pins */ - spin_lock_irqsave(&gpio_lock, flags); - if (USE_PORTS(priv)) { - val = *priv->port; - } else if (priv->minor == GPIO_MINOR_G) { - val = *R_PORT_G_DATA; - } - spin_unlock_irqrestore(&gpio_lock, flags); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - ret = -EFAULT; - break; - case IO_READ_OUTBITS: - /* *arg is result of reading the output shadow */ - spin_lock_irqsave(&gpio_lock, flags); - if (USE_PORTS(priv)) { - val = *priv->shadow; - } else if (priv->minor == GPIO_MINOR_G) { - val = port_g_data_shadow; - } - spin_unlock_irqrestore(&gpio_lock, flags); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - ret = -EFAULT; - break; - case IO_SETGET_INPUT: - /* bits set in *arg is set to input, - * *arg updated with current input pins. - */ - if (copy_from_user(&val, (void __user *)arg, sizeof(val))) - { - ret = -EFAULT; - break; - } - spin_lock_irqsave(&gpio_lock, flags); - val = setget_input(priv, val); - spin_unlock_irqrestore(&gpio_lock, flags); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - ret = -EFAULT; - break; - case IO_SETGET_OUTPUT: - /* bits set in *arg is set to output, - * *arg updated with current output pins. - */ - if (copy_from_user(&val, (void __user *)arg, sizeof(val))) { - ret = -EFAULT; - break; - } - spin_lock_irqsave(&gpio_lock, flags); - val = setget_output(priv, val); - spin_unlock_irqrestore(&gpio_lock, flags); - if (copy_to_user((void __user *)arg, &val, sizeof(val))) - ret = -EFAULT; - break; - default: - spin_lock_irqsave(&gpio_lock, flags); - if (priv->minor == GPIO_MINOR_LEDS) - ret = gpio_leds_ioctl(cmd, arg); - else - ret = -EINVAL; - spin_unlock_irqrestore(&gpio_lock, flags); - } /* switch */ - - return ret; -} - -static int -gpio_leds_ioctl(unsigned int cmd, unsigned long arg) -{ - unsigned char green; - unsigned char red; - - switch (_IOC_NR(cmd)) { - case IO_LEDACTIVE_SET: - green = ((unsigned char)arg) & 1; - red = (((unsigned char)arg) >> 1) & 1; - CRIS_LED_ACTIVE_SET_G(green); - CRIS_LED_ACTIVE_SET_R(red); - break; - - case IO_LED_SETBIT: - CRIS_LED_BIT_SET(arg); - break; - - case IO_LED_CLRBIT: - CRIS_LED_BIT_CLR(arg); - break; - - default: - return -EINVAL; - } /* switch */ - - return 0; -} - -static const struct file_operations gpio_fops = { - .owner = THIS_MODULE, - .poll = gpio_poll, - .unlocked_ioctl = gpio_ioctl, - .write = gpio_write, - .open = gpio_open, - .release = gpio_release, - .llseek = noop_llseek, -}; - -static void ioif_watcher(const unsigned int gpio_in_available, - const unsigned int gpio_out_available, - const unsigned char pa_available, - const unsigned char pb_available) -{ - unsigned long int flags; - - D(printk(KERN_DEBUG "gpio.c: ioif_watcher called\n")); - D(printk(KERN_DEBUG "gpio.c: G in: 0x%08x G out: 0x%08x " - "PA: 0x%02x PB: 0x%02x\n", - gpio_in_available, gpio_out_available, - pa_available, pb_available)); - - spin_lock_irqsave(&gpio_lock, flags); - - dir_g_in_bits = gpio_in_available; - dir_g_out_bits = gpio_out_available; - - /* Initialise the dir_g_shadow etc. depending on genconfig */ - /* 0=input 1=output */ - if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g0dir, out)) - dir_g_shadow |= (1 << 0); - if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g8_15dir, out)) - dir_g_shadow |= 0x0000FF00; - if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g16_23dir, out)) - dir_g_shadow |= 0x00FF0000; - if (genconfig_shadow & IO_STATE(R_GEN_CONFIG, g24dir, out)) - dir_g_shadow |= (1 << 24); - - changeable_dir_g = changeable_dir_g_mask; - changeable_dir_g &= dir_g_out_bits; - changeable_dir_g &= dir_g_in_bits; - - /* Correct the bits that can change direction */ - dir_g_out_bits &= ~changeable_dir_g; - dir_g_out_bits |= dir_g_shadow; - dir_g_in_bits &= ~changeable_dir_g; - dir_g_in_bits |= (~dir_g_shadow & changeable_dir_g); - - spin_unlock_irqrestore(&gpio_lock, flags); - - printk(KERN_INFO "GPIO port G: in_bits: 0x%08lX out_bits: 0x%08lX " - "val: %08lX\n", - dir_g_in_bits, dir_g_out_bits, (unsigned long)*R_PORT_G_DATA); - printk(KERN_INFO "GPIO port G: dir: %08lX changeable: %08lX\n", - dir_g_shadow, changeable_dir_g); -} - -/* main driver initialization routine, called from mem.c */ - -static int __init gpio_init(void) -{ - int res; -#if defined (CONFIG_ETRAX_CSP0_LEDS) - int i; -#endif - - res = register_chrdev(GPIO_MAJOR, gpio_name, &gpio_fops); - if (res < 0) { - printk(KERN_ERR "gpio: couldn't get a major number.\n"); - return res; - } - - /* Clear all leds */ -#if defined (CONFIG_ETRAX_CSP0_LEDS) || defined (CONFIG_ETRAX_PA_LEDS) || defined (CONFIG_ETRAX_PB_LEDS) - CRIS_LED_NETWORK_SET(0); - CRIS_LED_ACTIVE_SET(0); - CRIS_LED_DISK_READ(0); - CRIS_LED_DISK_WRITE(0); - -#if defined (CONFIG_ETRAX_CSP0_LEDS) - for (i = 0; i < 32; i++) - CRIS_LED_BIT_SET(i); -#endif - -#endif - /* The I/O interface allocation watcher will be called when - * registering it. */ - if (cris_io_interface_register_watcher(ioif_watcher)){ - printk(KERN_WARNING "gpio_init: Failed to install IO " - "if allocator watcher\n"); - } - - printk(KERN_INFO "ETRAX 100LX GPIO driver v2.5, (c) 2001-2008 " - "Axis Communications AB\n"); - /* We call etrax_gpio_wake_up_check() from timer interrupt and - * from default_idle() in kernel/process.c - * The check in default_idle() reduces latency from ~15 ms to ~6 ms - * in some tests. - */ - res = request_irq(TIMER0_IRQ_NBR, gpio_poll_timer_interrupt, - IRQF_SHARED, "gpio poll", gpio_name); - if (res) { - printk(KERN_CRIT "err: timer0 irq for gpio\n"); - return res; - } - res = request_irq(PA_IRQ_NBR, gpio_interrupt, - IRQF_SHARED, "gpio PA", gpio_name); - if (res) - printk(KERN_CRIT "err: PA irq for gpio\n"); - - return res; -} - -/* this makes sure that gpio_init is called during kernel boot */ -module_init(gpio_init); - diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c deleted file mode 100644 index ec35d62e8e63..000000000000 --- a/arch/cris/arch-v10/drivers/i2c.c +++ /dev/null @@ -1,699 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/*!*************************************************************************** -*! -*! FILE NAME : i2c.c -*! -*! DESCRIPTION: implements an interface for IIC/I2C, both directly from other -*! kernel modules (i2c_writereg/readreg) and from userspace using -*! ioctl()'s -*! -*! (C) Copyright 1999-2007 Axis Communications AB, LUND, SWEDEN -*! -*!***************************************************************************/ - -/****************** INCLUDE FILES SECTION ***********************************/ - -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/fs.h> -#include <linux/string.h> -#include <linux/init.h> - -#include <asm/etraxi2c.h> - -#include <arch/svinto.h> -#include <asm/io.h> -#include <asm/delay.h> -#include <arch/io_interface_mux.h> - -#include "i2c.h" - -/****************** I2C DEFINITION SECTION *************************/ - -#define D(x) - -#define I2C_MAJOR 123 /* LOCAL/EXPERIMENTAL */ -static const char i2c_name[] = "i2c"; - -#define CLOCK_LOW_TIME 8 -#define CLOCK_HIGH_TIME 8 -#define START_CONDITION_HOLD_TIME 8 -#define STOP_CONDITION_HOLD_TIME 8 -#define ENABLE_OUTPUT 0x01 -#define ENABLE_INPUT 0x00 -#define I2C_CLOCK_HIGH 1 -#define I2C_CLOCK_LOW 0 -#define I2C_DATA_HIGH 1 -#define I2C_DATA_LOW 0 - -#ifdef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C -/* Use PB and not PB_I2C */ -#ifndef CONFIG_ETRAX_I2C_DATA_PORT -#define CONFIG_ETRAX_I2C_DATA_PORT 0 -#endif -#ifndef CONFIG_ETRAX_I2C_CLK_PORT -#define CONFIG_ETRAX_I2C_CLK_PORT 1 -#endif - -#define SDABIT CONFIG_ETRAX_I2C_DATA_PORT -#define SCLBIT CONFIG_ETRAX_I2C_CLK_PORT -#define i2c_enable() -#define i2c_disable() - -/* enable or disable output-enable, to select output or input on the i2c bus */ - -#define i2c_dir_out() \ - REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, SDABIT, 1) -#define i2c_dir_in() \ - REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, SDABIT, 0) - -/* control the i2c clock and data signals */ - -#define i2c_clk(x) \ - REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, SCLBIT, x) -#define i2c_data(x) \ - REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, SDABIT, x) - -/* read a bit from the i2c interface */ - -#define i2c_getbit() (((*R_PORT_PB_READ & (1 << SDABIT))) >> SDABIT) - -#else -/* enable or disable the i2c interface */ - -#define i2c_enable() *R_PORT_PB_I2C = (port_pb_i2c_shadow |= IO_MASK(R_PORT_PB_I2C, i2c_en)) -#define i2c_disable() *R_PORT_PB_I2C = (port_pb_i2c_shadow &= ~IO_MASK(R_PORT_PB_I2C, i2c_en)) - -/* enable or disable output-enable, to select output or input on the i2c bus */ - -#define i2c_dir_out() \ - *R_PORT_PB_I2C = (port_pb_i2c_shadow &= ~IO_MASK(R_PORT_PB_I2C, i2c_oe_)); \ - REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, 0, 1); -#define i2c_dir_in() \ - *R_PORT_PB_I2C = (port_pb_i2c_shadow |= IO_MASK(R_PORT_PB_I2C, i2c_oe_)); \ - REG_SHADOW_SET(R_PORT_PB_DIR, port_pb_dir_shadow, 0, 0); - -/* control the i2c clock and data signals */ - -#define i2c_clk(x) \ - *R_PORT_PB_I2C = (port_pb_i2c_shadow = (port_pb_i2c_shadow & \ - ~IO_MASK(R_PORT_PB_I2C, i2c_clk)) | IO_FIELD(R_PORT_PB_I2C, i2c_clk, (x))); \ - REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 1, x); - -#define i2c_data(x) \ - *R_PORT_PB_I2C = (port_pb_i2c_shadow = (port_pb_i2c_shadow & \ - ~IO_MASK(R_PORT_PB_I2C, i2c_d)) | IO_FIELD(R_PORT_PB_I2C, i2c_d, (x))); \ - REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 0, x); - -/* read a bit from the i2c interface */ - -#define i2c_getbit() (*R_PORT_PB_READ & 0x1) -#endif - -/* use the kernels delay routine */ - -#define i2c_delay(usecs) udelay(usecs) - -static DEFINE_SPINLOCK(i2c_lock); /* Protect directions etc */ - -/****************** FUNCTION DEFINITION SECTION *************************/ - - -/* generate i2c start condition */ - -void -i2c_start(void) -{ - /* - * SCL=1 SDA=1 - */ - i2c_dir_out(); - i2c_delay(CLOCK_HIGH_TIME/6); - i2c_data(I2C_DATA_HIGH); - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - /* - * SCL=1 SDA=0 - */ - i2c_data(I2C_DATA_LOW); - i2c_delay(START_CONDITION_HOLD_TIME); - /* - * SCL=0 SDA=0 - */ - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_LOW_TIME); -} - -/* generate i2c stop condition */ - -void -i2c_stop(void) -{ - i2c_dir_out(); - - /* - * SCL=0 SDA=0 - */ - i2c_clk(I2C_CLOCK_LOW); - i2c_data(I2C_DATA_LOW); - i2c_delay(CLOCK_LOW_TIME*2); - /* - * SCL=1 SDA=0 - */ - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME*2); - /* - * SCL=1 SDA=1 - */ - i2c_data(I2C_DATA_HIGH); - i2c_delay(STOP_CONDITION_HOLD_TIME); - - i2c_dir_in(); -} - -/* write a byte to the i2c interface */ - -void -i2c_outbyte(unsigned char x) -{ - int i; - - i2c_dir_out(); - - for (i = 0; i < 8; i++) { - if (x & 0x80) { - i2c_data(I2C_DATA_HIGH); - } else { - i2c_data(I2C_DATA_LOW); - } - - i2c_delay(CLOCK_LOW_TIME/2); - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_LOW_TIME/2); - x <<= 1; - } - i2c_data(I2C_DATA_LOW); - i2c_delay(CLOCK_LOW_TIME/2); - - /* - * enable input - */ - i2c_dir_in(); -} - -/* read a byte from the i2c interface */ - -unsigned char -i2c_inbyte(void) -{ - unsigned char aBitByte = 0; - int i; - - /* Switch off I2C to get bit */ - i2c_disable(); - i2c_dir_in(); - i2c_delay(CLOCK_HIGH_TIME/2); - - /* Get bit */ - aBitByte |= i2c_getbit(); - - /* Enable I2C */ - i2c_enable(); - i2c_delay(CLOCK_LOW_TIME/2); - - for (i = 1; i < 8; i++) { - aBitByte <<= 1; - /* Clock pulse */ - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_LOW_TIME); - - /* Switch off I2C to get bit */ - i2c_disable(); - i2c_dir_in(); - i2c_delay(CLOCK_HIGH_TIME/2); - - /* Get bit */ - aBitByte |= i2c_getbit(); - - /* Enable I2C */ - i2c_enable(); - i2c_delay(CLOCK_LOW_TIME/2); - } - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - - /* - * we leave the clock low, getbyte is usually followed - * by sendack/nack, they assume the clock to be low - */ - i2c_clk(I2C_CLOCK_LOW); - return aBitByte; -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: i2c_getack -*# -*# DESCRIPTION : checks if ack was received from ic2 -*# -*#--------------------------------------------------------------------------*/ - -int -i2c_getack(void) -{ - int ack = 1; - /* - * enable output - */ - i2c_dir_out(); - /* - * Release data bus by setting - * data high - */ - i2c_data(I2C_DATA_HIGH); - /* - * enable input - */ - i2c_dir_in(); - i2c_delay(CLOCK_HIGH_TIME/4); - /* - * generate ACK clock pulse - */ - i2c_clk(I2C_CLOCK_HIGH); - /* - * Use PORT PB instead of I2C - * for input. (I2C not working) - */ - i2c_clk(1); - i2c_data(1); - /* - * switch off I2C - */ - i2c_data(1); - i2c_disable(); - i2c_dir_in(); - /* - * now wait for ack - */ - i2c_delay(CLOCK_HIGH_TIME/2); - /* - * check for ack - */ - if(i2c_getbit()) - ack = 0; - i2c_delay(CLOCK_HIGH_TIME/2); - if(!ack){ - if(!i2c_getbit()) /* receiver pulld SDA low */ - ack = 1; - i2c_delay(CLOCK_HIGH_TIME/2); - } - - /* - * our clock is high now, make sure data is low - * before we enable our output. If we keep data high - * and enable output, we would generate a stop condition. - */ - i2c_data(I2C_DATA_LOW); - - /* - * end clock pulse - */ - i2c_enable(); - i2c_dir_out(); - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_HIGH_TIME/4); - /* - * enable output - */ - i2c_dir_out(); - /* - * remove ACK clock pulse - */ - i2c_data(I2C_DATA_HIGH); - i2c_delay(CLOCK_LOW_TIME/2); - return ack; -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: I2C::sendAck -*# -*# DESCRIPTION : Send ACK on received data -*# -*#--------------------------------------------------------------------------*/ -void -i2c_sendack(void) -{ - /* - * enable output - */ - i2c_delay(CLOCK_LOW_TIME); - i2c_dir_out(); - /* - * set ack pulse high - */ - i2c_data(I2C_DATA_LOW); - /* - * generate clock pulse - */ - i2c_delay(CLOCK_HIGH_TIME/6); - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_LOW_TIME/6); - /* - * reset data out - */ - i2c_data(I2C_DATA_HIGH); - i2c_delay(CLOCK_LOW_TIME); - - i2c_dir_in(); -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: i2c_sendnack -*# -*# DESCRIPTION : Sends NACK on received data -*# -*#--------------------------------------------------------------------------*/ -void -i2c_sendnack(void) -{ - /* - * enable output - */ - i2c_delay(CLOCK_LOW_TIME); - i2c_dir_out(); - /* - * set data high - */ - i2c_data(I2C_DATA_HIGH); - /* - * generate clock pulse - */ - i2c_delay(CLOCK_HIGH_TIME/6); - i2c_clk(I2C_CLOCK_HIGH); - i2c_delay(CLOCK_HIGH_TIME); - i2c_clk(I2C_CLOCK_LOW); - i2c_delay(CLOCK_LOW_TIME); - - i2c_dir_in(); -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: i2c_writereg -*# -*# DESCRIPTION : Writes a value to an I2C device -*# -*#--------------------------------------------------------------------------*/ -int -i2c_writereg(unsigned char theSlave, unsigned char theReg, - unsigned char theValue) -{ - int error, cntr = 3; - unsigned long flags; - - spin_lock(&i2c_lock); - - do { - error = 0; - /* - * we don't like to be interrupted - */ - local_irq_save(flags); - - i2c_start(); - /* - * send slave address - */ - i2c_outbyte((theSlave & 0xfe)); - /* - * wait for ack - */ - if(!i2c_getack()) - error = 1; - /* - * now select register - */ - i2c_dir_out(); - i2c_outbyte(theReg); - /* - * now it's time to wait for ack - */ - if(!i2c_getack()) - error |= 2; - /* - * send register register data - */ - i2c_outbyte(theValue); - /* - * now it's time to wait for ack - */ - if(!i2c_getack()) - error |= 4; - /* - * end byte stream - */ - i2c_stop(); - /* - * enable interrupt again - */ - local_irq_restore(flags); - - } while(error && cntr--); - - i2c_delay(CLOCK_LOW_TIME); - - spin_unlock(&i2c_lock); - - return -error; -} - -/*#--------------------------------------------------------------------------- -*# -*# FUNCTION NAME: i2c_readreg -*# -*# DESCRIPTION : Reads a value from the decoder registers. -*# -*#--------------------------------------------------------------------------*/ -unsigned char -i2c_readreg(unsigned char theSlave, unsigned char theReg) -{ - unsigned char b = 0; - int error, cntr = 3; - unsigned long flags; - - spin_lock(&i2c_lock); - - do { - error = 0; - /* - * we don't like to be interrupted - */ - local_irq_save(flags); - /* - * generate start condition - */ - i2c_start(); - - /* - * send slave address - */ - i2c_outbyte((theSlave & 0xfe)); - /* - * wait for ack - */ - if(!i2c_getack()) - error = 1; - /* - * now select register - */ - i2c_dir_out(); - i2c_outbyte(theReg); - /* - * now it's time to wait for ack - */ - if(!i2c_getack()) - error = 1; - /* - * repeat start condition - */ - i2c_delay(CLOCK_LOW_TIME); - i2c_start(); - /* - * send slave address - */ - i2c_outbyte(theSlave | 0x01); - /* - * wait for ack - */ - if(!i2c_getack()) - error = 1; - /* - * fetch register - */ - b = i2c_inbyte(); - /* - * last received byte needs to be nacked - * instead of acked - */ - i2c_sendnack(); - /* - * end sequence - */ - i2c_stop(); - /* - * enable interrupt again - */ - local_irq_restore(flags); - - } while(error && cntr--); - - spin_unlock(&i2c_lock); - - return b; -} - -static int -i2c_open(struct inode *inode, struct file *filp) -{ - return 0; -} - -static int -i2c_release(struct inode *inode, struct file *filp) -{ - return 0; -} - -/* Main device API. ioctl's to write or read to/from i2c registers. - */ - -static long i2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - if(_IOC_TYPE(cmd) != ETRAXI2C_IOCTYPE) { - return -EINVAL; - } - - switch (_IOC_NR(cmd)) { - case I2C_WRITEREG: - /* write to an i2c slave */ - D(printk(KERN_DEBUG "i2cw %d %d %d\n", - I2C_ARGSLAVE(arg), - I2C_ARGREG(arg), - I2C_ARGVALUE(arg))); - - return i2c_writereg(I2C_ARGSLAVE(arg), - I2C_ARGREG(arg), - I2C_ARGVALUE(arg)); - case I2C_READREG: - { - unsigned char val; - /* read from an i2c slave */ - D(printk(KERN_DEBUG "i2cr %d %d ", - I2C_ARGSLAVE(arg), - I2C_ARGREG(arg))); - val = i2c_readreg(I2C_ARGSLAVE(arg), I2C_ARGREG(arg)); - D(printk(KERN_DEBUG "= %d\n", val)); - return val; - } - default: - return -EINVAL; - - } - return 0; -} - -static const struct file_operations i2c_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = i2c_ioctl, - .open = i2c_open, - .release = i2c_release, - .llseek = noop_llseek, -}; - -int __init -i2c_init(void) -{ - static int res = 0; - static int first = 1; - - if (!first) { - return res; - } - first = 0; - - /* Setup and enable the Port B I2C interface */ - -#ifndef CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C - if ((res = cris_request_io_interface(if_i2c, "I2C"))) { - printk(KERN_CRIT "i2c_init: Failed to get IO interface\n"); - return res; - } - - *R_PORT_PB_I2C = port_pb_i2c_shadow |= - IO_STATE(R_PORT_PB_I2C, i2c_en, on) | - IO_FIELD(R_PORT_PB_I2C, i2c_d, 1) | - IO_FIELD(R_PORT_PB_I2C, i2c_clk, 1) | - IO_STATE(R_PORT_PB_I2C, i2c_oe_, enable); - - port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir0); - port_pb_dir_shadow &= ~IO_MASK(R_PORT_PB_DIR, dir1); - - *R_PORT_PB_DIR = (port_pb_dir_shadow |= - IO_STATE(R_PORT_PB_DIR, dir0, input) | - IO_STATE(R_PORT_PB_DIR, dir1, output)); -#else - if ((res = cris_io_interface_allocate_pins(if_i2c, - 'b', - CONFIG_ETRAX_I2C_DATA_PORT, - CONFIG_ETRAX_I2C_DATA_PORT))) { - printk(KERN_WARNING "i2c_init: Failed to get IO pin for I2C data port\n"); - return res; - } else if ((res = cris_io_interface_allocate_pins(if_i2c, - 'b', - CONFIG_ETRAX_I2C_CLK_PORT, - CONFIG_ETRAX_I2C_CLK_PORT))) { - cris_io_interface_free_pins(if_i2c, - 'b', - CONFIG_ETRAX_I2C_DATA_PORT, - CONFIG_ETRAX_I2C_DATA_PORT); - printk(KERN_WARNING "i2c_init: Failed to get IO pin for I2C clk port\n"); - } -#endif - - return res; -} - -static int __init -i2c_register(void) -{ - int res; - - res = i2c_init(); - if (res < 0) - return res; - res = register_chrdev(I2C_MAJOR, i2c_name, &i2c_fops); - if(res < 0) { - printk(KERN_ERR "i2c: couldn't get a major number.\n"); - return res; - } - - printk(KERN_INFO "I2C driver v2.2, (c) 1999-2004 Axis Communications AB\n"); - - return 0; -} - -/* this makes sure that i2c_register is called during boot */ - -module_init(i2c_register); - -/****************** END OF FILE i2c.c ********************************/ diff --git a/arch/cris/arch-v10/drivers/i2c.h b/arch/cris/arch-v10/drivers/i2c.h deleted file mode 100644 index de45c1ffbd7b..000000000000 --- a/arch/cris/arch-v10/drivers/i2c.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* i2c.h */ -int i2c_init(void); - -/* High level I2C actions */ -int i2c_writereg(unsigned char theSlave, unsigned char theReg, unsigned char theValue); -unsigned char i2c_readreg(unsigned char theSlave, unsigned char theReg); - -/* Low level I2C */ -void i2c_start(void); -void i2c_stop(void); -void i2c_outbyte(unsigned char x); -unsigned char i2c_inbyte(void); -int i2c_getack(void); -void i2c_sendack(void); - - - diff --git a/arch/cris/arch-v10/drivers/sync_serial.c b/arch/cris/arch-v10/drivers/sync_serial.c deleted file mode 100644 index ed1a568a7217..000000000000 --- a/arch/cris/arch-v10/drivers/sync_serial.c +++ /dev/null @@ -1,1463 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Simple synchronous serial port driver for ETRAX 100LX. - * - * Synchronous serial ports are used for continuous streamed data like audio. - * The default setting for this driver is compatible with the STA 013 MP3 - * decoder. The driver can easily be tuned to fit other audio encoder/decoders - * and SPI - * - * Copyright (c) 2001-2008 Axis Communications AB - * - * Author: Mikael Starvik, Johan Adolfsson - * - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/major.h> -#include <linux/sched/signal.h> -#include <linux/interrupt.h> -#include <linux/poll.h> -#include <linux/init.h> -#include <linux/mutex.h> -#include <linux/timer.h> -#include <linux/wait.h> -#include <asm/irq.h> -#include <asm/dma.h> -#include <asm/io.h> -#include <arch/svinto.h> -#include <linux/uaccess.h> -#include <asm/sync_serial.h> -#include <arch/io_interface_mux.h> - -/* The receiver is a bit tricky because of the continuous stream of data.*/ -/* */ -/* Three DMA descriptors are linked together. Each DMA descriptor is */ -/* responsible for port->bufchunk of a common buffer. */ -/* */ -/* +---------------------------------------------+ */ -/* | +----------+ +----------+ +----------+ | */ -/* +-> | Descr[0] |-->| Descr[1] |-->| Descr[2] |-+ */ -/* +----------+ +----------+ +----------+ */ -/* | | | */ -/* v v v */ -/* +-------------------------------------+ */ -/* | BUFFER | */ -/* +-------------------------------------+ */ -/* |<- data_avail ->| */ -/* readp writep */ -/* */ -/* If the application keeps up the pace readp will be right after writep.*/ -/* If the application can't keep the pace we have to throw away data. */ -/* The idea is that readp should be ready with the data pointed out by */ -/* Descr[i] when the DMA has filled in Descr[i+1]. */ -/* Otherwise we will discard */ -/* the rest of the data pointed out by Descr1 and set readp to the start */ -/* of Descr2 */ - -#define SYNC_SERIAL_MAJOR 125 - -/* IN_BUFFER_SIZE should be a multiple of 6 to make sure that 24 bit */ -/* words can be handled */ -#define IN_BUFFER_SIZE 12288 -#define IN_DESCR_SIZE 256 -#define NUM_IN_DESCR (IN_BUFFER_SIZE/IN_DESCR_SIZE) -#define OUT_BUFFER_SIZE 4096 - -#define DEFAULT_FRAME_RATE 0 -#define DEFAULT_WORD_RATE 7 - -/* NOTE: Enabling some debug will likely cause overrun or underrun, - * especially if manual mode is use. - */ -#define DEBUG(x) -#define DEBUGREAD(x) -#define DEBUGWRITE(x) -#define DEBUGPOLL(x) -#define DEBUGRXINT(x) -#define DEBUGTXINT(x) - -/* Define some macros to access ETRAX 100 registers */ -#define SETF(var, reg, field, val) \ - do { \ - var = (var & ~IO_MASK_(reg##_, field##_)) | \ - IO_FIELD_(reg##_, field##_, val); \ - } while (0) - -#define SETS(var, reg, field, val) \ - do { \ - var = (var & ~IO_MASK_(reg##_, field##_)) | \ - IO_STATE_(reg##_, field##_, _##val); \ - } while (0) - -struct sync_port { - /* Etrax registers and bits*/ - const volatile unsigned *const status; - volatile unsigned *const ctrl_data; - volatile unsigned *const output_dma_first; - volatile unsigned char *const output_dma_cmd; - volatile unsigned char *const output_dma_clr_irq; - volatile unsigned *const input_dma_first; - volatile unsigned char *const input_dma_cmd; - volatile unsigned *const input_dma_descr; - /* 8*4 */ - volatile unsigned char *const input_dma_clr_irq; - volatile unsigned *const data_out; - const volatile unsigned *const data_in; - char data_avail_bit; /* In R_IRQ_MASK1_RD/SET/CLR */ - char transmitter_ready_bit; /* In R_IRQ_MASK1_RD/SET/CLR */ - char input_dma_descr_bit; /* In R_IRQ_MASK2_RD */ - - char output_dma_bit; /* In R_IRQ_MASK2_RD */ - /* End of fields initialised in array */ - char started; /* 1 if port has been started */ - char port_nbr; /* Port 0 or 1 */ - char busy; /* 1 if port is busy */ - - char enabled; /* 1 if port is enabled */ - char use_dma; /* 1 if port uses dma */ - char tr_running; - - char init_irqs; - - /* Register shadow */ - unsigned int ctrl_data_shadow; - /* Remaining bytes for current transfer */ - volatile unsigned int out_count; - /* Current position in out_buffer */ - unsigned char *outp; - /* 16*4 */ - /* Next byte to be read by application */ - volatile unsigned char *volatile readp; - /* Next byte to be written by etrax */ - volatile unsigned char *volatile writep; - - unsigned int in_buffer_size; - unsigned int inbufchunk; - struct etrax_dma_descr out_descr __attribute__ ((aligned(32))); - struct etrax_dma_descr in_descr[NUM_IN_DESCR] __attribute__ ((aligned(32))); - unsigned char out_buffer[OUT_BUFFER_SIZE] __attribute__ ((aligned(32))); - unsigned char in_buffer[IN_BUFFER_SIZE]__attribute__ ((aligned(32))); - unsigned char flip[IN_BUFFER_SIZE] __attribute__ ((aligned(32))); - struct etrax_dma_descr *next_rx_desc; - struct etrax_dma_descr *prev_rx_desc; - int full; - - wait_queue_head_t out_wait_q; - wait_queue_head_t in_wait_q; -}; - - -static DEFINE_MUTEX(sync_serial_mutex); -static int etrax_sync_serial_init(void); -static void initialize_port(int portnbr); -static inline int sync_data_avail(struct sync_port *port); - -static int sync_serial_open(struct inode *inode, struct file *file); -static int sync_serial_release(struct inode *inode, struct file *file); -static __poll_t sync_serial_poll(struct file *filp, poll_table *wait); - -static long sync_serial_ioctl(struct file *file, - unsigned int cmd, unsigned long arg); -static ssize_t sync_serial_write(struct file *file, const char *buf, - size_t count, loff_t *ppos); -static ssize_t sync_serial_read(struct file *file, char *buf, - size_t count, loff_t *ppos); - -#if ((defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \ - defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \ - (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \ - defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA))) -#define SYNC_SER_DMA -#endif - -static void send_word(struct sync_port *port); -static void start_dma(struct sync_port *port, const char *data, int count); -static void start_dma_in(struct sync_port *port); -#ifdef SYNC_SER_DMA -static irqreturn_t tr_interrupt(int irq, void *dev_id); -static irqreturn_t rx_interrupt(int irq, void *dev_id); -#endif -#if ((defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) && \ - !defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA)) || \ - (defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) && \ - !defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA))) -#define SYNC_SER_MANUAL -#endif -#ifdef SYNC_SER_MANUAL -static irqreturn_t manual_interrupt(int irq, void *dev_id); -#endif - -/* The ports */ -static struct sync_port ports[] = { - { - .status = R_SYNC_SERIAL1_STATUS, - .ctrl_data = R_SYNC_SERIAL1_CTRL, - .output_dma_first = R_DMA_CH8_FIRST, - .output_dma_cmd = R_DMA_CH8_CMD, - .output_dma_clr_irq = R_DMA_CH8_CLR_INTR, - .input_dma_first = R_DMA_CH9_FIRST, - .input_dma_cmd = R_DMA_CH9_CMD, - .input_dma_descr = R_DMA_CH9_DESCR, - .input_dma_clr_irq = R_DMA_CH9_CLR_INTR, - .data_out = R_SYNC_SERIAL1_TR_DATA, - .data_in = R_SYNC_SERIAL1_REC_DATA, - .data_avail_bit = IO_BITNR(R_IRQ_MASK1_RD, ser1_data), - .transmitter_ready_bit = IO_BITNR(R_IRQ_MASK1_RD, ser1_ready), - .input_dma_descr_bit = IO_BITNR(R_IRQ_MASK2_RD, dma9_descr), - .output_dma_bit = IO_BITNR(R_IRQ_MASK2_RD, dma8_eop), - .init_irqs = 1, -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA) - .use_dma = 1, -#else - .use_dma = 0, -#endif - }, - { - .status = R_SYNC_SERIAL3_STATUS, - .ctrl_data = R_SYNC_SERIAL3_CTRL, - .output_dma_first = R_DMA_CH4_FIRST, - .output_dma_cmd = R_DMA_CH4_CMD, - .output_dma_clr_irq = R_DMA_CH4_CLR_INTR, - .input_dma_first = R_DMA_CH5_FIRST, - .input_dma_cmd = R_DMA_CH5_CMD, - .input_dma_descr = R_DMA_CH5_DESCR, - .input_dma_clr_irq = R_DMA_CH5_CLR_INTR, - .data_out = R_SYNC_SERIAL3_TR_DATA, - .data_in = R_SYNC_SERIAL3_REC_DATA, - .data_avail_bit = IO_BITNR(R_IRQ_MASK1_RD, ser3_data), - .transmitter_ready_bit = IO_BITNR(R_IRQ_MASK1_RD, ser3_ready), - .input_dma_descr_bit = IO_BITNR(R_IRQ_MASK2_RD, dma5_descr), - .output_dma_bit = IO_BITNR(R_IRQ_MASK2_RD, dma4_eop), - .init_irqs = 1, -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA) - .use_dma = 1, -#else - .use_dma = 0, -#endif - } -}; - -/* Register shadows */ -static unsigned sync_serial_prescale_shadow; - -#define NUMBER_OF_PORTS 2 - -static const struct file_operations sync_serial_fops = { - .owner = THIS_MODULE, - .write = sync_serial_write, - .read = sync_serial_read, - .poll = sync_serial_poll, - .unlocked_ioctl = sync_serial_ioctl, - .open = sync_serial_open, - .release = sync_serial_release, - .llseek = noop_llseek, -}; - -static int __init etrax_sync_serial_init(void) -{ - ports[0].enabled = 0; - ports[1].enabled = 0; - -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) - if (cris_request_io_interface(if_sync_serial_1, "sync_ser1")) { - printk(KERN_CRIT "ETRAX100LX sync_serial: " - "Could not allocate IO group for port %d\n", 0); - return -EBUSY; - } -#endif -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) - if (cris_request_io_interface(if_sync_serial_3, "sync_ser3")) { -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) - cris_free_io_interface(if_sync_serial_1); -#endif - printk(KERN_CRIT "ETRAX100LX sync_serial: " - "Could not allocate IO group for port %d\n", 1); - return -EBUSY; - } -#endif - - if (register_chrdev(SYNC_SERIAL_MAJOR, "sync serial", - &sync_serial_fops) < 0) { -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) - cris_free_io_interface(if_sync_serial_3); -#endif -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) - cris_free_io_interface(if_sync_serial_1); -#endif - printk("unable to get major for synchronous serial port\n"); - return -EBUSY; - } - - /* Deselect synchronous serial ports while configuring. */ - SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async); - SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async); - *R_GEN_CONFIG_II = gen_config_ii_shadow; - - /* Initialize Ports */ -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT0) - ports[0].enabled = 1; - SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser1, ss1extra); - SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync); -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL0_DMA) - ports[0].use_dma = 1; -#else - ports[0].use_dma = 0; -#endif - initialize_port(0); -#endif - -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1) - ports[1].enabled = 1; - SETS(port_pb_i2c_shadow, R_PORT_PB_I2C, syncser3, ss3extra); - SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync); -#if defined(CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA) - ports[1].use_dma = 1; -#else - ports[1].use_dma = 0; -#endif - initialize_port(1); -#endif - - *R_PORT_PB_I2C = port_pb_i2c_shadow; /* Use PB4/PB7 */ - - /* Set up timing */ - *R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow = ( - IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u1, codec) | - IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u1, external) | - IO_STATE(R_SYNC_SERIAL_PRESCALE, clk_sel_u3, codec) | - IO_STATE(R_SYNC_SERIAL_PRESCALE, word_stb_sel_u3, external) | - IO_STATE(R_SYNC_SERIAL_PRESCALE, prescaler, div4) | - IO_FIELD(R_SYNC_SERIAL_PRESCALE, frame_rate, - DEFAULT_FRAME_RATE) | - IO_FIELD(R_SYNC_SERIAL_PRESCALE, word_rate, DEFAULT_WORD_RATE) | - IO_STATE(R_SYNC_SERIAL_PRESCALE, warp_mode, normal)); - - /* Select synchronous ports */ - *R_GEN_CONFIG_II = gen_config_ii_shadow; - - printk(KERN_INFO "ETRAX 100LX synchronous serial port driver\n"); - return 0; -} - -static void __init initialize_port(int portnbr) -{ - struct sync_port *port = &ports[portnbr]; - - DEBUG(printk(KERN_DEBUG "Init sync serial port %d\n", portnbr)); - - port->started = 0; - port->port_nbr = portnbr; - port->busy = 0; - port->tr_running = 0; - - port->out_count = 0; - port->outp = port->out_buffer; - - port->readp = port->flip; - port->writep = port->flip; - port->in_buffer_size = IN_BUFFER_SIZE; - port->inbufchunk = IN_DESCR_SIZE; - port->next_rx_desc = &port->in_descr[0]; - port->prev_rx_desc = &port->in_descr[NUM_IN_DESCR-1]; - port->prev_rx_desc->ctrl = d_eol; - - init_waitqueue_head(&port->out_wait_q); - init_waitqueue_head(&port->in_wait_q); - - port->ctrl_data_shadow = - IO_STATE(R_SYNC_SERIAL1_CTRL, tr_baud, c115k2Hz) | - IO_STATE(R_SYNC_SERIAL1_CTRL, mode, master_output) | - IO_STATE(R_SYNC_SERIAL1_CTRL, error, ignore) | - IO_STATE(R_SYNC_SERIAL1_CTRL, rec_enable, disable) | - IO_STATE(R_SYNC_SERIAL1_CTRL, f_synctype, normal) | - IO_STATE(R_SYNC_SERIAL1_CTRL, f_syncsize, word) | - IO_STATE(R_SYNC_SERIAL1_CTRL, f_sync, on) | - IO_STATE(R_SYNC_SERIAL1_CTRL, clk_mode, normal) | - IO_STATE(R_SYNC_SERIAL1_CTRL, clk_halt, stopped) | - IO_STATE(R_SYNC_SERIAL1_CTRL, bitorder, msb) | - IO_STATE(R_SYNC_SERIAL1_CTRL, tr_enable, disable) | - IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit) | - IO_STATE(R_SYNC_SERIAL1_CTRL, buf_empty, lmt_8) | - IO_STATE(R_SYNC_SERIAL1_CTRL, buf_full, lmt_8) | - IO_STATE(R_SYNC_SERIAL1_CTRL, flow_ctrl, enabled) | - IO_STATE(R_SYNC_SERIAL1_CTRL, clk_polarity, neg) | - IO_STATE(R_SYNC_SERIAL1_CTRL, frame_polarity, normal)| - IO_STATE(R_SYNC_SERIAL1_CTRL, status_polarity, inverted)| - IO_STATE(R_SYNC_SERIAL1_CTRL, clk_driver, normal) | - IO_STATE(R_SYNC_SERIAL1_CTRL, frame_driver, normal) | - IO_STATE(R_SYNC_SERIAL1_CTRL, status_driver, normal)| - IO_STATE(R_SYNC_SERIAL1_CTRL, def_out0, high); - - if (port->use_dma) - port->ctrl_data_shadow |= IO_STATE(R_SYNC_SERIAL1_CTRL, - dma_enable, on); - else - port->ctrl_data_shadow |= IO_STATE(R_SYNC_SERIAL1_CTRL, - dma_enable, off); - - *port->ctrl_data = port->ctrl_data_shadow; -} - -static inline int sync_data_avail(struct sync_port *port) -{ - int avail; - unsigned char *start; - unsigned char *end; - - start = (unsigned char *)port->readp; /* cast away volatile */ - end = (unsigned char *)port->writep; /* cast away volatile */ - /* 0123456789 0123456789 - * ----- - ----- - * ^rp ^wp ^wp ^rp - */ - if (end >= start) - avail = end - start; - else - avail = port->in_buffer_size - (start - end); - return avail; -} - -static inline int sync_data_avail_to_end(struct sync_port *port) -{ - int avail; - unsigned char *start; - unsigned char *end; - - start = (unsigned char *)port->readp; /* cast away volatile */ - end = (unsigned char *)port->writep; /* cast away volatile */ - /* 0123456789 0123456789 - * ----- ----- - * ^rp ^wp ^wp ^rp - */ - - if (end >= start) - avail = end - start; - else - avail = port->flip + port->in_buffer_size - start; - return avail; -} - - -static int sync_serial_open(struct inode *inode, struct file *file) -{ - int dev = MINOR(inode->i_rdev); - struct sync_port *port; - int mode; - int err = -EBUSY; - - mutex_lock(&sync_serial_mutex); - DEBUG(printk(KERN_DEBUG "Open sync serial port %d\n", dev)); - - if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) { - DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); - err = -ENODEV; - goto out; - } - port = &ports[dev]; - /* Allow open this device twice (assuming one reader and one writer) */ - if (port->busy == 2) { - DEBUG(printk(KERN_DEBUG "Device is busy.. \n")); - goto out; - } - if (port->init_irqs) { - if (port->use_dma) { - if (port == &ports[0]) { -#ifdef SYNC_SER_DMA - if (request_irq(24, tr_interrupt, 0, - "synchronous serial 1 dma tr", - &ports[0])) { - printk(KERN_CRIT "Can't alloc " - "sync serial port 1 IRQ"); - goto out; - } else if (request_irq(25, rx_interrupt, 0, - "synchronous serial 1 dma rx", - &ports[0])) { - free_irq(24, &port[0]); - printk(KERN_CRIT "Can't alloc " - "sync serial port 1 IRQ"); - goto out; - } else if (cris_request_dma(8, - "synchronous serial 1 dma tr", - DMA_VERBOSE_ON_ERROR, - dma_ser1)) { - free_irq(24, &port[0]); - free_irq(25, &port[0]); - printk(KERN_CRIT "Can't alloc " - "sync serial port 1 " - "TX DMA channel"); - goto out; - } else if (cris_request_dma(9, - "synchronous serial 1 dma rec", - DMA_VERBOSE_ON_ERROR, - dma_ser1)) { - cris_free_dma(8, NULL); - free_irq(24, &port[0]); - free_irq(25, &port[0]); - printk(KERN_CRIT "Can't alloc " - "sync serial port 1 " - "RX DMA channel"); - goto out; - } -#endif - RESET_DMA(8); WAIT_DMA(8); - RESET_DMA(9); WAIT_DMA(9); - *R_DMA_CH8_CLR_INTR = - IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, - do) | - IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, - do); - *R_DMA_CH9_CLR_INTR = - IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, - do) | - IO_STATE(R_DMA_CH9_CLR_INTR, clr_descr, - do); - *R_IRQ_MASK2_SET = - IO_STATE(R_IRQ_MASK2_SET, dma8_eop, - set) | - IO_STATE(R_IRQ_MASK2_SET, dma9_descr, - set); - } else if (port == &ports[1]) { -#ifdef SYNC_SER_DMA - if (request_irq(20, tr_interrupt, 0, - "synchronous serial 3 dma tr", - &ports[1])) { - printk(KERN_CRIT "Can't alloc " - "sync serial port 3 IRQ"); - goto out; - } else if (request_irq(21, rx_interrupt, 0, - "synchronous serial 3 dma rx", - &ports[1])) { - free_irq(20, &ports[1]); - printk(KERN_CRIT "Can't alloc " - "sync serial port 3 IRQ"); - goto out; - } else if (cris_request_dma(4, - "synchronous serial 3 dma tr", - DMA_VERBOSE_ON_ERROR, - dma_ser3)) { - free_irq(21, &ports[1]); - free_irq(20, &ports[1]); - printk(KERN_CRIT "Can't alloc " - "sync serial port 3 " - "TX DMA channel"); - goto out; - } else if (cris_request_dma(5, - "synchronous serial 3 dma rec", - DMA_VERBOSE_ON_ERROR, - dma_ser3)) { - cris_free_dma(4, NULL); - free_irq(21, &ports[1]); - free_irq(20, &ports[1]); - printk(KERN_CRIT "Can't alloc " - "sync serial port 3 " - "RX DMA channel"); - goto out; - } -#endif - RESET_DMA(4); WAIT_DMA(4); - RESET_DMA(5); WAIT_DMA(5); - *R_DMA_CH4_CLR_INTR = - IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, - do) | - IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, - do); - *R_DMA_CH5_CLR_INTR = - IO_STATE(R_DMA_CH5_CLR_INTR, clr_eop, - do) | - IO_STATE(R_DMA_CH5_CLR_INTR, clr_descr, - do); - *R_IRQ_MASK2_SET = - IO_STATE(R_IRQ_MASK2_SET, dma4_eop, - set) | - IO_STATE(R_IRQ_MASK2_SET, dma5_descr, - set); - } - start_dma_in(port); - port->init_irqs = 0; - } else { /* !port->use_dma */ -#ifdef SYNC_SER_MANUAL - if (port == &ports[0]) { - if (request_irq(8, - manual_interrupt, - IRQF_SHARED, - "synchronous serial manual irq", - &ports[0])) { - printk(KERN_CRIT "Can't alloc " - "sync serial manual irq"); - goto out; - } - } else if (port == &ports[1]) { - if (request_irq(8, - manual_interrupt, - IRQF_SHARED, - "synchronous serial manual irq", - &ports[1])) { - printk(KERN_CRIT "Can't alloc " - "sync serial manual irq"); - goto out; - } - } - port->init_irqs = 0; -#else - panic("sync_serial: Manual mode not supported.\n"); -#endif /* SYNC_SER_MANUAL */ - } - } /* port->init_irqs */ - - port->busy++; - /* Start port if we use it as input */ - mode = IO_EXTRACT(R_SYNC_SERIAL1_CTRL, mode, port->ctrl_data_shadow); - if (mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, master_input) || - mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, slave_input) || - mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, master_bidir) || - mode == IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, mode, slave_bidir)) { - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, - running); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, - enable); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, - enable); - port->started = 1; - *port->ctrl_data = port->ctrl_data_shadow; - if (!port->use_dma) - *R_IRQ_MASK1_SET = 1 << port->data_avail_bit; - DEBUG(printk(KERN_DEBUG "sser%d rec started\n", dev)); - } - err = 0; - -out: - mutex_unlock(&sync_serial_mutex); - return err; -} - -static int sync_serial_release(struct inode *inode, struct file *file) -{ - int dev = MINOR(inode->i_rdev); - struct sync_port *port; - - if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) { - DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); - return -ENODEV; - } - port = &ports[dev]; - if (port->busy) - port->busy--; - if (!port->busy) - *R_IRQ_MASK1_CLR = ((1 << port->data_avail_bit) | - (1 << port->transmitter_ready_bit)); - - return 0; -} - - - -static __poll_t sync_serial_poll(struct file *file, poll_table *wait) -{ - int dev = MINOR(file_inode(file)->i_rdev); - __poll_t mask = 0; - struct sync_port *port; - DEBUGPOLL(static __poll_t prev_mask = 0); - - port = &ports[dev]; - poll_wait(file, &port->out_wait_q, wait); - poll_wait(file, &port->in_wait_q, wait); - /* Some room to write */ - if (port->out_count < OUT_BUFFER_SIZE) - mask |= EPOLLOUT | EPOLLWRNORM; - /* At least an inbufchunk of data */ - if (sync_data_avail(port) >= port->inbufchunk) - mask |= EPOLLIN | EPOLLRDNORM; - - DEBUGPOLL(if (mask != prev_mask) - printk(KERN_DEBUG "sync_serial_poll: mask 0x%08X %s %s\n", - mask, - mask & EPOLLOUT ? "POLLOUT" : "", - mask & EPOLLIN ? "POLLIN" : ""); - prev_mask = mask; - ); - return mask; -} - -static int sync_serial_ioctl_unlocked(struct file *file, - unsigned int cmd, unsigned long arg) -{ - int return_val = 0; - unsigned long flags; - - int dev = MINOR(file_inode(file)->i_rdev); - struct sync_port *port; - - if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) { - DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); - return -1; - } - port = &ports[dev]; - - local_irq_save(flags); - /* Disable port while changing config */ - if (dev) { - if (port->use_dma) { - RESET_DMA(4); WAIT_DMA(4); - port->tr_running = 0; - port->out_count = 0; - port->outp = port->out_buffer; - *R_DMA_CH4_CLR_INTR = - IO_STATE(R_DMA_CH4_CLR_INTR, clr_eop, do) | - IO_STATE(R_DMA_CH4_CLR_INTR, clr_descr, do); - } - SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, async); - } else { - if (port->use_dma) { - RESET_DMA(8); WAIT_DMA(8); - port->tr_running = 0; - port->out_count = 0; - port->outp = port->out_buffer; - *R_DMA_CH8_CLR_INTR = - IO_STATE(R_DMA_CH8_CLR_INTR, clr_eop, do) | - IO_STATE(R_DMA_CH8_CLR_INTR, clr_descr, do); - } - SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, async); - } - *R_GEN_CONFIG_II = gen_config_ii_shadow; - local_irq_restore(flags); - - switch (cmd) { - case SSP_SPEED: - if (GET_SPEED(arg) == CODEC) { - if (dev) - SETS(sync_serial_prescale_shadow, - R_SYNC_SERIAL_PRESCALE, clk_sel_u3, - codec); - else - SETS(sync_serial_prescale_shadow, - R_SYNC_SERIAL_PRESCALE, clk_sel_u1, - codec); - - SETF(sync_serial_prescale_shadow, - R_SYNC_SERIAL_PRESCALE, prescaler, - GET_FREQ(arg)); - SETF(sync_serial_prescale_shadow, - R_SYNC_SERIAL_PRESCALE, frame_rate, - GET_FRAME_RATE(arg)); - SETF(sync_serial_prescale_shadow, - R_SYNC_SERIAL_PRESCALE, word_rate, - GET_WORD_RATE(arg)); - } else { - SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - tr_baud, GET_SPEED(arg)); - if (dev) - SETS(sync_serial_prescale_shadow, - R_SYNC_SERIAL_PRESCALE, clk_sel_u3, - baudrate); - else - SETS(sync_serial_prescale_shadow, - R_SYNC_SERIAL_PRESCALE, clk_sel_u1, - baudrate); - } - break; - case SSP_MODE: - if (arg > 5) - return -EINVAL; - if (arg == MASTER_OUTPUT || arg == SLAVE_OUTPUT) - *R_IRQ_MASK1_CLR = 1 << port->data_avail_bit; - else if (!port->use_dma) - *R_IRQ_MASK1_SET = 1 << port->data_avail_bit; - SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, mode, arg); - break; - case SSP_FRAME_SYNC: - if (arg & NORMAL_SYNC) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - f_synctype, normal); - else if (arg & EARLY_SYNC) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - f_synctype, early); - - if (arg & BIT_SYNC) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - f_syncsize, bit); - else if (arg & WORD_SYNC) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - f_syncsize, word); - else if (arg & EXTENDED_SYNC) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - f_syncsize, extended); - - if (arg & SYNC_ON) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - f_sync, on); - else if (arg & SYNC_OFF) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - f_sync, off); - - if (arg & WORD_SIZE_8) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - wordsize, size8bit); - else if (arg & WORD_SIZE_12) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - wordsize, size12bit); - else if (arg & WORD_SIZE_16) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - wordsize, size16bit); - else if (arg & WORD_SIZE_24) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - wordsize, size24bit); - else if (arg & WORD_SIZE_32) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - wordsize, size32bit); - - if (arg & BIT_ORDER_MSB) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - bitorder, msb); - else if (arg & BIT_ORDER_LSB) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - bitorder, lsb); - - if (arg & FLOW_CONTROL_ENABLE) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - flow_ctrl, enabled); - else if (arg & FLOW_CONTROL_DISABLE) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - flow_ctrl, disabled); - - if (arg & CLOCK_NOT_GATED) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - clk_mode, normal); - else if (arg & CLOCK_GATED) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - clk_mode, gated); - - break; - case SSP_IPOLARITY: - /* NOTE!! negedge is considered NORMAL */ - if (arg & CLOCK_NORMAL) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - clk_polarity, neg); - else if (arg & CLOCK_INVERT) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - clk_polarity, pos); - - if (arg & FRAME_NORMAL) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - frame_polarity, normal); - else if (arg & FRAME_INVERT) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - frame_polarity, inverted); - - if (arg & STATUS_NORMAL) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - status_polarity, normal); - else if (arg & STATUS_INVERT) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - status_polarity, inverted); - break; - case SSP_OPOLARITY: - if (arg & CLOCK_NORMAL) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - clk_driver, normal); - else if (arg & CLOCK_INVERT) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - clk_driver, inverted); - - if (arg & FRAME_NORMAL) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - frame_driver, normal); - else if (arg & FRAME_INVERT) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - frame_driver, inverted); - - if (arg & STATUS_NORMAL) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - status_driver, normal); - else if (arg & STATUS_INVERT) - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - status_driver, inverted); - break; - case SSP_SPI: - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, flow_ctrl, - disabled); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, bitorder, - msb); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, wordsize, - size8bit); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_sync, on); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_syncsize, - word); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, f_synctype, - normal); - if (arg & SPI_SLAVE) { - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - frame_polarity, inverted); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - clk_polarity, neg); - SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - mode, SLAVE_INPUT); - } else { - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - frame_driver, inverted); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - clk_driver, inverted); - SETF(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, - mode, MASTER_OUTPUT); - } - break; - case SSP_INBUFCHUNK: -#if 0 - if (arg > port->in_buffer_size/NUM_IN_DESCR) - return -EINVAL; - port->inbufchunk = arg; - /* Make sure in_buffer_size is a multiple of inbufchunk */ - port->in_buffer_size = - (port->in_buffer_size/port->inbufchunk) * - port->inbufchunk; - DEBUG(printk(KERN_DEBUG "inbufchunk %i in_buffer_size: %i\n", - port->inbufchunk, port->in_buffer_size)); - if (port->use_dma) { - if (port->port_nbr == 0) { - RESET_DMA(9); - WAIT_DMA(9); - } else { - RESET_DMA(5); - WAIT_DMA(5); - } - start_dma_in(port); - } -#endif - break; - default: - return_val = -1; - } - /* Make sure we write the config without interruption */ - local_irq_save(flags); - /* Set config and enable port */ - *port->ctrl_data = port->ctrl_data_shadow; - nop(); nop(); nop(); nop(); - *R_SYNC_SERIAL_PRESCALE = sync_serial_prescale_shadow; - nop(); nop(); nop(); nop(); - if (dev) - SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode3, sync); - else - SETS(gen_config_ii_shadow, R_GEN_CONFIG_II, sermode1, sync); - - *R_GEN_CONFIG_II = gen_config_ii_shadow; - /* Reset DMA. At readout from serial port the data could be shifted - * one byte if not resetting DMA. - */ - if (port->use_dma) { - if (port->port_nbr == 0) { - RESET_DMA(9); - WAIT_DMA(9); - } else { - RESET_DMA(5); - WAIT_DMA(5); - } - start_dma_in(port); - } - local_irq_restore(flags); - return return_val; -} - -static long sync_serial_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - long ret; - - mutex_lock(&sync_serial_mutex); - ret = sync_serial_ioctl_unlocked(file, cmd, arg); - mutex_unlock(&sync_serial_mutex); - - return ret; -} - - -static ssize_t sync_serial_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - int dev = MINOR(file_inode(file)->i_rdev); - DECLARE_WAITQUEUE(wait, current); - struct sync_port *port; - unsigned long flags; - unsigned long c, c1; - unsigned long free_outp; - unsigned long outp; - unsigned long out_buffer; - - if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) { - DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); - return -ENODEV; - } - port = &ports[dev]; - - DEBUGWRITE(printk(KERN_DEBUG "W d%d c %lu (%d/%d)\n", - port->port_nbr, count, port->out_count, OUT_BUFFER_SIZE)); - /* Space to end of buffer */ - /* - * out_buffer <c1>012345<- c ->OUT_BUFFER_SIZE - * outp^ +out_count - * ^free_outp - * out_buffer 45<- c ->0123OUT_BUFFER_SIZE - * +out_count outp^ - * free_outp - * - */ - - /* Read variables that may be updated by interrupts */ - local_irq_save(flags); - if (count > OUT_BUFFER_SIZE - port->out_count) - count = OUT_BUFFER_SIZE - port->out_count; - - outp = (unsigned long)port->outp; - free_outp = outp + port->out_count; - local_irq_restore(flags); - out_buffer = (unsigned long)port->out_buffer; - - /* Find out where and how much to write */ - if (free_outp >= out_buffer + OUT_BUFFER_SIZE) - free_outp -= OUT_BUFFER_SIZE; - if (free_outp >= outp) - c = out_buffer + OUT_BUFFER_SIZE - free_outp; - else - c = outp - free_outp; - if (c > count) - c = count; - - DEBUGWRITE(printk(KERN_DEBUG "w op %08lX fop %08lX c %lu\n", - outp, free_outp, c)); - if (copy_from_user((void *)free_outp, buf, c)) - return -EFAULT; - - if (c != count) { - buf += c; - c1 = count - c; - DEBUGWRITE(printk(KERN_DEBUG "w2 fi %lu c %lu c1 %lu\n", - free_outp-out_buffer, c, c1)); - if (copy_from_user((void *)out_buffer, buf, c1)) - return -EFAULT; - } - local_irq_save(flags); - port->out_count += count; - local_irq_restore(flags); - - /* Make sure transmitter/receiver is running */ - if (!port->started) { - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, - running); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, - enable); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, - enable); - port->started = 1; - } - - *port->ctrl_data = port->ctrl_data_shadow; - - if (file->f_flags & O_NONBLOCK) { - local_irq_save(flags); - if (!port->tr_running) { - if (!port->use_dma) { - /* Start sender by writing data */ - send_word(port); - /* and enable transmitter ready IRQ */ - *R_IRQ_MASK1_SET = 1 << - port->transmitter_ready_bit; - } else - start_dma(port, - (unsigned char *volatile)port->outp, c); - } - local_irq_restore(flags); - DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu NB\n", - port->port_nbr, count)); - return count; - } - - /* Sleep until all sent */ - add_wait_queue(&port->out_wait_q, &wait); - set_current_state(TASK_INTERRUPTIBLE); - local_irq_save(flags); - if (!port->tr_running) { - if (!port->use_dma) { - /* Start sender by writing data */ - send_word(port); - /* and enable transmitter ready IRQ */ - *R_IRQ_MASK1_SET = 1 << port->transmitter_ready_bit; - } else - start_dma(port, port->outp, c); - } - local_irq_restore(flags); - schedule(); - remove_wait_queue(&port->out_wait_q, &wait); - if (signal_pending(current)) - return -EINTR; - - DEBUGWRITE(printk(KERN_DEBUG "w d%d c %lu\n", port->port_nbr, count)); - return count; -} - -static ssize_t sync_serial_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - int dev = MINOR(file_inode(file)->i_rdev); - int avail; - struct sync_port *port; - unsigned char *start; - unsigned char *end; - unsigned long flags; - - if (dev < 0 || dev >= NUMBER_OF_PORTS || !ports[dev].enabled) { - DEBUG(printk(KERN_DEBUG "Invalid minor %d\n", dev)); - return -ENODEV; - } - port = &ports[dev]; - - DEBUGREAD(printk(KERN_DEBUG "R%d c %d ri %lu wi %lu /%lu\n", - dev, count, port->readp - port->flip, - port->writep - port->flip, port->in_buffer_size)); - - if (!port->started) { - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, clk_halt, - running); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, tr_enable, - enable); - SETS(port->ctrl_data_shadow, R_SYNC_SERIAL1_CTRL, rec_enable, - enable); - port->started = 1; - } - *port->ctrl_data = port->ctrl_data_shadow; - - /* Calculate number of available bytes */ - /* Save pointers to avoid that they are modified by interrupt */ - local_irq_save(flags); - start = (unsigned char *)port->readp; /* cast away volatile */ - end = (unsigned char *)port->writep; /* cast away volatile */ - local_irq_restore(flags); - while (start == end && !port->full) { - /* No data */ - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - wait_event_interruptible(port->in_wait_q, - !(start == end && !port->full)); - if (signal_pending(current)) - return -EINTR; - - local_irq_save(flags); - start = (unsigned char *)port->readp; /* cast away volatile */ - end = (unsigned char *)port->writep; /* cast away volatile */ - local_irq_restore(flags); - } - - /* Lazy read, never return wrapped data. */ - if (port->full) - avail = port->in_buffer_size; - else if (end > start) - avail = end - start; - else - avail = port->flip + port->in_buffer_size - start; - - count = count > avail ? avail : count; - if (copy_to_user(buf, start, count)) - return -EFAULT; - /* Disable interrupts while updating readp */ - local_irq_save(flags); - port->readp += count; - if (port->readp >= port->flip + port->in_buffer_size) /* Wrap? */ - port->readp = port->flip; - port->full = 0; - local_irq_restore(flags); - DEBUGREAD(printk(KERN_DEBUG "r %d\n", count)); - return count; -} - -static void send_word(struct sync_port *port) -{ - switch (IO_EXTRACT(R_SYNC_SERIAL1_CTRL, wordsize, - port->ctrl_data_shadow)) { - case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit): - port->out_count--; - *port->data_out = *port->outp++; - if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) - port->outp = port->out_buffer; - break; - case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit): - { - int data = (*port->outp++) << 8; - data |= *port->outp++; - port->out_count -= 2; - *port->data_out = data; - if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) - port->outp = port->out_buffer; - break; - } - case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit): - port->out_count -= 2; - *port->data_out = *(unsigned short *)port->outp; - port->outp += 2; - if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) - port->outp = port->out_buffer; - break; - case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit): - port->out_count -= 3; - *port->data_out = *(unsigned int *)port->outp; - port->outp += 3; - if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) - port->outp = port->out_buffer; - break; - case IO_STATE_VALUE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit): - port->out_count -= 4; - *port->data_out = *(unsigned int *)port->outp; - port->outp += 4; - if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) - port->outp = port->out_buffer; - break; - } -} - - -static void start_dma(struct sync_port *port, const char *data, int count) -{ - port->tr_running = 1; - port->out_descr.hw_len = 0; - port->out_descr.next = 0; - port->out_descr.ctrl = d_eol | d_eop; /* No d_wait to avoid glitches */ - port->out_descr.sw_len = count; - port->out_descr.buf = virt_to_phys(data); - port->out_descr.status = 0; - - *port->output_dma_first = virt_to_phys(&port->out_descr); - *port->output_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start); - DEBUGTXINT(printk(KERN_DEBUG "dma %08lX c %d\n", - (unsigned long)data, count)); -} - -static void start_dma_in(struct sync_port *port) -{ - int i; - unsigned long buf; - port->writep = port->flip; - - if (port->writep > port->flip + port->in_buffer_size) { - panic("Offset too large in sync serial driver\n"); - return; - } - buf = virt_to_phys(port->in_buffer); - for (i = 0; i < NUM_IN_DESCR; i++) { - port->in_descr[i].sw_len = port->inbufchunk; - port->in_descr[i].ctrl = d_int; - port->in_descr[i].next = virt_to_phys(&port->in_descr[i+1]); - port->in_descr[i].buf = buf; - port->in_descr[i].hw_len = 0; - port->in_descr[i].status = 0; - port->in_descr[i].fifo_len = 0; - buf += port->inbufchunk; - prepare_rx_descriptor(&port->in_descr[i]); - } - /* Link the last descriptor to the first */ - port->in_descr[i-1].next = virt_to_phys(&port->in_descr[0]); - port->in_descr[i-1].ctrl |= d_eol; - port->next_rx_desc = &port->in_descr[0]; - port->prev_rx_desc = &port->in_descr[NUM_IN_DESCR - 1]; - *port->input_dma_first = virt_to_phys(port->next_rx_desc); - *port->input_dma_cmd = IO_STATE(R_DMA_CH0_CMD, cmd, start); -} - -#ifdef SYNC_SER_DMA -static irqreturn_t tr_interrupt(int irq, void *dev_id) -{ - unsigned long ireg = *R_IRQ_MASK2_RD; - struct etrax_dma_descr *descr; - unsigned int sentl; - int handled = 0; - int i; - - for (i = 0; i < NUMBER_OF_PORTS; i++) { - struct sync_port *port = &ports[i]; - if (!port->enabled || !port->use_dma) - continue; - - /* IRQ active for the port? */ - if (!(ireg & (1 << port->output_dma_bit))) - continue; - - handled = 1; - - /* Clear IRQ */ - *port->output_dma_clr_irq = - IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do) | - IO_STATE(R_DMA_CH0_CLR_INTR, clr_descr, do); - - descr = &port->out_descr; - if (!(descr->status & d_stop)) - sentl = descr->sw_len; - else - /* Otherwise find amount of data sent here */ - sentl = descr->hw_len; - - port->out_count -= sentl; - port->outp += sentl; - if (port->outp >= port->out_buffer + OUT_BUFFER_SIZE) - port->outp = port->out_buffer; - if (port->out_count) { - int c = port->out_buffer + OUT_BUFFER_SIZE - port->outp; - if (c > port->out_count) - c = port->out_count; - DEBUGTXINT(printk(KERN_DEBUG - "tx_int DMAWRITE %i %i\n", sentl, c)); - start_dma(port, port->outp, c); - } else { - DEBUGTXINT(printk(KERN_DEBUG - "tx_int DMA stop %i\n", sentl)); - port->tr_running = 0; - } - /* wake up the waiting process */ - wake_up_interruptible(&port->out_wait_q); - } - return IRQ_RETVAL(handled); -} /* tr_interrupt */ - -static irqreturn_t rx_interrupt(int irq, void *dev_id) -{ - unsigned long ireg = *R_IRQ_MASK2_RD; - int i; - int handled = 0; - - for (i = 0; i < NUMBER_OF_PORTS; i++) { - struct sync_port *port = &ports[i]; - - if (!port->enabled || !port->use_dma) - continue; - - if (!(ireg & (1 << port->input_dma_descr_bit))) - continue; - - /* Descriptor interrupt */ - handled = 1; - while (*port->input_dma_descr != - virt_to_phys(port->next_rx_desc)) { - if (port->writep + port->inbufchunk > port->flip + - port->in_buffer_size) { - int first_size = port->flip + - port->in_buffer_size - port->writep; - memcpy(port->writep, - phys_to_virt(port->next_rx_desc->buf), - first_size); - memcpy(port->flip, - phys_to_virt(port->next_rx_desc->buf + - first_size), - port->inbufchunk - first_size); - port->writep = port->flip + - port->inbufchunk - first_size; - } else { - memcpy(port->writep, - phys_to_virt(port->next_rx_desc->buf), - port->inbufchunk); - port->writep += port->inbufchunk; - if (port->writep >= port->flip - + port->in_buffer_size) - port->writep = port->flip; - } - if (port->writep == port->readp) - port->full = 1; - prepare_rx_descriptor(port->next_rx_desc); - port->next_rx_desc->ctrl |= d_eol; - port->prev_rx_desc->ctrl &= ~d_eol; - port->prev_rx_desc = phys_to_virt((unsigned) - port->next_rx_desc); - port->next_rx_desc = phys_to_virt((unsigned) - port->next_rx_desc->next); - /* Wake up the waiting process */ - wake_up_interruptible(&port->in_wait_q); - *port->input_dma_cmd = IO_STATE(R_DMA_CH1_CMD, - cmd, restart); - /* DMA has reached end of descriptor */ - *port->input_dma_clr_irq = IO_STATE(R_DMA_CH0_CLR_INTR, - clr_descr, do); - } - } - return IRQ_RETVAL(handled); -} /* rx_interrupt */ -#endif /* SYNC_SER_DMA */ - -#ifdef SYNC_SER_MANUAL -static irqreturn_t manual_interrupt(int irq, void *dev_id) -{ - int i; - int handled = 0; - - for (i = 0; i < NUMBER_OF_PORTS; i++) { - struct sync_port *port = &ports[i]; - - if (!port->enabled || port->use_dma) - continue; - - /* Data received? */ - if (*R_IRQ_MASK1_RD & (1 << port->data_avail_bit)) { - handled = 1; - /* Read data */ - switch (port->ctrl_data_shadow & - IO_MASK(R_SYNC_SERIAL1_CTRL, wordsize)) { - case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size8bit): - *port->writep++ = - *(volatile char *)port->data_in; - break; - case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size12bit): - { - int data = *(unsigned short *)port->data_in; - *port->writep = (data & 0x0ff0) >> 4; - *(port->writep + 1) = data & 0x0f; - port->writep += 2; - break; - } - case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size16bit): - *(unsigned short *)port->writep = - *(volatile unsigned short *)port->data_in; - port->writep += 2; - break; - case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size24bit): - *(unsigned int *)port->writep = *port->data_in; - port->writep += 3; - break; - case IO_STATE(R_SYNC_SERIAL1_CTRL, wordsize, size32bit): - *(unsigned int *)port->writep = *port->data_in; - port->writep += 4; - break; - } - - /* Wrap? */ - if (port->writep >= port->flip + port->in_buffer_size) - port->writep = port->flip; - if (port->writep == port->readp) { - /* Receive buffer overrun, discard oldest */ - port->readp++; - /* Wrap? */ - if (port->readp >= port->flip + - port->in_buffer_size) - port->readp = port->flip; - } - if (sync_data_avail(port) >= port->inbufchunk) { - /* Wake up application */ - wake_up_interruptible(&port->in_wait_q); - } - } - - /* Transmitter ready? */ - if (*R_IRQ_MASK1_RD & (1 << port->transmitter_ready_bit)) { - if (port->out_count > 0) { - /* More data to send */ - send_word(port); - } else { - /* Transmission finished */ - /* Turn off IRQ */ - *R_IRQ_MASK1_CLR = 1 << - port->transmitter_ready_bit; - /* Wake up application */ - wake_up_interruptible(&port->out_wait_q); - } - } - } - return IRQ_RETVAL(handled); -} -#endif - -module_init(etrax_sync_serial_init); |