diff options
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); |