diff options
Diffstat (limited to 'arch/cris/arch-v10')
41 files changed, 0 insertions, 14820 deletions
diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig deleted file mode 100644 index d4015a931374..000000000000 --- a/arch/cris/arch-v10/Kconfig +++ /dev/null @@ -1,399 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -if ETRAX_ARCH_V10 - -menu "CRIS v10 options" - -# ETRAX 100LX v1 has a MMU "feature" requiring a low mapping -config CRIS_LOW_MAP - bool - depends on ETRAX_ARCH_V10 && ETRAX100LX - default y - -config ETRAX_DRAM_VIRTUAL_BASE - hex - depends on ETRAX_ARCH_V10 - default "c0000000" if !ETRAX100LX - default "60000000" if ETRAX100LX - -choice - prompt "Product LED port" - depends on ETRAX_ARCH_V10 - default ETRAX_PA_LEDS - -config ETRAX_PA_LEDS - bool "Port-PA-LEDs" - help - The ETRAX network driver is responsible for flashing LED's when - packets arrive and are sent. It uses macros defined in - <file:arch/cris/include/asm/io.h>, and those macros are defined after - what YOU choose in this option. The actual bits used are configured - separately. Select this if the LEDs are on port PA. Some products - put the leds on PB or a memory-mapped latch (CSP0) instead. - -config ETRAX_PB_LEDS - bool "Port-PB-LEDs" - help - The ETRAX network driver is responsible for flashing LED's when - packets arrive and are sent. It uses macros defined in - <file:arch/cris/include/asm/io.h>, and those macros are defined after - what YOU choose in this option. The actual bits used are configured - separately. Select this if the LEDs are on port PB. Some products - put the leds on PA or a memory-mapped latch (CSP0) instead. - -config ETRAX_CSP0_LEDS - bool "Port-CSP0-LEDs" - help - The ETRAX network driver is responsible for flashing LED's when - packets arrive and are sent. It uses macros defined in - <file:arch/cris/include/asm/io.h>, and those macros are defined after - what YOU choose in this option. The actual bits used are configured - separately. Select this if the LEDs are on a memory-mapped latch - using chip select CSP0, this is mapped at 0x90000000. - Some products put the leds on PA or PB instead. - -config ETRAX_NO_LEDS - bool "None" - help - Select this option if you don't have any LED at all. - -endchoice - -config ETRAX_LED1G - int "First green LED bit" - depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS - default "2" - help - Bit to use for the first green LED. - Most Axis products use bit 2 here. - -config ETRAX_LED1R - int "First red LED bit" - depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS - default "3" - help - Bit to use for the first red LED. - Most Axis products use bit 3 here. - For products with only one controllable LED, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED2G - int "Second green LED bit" - depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS - default "4" - help - Bit to use for the second green LED. The "Active" LED. - Most Axis products use bit 4 here. - For products with only one controllable LED, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED2R - int "Second red LED bit" - depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS - default "5" - help - Bit to use for the second red LED. - Most Axis products use bit 5 here. - For products with only one controllable LED, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED3G - int "Third green LED bit" - depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS - default "2" - help - Bit to use for the third green LED. The "Drive" LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED3R - int "Third red LED bit" - depends on ETRAX_ARCH_V10 && !ETRAX_NO_LEDS - default "2" - help - Bit to use for the third red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED4R - int "Fourth red LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the fourth red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED4G - int "Fourth green LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the fourth green LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED5R - int "Fifth red LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the fifth red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED5G - int "Fifth green LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the fifth green LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED6R - int "Sixth red LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the sixth red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED6G - int "Sixth green LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the sixth green LED. The "Drive" LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED7R - int "Seventh red LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the seventh red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED7G - int "Seventh green LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the seventh green LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED8Y - int "Eighth yellow LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the eighth yellow LED. The "Drive" LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED9Y - int "Ninth yellow LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the ninth yellow LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED10Y - int "Tenth yellow LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the tenth yellow LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED11Y - int "Eleventh yellow LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the eleventh yellow LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - -config ETRAX_LED12R - int "Twelfth red LED bit" - depends on ETRAX_CSP0_LEDS - default "2" - help - Bit to use for the twelfth red LED. - For products with only one or two controllable LEDs, - set this to same as CONFIG_ETRAX_LED1G (normally 2). - - -choice - prompt "Product rescue-port" - depends on ETRAX_ARCH_V10 - default ETRAX_RESCUE_SER0 - -config ETRAX_RESCUE_SER0 - bool "Serial-0" - help - Select one of the four serial ports as a rescue port. The default - is port 0. - -config ETRAX_RESCUE_SER1 - bool "Serial-1" - help - Use serial port 1 as the rescue port. - -config ETRAX_RESCUE_SER2 - bool "Serial-2" - help - Use serial port 2 as the rescue port. - -config ETRAX_RESCUE_SER3 - bool "Serial-3" - help - Use serial port 3 as the rescue port. - -endchoice - -config ETRAX_DEF_R_WAITSTATES - hex "R_WAITSTATES" - depends on ETRAX_ARCH_V10 - default "95a6" - help - Waitstates for SRAM, Flash and peripherals (not DRAM). 95f8 is a - good choice for most Axis products... - -config ETRAX_DEF_R_BUS_CONFIG - hex "R_BUS_CONFIG" - depends on ETRAX_ARCH_V10 - default "104" - help - Assorted bits controlling write mode, DMA burst length etc. 104 is - a good choice for most Axis products... - -config ETRAX_SDRAM - bool "SDRAM support" - depends on ETRAX_ARCH_V10 - help - Enable this if you use SDRAM chips and configure - R_SDRAM_CONFIG and R_SDRAM_TIMING as well. - -config ETRAX_DEF_R_DRAM_CONFIG - hex "R_DRAM_CONFIG" - depends on ETRAX_ARCH_V10 && !ETRAX_SDRAM - default "1a200040" - help - The R_DRAM_CONFIG register specifies everything on how the DRAM - chips in the system are connected to the ETRAX CPU. This is - different depending on the manufacturer, chip type and number of - chips. So this value often needs to be different for each Axis - product. - -config ETRAX_DEF_R_DRAM_TIMING - hex "R_DRAM_TIMING" - depends on ETRAX_ARCH_V10 && !ETRAX_SDRAM - default "5611" - help - Different DRAM chips have different speeds. Current Axis products - use 50ns DRAM chips which can use the timing: 5611. - -config ETRAX_DEF_R_SDRAM_CONFIG - hex "R_SDRAM_CONFIG" - depends on ETRAX_ARCH_V10 && ETRAX_SDRAM - default "d2fa7878" - help - The R_SDRAM_CONFIG register specifies everything on how the SDRAM - chips in the system are connected to the ETRAX CPU. This is - different depending on the manufacturer, chip type and number of - chips. So this value often needs to be different for each Axis - product. - -config ETRAX_DEF_R_SDRAM_TIMING - hex "R_SDRAM_TIMING" - depends on ETRAX_ARCH_V10 && ETRAX_SDRAM - default "80004801" - help - Different SDRAM chips have different timing. - -config ETRAX_DEF_R_PORT_PA_DIR - hex "R_PORT_PA_DIR" - depends on ETRAX_ARCH_V10 - default "1c" - help - Configures the direction of general port A bits. 1 is out, 0 is in. - This is often totally different depending on the product used. - There are some guidelines though - if you know that only LED's are - connected to port PA, then they are usually connected to bits 2-4 - and you can therefore use 1c. On other boards which don't have the - LED's at the general ports, these bits are used for all kinds of - stuff. If you don't know what to use, it is always safe to put all - as inputs, although floating inputs isn't good. - -config ETRAX_DEF_R_PORT_PA_DATA - hex "R_PORT_PA_DATA" - depends on ETRAX_ARCH_V10 - default "00" - help - Configures the initial data for the general port A bits. Most - products should use 00 here. - -config ETRAX_DEF_R_PORT_PB_CONFIG - hex "R_PORT_PB_CONFIG" - depends on ETRAX_ARCH_V10 - default "00" - help - Configures the type of the general port B bits. 1 is chip select, - 0 is port. Most products should use 00 here. - -config ETRAX_DEF_R_PORT_PB_DIR - hex "R_PORT_PB_DIR" - depends on ETRAX_ARCH_V10 - default "00" - help - Configures the direction of general port B bits. 1 is out, 0 is in. - This is often totally different depending on the product used. Bits - 0 and 1 on port PB are usually used for I2C communication, but the - kernel I2C driver sets the appropriate directions itself so you - don't need to take that into consideration when setting this option. - If you don't know what to use, it is always safe to put all as - inputs. - -config ETRAX_DEF_R_PORT_PB_DATA - hex "R_PORT_PB_DATA" - depends on ETRAX_ARCH_V10 - default "ff" - help - Configures the initial data for the general port A bits. Most - products should use FF here. - -config ETRAX_SOFT_SHUTDOWN - bool "Software Shutdown Support" - depends on ETRAX_ARCH_V10 - help - Enable this if ETRAX is used with a power-supply that can be turned - off and on with PS_ON signal. Gives the possibility to detect - powerbutton and then do a power off after unmounting disks. - -config ETRAX_SHUTDOWN_BIT - int "Shutdown bit on port CSP0" - depends on ETRAX_SOFT_SHUTDOWN - default "12" - help - Configure what pin on CSPO-port that is used for controlling power - supply. - -config ETRAX_POWERBUTTON_BIT - int "Power button bit on port G" - depends on ETRAX_SOFT_SHUTDOWN - default "25" - help - Configure where power button is connected. - -endmenu - -endif diff --git a/arch/cris/arch-v10/README.mm b/arch/cris/arch-v10/README.mm deleted file mode 100644 index 67731d75cb51..000000000000 --- a/arch/cris/arch-v10/README.mm +++ /dev/null @@ -1,244 +0,0 @@ -Memory management for CRIS/MMU ------------------------------- -HISTORY: - -$Log: README.mm,v $ -Revision 1.1 2001/12/17 13:59:27 bjornw -Initial revision - -Revision 1.1 2000/07/10 16:25:21 bjornw -Initial revision - -Revision 1.4 2000/01/17 02:31:59 bjornw -Added discussion of paging and VM. - -Revision 1.3 1999/12/03 16:43:23 hp -Blurb about that the 3.5G-limitation is not a MMU limitation - -Revision 1.2 1999/12/03 16:04:21 hp -Picky comment about not mapping the first page - -Revision 1.1 1999/12/03 15:41:30 bjornw -First version of CRIS/MMU memory layout specification. - - - - - ------------------------------- - -See the ETRAX-NG HSDD for reference. - -We use the page-size of 8 kbytes, as opposed to the i386 page-size of 4 kbytes. - -The MMU can, apart from the normal mapping of pages, also do a top-level -segmentation of the kernel memory space. We use this feature to avoid having -to use page-tables to map the physical memory into the kernel's address -space. We also use it to keep the user-mode virtual mapping in the same -map during kernel-mode, so that the kernel easily can access the corresponding -user-mode process' data. - -As a comparison, the Linux/i386 2.0 puts the kernel and physical RAM at -address 0, overlapping with the user-mode virtual space, so that descriptor -registers are needed for each memory access to specify which MMU space to -map through. That changed in 2.2, putting the kernel/physical RAM at -0xc0000000, to co-exist with the user-mode mapping. We will do something -quite similar, but with the additional complexity of having to map the -internal chip I/O registers and the flash memory area (including SRAM -and peripherial chip-selets). - -The kernel-mode segmentation map: - - ------------------------ ------------------------ -FFFFFFFF| | => cached | | - | kernel seg_f | flash | | -F0000000|______________________| | | -EFFFFFFF| | => uncached | | - | kernel seg_e | flash | | -E0000000|______________________| | DRAM | -DFFFFFFF| | paged to any | Un-cached | - | kernel seg_d | =======> | | -D0000000|______________________| | | -CFFFFFFF| | | | - | kernel seg_c |==\ | | -C0000000|______________________| \ |______________________| -BFFFFFFF| | uncached | | - | kernel seg_b |=====\=========>| Registers | -B0000000|______________________| \c |______________________| -AFFFFFFF| | \a | | - | | \c | FLASH/SRAM/Peripheral| - | | \h |______________________| - | | \e | | - | | \d | | - | kernel seg_0 - seg_a | \==>| DRAM | - | | | Cached | - | | paged to any | | - | | =======> |______________________| - | | | | - | | | Illegal | - | | |______________________| - | | | | - | | | FLASH/SRAM/Peripheral| -00000000|______________________| |______________________| - -In user-mode it looks the same except that only the space 0-AFFFFFFF is -available. Therefore, in this model, the virtual address space per process -is limited to 0xb0000000 bytes (minus 8192 bytes, since the first page, -0..8191, is never mapped, in order to trap NULL references). - -It also means that the total physical RAM that can be mapped is 256 MB -(kseg_c above). More RAM can be mapped by choosing a different segmentation -and shrinking the user-mode memory space. - -The MMU can map all 4 GB in user mode, but doing that would mean that a -few extra instructions would be needed for each access to user mode -memory. - -The kernel needs access to both cached and uncached flash. Uncached is -necessary because of the special write/erase sequences. Also, the -peripherial chip-selects are decoded from that region. - -The kernel also needs its own virtual memory space. That is kseg_d. It -is used by the vmalloc() kernel function to allocate virtual contiguous -chunks of memory not possible using the normal kmalloc physical RAM -allocator. - -The setting of the actual MMU control registers to use this layout would -be something like this: - -R_MMU_KSEG = ( ( seg_f, seg ) | // Flash cached - ( seg_e, seg ) | // Flash uncached - ( seg_d, page ) | // kernel vmalloc area - ( seg_c, seg ) | // kernel linear segment - ( seg_b, seg ) | // kernel linear segment - ( seg_a, page ) | - ( seg_9, page ) | - ( seg_8, page ) | - ( seg_7, page ) | - ( seg_6, page ) | - ( seg_5, page ) | - ( seg_4, page ) | - ( seg_3, page ) | - ( seg_2, page ) | - ( seg_1, page ) | - ( seg_0, page ) ); - -R_MMU_KBASE_HI = ( ( base_f, 0x0 ) | // flash/sram/periph cached - ( base_e, 0x8 ) | // flash/sram/periph uncached - ( base_d, 0x0 ) | // don't care - ( base_c, 0x4 ) | // physical RAM cached area - ( base_b, 0xb ) | // uncached on-chip registers - ( base_a, 0x0 ) | // don't care - ( base_9, 0x0 ) | // don't care - ( base_8, 0x0 ) ); // don't care - -R_MMU_KBASE_LO = ( ( base_7, 0x0 ) | // don't care - ( base_6, 0x0 ) | // don't care - ( base_5, 0x0 ) | // don't care - ( base_4, 0x0 ) | // don't care - ( base_3, 0x0 ) | // don't care - ( base_2, 0x0 ) | // don't care - ( base_1, 0x0 ) | // don't care - ( base_0, 0x0 ) ); // don't care - -NOTE: while setting up the MMU, we run in a non-mapped mode in the DRAM (0x40 -segment) and need to setup the seg_4 to a unity mapping, so that we don't get -a fault before we have had time to jump into the real kernel segment (0xc0). This -is done in head.S temporarily, but fixed by the kernel later in paging_init. - - -Paging - PTE's, PMD's and PGD's -------------------------------- - -[ References: asm/pgtable.h, asm/page.h, asm/mmu.h ] - -The paging mechanism uses virtual addresses to split a process memory-space into -pages, a page being the smallest unit that can be freely remapped in memory. On -Linux/CRIS, a page is 8192 bytes (for technical reasons not equal to 4096 as in -most other 32-bit architectures). It would be inefficient to let a virtual memory -mapping be controlled by a long table of page mappings, so it is broken down into -a 2-level structure with a Page Directory containing pointers to Page Tables which -each have maps of up to 2048 pages (8192 / sizeof(void *)). Linux can actually -handle 3-level structures as well, with a Page Middle Directory in between, but -in many cases, this is folded into a two-level structure by excluding the Middle -Directory. - -We'll take a look at how an address is translated while we discuss how it's handled -in the Linux kernel. - -The example address is 0xd004000c; in binary this is: - -31 23 15 7 0 -11010000 00000100 00000000 00001100 - -|______| |__________||____________| - PGD PTE page offset - -Given the top-level Page Directory, the offset in that directory is calculated -using the upper 8 bits: - -static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address) -{ - return mm->pgd + (address >> PGDIR_SHIFT); -} - -PGDIR_SHIFT is the log2 of the amount of memory an entry in the PGD can map; in our -case it is 24, corresponding to 16 MB. This means that each entry in the PGD -corresponds to 16 MB of virtual memory. - -The pgd_t from our example will therefore be the 208'th (0xd0) entry in mm->pgd. - -Since the Middle Directory does not exist, it is a unity mapping: - -static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) dir; -} - -The Page Table provides the final lookup by using bits 13 to 23 as index: - -static inline pte_t * pte_offset(pmd_t * dir, unsigned long address) -{ - return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & - (PTRS_PER_PTE - 1)); -} - -PAGE_SHIFT is the log2 of the size of a page; 13 in our case. PTRS_PER_PTE is -the number of pointers that fit in a Page Table and is used to mask off the -PGD-part of the address. - -The so-far unused bits 0 to 12 are used to index inside a page linearily. - -The VM system -------------- - -The kernels own page-directory is the swapper_pg_dir, cleared in paging_init, -and contains the kernels virtual mappings (the kernel itself is not paged - it -is mapped linearily using kseg_c as described above). Architectures without -kernel segments like the i386, need to setup swapper_pg_dir directly in head.S -to map the kernel itself. swapper_pg_dir is pointed to by init_mm.pgd as the -init-task's PGD. - -To see what support functions are used to setup a page-table, let's look at the -kernel's internal paged memory system, vmalloc/vfree. - -void * vmalloc(unsigned long size) - -The vmalloc-system keeps a paged segment in kernel-space at 0xd0000000. What -happens first is that a virtual address chunk is allocated to the request using -get_vm_area(size). After that, physical RAM pages are allocated and put into -the kernel's page-table using alloc_area_pages(addr, size). - -static int alloc_area_pages(unsigned long address, unsigned long size) - -First the PGD entry is found using init_mm.pgd. This is passed to -alloc_area_pmd (remember the 3->2 folding). It uses pte_alloc_kernel to -check if the PGD entry points anywhere - if not, a page table page is -allocated and the PGD entry updated. Then the alloc_area_pte function is -used just like alloc_area_pmd to check which page table entry is desired, -and a physical page is allocated and the table entry updated. All of this -is repeated at the top-level until the entire address range specified has -been mapped. - - - 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); diff --git a/arch/cris/arch-v10/kernel/Makefile b/arch/cris/arch-v10/kernel/Makefile deleted file mode 100644 index 7ec04b4a285e..000000000000 --- a/arch/cris/arch-v10/kernel/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the linux kernel. -# - -extra-y := head.o - - -obj-y := entry.o traps.o shadows.o debugport.o irq.o \ - process.o setup.o signal.o traps.o time.o ptrace.o \ - dma.o io_interface_mux.o - -obj-$(CONFIG_ETRAX_KGDB) += kgdb.o -obj-$(CONFIG_ETRAX_FAST_TIMER) += fasttimer.o -obj-$(CONFIG_MODULES) += crisksyms.o - -clean: - diff --git a/arch/cris/arch-v10/kernel/crisksyms.c b/arch/cris/arch-v10/kernel/crisksyms.c deleted file mode 100644 index e1d897ed5b37..000000000000 --- a/arch/cris/arch-v10/kernel/crisksyms.c +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/module.h> -#include <asm/io.h> -#include <arch/svinto.h> - -/* Export shadow registers for the CPU I/O pins */ -EXPORT_SYMBOL(genconfig_shadow); -EXPORT_SYMBOL(port_pa_data_shadow); -EXPORT_SYMBOL(port_pa_dir_shadow); -EXPORT_SYMBOL(port_pb_data_shadow); -EXPORT_SYMBOL(port_pb_dir_shadow); -EXPORT_SYMBOL(port_pb_config_shadow); -EXPORT_SYMBOL(port_g_data_shadow); - -/* Cache flush functions */ -EXPORT_SYMBOL(flush_etrax_cache); -EXPORT_SYMBOL(prepare_rx_descriptor); diff --git a/arch/cris/arch-v10/kernel/debugport.c b/arch/cris/arch-v10/kernel/debugport.c deleted file mode 100644 index d30834d4dd7e..000000000000 --- a/arch/cris/arch-v10/kernel/debugport.c +++ /dev/null @@ -1,560 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Serialport functions for debugging - * - * Copyright (c) 2000-2007 Axis Communications AB - * - * Authors: Bjorn Wesen - * - * Exports: - * console_print_etrax(char *buf) - * int getDebugChar() - * putDebugChar(int) - * enableDebugIRQ() - * init_etrax_debug() - * - */ - -#include <linux/console.h> -#include <linux/init.h> -#include <linux/major.h> -#include <linux/delay.h> -#include <linux/tty.h> -#include <arch/svinto.h> - -extern void reset_watchdog(void); - -struct dbg_port -{ - unsigned int index; - const volatile unsigned* read; - volatile char* write; - volatile unsigned* xoff; - volatile char* baud; - volatile char* tr_ctrl; - volatile char* rec_ctrl; - unsigned long irq; - unsigned int started; - unsigned long baudrate; - unsigned char parity; - unsigned int bits; -}; - -struct dbg_port ports[]= -{ - { - 0, - R_SERIAL0_READ, - R_SERIAL0_TR_DATA, - R_SERIAL0_XOFF, - R_SERIAL0_BAUD, - R_SERIAL0_TR_CTRL, - R_SERIAL0_REC_CTRL, - IO_STATE(R_IRQ_MASK1_SET, ser0_data, set), - 0, - 115200, - 'N', - 8 - }, - { - 1, - R_SERIAL1_READ, - R_SERIAL1_TR_DATA, - R_SERIAL1_XOFF, - R_SERIAL1_BAUD, - R_SERIAL1_TR_CTRL, - R_SERIAL1_REC_CTRL, - IO_STATE(R_IRQ_MASK1_SET, ser1_data, set), - 0, - 115200, - 'N', - 8 - }, - { - 2, - R_SERIAL2_READ, - R_SERIAL2_TR_DATA, - R_SERIAL2_XOFF, - R_SERIAL2_BAUD, - R_SERIAL2_TR_CTRL, - R_SERIAL2_REC_CTRL, - IO_STATE(R_IRQ_MASK1_SET, ser2_data, set), - 0, - 115200, - 'N', - 8 - }, - { - 3, - R_SERIAL3_READ, - R_SERIAL3_TR_DATA, - R_SERIAL3_XOFF, - R_SERIAL3_BAUD, - R_SERIAL3_TR_CTRL, - R_SERIAL3_REC_CTRL, - IO_STATE(R_IRQ_MASK1_SET, ser3_data, set), - 0, - 115200, - 'N', - 8 - } -}; - -#ifdef CONFIG_ETRAX_SERIAL -extern struct tty_driver *serial_driver; -#endif - -struct dbg_port* port = -#if defined(CONFIG_ETRAX_DEBUG_PORT0) - &ports[0]; -#elif defined(CONFIG_ETRAX_DEBUG_PORT1) - &ports[1]; -#elif defined(CONFIG_ETRAX_DEBUG_PORT2) - &ports[2]; -#elif defined(CONFIG_ETRAX_DEBUG_PORT3) - &ports[3]; -#else - NULL; -#endif - -static struct dbg_port* kgdb_port = -#if defined(CONFIG_ETRAX_KGDB_PORT0) - &ports[0]; -#elif defined(CONFIG_ETRAX_KGDB_PORT1) - &ports[1]; -#elif defined(CONFIG_ETRAX_KGDB_PORT2) - &ports[2]; -#elif defined(CONFIG_ETRAX_KGDB_PORT3) - &ports[3]; -#else - NULL; -#endif - -static void -start_port(struct dbg_port* p) -{ - unsigned long rec_ctrl = 0; - unsigned long tr_ctrl = 0; - - if (!p) - return; - - if (p->started) - return; - p->started = 1; - - if (p->index == 0) - { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma6); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma6, unused); - } - else if (p->index == 1) - { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma8); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma8, usb); - } - else if (p->index == 2) - { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma2); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma2, par0); - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma3); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma3, par0); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, ser2, select); - } - else - { - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma4); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma4, par1); - genconfig_shadow &= ~IO_MASK(R_GEN_CONFIG, dma5); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, dma5, par1); - genconfig_shadow |= IO_STATE(R_GEN_CONFIG, ser3, select); - } - - *R_GEN_CONFIG = genconfig_shadow; - - *p->xoff = - IO_STATE(R_SERIAL0_XOFF, tx_stop, enable) | - IO_STATE(R_SERIAL0_XOFF, auto_xoff, disable) | - IO_FIELD(R_SERIAL0_XOFF, xoff_char, 0); - - switch (p->baudrate) - { - case 0: - case 115200: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz); - break; - case 1200: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c1200Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c1200Hz); - break; - case 2400: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c2400Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c2400Hz); - break; - case 4800: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c4800Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c4800Hz); - break; - case 9600: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c9600Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c9600Hz); - break; - case 19200: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c19k2Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c19k2Hz); - break; - case 38400: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c38k4Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c38k4Hz); - break; - case 57600: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c57k6Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c57k6Hz); - break; - default: - *p->baud = - IO_STATE(R_SERIAL0_BAUD, tr_baud, c115k2Hz) | - IO_STATE(R_SERIAL0_BAUD, rec_baud, c115k2Hz); - break; - } - - if (p->parity == 'E') { - rec_ctrl = - IO_STATE(R_SERIAL0_REC_CTRL, rec_par, even) | - IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); - tr_ctrl = - IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) | - IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable); - } else if (p->parity == 'O') { - rec_ctrl = - IO_STATE(R_SERIAL0_REC_CTRL, rec_par, odd) | - IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, enable); - tr_ctrl = - IO_STATE(R_SERIAL0_TR_CTRL, tr_par, odd) | - IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, enable); - } else { - rec_ctrl = - IO_STATE(R_SERIAL0_REC_CTRL, rec_par, even) | - IO_STATE(R_SERIAL0_REC_CTRL, rec_par_en, disable); - tr_ctrl = - IO_STATE(R_SERIAL0_TR_CTRL, tr_par, even) | - IO_STATE(R_SERIAL0_TR_CTRL, tr_par_en, disable); - } - if (p->bits == 7) - { - rec_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_7bit); - tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_7bit); - } - else - { - rec_ctrl |= IO_STATE(R_SERIAL0_REC_CTRL, rec_bitnr, rec_8bit); - tr_ctrl |= IO_STATE(R_SERIAL0_TR_CTRL, tr_bitnr, tr_8bit); - } - - *p->rec_ctrl = - IO_STATE(R_SERIAL0_REC_CTRL, dma_err, stop) | - IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable) | - IO_STATE(R_SERIAL0_REC_CTRL, rts_, active) | - IO_STATE(R_SERIAL0_REC_CTRL, sampling, middle) | - IO_STATE(R_SERIAL0_REC_CTRL, rec_stick_par, normal) | - rec_ctrl; - - *p->tr_ctrl = - IO_FIELD(R_SERIAL0_TR_CTRL, txd, 0) | - IO_STATE(R_SERIAL0_TR_CTRL, tr_enable, enable) | - IO_STATE(R_SERIAL0_TR_CTRL, auto_cts, disabled) | - IO_STATE(R_SERIAL0_TR_CTRL, stop_bits, one_bit) | - IO_STATE(R_SERIAL0_TR_CTRL, tr_stick_par, normal) | - tr_ctrl; -} - -static void -console_write_direct(struct console *co, const char *buf, unsigned int len) -{ - int i; - unsigned long flags; - - if (!port) - return; - - local_irq_save(flags); - - /* Send data */ - for (i = 0; i < len; i++) { - /* LF -> CRLF */ - if (buf[i] == '\n') { - while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) - ; - *port->write = '\r'; - } - /* Wait until transmitter is ready and send.*/ - while (!(*port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) - ; - *port->write = buf[i]; - } - - /* - * Feed the watchdog, otherwise it will reset the chip during boot. - * The time to send an ordinary boot message line (10-90 chars) - * varies between 1-8ms at 115200. What makes up for the additional - * 90ms that allows the watchdog to bite? - */ - reset_watchdog(); - - local_irq_restore(flags); -} - -static void -console_write(struct console *co, const char *buf, unsigned int len) -{ - if (!port) - return; - - console_write_direct(co, buf, len); -} - -/* legacy function */ - -void -console_print_etrax(const char *buf) -{ - console_write(NULL, buf, strlen(buf)); -} - -/* Use polling to get a single character FROM the debug port */ - -int -getDebugChar(void) -{ - unsigned long readval; - - if (!kgdb_port) - return 0; - - do { - readval = *kgdb_port->read; - } while (!(readval & IO_MASK(R_SERIAL0_READ, data_avail))); - - return (readval & IO_MASK(R_SERIAL0_READ, data_in)); -} - -/* Use polling to put a single character to the debug port */ - -void -putDebugChar(int val) -{ - if (!kgdb_port) - return; - - while (!(*kgdb_port->read & IO_MASK(R_SERIAL0_READ, tr_ready))) - ; - *kgdb_port->write = val; -} - -/* Enable irq for receiving chars on the debug port, used by kgdb */ - -void -enableDebugIRQ(void) -{ - if (!kgdb_port) - return; - - *R_IRQ_MASK1_SET = kgdb_port->irq; - /* use R_VECT_MASK directly, since we really bypass Linux normal - * IRQ handling in kgdb anyway, we don't need to use enable_irq - */ - *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set); - - *kgdb_port->rec_ctrl = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable); -} - -static int __init -console_setup(struct console *co, char *options) -{ - char* s; - - if (options) { - port = &ports[co->index]; - port->baudrate = 115200; - port->parity = 'N'; - port->bits = 8; - port->baudrate = simple_strtoul(options, NULL, 10); - s = options; - while(*s >= '0' && *s <= '9') - s++; - if (*s) port->parity = *s++; - if (*s) port->bits = *s++ - '0'; - port->started = 0; - start_port(0); - } - return 0; -} - - -/* This is a dummy serial device that throws away anything written to it. - * This is used when no debug output is wanted. - */ -static struct tty_driver dummy_driver; - -static int dummy_open(struct tty_struct *tty, struct file * filp) -{ - return 0; -} - -static void dummy_close(struct tty_struct *tty, struct file * filp) -{ -} - -static int dummy_write(struct tty_struct * tty, - const unsigned char *buf, int count) -{ - return count; -} - -static int dummy_write_room(struct tty_struct *tty) -{ - return 8192; -} - -static const struct tty_operations dummy_ops = { - .open = dummy_open, - .close = dummy_close, - .write = dummy_write, - .write_room = dummy_write_room, -}; - -void __init -init_dummy_console(void) -{ - memset(&dummy_driver, 0, sizeof(struct tty_driver)); - dummy_driver.driver_name = "serial"; - dummy_driver.name = "ttyS"; - dummy_driver.major = TTY_MAJOR; - dummy_driver.minor_start = 68; - dummy_driver.num = 1; /* etrax100 has 4 serial ports */ - dummy_driver.type = TTY_DRIVER_TYPE_SERIAL; - dummy_driver.subtype = SERIAL_TYPE_NORMAL; - dummy_driver.init_termios = tty_std_termios; - /* Normally B9600 default... */ - dummy_driver.init_termios.c_cflag = - B115200 | CS8 | CREAD | HUPCL | CLOCAL; - dummy_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - dummy_driver.init_termios.c_ispeed = 115200; - dummy_driver.init_termios.c_ospeed = 115200; - - dummy_driver.ops = &dummy_ops; - if (tty_register_driver(&dummy_driver)) - panic("Couldn't register dummy serial driver\n"); -} - -static struct tty_driver* -etrax_console_device(struct console* co, int *index) -{ - if (port) - *index = port->index; - else - *index = 0; -#ifdef CONFIG_ETRAX_SERIAL - return port ? serial_driver : &dummy_driver; -#else - return &dummy_driver; -#endif -} - -static struct console ser_console = { - name : "ttyS", - write: console_write, - read : NULL, - device : etrax_console_device, - unblank : NULL, - setup : console_setup, - flags : CON_PRINTBUFFER, - index : -1, - cflag : 0, - next : NULL -}; -static struct console ser0_console = { - name : "ttyS", - write: console_write, - read : NULL, - device : etrax_console_device, - unblank : NULL, - setup : console_setup, - flags : CON_PRINTBUFFER, - index : 0, - cflag : 0, - next : NULL -}; - -static struct console ser1_console = { - name : "ttyS", - write: console_write, - read : NULL, - device : etrax_console_device, - unblank : NULL, - setup : console_setup, - flags : CON_PRINTBUFFER, - index : 1, - cflag : 0, - next : NULL -}; -static struct console ser2_console = { - name : "ttyS", - write: console_write, - read : NULL, - device : etrax_console_device, - unblank : NULL, - setup : console_setup, - flags : CON_PRINTBUFFER, - index : 2, - cflag : 0, - next : NULL -}; -static struct console ser3_console = { - name : "ttyS", - write: console_write, - read : NULL, - device : etrax_console_device, - unblank : NULL, - setup : console_setup, - flags : CON_PRINTBUFFER, - index : 3, - cflag : 0, - next : NULL -}; -/* - * Register console (for printk's etc) - */ - -int __init -init_etrax_debug(void) -{ - static int first = 1; - - if (!first) { - unregister_console(&ser_console); - register_console(&ser0_console); - register_console(&ser1_console); - register_console(&ser2_console); - register_console(&ser3_console); - init_dummy_console(); - return 0; - } - - first = 0; - register_console(&ser_console); - start_port(port); -#ifdef CONFIG_ETRAX_KGDB - start_port(kgdb_port); -#endif - return 0; -} -__initcall(init_etrax_debug); diff --git a/arch/cris/arch-v10/kernel/dma.c b/arch/cris/arch-v10/kernel/dma.c deleted file mode 100644 index c68e978def05..000000000000 --- a/arch/cris/arch-v10/kernel/dma.c +++ /dev/null @@ -1,288 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Wrapper for DMA channel allocator that updates DMA client muxing. - * Copyright 2004-2007, Axis Communications AB - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/errno.h> - -#include <asm/dma.h> -#include <arch/svinto.h> -#include <arch/system.h> - -/* Macro to access ETRAX 100 registers */ -#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \ - IO_STATE_(reg##_, field##_, _##val) - - -static char used_dma_channels[MAX_DMA_CHANNELS]; -static const char * used_dma_channels_users[MAX_DMA_CHANNELS]; - -int cris_request_dma(unsigned int dmanr, const char * device_id, - unsigned options, enum dma_owner owner) -{ - unsigned long flags; - unsigned long int gens; - int fail = -EINVAL; - - if (dmanr >= MAX_DMA_CHANNELS) { - printk(KERN_CRIT "cris_request_dma: invalid DMA channel %u\n", dmanr); - return -EINVAL; - } - - local_irq_save(flags); - if (used_dma_channels[dmanr]) { - local_irq_restore(flags); - if (options & DMA_VERBOSE_ON_ERROR) { - printk(KERN_CRIT "Failed to request DMA %i for %s, already allocated by %s\n", dmanr, device_id, used_dma_channels_users[dmanr]); - } - if (options & DMA_PANIC_ON_ERROR) { - panic("request_dma error!"); - } - return -EBUSY; - } - - gens = genconfig_shadow; - - switch(owner) - { - case dma_eth: - if ((dmanr != NETWORK_TX_DMA_NBR) && - (dmanr != NETWORK_RX_DMA_NBR)) { - printk(KERN_CRIT "Invalid DMA channel for eth\n"); - goto bail; - } - break; - case dma_ser0: - if (dmanr == SER0_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma6, serial0); - } else if (dmanr == SER0_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma7, serial0); - } else { - printk(KERN_CRIT "Invalid DMA channel for ser0\n"); - goto bail; - } - break; - case dma_ser1: - if (dmanr == SER1_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma8, serial1); - } else if (dmanr == SER1_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma9, serial1); - } else { - printk(KERN_CRIT "Invalid DMA channel for ser1\n"); - goto bail; - } - break; - case dma_ser2: - if (dmanr == SER2_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma2, serial2); - } else if (dmanr == SER2_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma3, serial2); - } else { - printk(KERN_CRIT "Invalid DMA channel for ser2\n"); - goto bail; - } - break; - case dma_ser3: - if (dmanr == SER3_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma4, serial3); - } else if (dmanr == SER3_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma5, serial3); - } else { - printk(KERN_CRIT "Invalid DMA channel for ser3\n"); - goto bail; - } - break; - case dma_ata: - if (dmanr == ATA_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma2, ata); - } else if (dmanr == ATA_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma3, ata); - } else { - printk(KERN_CRIT "Invalid DMA channel for ata\n"); - goto bail; - } - break; - case dma_ext0: - if (dmanr == EXTDMA0_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma4, extdma0); - } else if (dmanr == EXTDMA0_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma5, extdma0); - } else { - printk(KERN_CRIT "Invalid DMA channel for ext0\n"); - goto bail; - } - break; - case dma_ext1: - if (dmanr == EXTDMA1_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma6, extdma1); - } else if (dmanr == EXTDMA1_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma7, extdma1); - } else { - printk(KERN_CRIT "Invalid DMA channel for ext1\n"); - goto bail; - } - break; - case dma_int6: - if (dmanr == MEM2MEM_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma7, intdma6); - } else { - printk(KERN_CRIT "Invalid DMA channel for int6\n"); - goto bail; - } - break; - case dma_int7: - if (dmanr == MEM2MEM_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma6, intdma7); - } else { - printk(KERN_CRIT "Invalid DMA channel for int7\n"); - goto bail; - } - break; - case dma_usb: - if (dmanr == USB_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma8, usb); - } else if (dmanr == USB_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma9, usb); - } else { - printk(KERN_CRIT "Invalid DMA channel for usb\n"); - goto bail; - } - break; - case dma_scsi0: - if (dmanr == SCSI0_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma2, scsi0); - } else if (dmanr == SCSI0_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma3, scsi0); - } else { - printk(KERN_CRIT "Invalid DMA channel for scsi0\n"); - goto bail; - } - break; - case dma_scsi1: - if (dmanr == SCSI1_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma4, scsi1); - } else if (dmanr == SCSI1_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma5, scsi1); - } else { - printk(KERN_CRIT "Invalid DMA channel for scsi1\n"); - goto bail; - } - break; - case dma_par0: - if (dmanr == PAR0_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma2, par0); - } else if (dmanr == PAR0_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma3, par0); - } else { - printk(KERN_CRIT "Invalid DMA channel for par0\n"); - goto bail; - } - break; - case dma_par1: - if (dmanr == PAR1_TX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma4, par1); - } else if (dmanr == PAR1_RX_DMA_NBR) { - SETS(gens, R_GEN_CONFIG, dma5, par1); - } else { - printk(KERN_CRIT "Invalid DMA channel for par1\n"); - goto bail; - } - break; - default: - printk(KERN_CRIT "Invalid DMA owner.\n"); - goto bail; - } - - used_dma_channels[dmanr] = 1; - used_dma_channels_users[dmanr] = device_id; - - { - volatile int i; - genconfig_shadow = gens; - *R_GEN_CONFIG = genconfig_shadow; - /* Wait 12 cycles before doing any DMA command */ - for(i = 6; i > 0; i--) - nop(); - } - fail = 0; - bail: - local_irq_restore(flags); - return fail; -} - -void cris_free_dma(unsigned int dmanr, const char * device_id) -{ - unsigned long flags; - if (dmanr >= MAX_DMA_CHANNELS) { - printk(KERN_CRIT "cris_free_dma: invalid DMA channel %u\n", dmanr); - return; - } - - local_irq_save(flags); - if (!used_dma_channels[dmanr]) { - printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated\n", dmanr); - } else if (device_id != used_dma_channels_users[dmanr]) { - printk(KERN_CRIT "cris_free_dma: DMA channel %u not allocated by device\n", dmanr); - } else { - switch(dmanr) - { - case 0: - *R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH0_CMD, cmd, *R_DMA_CH0_CMD) == - IO_STATE_VALUE(R_DMA_CH0_CMD, cmd, reset)); - break; - case 1: - *R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH1_CMD, cmd, *R_DMA_CH1_CMD) == - IO_STATE_VALUE(R_DMA_CH1_CMD, cmd, reset)); - break; - case 2: - *R_DMA_CH2_CMD = IO_STATE(R_DMA_CH2_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH2_CMD, cmd, *R_DMA_CH2_CMD) == - IO_STATE_VALUE(R_DMA_CH2_CMD, cmd, reset)); - break; - case 3: - *R_DMA_CH3_CMD = IO_STATE(R_DMA_CH3_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH3_CMD, cmd, *R_DMA_CH3_CMD) == - IO_STATE_VALUE(R_DMA_CH3_CMD, cmd, reset)); - break; - case 4: - *R_DMA_CH4_CMD = IO_STATE(R_DMA_CH4_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH4_CMD, cmd, *R_DMA_CH4_CMD) == - IO_STATE_VALUE(R_DMA_CH4_CMD, cmd, reset)); - break; - case 5: - *R_DMA_CH5_CMD = IO_STATE(R_DMA_CH5_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH5_CMD, cmd, *R_DMA_CH5_CMD) == - IO_STATE_VALUE(R_DMA_CH5_CMD, cmd, reset)); - break; - case 6: - *R_DMA_CH6_CMD = IO_STATE(R_DMA_CH6_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH6_CMD, cmd, *R_DMA_CH6_CMD) == - IO_STATE_VALUE(R_DMA_CH6_CMD, cmd, reset)); - break; - case 7: - *R_DMA_CH7_CMD = IO_STATE(R_DMA_CH7_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH7_CMD, cmd, *R_DMA_CH7_CMD) == - IO_STATE_VALUE(R_DMA_CH7_CMD, cmd, reset)); - break; - case 8: - *R_DMA_CH8_CMD = IO_STATE(R_DMA_CH8_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH8_CMD, cmd, *R_DMA_CH8_CMD) == - IO_STATE_VALUE(R_DMA_CH8_CMD, cmd, reset)); - break; - case 9: - *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, reset); - while (IO_EXTRACT(R_DMA_CH9_CMD, cmd, *R_DMA_CH9_CMD) == - IO_STATE_VALUE(R_DMA_CH9_CMD, cmd, reset)); - break; - } - used_dma_channels[dmanr] = 0; - } - local_irq_restore(flags); -} - -EXPORT_SYMBOL(cris_request_dma); -EXPORT_SYMBOL(cris_free_dma); diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S deleted file mode 100644 index 1f066eebbd2b..000000000000 --- a/arch/cris/arch-v10/kernel/entry.S +++ /dev/null @@ -1,978 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * linux/arch/cris/entry.S - * - * Copyright (C) 2000, 2001, 2002 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - */ - -/* - * entry.S contains the system-call and fault low-level handling routines. - * - * NOTE: This code handles signal-recognition, which happens every time - * after a timer-interrupt and after each system call. - * - * Stack layout in 'ret_from_system_call': - * ptrace needs to have all regs on the stack. - * if the order here is changed, it needs to be - * updated in fork.c:copy_process, signal.c:do_signal, - * ptrace.c and ptrace.h - * - */ - -#include <linux/linkage.h> -#include <linux/sys.h> -#include <asm/unistd.h> -#include <arch/sv_addr_ag.h> -#include <asm/errno.h> -#include <asm/thread_info.h> -#include <asm/asm-offsets.h> -#include <asm/page.h> -#include <asm/pgtable.h> - - ;; functions exported from this file - - .globl system_call - .globl ret_from_intr - .globl ret_from_fork - .globl ret_from_kernel_thread - .globl resume - .globl multiple_interrupt - .globl hwbreakpoint - .globl IRQ1_interrupt - .globl spurious_interrupt - .globl hw_bp_trigs - .globl mmu_bus_fault - .globl do_sigtrap - .globl gdb_handle_breakpoint - .globl sys_call_table - - ;; below are various parts of system_call which are not in the fast-path - -#ifdef CONFIG_PREEMPT - ; Check if preemptive kernel scheduling should be done -_resume_kernel: - di - ; Load current task struct - movs.w -8192, $r0 ; THREAD_SIZE = 8192 - and.d $sp, $r0 - move.d [$r0+TI_preempt_count], $r10 ; Preemption disabled? - bne _Rexit - nop -_need_resched: - move.d [$r0+TI_flags], $r10 - btstq TIF_NEED_RESCHED, $r10 ; Check if need_resched is set - bpl _Rexit - nop - ; Ok, lets's do some preemptive kernel scheduling - jsr preempt_schedule_irq - ; Load new task struct - movs.w -8192, $r0 ; THREAD_SIZE = 8192 - and.d $sp, $r0 - ; One more time (with new task) - ba _need_resched - nop -#else -#define _resume_kernel _Rexit -#endif - - ; Called at exit from fork. schedule_tail must be called to drop - ; spinlock if CONFIG_PREEMPT -ret_from_fork: - jsr schedule_tail - ba ret_from_sys_call - nop - -ret_from_kernel_thread: - jsr schedule_tail - move.d $r2, $r10 ; argument is here - jsr $r1 ; call the payload - moveq 0, $r9 ; no syscall restarts, TYVM... - ba ret_from_sys_call - -ret_from_intr: - ;; check for resched if preemptive kernel or if we're going back to user-mode - ;; this test matches the user_regs(regs) macro - ;; we cannot simply test $dccr, because that does not necessarily - ;; reflect what mode we'll return into. - - move.d [$sp + PT_dccr], $r0; regs->dccr - btstq 8, $r0 ; U-flag - bpl _resume_kernel - ; Note that di below is in delay slot - -_resume_userspace: - di ; so need_resched and sigpending don't change - - movs.w -8192, $r0 ; THREAD_SIZE == 8192 - and.d $sp, $r0 - - move.d [$r0+TI_flags], $r10 ; current->work - and.d _TIF_WORK_MASK, $r10 ; is there any work to be done on return - bne _work_pending - nop - ba _Rexit - nop - - ;; The system_call is called by a BREAK instruction, which works like - ;; an interrupt call but it stores the return PC in BRP instead of IRP. - ;; Since we dont really want to have two epilogues (one for system calls - ;; and one for interrupts) we push the contents of BRP instead of IRP in the - ;; system call prologue, to make it look like an ordinary interrupt on the - ;; stackframe. - ;; - ;; Since we can't have system calls inside interrupts, it should not matter - ;; that we don't stack IRP. - ;; - ;; In r9 we have the wanted syscall number. Arguments come in r10,r11,r12,r13,mof,srp - ;; - ;; This function looks on the _surface_ like spaghetti programming, but it's - ;; really designed so that the fast-path does not force cache-loading of non-used - ;; instructions. Only the non-common cases cause the outlined code to run.. - -system_call: - ;; stack-frame similar to the irq heads, which is reversed in ret_from_sys_call - move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame - push $srp - push $dccr - push $mof - subq 14*4, $sp ; make room for r0-r13 - movem $r13, [$sp] ; push r0-r13 - push $r10 ; push orig_r10 - clear.d [$sp=$sp-4] ; frametype == 0, normal stackframe - - movs.w -ENOSYS, $r0 - move.d $r0, [$sp+PT_r10] ; put the default return value in r10 in the frame - - ;; check if this process is syscall-traced - - movs.w -8192, $r0 ; THREAD_SIZE == 8192 - and.d $sp, $r0 - - move.d [$r0+TI_flags], $r0 - btstq TIF_SYSCALL_TRACE, $r0 - bmi _syscall_trace_entry - nop - -_syscall_traced: - - ;; check for sanity in the requested syscall number - - cmpu.w NR_syscalls, $r9 - bcc ret_from_sys_call - lslq 2, $r9 ; multiply by 4, in the delay slot - - ;; as a bonus 7th parameter, we give the location on the stack - ;; of the register structure itself. some syscalls need this. - - push $sp - - ;; the parameter carrying registers r10, r11, r12 and 13 are intact. - ;; the fifth and sixth parameters (if any) was in mof and srp - ;; respectively, and we need to put them on the stack. - - push $srp - push $mof - - jsr [$r9+sys_call_table] ; actually do the system call - addq 3*4, $sp ; pop the mof, srp and regs parameters - move.d $r10, [$sp+PT_r10] ; save the return value - - moveq 1, $r9 ; "parameter" to ret_from_sys_call to show it was a sys call - - ;; fall through into ret_from_sys_call to return - -ret_from_sys_call: - ;; r9 is a parameter - if >=1 we came from a syscall, if 0, from an irq - - ;; get the current task-struct pointer (see top for defs) - - movs.w -8192, $r0 ; THREAD_SIZE == 8192 - and.d $sp, $r0 - - di ; make sure need_resched and sigpending don't change - move.d [$r0+TI_flags],$r1 - and.d _TIF_ALLWORK_MASK, $r1 - bne _syscall_exit_work - nop - -_Rexit: - ;; this epilogue MUST match the prologues in multiple_interrupt, irq.h and ptregs.h - pop $r10 ; frametype - bne _RBFexit ; was not CRIS_FRAME_NORMAL, handle otherwise - addq 4, $sp ; skip orig_r10, in delayslot - movem [$sp+], $r13 ; registers r0-r13 - pop $mof ; multiply overflow register - pop $dccr ; condition codes - pop $srp ; subroutine return pointer - ;; now we have a 4-word SBFS frame which we do not want to restore - ;; using RBF since it was not stacked with SBFS. instead we would like to - ;; just get the PC value to restart it with, and skip the rest of - ;; the frame. - ;; Also notice that it's important to use instructions here that - ;; keep the interrupts disabled (since we've already popped DCCR) - move [$sp=$sp+16], $p8; pop the SBFS frame from the sp - jmpu [$sp-16] ; return through the irp field in the sbfs frame - -_RBFexit: - movem [$sp+], $r13 ; registers r0-r13, in delay slot - pop $mof ; multiply overflow register - pop $dccr ; condition codes - pop $srp ; subroutine return pointer - rbf [$sp+] ; return by popping the CPU status - - ;; We get here after doing a syscall if extra work might need to be done - ;; perform syscall exit tracing if needed - -_syscall_exit_work: - ;; $r0 contains current at this point and irq's are disabled - - move.d [$r0+TI_flags], $r1 - btstq TIF_SYSCALL_TRACE, $r1 - bpl _work_pending - nop - - ei - - move.d $r9, $r1 ; preserve r9 - jsr do_syscall_trace - move.d $r1, $r9 - - ba _resume_userspace - nop - -_work_pending: - move.d [$r0+TI_flags], $r1 - btstq TIF_NEED_RESCHED, $r1 - bpl _work_notifysig ; was neither trace nor sched, must be signal/notify - nop - -_work_resched: - move.d $r9, $r1 ; preserve r9 - jsr schedule - move.d $r1, $r9 - di - - move.d [$r0+TI_flags], $r1 - and.d _TIF_WORK_MASK, $r1; ignore the syscall trace counter - beq _Rexit - nop - btstq TIF_NEED_RESCHED, $r1 - bmi _work_resched ; current->work.need_resched - nop - -_work_notifysig: - ;; deal with pending signals and notify-resume requests - - move.d $r9, $r10 ; do_notify_resume syscall/irq param - move.d $sp, $r11 ; the regs param - move.d $r1, $r12 ; the thread_info_flags parameter - jsr do_notify_resume - - ba _Rexit - nop - - ;; We get here as a sidetrack when we've entered a syscall with the - ;; trace-bit set. We need to call do_syscall_trace and then continue - ;; with the call. - -_syscall_trace_entry: - ;; PT_r10 in the frame contains -ENOSYS as required, at this point - - jsr do_syscall_trace - - ;; now re-enter the syscall code to do the syscall itself - ;; we need to restore $r9 here to contain the wanted syscall, and - ;; the other parameter-bearing registers - - move.d [$sp+PT_r9], $r9 - move.d [$sp+PT_orig_r10], $r10 ; PT_r10 is already filled with -ENOSYS. - move.d [$sp+PT_r11], $r11 - move.d [$sp+PT_r12], $r12 - move.d [$sp+PT_r13], $r13 - move [$sp+PT_mof], $mof - move [$sp+PT_srp], $srp - - ba _syscall_traced - nop - - ;; resume performs the actual task-switching, by switching stack pointers - ;; input arguments: r10 = prev, r11 = next, r12 = thread offset in task struct - ;; returns old current in r10 - ;; - ;; TODO: see the i386 version. The switch_to which calls resume in our version - ;; could really be an inline asm of this. - -resume: - push $srp ; we keep the old/new PC on the stack - add.d $r12, $r10 ; r10 = current tasks tss - move $dccr, [$r10+THREAD_dccr]; save irq enable state - di - - move $usp, [$r10+ THREAD_usp] ; save user-mode stackpointer - - ;; See copy_thread for the reason why register R9 is saved. - subq 10*4, $sp - movem $r9, [$sp] ; save non-scratch registers and R9. - - move.d $sp, [$r10+THREAD_ksp] ; save the kernel stack pointer for the old task - move.d $sp, $r10 ; return last running task in r10 - and.d -8192, $r10 ; get thread_info from stackpointer - move.d [$r10+TI_task], $r10 ; get task - add.d $r12, $r11 ; find the new tasks tss - move.d [$r11+THREAD_ksp], $sp ; switch into the new stackframe by restoring kernel sp - - movem [$sp+], $r9 ; restore non-scratch registers and R9. - - move [$r11+THREAD_usp], $usp ; restore user-mode stackpointer - - move [$r11+THREAD_dccr], $dccr ; restore irq enable status - jump [$sp+] ; restore PC - - ;; This is the MMU bus fault handler. - ;; It needs to stack the CPU status and overall is different - ;; from the other interrupt handlers. - -mmu_bus_fault: - ;; For refills we try to do a quick page table lookup. If it is - ;; a real fault we let the mm subsystem handle it. - - ;; the first longword in the sbfs frame was the interrupted PC - ;; which fits nicely with the "IRP" slot in pt_regs normally used to - ;; contain the return address. used by Oops to print kernel errors. - sbfs [$sp=$sp-16] ; push the internal CPU status - push $dccr - di - subq 2*4, $sp - movem $r1, [$sp] - move.d [R_MMU_CAUSE], $r1 - ;; ETRAX 100LX TR89 bugfix: if the second half of an unaligned - ;; write causes a MMU-fault, it will not be restarted correctly. - ;; This could happen if a write crosses a page-boundary and the - ;; second page is not yet COW'ed or even loaded. The workaround - ;; is to clear the unaligned bit in the CPU status record, so - ;; that the CPU will rerun both the first and second halves of - ;; the instruction. This will not have any sideeffects unless - ;; the first half goes to any device or memory that can't be - ;; written twice, and which is mapped through the MMU. - ;; - ;; We only need to do this for writes. - btstq 8, $r1 ; Write access? - bpl 1f - nop - move.d [$sp+16], $r0 ; Clear unaligned bit in csrinstr - and.d ~(1<<5), $r0 - move.d $r0, [$sp+16] -1: btstq 12, $r1 ; Refill? - bpl 2f - lsrq 24, $r1 ; Get PGD index (bit 24-31) - move.d [current_pgd], $r0 ; PGD for the current process - move.d [$r0+$r1.d], $r0 ; Get PMD - beq 2f - nop - and.w PAGE_MASK, $r0 ; Remove PMD flags - move.d [R_MMU_CAUSE], $r1 - lsrq PAGE_SHIFT, $r1 - and.d 0x7ff, $r1 ; Get PTE index into PGD (bit 13-23) - move.d [$r0+$r1.d], $r1 ; Get PTE - beq 2f - nop - ;; Store in TLB - move.d $r1, [R_TLB_LO] - ;; Return - movem [$sp+], $r1 - pop $dccr - rbf [$sp+] ; return by popping the CPU status - -2: ; PMD or PTE missing, let the mm subsystem fix it up. - movem [$sp+], $r1 - pop $dccr - - ; Ok, not that easy, pass it on to the mm subsystem - ; The MMU status record is now on the stack - push $srp ; make a stackframe similar to pt_regs - push $dccr - push $mof - di - subq 14*4, $sp - movem $r13, [$sp] - push $r10 ; dummy orig_r10 - moveq 1, $r10 - push $r10 ; frametype == 1, BUSFAULT frame type - - move.d $sp, $r10 ; pt_regs argument to handle_mmu_bus_fault - - jsr handle_mmu_bus_fault ; in arch/cris/arch-v10/mm/fault.c - - ;; now we need to return through the normal path, we cannot just - ;; do the RBFexit since we might have killed off the running - ;; process due to a SEGV, scheduled due to a page blocking or - ;; whatever. - - moveq 0, $r9 ; busfault is equivalent to an irq - - ba ret_from_intr - nop - - ;; special handlers for breakpoint and NMI -hwbreakpoint: - push $dccr - di - push $r10 - push $r11 - move.d [hw_bp_trig_ptr],$r10 - move $brp,$r11 - move.d $r11,[$r10+] - move.d $r10,[hw_bp_trig_ptr] -1: pop $r11 - pop $r10 - pop $dccr - retb - nop - -IRQ1_interrupt: - ;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!! - move $brp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame - push $srp - push $dccr - push $mof - di - subq 14*4, $sp - movem $r13, [$sp] - push $r10 ; push orig_r10 - clear.d [$sp=$sp-4] ; frametype == 0, normal frame - - ;; If there is a glitch on the NMI pin shorter than ~100ns - ;; (i.e. non-active by the time we get here) then the nmi_pin bit - ;; in R_IRQ_MASK0_RD will already be cleared. The watchdog_nmi bit - ;; is cleared by us however (when feeding the watchdog), which is why - ;; we use that bit to determine what brought us here. - - move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog? - and.d (1<<30), $r1 - bne wdog - move.d $sp, $r10 - jsr handle_nmi - setf m ; Enable NMI again - ba _Rexit ; Return the standard way - nop -wdog: -#if defined(CONFIG_ETRAX_WATCHDOG) -;; Check if we're waiting for reset to happen, as signalled by -;; hard_reset_now setting cause_of_death to a magic value. If so, just -;; get stuck until reset happens. - .comm cause_of_death, 4 ;; Don't declare this anywhere. - move.d [cause_of_death], $r10 - cmp.d 0xbedead, $r10 -_killed_by_death: - beq _killed_by_death - nop - -;; We'll see this in ksymoops dumps. -Watchdog_bite: - -#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY - ;; We just restart the watchdog here to be sure we dont get - ;; hit while printing the watchdogmsg below - ;; This restart is compatible with the rest of the C-code, so - ;; the C-code can keep restarting the watchdog after this point. - ;; The non-NICE_DOGGY code below though, disables the possibility - ;; to restart since it changes the watchdog key, to avoid any - ;; buggy loops etc. keeping the watchdog alive after this. - jsr reset_watchdog -#else - -;; We need to extend the 3.3ms after the NMI at watchdog bite, so we have -;; time for an oops-dump over a 115k2 serial wire. Another 100ms should do. - -;; Change the watchdog key to an arbitrary 3-bit value and restart the -;; watchdog. -#define WD_INIT 2 - moveq IO_FIELD (R_WATCHDOG, key, WD_INIT), $r10 - move.d R_WATCHDOG, $r11 - - move.d $r10, [$r11] - moveq IO_FIELD (R_WATCHDOG, key, \ - IO_EXTRACT (R_WATCHDOG, key, \ - IO_MASK (R_WATCHDOG, key)) \ - ^ WD_INIT) \ - | IO_STATE (R_WATCHDOG, enable, start), $r10 - move.d $r10, [$r11] - -#endif - -;; Note that we don't do "setf m" here (or after two necessary NOPs), -;; since *not* doing that saves us from re-entrancy checks. We don't want -;; to get here again due to possible subsequent NMIs; we want the watchdog -;; to reset us. - - move.d _watchdogmsg,$r10 - jsr printk - - move.d $sp, $r10 - jsr watchdog_bite_hook - -;; This nop is here so we see the "Watchdog_bite" label in ksymoops dumps -;; rather than "spurious_interrupt". - nop -;; At this point we drop down into spurious_interrupt, which will do a -;; hard reset. - - .section .rodata,"a" -_watchdogmsg: - .ascii "Oops: bitten by watchdog\n\0" - .previous - -#endif /* CONFIG_ETRAX_WATCHDOG */ - -spurious_interrupt: - di - jump hard_reset_now - - ;; this handles the case when multiple interrupts arrive at the same time - ;; we jump to the first set interrupt bit in a priority fashion - ;; the hardware will call the unserved interrupts after the handler finishes - -multiple_interrupt: - ;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!! - move $irp,[$sp=$sp-16]; instruction pointer and room for a fake SBFS frame - push $srp - push $dccr - push $mof - di - subq 14*4, $sp - movem $r13, [$sp] - push $r10 ; push orig_r10 - clear.d [$sp=$sp-4] ; frametype == 0, normal frame - - move.d $sp, $r10 - jsr do_multiple_IRQ - - jump ret_from_intr - -do_sigtrap: - ;; - ;; SIGTRAP the process that executed the break instruction. - ;; Make a frame that Rexit in entry.S expects. - ;; - move $brp, [$sp=$sp-16] ; Push BRP while faking a cpu status record. - push $srp ; Push subroutine return pointer. - push $dccr ; Push condition codes. - push $mof ; Push multiply overflow reg. - di ; Need to disable irq's at this point. - subq 14*4, $sp ; Make room for r0-r13. - movem $r13, [$sp] ; Push the r0-r13 registers. - push $r10 ; Push orig_r10. - clear.d [$sp=$sp-4] ; Frametype - this is a normal stackframe. - - movs.w -8192,$r9 ; THREAD_SIZE == 8192 - and.d $sp, $r9 - move.d [$r9+TI_task], $r10 - move.d [$r10+TASK_pid], $r10 ; current->pid as arg1. - moveq 5, $r11 ; SIGTRAP as arg2. - jsr sys_kill - jump ret_from_intr ; Use the return routine for interrupts. - -gdb_handle_breakpoint: - push $dccr - push $r0 -#ifdef CONFIG_ETRAX_KGDB - move $dccr, $r0 ; U-flag not affected by previous insns. - btstq 8, $r0 ; Test the U-flag. - bmi _ugdb_handle_breakpoint ; Go to user mode debugging. - nop ; Empty delay slot (cannot pop r0 here). - pop $r0 ; Restore r0. - ba kgdb_handle_breakpoint ; Go to kernel debugging. - pop $dccr ; Restore dccr in delay slot. -#endif - -_ugdb_handle_breakpoint: - move $brp, $r0 ; Use r0 temporarily for calculation. - subq 2, $r0 ; Set to address of previous instruction. - move $r0, $brp - pop $r0 ; Restore r0. - ba do_sigtrap ; SIGTRAP the offending process. - pop $dccr ; Restore dccr in delay slot. - - .data - -hw_bp_trigs: - .space 64*4 -hw_bp_trig_ptr: - .dword hw_bp_trigs - - .section .rodata,"a" -sys_call_table: - .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ - .long sys_exit - .long sys_fork - .long sys_read - .long sys_write - .long sys_open /* 5 */ - .long sys_close - .long sys_waitpid - .long sys_creat - .long sys_link - .long sys_unlink /* 10 */ - .long sys_execve - .long sys_chdir - .long sys_time - .long sys_mknod - .long sys_chmod /* 15 */ - .long sys_lchown16 - .long sys_ni_syscall /* old break syscall holder */ - .long sys_stat - .long sys_lseek - .long sys_getpid /* 20 */ - .long sys_mount - .long sys_oldumount - .long sys_setuid16 - .long sys_getuid16 - .long sys_stime /* 25 */ - .long sys_ptrace - .long sys_alarm - .long sys_fstat - .long sys_pause - .long sys_utime /* 30 */ - .long sys_ni_syscall /* old stty syscall holder */ - .long sys_ni_syscall /* old gtty syscall holder */ - .long sys_access - .long sys_nice - .long sys_ni_syscall /* 35 old ftime syscall holder */ - .long sys_sync - .long sys_kill - .long sys_rename - .long sys_mkdir - .long sys_rmdir /* 40 */ - .long sys_dup - .long sys_pipe - .long sys_times - .long sys_ni_syscall /* old prof syscall holder */ - .long sys_brk /* 45 */ - .long sys_setgid16 - .long sys_getgid16 - .long sys_signal - .long sys_geteuid16 - .long sys_getegid16 /* 50 */ - .long sys_acct - .long sys_umount /* recycled never used phys( */ - .long sys_ni_syscall /* old lock syscall holder */ - .long sys_ioctl - .long sys_fcntl /* 55 */ - .long sys_ni_syscall /* old mpx syscall holder */ - .long sys_setpgid - .long sys_ni_syscall /* old ulimit syscall holder */ - .long sys_ni_syscall /* old sys_olduname holder */ - .long sys_umask /* 60 */ - .long sys_chroot - .long sys_ustat - .long sys_dup2 - .long sys_getppid - .long sys_getpgrp /* 65 */ - .long sys_setsid - .long sys_sigaction - .long sys_sgetmask - .long sys_ssetmask - .long sys_setreuid16 /* 70 */ - .long sys_setregid16 - .long sys_sigsuspend - .long sys_sigpending - .long sys_sethostname - .long sys_setrlimit /* 75 */ - .long sys_old_getrlimit - .long sys_getrusage - .long sys_gettimeofday - .long sys_settimeofday - .long sys_getgroups16 /* 80 */ - .long sys_setgroups16 - .long sys_select /* was old_select in Linux/E100 */ - .long sys_symlink - .long sys_lstat - .long sys_readlink /* 85 */ - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long sys_old_readdir - .long sys_old_mmap /* 90 */ - .long sys_munmap - .long sys_truncate - .long sys_ftruncate - .long sys_fchmod - .long sys_fchown16 /* 95 */ - .long sys_getpriority - .long sys_setpriority - .long sys_ni_syscall /* old profil syscall holder */ - .long sys_statfs - .long sys_fstatfs /* 100 */ - .long sys_ni_syscall /* sys_ioperm in i386 */ - .long sys_socketcall - .long sys_syslog - .long sys_setitimer - .long sys_getitimer /* 105 */ - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_ni_syscall /* old sys_uname holder */ - .long sys_ni_syscall /* 110 */ /* sys_iopl in i386 */ - .long sys_vhangup - .long sys_ni_syscall /* old "idle" system call */ - .long sys_ni_syscall /* vm86old in i386 */ - .long sys_wait4 - .long sys_swapoff /* 115 */ - .long sys_sysinfo - .long sys_ipc - .long sys_fsync - .long sys_sigreturn - .long sys_clone /* 120 */ - .long sys_setdomainname - .long sys_newuname - .long sys_ni_syscall /* sys_modify_ldt */ - .long sys_adjtimex - .long sys_mprotect /* 125 */ - .long sys_sigprocmask - .long sys_ni_syscall /* old "create_module" */ - .long sys_init_module - .long sys_delete_module - .long sys_ni_syscall /* 130: old "get_kernel_syms" */ - .long sys_quotactl - .long sys_getpgid - .long sys_fchdir - .long sys_bdflush - .long sys_sysfs /* 135 */ - .long sys_personality - .long sys_ni_syscall /* for afs_syscall */ - .long sys_setfsuid16 - .long sys_setfsgid16 - .long sys_llseek /* 140 */ - .long sys_getdents - .long sys_select - .long sys_flock - .long sys_msync - .long sys_readv /* 145 */ - .long sys_writev - .long sys_getsid - .long sys_fdatasync - .long sys_sysctl - .long sys_mlock /* 150 */ - .long sys_munlock - .long sys_mlockall - .long sys_munlockall - .long sys_sched_setparam - .long sys_sched_getparam /* 155 */ - .long sys_sched_setscheduler - .long sys_sched_getscheduler - .long sys_sched_yield - .long sys_sched_get_priority_max - .long sys_sched_get_priority_min /* 160 */ - .long sys_sched_rr_get_interval - .long sys_nanosleep - .long sys_mremap - .long sys_setresuid16 - .long sys_getresuid16 /* 165 */ - .long sys_ni_syscall /* sys_vm86 */ - .long sys_ni_syscall /* Old sys_query_module */ - .long sys_poll - .long sys_ni_syscall /* old nfsservctl */ - .long sys_setresgid16 /* 170 */ - .long sys_getresgid16 - .long sys_prctl - .long sys_rt_sigreturn - .long sys_rt_sigaction - .long sys_rt_sigprocmask /* 175 */ - .long sys_rt_sigpending - .long sys_rt_sigtimedwait - .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend - .long sys_pread64 /* 180 */ - .long sys_pwrite64 - .long sys_chown16 - .long sys_getcwd - .long sys_capget - .long sys_capset /* 185 */ - .long sys_sigaltstack - .long sys_sendfile - .long sys_ni_syscall /* streams1 */ - .long sys_ni_syscall /* streams2 */ - .long sys_vfork /* 190 */ - .long sys_getrlimit - .long sys_mmap2 /* mmap_pgoff */ - .long sys_truncate64 - .long sys_ftruncate64 - .long sys_stat64 /* 195 */ - .long sys_lstat64 - .long sys_fstat64 - .long sys_lchown - .long sys_getuid - .long sys_getgid /* 200 */ - .long sys_geteuid - .long sys_getegid - .long sys_setreuid - .long sys_setregid - .long sys_getgroups /* 205 */ - .long sys_setgroups - .long sys_fchown - .long sys_setresuid - .long sys_getresuid - .long sys_setresgid /* 210 */ - .long sys_getresgid - .long sys_chown - .long sys_setuid - .long sys_setgid - .long sys_setfsuid /* 215 */ - .long sys_setfsgid - .long sys_pivot_root - .long sys_mincore - .long sys_madvise - .long sys_getdents64 /* 220 */ - .long sys_fcntl64 - .long sys_ni_syscall /* reserved for TUX */ - .long sys_ni_syscall - .long sys_gettid - .long sys_readahead /* 225 */ - .long sys_setxattr - .long sys_lsetxattr - .long sys_fsetxattr - .long sys_getxattr - .long sys_lgetxattr /* 230 */ - .long sys_fgetxattr - .long sys_listxattr - .long sys_llistxattr - .long sys_flistxattr - .long sys_removexattr /* 235 */ - .long sys_lremovexattr - .long sys_fremovexattr - .long sys_tkill - .long sys_sendfile64 - .long sys_futex /* 240 */ - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_ni_syscall /* sys_set_thread_area */ - .long sys_ni_syscall /* sys_get_thread_area */ - .long sys_io_setup /* 245 */ - .long sys_io_destroy - .long sys_io_getevents - .long sys_io_submit - .long sys_io_cancel - .long sys_fadvise64 /* 250 */ - .long sys_ni_syscall - .long sys_exit_group - .long sys_lookup_dcookie - .long sys_epoll_create - .long sys_epoll_ctl /* 255 */ - .long sys_epoll_wait - .long sys_remap_file_pages - .long sys_set_tid_address - .long sys_timer_create - .long sys_timer_settime /* 260 */ - .long sys_timer_gettime - .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime /* 265 */ - .long sys_clock_getres - .long sys_clock_nanosleep - .long sys_statfs64 - .long sys_fstatfs64 - .long sys_tgkill /* 270 */ - .long sys_utimes - .long sys_fadvise64_64 - .long sys_ni_syscall /* sys_vserver */ - .long sys_ni_syscall /* sys_mbind */ - .long sys_ni_syscall /* 275 sys_get_mempolicy */ - .long sys_ni_syscall /* sys_set_mempolicy */ - .long sys_mq_open - .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive /* 280 */ - .long sys_mq_notify - .long sys_mq_getsetattr - .long sys_ni_syscall - .long sys_waitid - .long sys_ni_syscall /* 285 */ /* available */ - .long sys_add_key - .long sys_request_key - .long sys_keyctl - .long sys_ioprio_set - .long sys_ioprio_get /* 290 */ - .long sys_inotify_init - .long sys_inotify_add_watch - .long sys_inotify_rm_watch - .long sys_migrate_pages - .long sys_openat /* 295 */ - .long sys_mkdirat - .long sys_mknodat - .long sys_fchownat - .long sys_futimesat - .long sys_fstatat64 /* 300 */ - .long sys_unlinkat - .long sys_renameat - .long sys_linkat - .long sys_symlinkat - .long sys_readlinkat /* 305 */ - .long sys_fchmodat - .long sys_faccessat - .long sys_pselect6 - .long sys_ppoll - .long sys_unshare /* 310 */ - .long sys_set_robust_list - .long sys_get_robust_list - .long sys_splice - .long sys_sync_file_range - .long sys_tee /* 315 */ - .long sys_vmsplice - .long sys_move_pages - .long sys_getcpu - .long sys_epoll_pwait - .long sys_utimensat /* 320 */ - .long sys_signalfd - .long sys_timerfd_create - .long sys_eventfd - .long sys_fallocate - .long sys_timerfd_settime /* 325 */ - .long sys_timerfd_gettime - .long sys_signalfd4 - .long sys_eventfd2 - .long sys_epoll_create1 - .long sys_dup3 /* 330 */ - .long sys_pipe2 - .long sys_inotify_init1 - .long sys_preadv - .long sys_pwritev - .long sys_setns /* 335 */ - .long sys_name_to_handle_at - .long sys_open_by_handle_at - .long sys_rt_tgsigqueueinfo - .long sys_perf_event_open - .long sys_recvmmsg /* 340 */ - .long sys_accept4 - .long sys_fanotify_init - .long sys_fanotify_mark - .long sys_prlimit64 - .long sys_clock_adjtime /* 345 */ - .long sys_syncfs - .long sys_sendmmsg - .long sys_process_vm_readv - .long sys_process_vm_writev - .long sys_kcmp /* 350 */ - .long sys_finit_module - .long sys_sched_setattr - .long sys_sched_getattr - .long sys_renameat2 - .long sys_seccomp /* 355 */ - .long sys_getrandom - .long sys_memfd_create - .long sys_bpf - .long sys_execveat - - /* - * NOTE!! This doesn't have to be exact - we just have - * to make sure we have _enough_ of the "sys_ni_syscall" - * entries. Don't panic if you notice that this hasn't - * been shrunk every time we add a new system call. - */ - - .rept NR_syscalls-(.-sys_call_table)/4 - .long sys_ni_syscall - .endr - diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c deleted file mode 100644 index 94abbff557ff..000000000000 --- a/arch/cris/arch-v10/kernel/fasttimer.c +++ /dev/null @@ -1,835 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/kernel/fasttimer.c - * - * Fast timers for ETRAX100/ETRAX100LX - * - * Copyright (C) 2000-2007 Axis Communications AB, Lund, Sweden - */ - -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/param.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/vmalloc.h> -#include <linux/interrupt.h> -#include <linux/time.h> -#include <linux/delay.h> - -#include <asm/segment.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/delay.h> - -#include <arch/svinto.h> -#include <asm/fasttimer.h> -#include <linux/proc_fs.h> -#include <linux/seq_file.h> - - -#define DEBUG_LOG_INCLUDED -#define FAST_TIMER_LOG -/* #define FAST_TIMER_TEST */ - -#define FAST_TIMER_SANITY_CHECKS - -#ifdef FAST_TIMER_SANITY_CHECKS -static int sanity_failed; -#endif - -#define D1(x) -#define D2(x) -#define DP(x) - -static unsigned int fast_timer_running; -static unsigned int fast_timers_added; -static unsigned int fast_timers_started; -static unsigned int fast_timers_expired; -static unsigned int fast_timers_deleted; -static unsigned int fast_timer_is_init; -static unsigned int fast_timer_ints; - -struct fast_timer *fast_timer_list = NULL; - -#ifdef DEBUG_LOG_INCLUDED -#define DEBUG_LOG_MAX 128 -static const char * debug_log_string[DEBUG_LOG_MAX]; -static unsigned long debug_log_value[DEBUG_LOG_MAX]; -static unsigned int debug_log_cnt; -static unsigned int debug_log_cnt_wrapped; - -#define DEBUG_LOG(string, value) \ -{ \ - unsigned long log_flags; \ - local_irq_save(log_flags); \ - debug_log_string[debug_log_cnt] = (string); \ - debug_log_value[debug_log_cnt] = (unsigned long)(value); \ - if (++debug_log_cnt >= DEBUG_LOG_MAX) \ - { \ - debug_log_cnt = debug_log_cnt % DEBUG_LOG_MAX; \ - debug_log_cnt_wrapped = 1; \ - } \ - local_irq_restore(log_flags); \ -} -#else -#define DEBUG_LOG(string, value) -#endif - - -/* The frequencies for index = clkselx number in R_TIMER_CTRL */ -#define NUM_TIMER_FREQ 15 -#define MAX_USABLE_TIMER_FREQ 7 -#define MAX_DELAY_US 853333L -const unsigned long timer_freq_100[NUM_TIMER_FREQ] = -{ - 3, /* 0 3333 - 853333 us */ - 6, /* 1 1666 - 426666 us */ - 12, /* 2 833 - 213333 us */ - 24, /* 3 416 - 106666 us */ - 48, /* 4 208 - 53333 us */ - 96, /* 5 104 - 26666 us */ - 192, /* 6 52 - 13333 us */ - 384, /* 7 26 - 6666 us */ - 576, - 1152, - 2304, - 4608, - 9216, - 18432, - 62500, - /* 15 = cascade */ -}; -#define NUM_TIMER_STATS 16 -#ifdef FAST_TIMER_LOG -struct fast_timer timer_added_log[NUM_TIMER_STATS]; -struct fast_timer timer_started_log[NUM_TIMER_STATS]; -struct fast_timer timer_expired_log[NUM_TIMER_STATS]; -#endif - -int timer_div_settings[NUM_TIMER_STATS]; -int timer_freq_settings[NUM_TIMER_STATS]; -int timer_delay_settings[NUM_TIMER_STATS]; - -/* Not true gettimeofday, only checks the jiffies (uptime) + useconds */ -inline void do_gettimeofday_fast(struct fasttime_t *tv) -{ - tv->tv_jiff = jiffies; - tv->tv_usec = GET_JIFFIES_USEC(); -} - -inline int fasttime_cmp(struct fasttime_t *t0, struct fasttime_t *t1) -{ - /* Compare jiffies. Takes care of wrapping */ - if (time_before(t0->tv_jiff, t1->tv_jiff)) - return -1; - else if (time_after(t0->tv_jiff, t1->tv_jiff)) - return 1; - - /* Compare us */ - if (t0->tv_usec < t1->tv_usec) - return -1; - else if (t0->tv_usec > t1->tv_usec) - return 1; - return 0; -} - -inline void start_timer1(unsigned long delay_us) -{ - int freq_index = 0; /* This is the lowest resolution */ - unsigned long upper_limit = MAX_DELAY_US; - - unsigned long div; - /* Start/Restart the timer to the new shorter value */ - /* t = 1/freq = 1/19200 = 53us - * T=div*t, div = T/t = delay_us*freq/1000000 - */ -#if 1 /* Adaptive timer settings */ - while (delay_us < upper_limit && freq_index < MAX_USABLE_TIMER_FREQ) - { - freq_index++; - upper_limit >>= 1; /* Divide by 2 using shift */ - } - if (freq_index > 0) - { - freq_index--; - } -#else - freq_index = 6; -#endif - div = delay_us * timer_freq_100[freq_index]/10000; - if (div < 2) - { - /* Maybe increase timer freq? */ - div = 2; - } - if (div > 255) - { - div = 0; /* This means 256, the max the timer takes */ - /* If a longer timeout than the timer can handle is used, - * then we must restart it when it goes off. - */ - } - - timer_div_settings[fast_timers_started % NUM_TIMER_STATS] = div; - timer_freq_settings[fast_timers_started % NUM_TIMER_STATS] = freq_index; - timer_delay_settings[fast_timers_started % NUM_TIMER_STATS] = delay_us; - - D1(printk(KERN_DEBUG "start_timer1 : %d us freq: %i div: %i\n", - delay_us, freq_index, div)); - /* Clear timer1 irq */ - *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr); - - /* Set timer values */ - *R_TIMER_CTRL = r_timer_ctrl_shadow = - (r_timer_ctrl_shadow & - ~IO_MASK(R_TIMER_CTRL, timerdiv1) & - ~IO_MASK(R_TIMER_CTRL, tm1) & - ~IO_MASK(R_TIMER_CTRL, clksel1)) | - IO_FIELD(R_TIMER_CTRL, timerdiv1, div) | - IO_STATE(R_TIMER_CTRL, tm1, stop_ld) | - IO_FIELD(R_TIMER_CTRL, clksel1, freq_index ); /* 6=c19k2Hz */ - - /* Ack interrupt */ - *R_TIMER_CTRL = r_timer_ctrl_shadow | - IO_STATE(R_TIMER_CTRL, i1, clr); - - /* Start timer */ - *R_TIMER_CTRL = r_timer_ctrl_shadow = - (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) | - IO_STATE(R_TIMER_CTRL, tm1, run); - - /* Enable timer1 irq */ - *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer1, set); - fast_timers_started++; - fast_timer_running = 1; -} - -/* In version 1.4 this function takes 27 - 50 us */ -void start_one_shot_timer(struct fast_timer *t, - fast_timer_function_type *function, - unsigned long data, - unsigned long delay_us, - const char *name) -{ - unsigned long flags; - struct fast_timer *tmp; - - D1(printk("sft %s %d us\n", name, delay_us)); - - local_irq_save(flags); - - do_gettimeofday_fast(&t->tv_set); - tmp = fast_timer_list; - -#ifdef FAST_TIMER_SANITY_CHECKS - /* Check so this is not in the list already... */ - while (tmp != NULL) { - if (tmp == t) { - printk(KERN_WARNING "timer name: %s data: " - "0x%08lX already in list!\n", name, data); - sanity_failed++; - goto done; - } else - tmp = tmp->next; - } - tmp = fast_timer_list; -#endif - - t->delay_us = delay_us; - t->function = function; - t->data = data; - t->name = name; - - t->tv_expires.tv_usec = t->tv_set.tv_usec + delay_us % 1000000; - t->tv_expires.tv_jiff = t->tv_set.tv_jiff + delay_us / 1000000 / HZ; - if (t->tv_expires.tv_usec > 1000000) - { - t->tv_expires.tv_usec -= 1000000; - t->tv_expires.tv_jiff += HZ; - } -#ifdef FAST_TIMER_LOG - timer_added_log[fast_timers_added % NUM_TIMER_STATS] = *t; -#endif - fast_timers_added++; - - /* Check if this should timeout before anything else */ - if (tmp == NULL || fasttime_cmp(&t->tv_expires, &tmp->tv_expires) < 0) - { - /* Put first in list and modify the timer value */ - t->prev = NULL; - t->next = fast_timer_list; - if (fast_timer_list) - { - fast_timer_list->prev = t; - } - fast_timer_list = t; -#ifdef FAST_TIMER_LOG - timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; -#endif - start_timer1(delay_us); - } else { - /* Put in correct place in list */ - while (tmp->next && fasttime_cmp(&t->tv_expires, - &tmp->next->tv_expires) > 0) - { - tmp = tmp->next; - } - /* Insert t after tmp */ - t->prev = tmp; - t->next = tmp->next; - if (tmp->next) - { - tmp->next->prev = t; - } - tmp->next = t; - } - - D2(printk("start_one_shot_timer: %d us done\n", delay_us)); - -done: - local_irq_restore(flags); -} /* start_one_shot_timer */ - -static inline int fast_timer_pending (const struct fast_timer * t) -{ - return (t->next != NULL) || (t->prev != NULL) || (t == fast_timer_list); -} - -static inline int detach_fast_timer (struct fast_timer *t) -{ - struct fast_timer *next, *prev; - if (!fast_timer_pending(t)) - return 0; - next = t->next; - prev = t->prev; - if (next) - next->prev = prev; - if (prev) - prev->next = next; - else - fast_timer_list = next; - fast_timers_deleted++; - return 1; -} - -int del_fast_timer(struct fast_timer * t) -{ - unsigned long flags; - int ret; - - local_irq_save(flags); - ret = detach_fast_timer(t); - t->next = t->prev = NULL; - local_irq_restore(flags); - return ret; -} /* del_fast_timer */ - - -/* Interrupt routines or functions called in interrupt context */ - -/* Timer 1 interrupt handler */ - -static irqreturn_t -timer1_handler(int irq, void *dev_id) -{ - struct fast_timer *t; - unsigned long flags; - - /* We keep interrupts disabled not only when we modify the - * fast timer list, but any time we hold a reference to a - * timer in the list, since del_fast_timer may be called - * from (another) interrupt context. Thus, the only time - * when interrupts are enabled is when calling the timer - * callback function. - */ - local_irq_save(flags); - - /* Clear timer1 irq */ - *R_IRQ_MASK0_CLR = IO_STATE(R_IRQ_MASK0_CLR, timer1, clr); - - /* First stop timer, then ack interrupt */ - /* Stop timer */ - *R_TIMER_CTRL = r_timer_ctrl_shadow = - (r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) | - IO_STATE(R_TIMER_CTRL, tm1, stop_ld); - - /* Ack interrupt */ - *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i1, clr); - - fast_timer_running = 0; - fast_timer_ints++; - - t = fast_timer_list; - while (t) - { - struct fasttime_t tv; - fast_timer_function_type *f; - unsigned long d; - - /* Has it really expired? */ - do_gettimeofday_fast(&tv); - D1(printk(KERN_DEBUG "t: %is %06ius\n", - tv.tv_jiff, tv.tv_usec)); - - if (fasttime_cmp(&t->tv_expires, &tv) <= 0) - { - /* Yes it has expired */ -#ifdef FAST_TIMER_LOG - timer_expired_log[fast_timers_expired % NUM_TIMER_STATS] = *t; -#endif - fast_timers_expired++; - - /* Remove this timer before call, since it may reuse the timer */ - if (t->prev) - { - t->prev->next = t->next; - } - else - { - fast_timer_list = t->next; - } - if (t->next) - { - t->next->prev = t->prev; - } - t->prev = NULL; - t->next = NULL; - - /* Save function callback data before enabling - * interrupts, since the timer may be removed and - * we don't know how it was allocated - * (e.g. ->function and ->data may become overwritten - * after deletion if the timer was stack-allocated). - */ - f = t->function; - d = t->data; - - if (f != NULL) { - /* Run callback with interrupts enabled. */ - local_irq_restore(flags); - f(d); - local_irq_save(flags); - } else - DEBUG_LOG("!timer1 %i function==NULL!\n", fast_timer_ints); - } - else - { - /* Timer is to early, let's set it again using the normal routines */ - D1(printk(".\n")); - } - - if ((t = fast_timer_list) != NULL) - { - /* Start next timer.. */ - long us = 0; - struct fasttime_t tv; - - do_gettimeofday_fast(&tv); - - /* time_after_eq takes care of wrapping */ - if (time_after_eq(t->tv_expires.tv_jiff, tv.tv_jiff)) - us = ((t->tv_expires.tv_jiff - tv.tv_jiff) * - 1000000 / HZ + t->tv_expires.tv_usec - - tv.tv_usec); - - if (us > 0) - { - if (!fast_timer_running) - { -#ifdef FAST_TIMER_LOG - timer_started_log[fast_timers_started % NUM_TIMER_STATS] = *t; -#endif - start_timer1(us); - } - break; - } - else - { - /* Timer already expired, let's handle it better late than never. - * The normal loop handles it - */ - D1(printk("e! %d\n", us)); - } - } - } - - local_irq_restore(flags); - - if (!t) - { - D1(printk("t1 stop!\n")); - } - - return IRQ_HANDLED; -} - -static void wake_up_func(unsigned long data) -{ - wait_queue_head_t *sleep_wait_p = (wait_queue_head_t *)data; - wake_up(sleep_wait_p); -} - - -/* Useful API */ - -void schedule_usleep(unsigned long us) -{ - struct fast_timer t; - wait_queue_head_t sleep_wait; - init_waitqueue_head(&sleep_wait); - - D1(printk("schedule_usleep(%d)\n", us)); - start_one_shot_timer(&t, wake_up_func, (unsigned long)&sleep_wait, us, - "usleep"); - /* Uninterruptible sleep on the fast timer. (The condition is somewhat - * redundant since the timer is what wakes us up.) */ - wait_event(sleep_wait, !fast_timer_pending(&t)); - - D1(printk("done schedule_usleep(%d)\n", us)); -} - -#ifdef CONFIG_PROC_FS -/* This value is very much based on testing */ -#define BIG_BUF_SIZE (500 + NUM_TIMER_STATS * 300) - -static int proc_fasttimer_show(struct seq_file *m, void *v) -{ - unsigned long flags; - int i = 0; - int num_to_show; - struct fasttime_t tv; - struct fast_timer *t, *nextt; - - do_gettimeofday_fast(&tv); - - seq_printf(m, "Fast timers added: %i\n", fast_timers_added); - seq_printf(m, "Fast timers started: %i\n", fast_timers_started); - seq_printf(m, "Fast timer interrupts: %i\n", fast_timer_ints); - seq_printf(m, "Fast timers expired: %i\n", fast_timers_expired); - seq_printf(m, "Fast timers deleted: %i\n", fast_timers_deleted); - seq_printf(m, "Fast timer running: %s\n", - fast_timer_running ? "yes" : "no"); - seq_printf(m, "Current time: %lu.%06lu\n", - (unsigned long)tv.tv_jiff, - (unsigned long)tv.tv_usec); -#ifdef FAST_TIMER_SANITY_CHECKS - seq_printf(m, "Sanity failed: %i\n", sanity_failed); -#endif - seq_putc(m, '\n'); - -#ifdef DEBUG_LOG_INCLUDED - { - int end_i = debug_log_cnt; - i = 0; - - if (debug_log_cnt_wrapped) - i = debug_log_cnt; - - while (i != end_i || debug_log_cnt_wrapped) { - seq_printf(m, debug_log_string[i], debug_log_value[i]); - if (seq_has_overflowed(m)) - return 0; - i = (i+1) % DEBUG_LOG_MAX; - } - } - seq_putc(m, '\n'); -#endif - - num_to_show = (fast_timers_started < NUM_TIMER_STATS ? fast_timers_started: - NUM_TIMER_STATS); - seq_printf(m, "Timers started: %i\n", fast_timers_started); - for (i = 0; i < num_to_show; i++) { - int cur = (fast_timers_started - i - 1) % NUM_TIMER_STATS; - -#if 1 //ndef FAST_TIMER_LOG - seq_printf(m, "div: %i freq: %i delay: %i\n", - timer_div_settings[cur], - timer_freq_settings[cur], - timer_delay_settings[cur]); -#endif -#ifdef FAST_TIMER_LOG - t = &timer_started_log[cur]; - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; -#endif - } - seq_putc(m, '\n'); - -#ifdef FAST_TIMER_LOG - num_to_show = (fast_timers_added < NUM_TIMER_STATS ? fast_timers_added: - NUM_TIMER_STATS); - seq_printf(m, "Timers added: %i\n", fast_timers_added); - for (i = 0; i < num_to_show; i++) { - t = &timer_added_log[(fast_timers_added - i - 1) % NUM_TIMER_STATS]; - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; - } - seq_putc(m, '\n'); - - num_to_show = (fast_timers_expired < NUM_TIMER_STATS ? fast_timers_expired: - NUM_TIMER_STATS); - seq_printf(m, "Timers expired: %i\n", fast_timers_expired); - for (i = 0; i < num_to_show; i++) { - t = &timer_expired_log[(fast_timers_expired - i - 1) % NUM_TIMER_STATS]; - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; - } - seq_putc(m, '\n'); -#endif - - seq_puts(m, "Active timers:\n"); - local_irq_save(flags); - t = fast_timer_list; - while (t) { - nextt = t->next; - local_irq_restore(flags); - seq_printf(m, "%-14s s: %6lu.%06lu e: %6lu.%06lu d: %6li us data: 0x%08lX\n", - t->name, - (unsigned long)t->tv_set.tv_jiff, - (unsigned long)t->tv_set.tv_usec, - (unsigned long)t->tv_expires.tv_jiff, - (unsigned long)t->tv_expires.tv_usec, - t->delay_us, - t->data); - if (seq_has_overflowed(m)) - return 0; - local_irq_save(flags); - if (t->next != nextt) - printk(KERN_WARNING "timer removed!\n"); - t = nextt; - } - local_irq_restore(flags); - - return 0; -} - -static int proc_fasttimer_open(struct inode *inode, struct file *file) -{ - return single_open_size(file, proc_fasttimer_show, PDE_DATA(inode), BIG_BUF_SIZE); -} - -static const struct file_operations proc_fasttimer_fops = { - .open = proc_fasttimer_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif /* PROC_FS */ - -#ifdef FAST_TIMER_TEST -static volatile unsigned long i = 0; -static volatile int num_test_timeout = 0; -static struct fast_timer tr[10]; -static int exp_num[10]; - -static struct fasttime_t tv_exp[100]; - -static void test_timeout(unsigned long data) -{ - do_gettimeofday_fast(&tv_exp[data]); - exp_num[data] = num_test_timeout; - - num_test_timeout++; -} - -static void test_timeout1(unsigned long data) -{ - do_gettimeofday_fast(&tv_exp[data]); - exp_num[data] = num_test_timeout; - if (data < 7) - { - start_one_shot_timer(&tr[i], test_timeout1, i, 1000, "timeout1"); - i++; - } - num_test_timeout++; -} - -DP( -static char buf0[2000]; -static char buf1[2000]; -static char buf2[2000]; -static char buf3[2000]; -static char buf4[2000]; -); - -static char buf5[6000]; -static int j_u[1000]; - -static void fast_timer_test(void) -{ - int prev_num; - int j; - - struct fasttime_t tv, tv0, tv1, tv2; - - printk("fast_timer_test() start\n"); - do_gettimeofday_fast(&tv); - - for (j = 0; j < 1000; j++) - { - j_u[j] = GET_JIFFIES_USEC(); - } - for (j = 0; j < 100; j++) - { - do_gettimeofday_fast(&tv_exp[j]); - } - printk(KERN_DEBUG "fast_timer_test() %is %06i\n", - tv.tv_jiff, tv.tv_usec); - - for (j = 0; j < 1000; j++) - { - printk("%i %i %i %i %i\n",j_u[j], j_u[j+1], j_u[j+2], j_u[j+3], j_u[j+4]); - j += 4; - } - for (j = 0; j < 100; j++) - { - printk(KERN_DEBUG "%i.%i %i.%i %i.%i %i.%i %i.%i\n", - tv_exp[j].tv_jiff, tv_exp[j].tv_usec, - tv_exp[j+1].tv_jiff, tv_exp[j+1].tv_usec, - tv_exp[j+2].tv_jiff, tv_exp[j+2].tv_usec, - tv_exp[j+3].tv_jiff, tv_exp[j+3].tv_usec, - tv_exp[j+4].tv_jiff, tv_exp[j+4].tv_usec); - j += 4; - } - do_gettimeofday_fast(&tv0); - start_one_shot_timer(&tr[i], test_timeout, i, 50000, "test0"); - DP(proc_fasttimer_read(buf0, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout, i, 70000, "test1"); - DP(proc_fasttimer_read(buf1, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout, i, 40000, "test2"); - DP(proc_fasttimer_read(buf2, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout, i, 60000, "test3"); - DP(proc_fasttimer_read(buf3, NULL, 0, 0, 0)); - i++; - start_one_shot_timer(&tr[i], test_timeout1, i, 55000, "test4xx"); - DP(proc_fasttimer_read(buf4, NULL, 0, 0, 0)); - i++; - do_gettimeofday_fast(&tv1); - - proc_fasttimer_read(buf5, NULL, 0, 0, 0); - - prev_num = num_test_timeout; - while (num_test_timeout < i) - { - if (num_test_timeout != prev_num) - { - prev_num = num_test_timeout; - } - } - do_gettimeofday_fast(&tv2); - printk(KERN_DEBUG "Timers started %is %06i\n", - tv0.tv_jiff, tv0.tv_usec); - printk(KERN_DEBUG "Timers started at %is %06i\n", - tv1.tv_jiff, tv1.tv_usec); - printk(KERN_DEBUG "Timers done %is %06i\n", - tv2.tv_jiff, tv2.tv_usec); - DP(printk("buf0:\n"); - printk(buf0); - printk("buf1:\n"); - printk(buf1); - printk("buf2:\n"); - printk(buf2); - printk("buf3:\n"); - printk(buf3); - printk("buf4:\n"); - printk(buf4); - ); - printk("buf5:\n"); - printk(buf5); - - printk("timers set:\n"); - for(j = 0; j<i; j++) - { - struct fast_timer *t = &tr[j]; - printk("%-10s set: %6is %06ius exp: %6is %06ius " - "data: 0x%08X func: 0x%08X\n", - t->name, - t->tv_set.tv_jiff, - t->tv_set.tv_usec, - t->tv_expires.tv_jiff, - t->tv_expires.tv_usec, - t->data, - t->function - ); - - printk(" del: %6ius did exp: %6is %06ius as #%i error: %6li\n", - t->delay_us, - tv_exp[j].tv_jiff, - tv_exp[j].tv_usec, - exp_num[j], - (tv_exp[j].tv_jiff - t->tv_expires.tv_jiff) * - 1000000 + tv_exp[j].tv_usec - - t->tv_expires.tv_usec); - } - proc_fasttimer_read(buf5, NULL, 0, 0, 0); - printk("buf5 after all done:\n"); - printk(buf5); - printk("fast_timer_test() done\n"); -} -#endif - - -int fast_timer_init(void) -{ - /* For some reason, request_irq() hangs when called froom time_init() */ - if (!fast_timer_is_init) - { -#if 0 && defined(FAST_TIMER_TEST) - int i; -#endif - - printk(KERN_INFO "fast_timer_init()\n"); - -#if 0 && defined(FAST_TIMER_TEST) - for (i = 0; i <= TIMER0_DIV; i++) - { - /* We must be careful not to get overflow... */ - printk("%3i %6u\n", i, timer0_value_us[i]); - } -#endif -#ifdef CONFIG_PROC_FS - proc_create("fasttimer", 0, NULL, &proc_fasttimer_fops); -#endif /* PROC_FS */ - if(request_irq(TIMER1_IRQ_NBR, timer1_handler, 0, - "fast timer int", NULL)) - { - printk("err: timer1 irq\n"); - } - fast_timer_is_init = 1; -#ifdef FAST_TIMER_TEST - printk("do test\n"); - fast_timer_test(); -#endif - } - return 0; -} -__initcall(fast_timer_init); diff --git a/arch/cris/arch-v10/kernel/head.S b/arch/cris/arch-v10/kernel/head.S deleted file mode 100644 index b260a8833903..000000000000 --- a/arch/cris/arch-v10/kernel/head.S +++ /dev/null @@ -1,620 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Head of the kernel - alter with care - * - * Copyright (C) 2000, 2001, 2010 Axis Communications AB - * - */ - -#include <linux/init.h> - -#define ASSEMBLER_MACROS_ONLY -/* The IO_* macros use the ## token concatenation operator, so - -traditional must not be used when assembling this file. */ -#include <arch/sv_addr_ag.h> - -#define CRAMFS_MAGIC 0x28cd3d45 -#define RAM_INIT_MAGIC 0x56902387 -#define COMMAND_LINE_MAGIC 0x87109563 - -#define START_ETHERNET_CLOCK IO_STATE(R_NETWORK_GEN_CONFIG, enable, on) |\ - IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) - - ;; exported symbols - - .globl etrax_irv - .globl romfs_start - .globl romfs_length - .globl romfs_in_flash - .globl swapper_pg_dir - - __HEAD - - ;; This is the entry point of the kernel. We are in supervisor mode. - ;; 0x00000000 if Flash, 0x40004000 if DRAM - ;; since etrax actually starts at address 2 when booting from flash, we - ;; put a nop (2 bytes) here first so we dont accidentally skip the di - ;; - ;; NOTICE! The registers r8 and r9 are used as parameters carrying - ;; information from the decompressor (if the kernel was compressed). - ;; They should not be used in the code below until read. - - nop - di - - ;; First setup the kseg_c mapping from where the kernel is linked - ;; to 0x40000000 (where the actual DRAM resides) otherwise - ;; we cannot do very much! See arch/cris/README.mm - ;; - ;; Notice that since we're potentially running at 0x00 or 0x40 right now, - ;; we will get a fault as soon as we enable the MMU if we dont - ;; temporarily map those segments linearily. - ;; - ;; Due to a bug in Etrax-100 LX version 1 we need to map the memory - ;; slightly different. The bug is that you can't remap bit 31 of - ;; an address. Though we can check the version register for - ;; whether the bug is present, some constants would then have to - ;; be variables, so we don't. The drawback is that you can "only" map - ;; 1G per process with CONFIG_CRIS_LOW_MAP. - -#ifdef CONFIG_CRIS_LOW_MAP - ; kseg mappings, temporary map of 0xc0->0x40 - move.d IO_FIELD (R_MMU_KBASE_HI, base_c, 4) \ - | IO_FIELD (R_MMU_KBASE_HI, base_b, 0xb) \ - | IO_FIELD (R_MMU_KBASE_HI, base_9, 9) \ - | IO_FIELD (R_MMU_KBASE_HI, base_8, 8), $r0 - move.d $r0, [R_MMU_KBASE_HI] - - ; temporary map of 0x40->0x40 and 0x60->0x40 - move.d IO_FIELD (R_MMU_KBASE_LO, base_6, 4) \ - | IO_FIELD (R_MMU_KBASE_LO, base_4, 4), $r0 - move.d $r0, [R_MMU_KBASE_LO] - - ; mmu enable, segs e,c,b,a,6,5,4,0 segment mapped - move.d IO_STATE (R_MMU_CONFIG, mmu_enable, enable) \ - | IO_STATE (R_MMU_CONFIG, inv_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, acc_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, we_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, seg_f, page) \ - | IO_STATE (R_MMU_CONFIG, seg_e, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_d, page) \ - | IO_STATE (R_MMU_CONFIG, seg_c, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_b, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_a, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_9, page) \ - | IO_STATE (R_MMU_CONFIG, seg_8, page) \ - | IO_STATE (R_MMU_CONFIG, seg_7, page) \ - | IO_STATE (R_MMU_CONFIG, seg_6, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_5, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_4, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_3, page) \ - | IO_STATE (R_MMU_CONFIG, seg_2, page) \ - | IO_STATE (R_MMU_CONFIG, seg_1, page) \ - | IO_STATE (R_MMU_CONFIG, seg_0, seg), $r0 - move.d $r0, [R_MMU_CONFIG] -#else - ; kseg mappings - move.d IO_FIELD (R_MMU_KBASE_HI, base_e, 8) \ - | IO_FIELD (R_MMU_KBASE_HI, base_c, 4) \ - | IO_FIELD (R_MMU_KBASE_HI, base_b, 0xb), $r0 - move.d $r0, [R_MMU_KBASE_HI] - - ; temporary map of 0x40->0x40 and 0x00->0x00 - move.d IO_FIELD (R_MMU_KBASE_LO, base_4, 4), $r0 - move.d $r0, [R_MMU_KBASE_LO] - - ; mmu enable, segs f,e,c,b,4,0 segment mapped - move.d IO_STATE (R_MMU_CONFIG, mmu_enable, enable) \ - | IO_STATE (R_MMU_CONFIG, inv_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, acc_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, we_excp, enable) \ - | IO_STATE (R_MMU_CONFIG, seg_f, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_e, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_d, page) \ - | IO_STATE (R_MMU_CONFIG, seg_c, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_b, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_a, page) \ - | IO_STATE (R_MMU_CONFIG, seg_9, page) \ - | IO_STATE (R_MMU_CONFIG, seg_8, page) \ - | IO_STATE (R_MMU_CONFIG, seg_7, page) \ - | IO_STATE (R_MMU_CONFIG, seg_6, page) \ - | IO_STATE (R_MMU_CONFIG, seg_5, page) \ - | IO_STATE (R_MMU_CONFIG, seg_4, seg) \ - | IO_STATE (R_MMU_CONFIG, seg_3, page) \ - | IO_STATE (R_MMU_CONFIG, seg_2, page) \ - | IO_STATE (R_MMU_CONFIG, seg_1, page) \ - | IO_STATE (R_MMU_CONFIG, seg_0, seg), $r0 - move.d $r0, [R_MMU_CONFIG] -#endif - - ;; Now we need to sort out the segments and their locations in RAM or - ;; Flash. The image in the Flash (or in DRAM) consists of 3 pieces: - ;; 1) kernel text, 2) kernel data, 3) ROM filesystem image - ;; But the linker has linked the kernel to expect this layout in - ;; DRAM memory: - ;; 1) kernel text, 2) kernel data, 3) kernel BSS - ;; (the location of the ROM filesystem is determined by the krom driver) - ;; If we boot this from Flash, we want to keep the ROM filesystem in - ;; the flash, we want to copy the text and need to copy the data to DRAM. - ;; But if we boot from DRAM, we need to move the ROMFS image - ;; from its position after kernel data, to after kernel BSS, BEFORE the - ;; kernel starts using the BSS area (since its "overlayed" with the ROMFS) - ;; - ;; In both cases, we start in un-cached mode, and need to jump into a - ;; cached PC after we're done fiddling around with the segments. - ;; - ;; arch/etrax100/etrax100.ld sets some symbols that define the start - ;; and end of each segment. - - ;; Check if we start from DRAM or FLASH by testing PC - - move.d $pc,$r0 - and.d 0x7fffffff,$r0 ; get rid of the non-cache bit - cmp.d 0x10000,$r0 ; arbitrary... just something above this code - blo _inflash0 - nop - - jump _inram ; enter cached ram - - ;; Jumpgate for branches. -_inflash0: - jump _inflash - - ;; Put this in a suitable section where we can reclaim storage - ;; after init. - __INIT -_inflash: -#ifdef CONFIG_ETRAX_ETHERNET - ;; Start MII clock to make sure it is running when tranceiver is reset - move.d START_ETHERNET_CLOCK, $r0 - move.d $r0, [R_NETWORK_GEN_CONFIG] -#endif - - ;; Set up waitstates etc according to kernel configuration. - move.d CONFIG_ETRAX_DEF_R_WAITSTATES, $r0 - move.d $r0, [R_WAITSTATES] - - move.d CONFIG_ETRAX_DEF_R_BUS_CONFIG, $r0 - move.d $r0, [R_BUS_CONFIG] - - ;; We need to initialze DRAM registers before we start using the DRAM - - cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized? - beq _dram_init_finished - nop - -#include "../lib/dram_init.S" - -_dram_init_finished: - ;; Copy text+data to DRAM - ;; This is fragile - the calculation of r4 as the image size depends - ;; on that the labels below actually are the first and last positions - ;; in the linker-script. - ;; - ;; Then the locating of the cramfs image depends on the aforementioned - ;; image being located in the flash at 0. This is most often not true, - ;; thus the following does not work (normally there is a rescue-block - ;; between the physical start of the flash and the flash-image start, - ;; and when run with compression, the kernel is actually unpacked to - ;; DRAM and we never get here in the first place :)) - - moveq 0, $r0 ; source - move.d text_start, $r1 ; destination - move.d __vmlinux_end, $r2 ; end destination - move.d $r2, $r4 - sub.d $r1, $r4 ; r4=__vmlinux_end in flash, used below -1: move.w [$r0+], $r3 - move.w $r3, [$r1+] - cmp.d $r2, $r1 - blo 1b - nop - - ;; We keep the cramfs in the flash. - ;; There might be none, but that does not matter because - ;; we don't do anything than read some bytes here. - - moveq 0, $r0 - move.d $r0, [romfs_length] ; default if there is no cramfs - - move.d [$r4], $r0 ; cramfs_super.magic - cmp.d CRAMFS_MAGIC, $r0 - bne 1f - nop - move.d [$r4 + 4], $r0 ; cramfs_super.size - move.d $r0, [romfs_length] -#ifdef CONFIG_CRIS_LOW_MAP - add.d 0x50000000, $r4 ; add flash start in virtual memory (cached) -#else - add.d 0xf0000000, $r4 ; add flash start in virtual memory (cached) -#endif - move.d $r4, [romfs_start] -1: - moveq 1, $r0 - move.d $r0, [romfs_in_flash] - - jump _start_it ; enter code, cached this time - -_inram: - ;; Move the ROM fs to after BSS end. This assumes that the cramfs - ;; second longword contains the length of the cramfs - - moveq 0, $r0 - move.d $r0, [romfs_length] ; default if there is no cramfs - - ;; The kernel could have been unpacked to DRAM by the loader, but - ;; the cramfs image could still be in the Flash directly after the - ;; compressed kernel image. The loader passes the address of the - ;; byte succeeding the last compressed byte in the flash in the - ;; register r9 when starting the kernel. Check if r9 points to a - ;; decent cramfs image! - ;; (Notice that if this is not booted from the loader, r9 will be - ;; garbage but we do sanity checks on it, the chance that it points - ;; to a cramfs magic is small.. ) - - cmp.d 0x0ffffff8, $r9 - bhs _no_romfs_in_flash ; r9 points outside the flash area - nop - move.d [$r9], $r0 ; cramfs_super.magic - cmp.d CRAMFS_MAGIC, $r0 - bne _no_romfs_in_flash - nop - move.d [$r9+4], $r0 ; cramfs_super.length - move.d $r0, [romfs_length] -#ifdef CONFIG_CRIS_LOW_MAP - add.d 0x50000000, $r9 ; add flash start in virtual memory (cached) -#else - add.d 0xf0000000, $r9 ; add flash start in virtual memory (cached) -#endif - move.d $r9, [romfs_start] - - moveq 1, $r0 - move.d $r0, [romfs_in_flash] - - jump _start_it ; enter code, cached this time - -_no_romfs_in_flash: - - ;; Check if there is a cramfs (magic value). - ;; Notice that we check for cramfs magic value - which is - ;; the "rom fs" we'll possibly use in 2.4 if not JFFS (which does - ;; not need this mechanism anyway) - - move.d __init_end, $r0; the image will be after the end of init - move.d [$r0], $r1 ; cramfs assumes same endian on host/target - cmp.d CRAMFS_MAGIC, $r1; magic value in cramfs superblock - bne 2f - nop - - ;; Ok. What is its size ? - - move.d [$r0 + 4], $r2 ; cramfs_super.size (again, no need to swapwb) - - ;; We want to copy it to the end of the BSS - - move.d _end, $r1 - - ;; Remember values so cramfs and setup can find this info - - move.d $r1, [romfs_start] ; new romfs location - move.d $r2, [romfs_length] - - ;; We need to copy it backwards, since they can be overlapping - - add.d $r2, $r0 - add.d $r2, $r1 - - ;; Go ahead. Make my loop. - - lsrq 1, $r2 ; size is in bytes, we copy words - -1: move.w [$r0=$r0-2],$r3 - move.w $r3,[$r1=$r1-2] - subq 1, $r2 - bne 1b - nop - -2: - ;; Dont worry that the BSS is tainted. It will be cleared later. - - moveq 0, $r0 - move.d $r0, [romfs_in_flash] - - jump _start_it ; better skip the additional cramfs check below - -_start_it: - - ;; Check if kernel command line is supplied - cmp.d COMMAND_LINE_MAGIC, $r10 - bne no_command_line - nop - - move.d 256, $r13 - move.d cris_command_line, $r10 - or.d 0x80000000, $r11 ; Make it virtual -1: - move.b [$r11+], $r12 - move.b $r12, [$r10+] - subq 1, $r13 - bne 1b - nop - -no_command_line: - - ;; the kernel stack is overlayed with the task structure for each - ;; task. thus the initial kernel stack is in the same page as the - ;; init_task (but starts in the top of the page, size 8192) - move.d init_thread_union + 8192, $sp - move.d ibr_start,$r0 ; this symbol is set by the linker script - move $r0,$ibr - move.d $r0,[etrax_irv] ; set the interrupt base register and pointer - - ;; Clear BSS region, from _bss_start to _end - - move.d __bss_start, $r0 - move.d _end, $r1 -1: clear.d [$r0+] - cmp.d $r1, $r0 - blo 1b - nop - - ;; Etrax product HW genconfig setup - - moveq 0,$r0 - - ;; Select or disable serial port 2 -#ifdef CONFIG_ETRAX_SERIAL_PORT2 - or.d IO_STATE (R_GEN_CONFIG, ser2, select),$r0 -#else - or.d IO_STATE (R_GEN_CONFIG, ser2, disable),$r0 -#endif - - ;; Init interfaces (disable them). - or.d IO_STATE (R_GEN_CONFIG, scsi0, disable) \ - | IO_STATE (R_GEN_CONFIG, ata, disable) \ - | IO_STATE (R_GEN_CONFIG, par0, disable) \ - | IO_STATE (R_GEN_CONFIG, mio, disable) \ - | IO_STATE (R_GEN_CONFIG, scsi1, disable) \ - | IO_STATE (R_GEN_CONFIG, scsi0w, disable) \ - | IO_STATE (R_GEN_CONFIG, par1, disable) \ - | IO_STATE (R_GEN_CONFIG, ser3, disable) \ - | IO_STATE (R_GEN_CONFIG, mio_w, disable) \ - | IO_STATE (R_GEN_CONFIG, usb1, disable) \ - | IO_STATE (R_GEN_CONFIG, usb2, disable) \ - | IO_STATE (R_GEN_CONFIG, par_w, disable),$r0 - - ;; Init DMA channel muxing (set to unused clients). - or.d IO_STATE (R_GEN_CONFIG, dma2, ata) \ - | IO_STATE (R_GEN_CONFIG, dma3, ata) \ - | IO_STATE (R_GEN_CONFIG, dma4, scsi1) \ - | IO_STATE (R_GEN_CONFIG, dma5, scsi1) \ - | IO_STATE (R_GEN_CONFIG, dma6, unused) \ - | IO_STATE (R_GEN_CONFIG, dma7, unused) \ - | IO_STATE (R_GEN_CONFIG, dma8, usb) \ - | IO_STATE (R_GEN_CONFIG, dma9, usb),$r0 - - - move.d $r0,[genconfig_shadow] ; init a shadow register of R_GEN_CONFIG - - move.d $r0,[R_GEN_CONFIG] - -#if 0 - moveq 4,$r0 - move.b $r0,[R_DMA_CH6_CMD] ; reset (ser0 dma out) - move.b $r0,[R_DMA_CH7_CMD] ; reset (ser0 dma in) -1: move.b [R_DMA_CH6_CMD],$r0 ; wait for reset cycle to finish - and.b 7,$r0 - cmp.b 4,$r0 - beq 1b - nop -1: move.b [R_DMA_CH7_CMD],$r0 ; wait for reset cycle to finish - and.b 7,$r0 - cmp.b 4,$r0 - beq 1b - nop -#endif - - moveq IO_STATE (R_DMA_CH8_CMD, cmd, reset),$r0 - move.b $r0,[R_DMA_CH8_CMD] ; reset (ser1 dma out) - move.b $r0,[R_DMA_CH9_CMD] ; reset (ser1 dma in) -1: move.b [R_DMA_CH8_CMD],$r0 ; wait for reset cycle to finish - andq IO_MASK (R_DMA_CH8_CMD, cmd),$r0 - cmpq IO_STATE (R_DMA_CH8_CMD, cmd, reset),$r0 - beq 1b - nop -1: move.b [R_DMA_CH9_CMD],$r0 ; wait for reset cycle to finish - andq IO_MASK (R_DMA_CH9_CMD, cmd),$r0 - cmpq IO_STATE (R_DMA_CH9_CMD, cmd, reset),$r0 - beq 1b - nop - - ;; setup port PA and PB default initial directions and data - ;; including their shadow registers - - move.b CONFIG_ETRAX_DEF_R_PORT_PA_DIR,$r0 - move.b $r0,[port_pa_dir_shadow] - move.b $r0,[R_PORT_PA_DIR] - move.b CONFIG_ETRAX_DEF_R_PORT_PA_DATA,$r0 - move.b $r0,[port_pa_data_shadow] - move.b $r0,[R_PORT_PA_DATA] - - move.b CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG,$r0 - move.b $r0,[port_pb_config_shadow] - move.b $r0,[R_PORT_PB_CONFIG] - move.b CONFIG_ETRAX_DEF_R_PORT_PB_DIR,$r0 - move.b $r0,[port_pb_dir_shadow] - move.b $r0,[R_PORT_PB_DIR] - move.b CONFIG_ETRAX_DEF_R_PORT_PB_DATA,$r0 - move.b $r0,[port_pb_data_shadow] - move.b $r0,[R_PORT_PB_DATA] - - moveq 0, $r0 - move.d $r0,[port_pb_i2c_shadow] - move.d $r0, [R_PORT_PB_I2C] - - moveq 0,$r0 - move.d $r0,[port_g_data_shadow] - move.d $r0,[R_PORT_G_DATA] - - ;; setup the serial port 0 at 115200 baud for debug purposes - - moveq IO_STATE (R_SERIAL0_XOFF, tx_stop, enable) \ - | IO_STATE (R_SERIAL0_XOFF, auto_xoff, disable) \ - | IO_FIELD (R_SERIAL0_XOFF, xoff_char, 0),$r0 - move.d $r0,[R_SERIAL0_XOFF] - - ; 115.2kbaud for both transmit and receive - move.b IO_STATE (R_SERIAL0_BAUD, tr_baud, c115k2Hz) \ - | IO_STATE (R_SERIAL0_BAUD, rec_baud, c115k2Hz),$r0 - move.b $r0,[R_SERIAL0_BAUD] - - ; Set up and enable the serial0 receiver. - move.b IO_STATE (R_SERIAL0_REC_CTRL, dma_err, stop) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rec_enable, enable) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rts_, active) \ - | IO_STATE (R_SERIAL0_REC_CTRL, sampling, middle) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rec_stick_par, normal) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rec_par, even) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rec_par_en, disable) \ - | IO_STATE (R_SERIAL0_REC_CTRL, rec_bitnr, rec_8bit),$r0 - move.b $r0,[R_SERIAL0_REC_CTRL] - - ; Set up and enable the serial0 transmitter. - move.b IO_FIELD (R_SERIAL0_TR_CTRL, txd, 0) \ - | IO_STATE (R_SERIAL0_TR_CTRL, tr_enable, enable) \ - | IO_STATE (R_SERIAL0_TR_CTRL, auto_cts, disabled) \ - | IO_STATE (R_SERIAL0_TR_CTRL, stop_bits, one_bit) \ - | IO_STATE (R_SERIAL0_TR_CTRL, tr_stick_par, normal) \ - | IO_STATE (R_SERIAL0_TR_CTRL, tr_par, even) \ - | IO_STATE (R_SERIAL0_TR_CTRL, tr_par_en, disable) \ - | IO_STATE (R_SERIAL0_TR_CTRL, tr_bitnr, tr_8bit),$r0 - move.b $r0,[R_SERIAL0_TR_CTRL] - - ;; setup the serial port 1 at 115200 baud for debug purposes - - moveq IO_STATE (R_SERIAL1_XOFF, tx_stop, enable) \ - | IO_STATE (R_SERIAL1_XOFF, auto_xoff, disable) \ - | IO_FIELD (R_SERIAL1_XOFF, xoff_char, 0),$r0 - move.d $r0,[R_SERIAL1_XOFF] - - ; 115.2kbaud for both transmit and receive - move.b IO_STATE (R_SERIAL1_BAUD, tr_baud, c115k2Hz) \ - | IO_STATE (R_SERIAL1_BAUD, rec_baud, c115k2Hz),$r0 - move.b $r0,[R_SERIAL1_BAUD] - - ; Set up and enable the serial1 receiver. - move.b IO_STATE (R_SERIAL1_REC_CTRL, dma_err, stop) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rec_enable, enable) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rts_, active) \ - | IO_STATE (R_SERIAL1_REC_CTRL, sampling, middle) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rec_stick_par, normal) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rec_par, even) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rec_par_en, disable) \ - | IO_STATE (R_SERIAL1_REC_CTRL, rec_bitnr, rec_8bit),$r0 - move.b $r0,[R_SERIAL1_REC_CTRL] - - ; Set up and enable the serial1 transmitter. - move.b IO_FIELD (R_SERIAL1_TR_CTRL, txd, 0) \ - | IO_STATE (R_SERIAL1_TR_CTRL, tr_enable, enable) \ - | IO_STATE (R_SERIAL1_TR_CTRL, auto_cts, disabled) \ - | IO_STATE (R_SERIAL1_TR_CTRL, stop_bits, one_bit) \ - | IO_STATE (R_SERIAL1_TR_CTRL, tr_stick_par, normal) \ - | IO_STATE (R_SERIAL1_TR_CTRL, tr_par, even) \ - | IO_STATE (R_SERIAL1_TR_CTRL, tr_par_en, disable) \ - | IO_STATE (R_SERIAL1_TR_CTRL, tr_bitnr, tr_8bit),$r0 - move.b $r0,[R_SERIAL1_TR_CTRL] - -#ifdef CONFIG_ETRAX_SERIAL_PORT2 - ;; setup the serial port 2 at 115200 baud for debug purposes - - moveq IO_STATE (R_SERIAL2_XOFF, tx_stop, enable) \ - | IO_STATE (R_SERIAL2_XOFF, auto_xoff, disable) \ - | IO_FIELD (R_SERIAL2_XOFF, xoff_char, 0),$r0 - move.d $r0,[R_SERIAL2_XOFF] - - ; 115.2kbaud for both transmit and receive - move.b IO_STATE (R_SERIAL2_BAUD, tr_baud, c115k2Hz) \ - | IO_STATE (R_SERIAL2_BAUD, rec_baud, c115k2Hz),$r0 - move.b $r0,[R_SERIAL2_BAUD] - - ; Set up and enable the serial2 receiver. - move.b IO_STATE (R_SERIAL2_REC_CTRL, dma_err, stop) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rec_enable, enable) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rts_, active) \ - | IO_STATE (R_SERIAL2_REC_CTRL, sampling, middle) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rec_stick_par, normal) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rec_par, even) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rec_par_en, disable) \ - | IO_STATE (R_SERIAL2_REC_CTRL, rec_bitnr, rec_8bit),$r0 - move.b $r0,[R_SERIAL2_REC_CTRL] - - ; Set up and enable the serial2 transmitter. - move.b IO_FIELD (R_SERIAL2_TR_CTRL, txd, 0) \ - | IO_STATE (R_SERIAL2_TR_CTRL, tr_enable, enable) \ - | IO_STATE (R_SERIAL2_TR_CTRL, auto_cts, disabled) \ - | IO_STATE (R_SERIAL2_TR_CTRL, stop_bits, one_bit) \ - | IO_STATE (R_SERIAL2_TR_CTRL, tr_stick_par, normal) \ - | IO_STATE (R_SERIAL2_TR_CTRL, tr_par, even) \ - | IO_STATE (R_SERIAL2_TR_CTRL, tr_par_en, disable) \ - | IO_STATE (R_SERIAL2_TR_CTRL, tr_bitnr, tr_8bit),$r0 - move.b $r0,[R_SERIAL2_TR_CTRL] -#endif - -#ifdef CONFIG_ETRAX_SERIAL_PORT3 - ;; setup the serial port 3 at 115200 baud for debug purposes - - moveq IO_STATE (R_SERIAL3_XOFF, tx_stop, enable) \ - | IO_STATE (R_SERIAL3_XOFF, auto_xoff, disable) \ - | IO_FIELD (R_SERIAL3_XOFF, xoff_char, 0),$r0 - move.d $r0,[R_SERIAL3_XOFF] - - ; 115.2kbaud for both transmit and receive - move.b IO_STATE (R_SERIAL3_BAUD, tr_baud, c115k2Hz) \ - | IO_STATE (R_SERIAL3_BAUD, rec_baud, c115k2Hz),$r0 - move.b $r0,[R_SERIAL3_BAUD] - - ; Set up and enable the serial3 receiver. - move.b IO_STATE (R_SERIAL3_REC_CTRL, dma_err, stop) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rec_enable, enable) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rts_, active) \ - | IO_STATE (R_SERIAL3_REC_CTRL, sampling, middle) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rec_stick_par, normal) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rec_par, even) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rec_par_en, disable) \ - | IO_STATE (R_SERIAL3_REC_CTRL, rec_bitnr, rec_8bit),$r0 - move.b $r0,[R_SERIAL3_REC_CTRL] - - ; Set up and enable the serial3 transmitter. - move.b IO_FIELD (R_SERIAL3_TR_CTRL, txd, 0) \ - | IO_STATE (R_SERIAL3_TR_CTRL, tr_enable, enable) \ - | IO_STATE (R_SERIAL3_TR_CTRL, auto_cts, disabled) \ - | IO_STATE (R_SERIAL3_TR_CTRL, stop_bits, one_bit) \ - | IO_STATE (R_SERIAL3_TR_CTRL, tr_stick_par, normal) \ - | IO_STATE (R_SERIAL3_TR_CTRL, tr_par, even) \ - | IO_STATE (R_SERIAL3_TR_CTRL, tr_par_en, disable) \ - | IO_STATE (R_SERIAL3_TR_CTRL, tr_bitnr, tr_8bit),$r0 - move.b $r0,[R_SERIAL3_TR_CTRL] -#endif - - jump start_kernel ; jump into the C-function start_kernel in init/main.c - - .data -etrax_irv: - .dword 0 -romfs_start: - .dword 0 -romfs_length: - .dword 0 -romfs_in_flash: - .dword 0 - - ;; put some special pages at the beginning of the kernel aligned - ;; to page boundaries - the kernel cannot start until after this - -#ifdef CONFIG_CRIS_LOW_MAP -swapper_pg_dir = 0x60002000 -#else -swapper_pg_dir = 0xc0002000 -#endif - - .section ".init.data", "aw" -#include "../lib/hw_settings.S" diff --git a/arch/cris/arch-v10/kernel/io_interface_mux.c b/arch/cris/arch-v10/kernel/io_interface_mux.c deleted file mode 100644 index 13a887ce115a..000000000000 --- a/arch/cris/arch-v10/kernel/io_interface_mux.c +++ /dev/null @@ -1,1183 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* IO interface mux allocator for ETRAX100LX. - * Copyright 2004-2007, Axis Communications AB - */ - - -/* C.f. ETRAX100LX Designer's Reference chapter 19.9 */ - -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/init.h> - -#include <arch/svinto.h> -#include <asm/io.h> -#include <arch/io_interface_mux.h> -#include <arch/system.h> - - -#define DBG(s) - -/* Macro to access ETRAX 100 registers */ -#define SETS(var, reg, field, val) var = (var & ~IO_MASK_(reg##_, field##_)) | \ - IO_STATE_(reg##_, field##_, _##val) - -enum io_if_group { - group_a = (1<<0), - group_b = (1<<1), - group_c = (1<<2), - group_d = (1<<3), - group_e = (1<<4), - group_f = (1<<5) -}; - -struct watcher -{ - void (*notify)(const unsigned int gpio_in_available, - const unsigned int gpio_out_available, - const unsigned char pa_available, - const unsigned char pb_available); - struct watcher *next; -}; - - -struct if_group -{ - enum io_if_group group; - /* name - the name of the group 'A' to 'F' */ - char *name; - /* used - a bit mask of all pins in the group in the order listed - * in the tables in 19.9.1 to 19.9.6. Note that no - * distinction is made between in, out and in/out pins. */ - unsigned int used; -}; - - -struct interface -{ - enum cris_io_interface ioif; - /* name - the name of the interface */ - char *name; - /* groups - OR'ed together io_if_group flags describing what pin groups - * the interface uses pins in. */ - unsigned char groups; - /* used - set when the interface is allocated. */ - unsigned char used; - char *owner; - /* group_a through group_f - bit masks describing what pins in the - * pin groups the interface uses. */ - unsigned int group_a; - unsigned int group_b; - unsigned int group_c; - unsigned int group_d; - unsigned int group_e; - unsigned int group_f; - - /* gpio_g_in, gpio_g_out, gpio_b - bit masks telling what pins in the - * GPIO ports the interface uses. This could be reconstucted using - * the group_X masks and a table of what pins the GPIO ports use, - * but that would be messy. */ - unsigned int gpio_g_in; - unsigned int gpio_g_out; - unsigned char gpio_b; -}; - -static struct if_group if_groups[6] = { - { - .group = group_a, - .name = "A", - .used = 0, - }, - { - .group = group_b, - .name = "B", - .used = 0, - }, - { - .group = group_c, - .name = "C", - .used = 0, - }, - { - .group = group_d, - .name = "D", - .used = 0, - }, - { - .group = group_e, - .name = "E", - .used = 0, - }, - { - .group = group_f, - .name = "F", - .used = 0, - } -}; - -/* The order in the array must match the order of enum - * cris_io_interface in io_interface_mux.h */ -static struct interface interfaces[] = { - /* Begin Non-multiplexed interfaces */ - { - .ioif = if_eth, - .name = "ethernet", - .groups = 0, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0, - .gpio_g_out = 0, - .gpio_b = 0 - }, - { - .ioif = if_serial_0, - .name = "serial_0", - .groups = 0, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0, - .gpio_g_out = 0, - .gpio_b = 0 - }, - /* End Non-multiplexed interfaces */ - { - .ioif = if_serial_1, - .name = "serial_1", - .groups = group_e, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0x0f, - .group_f = 0, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0x00 - }, - { - .ioif = if_serial_2, - .name = "serial_2", - .groups = group_b, - - .group_a = 0, - .group_b = 0x0f, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x000000c0, - .gpio_g_out = 0x000000c0, - .gpio_b = 0x00 - }, - { - .ioif = if_serial_3, - .name = "serial_3", - .groups = group_c, - - .group_a = 0, - .group_b = 0, - .group_c = 0x0f, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0xc0000000, - .gpio_g_out = 0xc0000000, - .gpio_b = 0x00 - }, - { - .ioif = if_sync_serial_1, - .name = "sync_serial_1", - .groups = group_e | group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0x0f, - .group_f = 0x10, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0x10 - }, - { - .ioif = if_sync_serial_3, - .name = "sync_serial_3", - .groups = group_c | group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0x0f, - .group_d = 0, - .group_e = 0, - .group_f = 0x80, - - .gpio_g_in = 0xc0000000, - .gpio_g_out = 0xc0000000, - .gpio_b = 0x80 - }, - { - .ioif = if_shared_ram, - .name = "shared_ram", - .groups = group_a, - - .group_a = 0x7f8ff, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x0000ff3e, - .gpio_g_out = 0x0000ff38, - .gpio_b = 0x00 - }, - { - .ioif = if_shared_ram_w, - .name = "shared_ram_w", - .groups = group_a | group_d, - - .group_a = 0x7f8ff, - .group_b = 0, - .group_c = 0, - .group_d = 0xff, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x00ffff3e, - .gpio_g_out = 0x00ffff38, - .gpio_b = 0x00 - }, - { - .ioif = if_par_0, - .name = "par_0", - .groups = group_a, - - .group_a = 0x7fbff, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x0000ff3e, - .gpio_g_out = 0x0000ff3e, - .gpio_b = 0x00 - }, - { - .ioif = if_par_1, - .name = "par_1", - .groups = group_d, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0x7feff, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x3eff0000, - .gpio_g_out = 0x3eff0000, - .gpio_b = 0x00 - }, - { - .ioif = if_par_w, - .name = "par_w", - .groups = group_a | group_d, - - .group_a = 0x7fbff, - .group_b = 0, - .group_c = 0, - .group_d = 0xff, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x00ffff3e, - .gpio_g_out = 0x00ffff3e, - .gpio_b = 0x00 - }, - { - .ioif = if_scsi8_0, - .name = "scsi8_0", - .groups = group_a | group_b | group_f, - - .group_a = 0x7ffff, - .group_b = 0x0f, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0x10, - - .gpio_g_in = 0x0000ffff, - .gpio_g_out = 0x0000ffff, - .gpio_b = 0x10 - }, - { - .ioif = if_scsi8_1, - .name = "scsi8_1", - .groups = group_c | group_d | group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0x0f, - .group_d = 0x7ffff, - .group_e = 0, - .group_f = 0x80, - - .gpio_g_in = 0xffff0000, - .gpio_g_out = 0xffff0000, - .gpio_b = 0x80 - }, - { - .ioif = if_scsi_w, - .name = "scsi_w", - .groups = group_a | group_b | group_d | group_f, - - .group_a = 0x7ffff, - .group_b = 0x0f, - .group_c = 0, - .group_d = 0x601ff, - .group_e = 0, - .group_f = 0x90, - - .gpio_g_in = 0x01ffffff, - .gpio_g_out = 0x07ffffff, - .gpio_b = 0x80 - }, - { - .ioif = if_ata, - .name = "ata", - .groups = group_a | group_b | group_c | group_d, - - .group_a = 0x7ffff, - .group_b = 0x0f, - .group_c = 0x0f, - .group_d = 0x7cfff, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0xf9ffffff, - .gpio_g_out = 0xffffffff, - .gpio_b = 0x80 - }, - { - .ioif = if_csp, - .name = "csp", - .groups = group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0xfc, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0xfc - }, - { - .ioif = if_i2c, - .name = "i2c", - .groups = group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0x03, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0x03 - }, - { - .ioif = if_usb_1, - .name = "usb_1", - .groups = group_e | group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0x0f, - .group_f = 0x2c, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0x2c - }, - { - .ioif = if_usb_2, - .name = "usb_2", - .groups = group_d, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0x33e00, - .group_f = 0, - - .gpio_g_in = 0x3e000000, - .gpio_g_out = 0x0c000000, - .gpio_b = 0x00 - }, - /* GPIO pins */ - { - .ioif = if_gpio_grp_a, - .name = "gpio_a", - .groups = group_a, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x0000ff3f, - .gpio_g_out = 0x0000ff3f, - .gpio_b = 0x00 - }, - { - .ioif = if_gpio_grp_b, - .name = "gpio_b", - .groups = group_b, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x000000c0, - .gpio_g_out = 0x000000c0, - .gpio_b = 0x00 - }, - { - .ioif = if_gpio_grp_c, - .name = "gpio_c", - .groups = group_c, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0xc0000000, - .gpio_g_out = 0xc0000000, - .gpio_b = 0x00 - }, - { - .ioif = if_gpio_grp_d, - .name = "gpio_d", - .groups = group_d, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x3fff0000, - .gpio_g_out = 0x3fff0000, - .gpio_b = 0x00 - }, - { - .ioif = if_gpio_grp_e, - .name = "gpio_e", - .groups = group_e, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0x00 - }, - { - .ioif = if_gpio_grp_f, - .name = "gpio_f", - .groups = group_f, - - .group_a = 0, - .group_b = 0, - .group_c = 0, - .group_d = 0, - .group_e = 0, - .group_f = 0, - - .gpio_g_in = 0x00000000, - .gpio_g_out = 0x00000000, - .gpio_b = 0xff - } - /* Array end */ -}; - -static struct watcher *watchers = NULL; - -/* The pins that are free to use in the GPIO ports. */ -static unsigned int gpio_in_pins = 0xffffffff; -static unsigned int gpio_out_pins = 0xffffffff; -static unsigned char gpio_pb_pins = 0xff; -static unsigned char gpio_pa_pins = 0xff; - -/* Identifiers for the owners of the GPIO pins. */ -static enum cris_io_interface gpio_pa_owners[8]; -static enum cris_io_interface gpio_pb_owners[8]; -static enum cris_io_interface gpio_pg_owners[32]; - -static int cris_io_interface_init(void); - -static unsigned char clear_group_from_set(const unsigned char groups, struct if_group *group) -{ - return (groups & ~group->group); -} - - -static struct if_group *get_group(const unsigned char groups) -{ - int i; - for (i = 0; i < ARRAY_SIZE(if_groups); i++) { - if (groups & if_groups[i].group) { - return &if_groups[i]; - } - } - return NULL; -} - - -static void notify_watchers(void) -{ - struct watcher *w = watchers; - - DBG(printk("io_interface_mux: notifying watchers\n")); - - while (NULL != w) { - w->notify((const unsigned int)gpio_in_pins, - (const unsigned int)gpio_out_pins, - (const unsigned char)gpio_pa_pins, - (const unsigned char)gpio_pb_pins); - w = w->next; - } -} - - -int cris_request_io_interface(enum cris_io_interface ioif, const char *device_id) -{ - int set_gen_config = 0; - int set_gen_config_ii = 0; - unsigned long int gens; - unsigned long int gens_ii; - struct if_group *grp; - unsigned char group_set; - unsigned long flags; - int res = 0; - - (void)cris_io_interface_init(); - - DBG(printk("cris_request_io_interface(%d, \"%s\")\n", ioif, device_id)); - - if ((ioif >= if_max_interfaces) || (ioif < 0)) { - printk(KERN_CRIT "cris_request_io_interface: Bad interface " - "%u submitted for %s\n", - ioif, - device_id); - return -EINVAL; - } - - local_irq_save(flags); - - if (interfaces[ioif].used) { - printk(KERN_CRIT "cris_io_interface: Cannot allocate interface " - "%s for %s, in use by %s\n", - interfaces[ioif].name, - device_id, - interfaces[ioif].owner); - res = -EBUSY; - goto exit; - } - - /* Check that all required pins in the used groups are free - * before allocating. */ - group_set = interfaces[ioif].groups; - while (NULL != (grp = get_group(group_set))) { - unsigned int if_group_use = 0; - - switch (grp->group) { - case group_a: - if_group_use = interfaces[ioif].group_a; - break; - case group_b: - if_group_use = interfaces[ioif].group_b; - break; - case group_c: - if_group_use = interfaces[ioif].group_c; - break; - case group_d: - if_group_use = interfaces[ioif].group_d; - break; - case group_e: - if_group_use = interfaces[ioif].group_e; - break; - case group_f: - if_group_use = interfaces[ioif].group_f; - break; - default: - BUG_ON(1); - } - - if (if_group_use & grp->used) { - printk(KERN_INFO "cris_request_io_interface: group " - "%s needed by %s not available\n", - grp->name, interfaces[ioif].name); - res = -EBUSY; - goto exit; - } - - group_set = clear_group_from_set(group_set, grp); - } - - /* Are the required GPIO pins available too? */ - if (((interfaces[ioif].gpio_g_in & gpio_in_pins) != - interfaces[ioif].gpio_g_in) || - ((interfaces[ioif].gpio_g_out & gpio_out_pins) != - interfaces[ioif].gpio_g_out) || - ((interfaces[ioif].gpio_b & gpio_pb_pins) != - interfaces[ioif].gpio_b)) { - printk(KERN_CRIT "cris_request_io_interface: Could not get " - "required pins for interface %u\n", ioif); - res = -EBUSY; - goto exit; - } - - /* Check which registers need to be reconfigured. */ - gens = genconfig_shadow; - gens_ii = gen_config_ii_shadow; - - set_gen_config = 1; - switch (ioif) - { - /* Begin Non-multiplexed interfaces */ - case if_eth: - /* fall through */ - case if_serial_0: - set_gen_config = 0; - break; - /* End Non-multiplexed interfaces */ - case if_serial_1: - set_gen_config_ii = 1; - SETS(gens_ii, R_GEN_CONFIG_II, sermode1, async); - break; - case if_serial_2: - SETS(gens, R_GEN_CONFIG, ser2, select); - break; - case if_serial_3: - SETS(gens, R_GEN_CONFIG, ser3, select); - set_gen_config_ii = 1; - SETS(gens_ii, R_GEN_CONFIG_II, sermode3, async); - break; - case if_sync_serial_1: - set_gen_config_ii = 1; - SETS(gens_ii, R_GEN_CONFIG_II, sermode1, sync); - break; - case if_sync_serial_3: - SETS(gens, R_GEN_CONFIG, ser3, select); - set_gen_config_ii = 1; - SETS(gens_ii, R_GEN_CONFIG_II, sermode3, sync); - break; - case if_shared_ram: - SETS(gens, R_GEN_CONFIG, mio, select); - break; - case if_shared_ram_w: - SETS(gens, R_GEN_CONFIG, mio_w, select); - break; - case if_par_0: - SETS(gens, R_GEN_CONFIG, par0, select); - break; - case if_par_1: - SETS(gens, R_GEN_CONFIG, par1, select); - break; - case if_par_w: - SETS(gens, R_GEN_CONFIG, par0, select); - SETS(gens, R_GEN_CONFIG, par_w, select); - break; - case if_scsi8_0: - SETS(gens, R_GEN_CONFIG, scsi0, select); - break; - case if_scsi8_1: - SETS(gens, R_GEN_CONFIG, scsi1, select); - break; - case if_scsi_w: - SETS(gens, R_GEN_CONFIG, scsi0, select); - SETS(gens, R_GEN_CONFIG, scsi0w, select); - break; - case if_ata: - SETS(gens, R_GEN_CONFIG, ata, select); - break; - case if_csp: - /* fall through */ - case if_i2c: - set_gen_config = 0; - break; - case if_usb_1: - SETS(gens, R_GEN_CONFIG, usb1, select); - break; - case if_usb_2: - SETS(gens, R_GEN_CONFIG, usb2, select); - break; - case if_gpio_grp_a: - /* GPIO groups are only accounted, don't do configuration changes. */ - /* fall through */ - case if_gpio_grp_b: - /* fall through */ - case if_gpio_grp_c: - /* fall through */ - case if_gpio_grp_d: - /* fall through */ - case if_gpio_grp_e: - /* fall through */ - case if_gpio_grp_f: - set_gen_config = 0; - break; - default: - printk(KERN_INFO "cris_request_io_interface: Bad interface " - "%u submitted for %s\n", - ioif, device_id); - res = -EBUSY; - goto exit; - } - - /* All needed I/O pins and pin groups are free, allocate. */ - group_set = interfaces[ioif].groups; - while (NULL != (grp = get_group(group_set))) { - unsigned int if_group_use = 0; - - switch (grp->group) { - case group_a: - if_group_use = interfaces[ioif].group_a; - break; - case group_b: - if_group_use = interfaces[ioif].group_b; - break; - case group_c: - if_group_use = interfaces[ioif].group_c; - break; - case group_d: - if_group_use = interfaces[ioif].group_d; - break; - case group_e: - if_group_use = interfaces[ioif].group_e; - break; - case group_f: - if_group_use = interfaces[ioif].group_f; - break; - default: - BUG_ON(1); - } - grp->used |= if_group_use; - - group_set = clear_group_from_set(group_set, grp); - } - - interfaces[ioif].used = 1; - interfaces[ioif].owner = (char*)device_id; - - if (set_gen_config) { - volatile int i; - genconfig_shadow = gens; - *R_GEN_CONFIG = genconfig_shadow; - /* Wait 12 cycles before doing any DMA command */ - for(i = 6; i > 0; i--) - nop(); - } - if (set_gen_config_ii) { - gen_config_ii_shadow = gens_ii; - *R_GEN_CONFIG_II = gen_config_ii_shadow; - } - - DBG(printk(KERN_DEBUG "GPIO pins: available before: " - "g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - gpio_in_pins, gpio_out_pins, gpio_pb_pins)); - DBG(printk(KERN_DEBUG - "grabbing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - interfaces[ioif].gpio_g_in, - interfaces[ioif].gpio_g_out, - interfaces[ioif].gpio_b)); - - gpio_in_pins &= ~interfaces[ioif].gpio_g_in; - gpio_out_pins &= ~interfaces[ioif].gpio_g_out; - gpio_pb_pins &= ~interfaces[ioif].gpio_b; - - DBG(printk(KERN_DEBUG "GPIO pins: available after: " - "g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - gpio_in_pins, gpio_out_pins, gpio_pb_pins)); - -exit: - local_irq_restore(flags); - if (res == 0) - notify_watchers(); - return res; -} - - -void cris_free_io_interface(enum cris_io_interface ioif) -{ - struct if_group *grp; - unsigned char group_set; - unsigned long flags; - - (void)cris_io_interface_init(); - - if ((ioif >= if_max_interfaces) || (ioif < 0)) { - printk(KERN_CRIT "cris_free_io_interface: Bad interface %u\n", - ioif); - return; - } - local_irq_save(flags); - if (!interfaces[ioif].used) { - printk(KERN_CRIT "cris_free_io_interface: Freeing free interface %u\n", - ioif); - local_irq_restore(flags); - return; - } - group_set = interfaces[ioif].groups; - while (NULL != (grp = get_group(group_set))) { - unsigned int if_group_use = 0; - - switch (grp->group) { - case group_a: - if_group_use = interfaces[ioif].group_a; - break; - case group_b: - if_group_use = interfaces[ioif].group_b; - break; - case group_c: - if_group_use = interfaces[ioif].group_c; - break; - case group_d: - if_group_use = interfaces[ioif].group_d; - break; - case group_e: - if_group_use = interfaces[ioif].group_e; - break; - case group_f: - if_group_use = interfaces[ioif].group_f; - break; - default: - BUG_ON(1); - } - - if ((grp->used & if_group_use) != if_group_use) - BUG_ON(1); - grp->used = grp->used & ~if_group_use; - - group_set = clear_group_from_set(group_set, grp); - } - interfaces[ioif].used = 0; - interfaces[ioif].owner = NULL; - - DBG(printk("GPIO pins: available before: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - gpio_in_pins, gpio_out_pins, gpio_pb_pins)); - DBG(printk("freeing pins: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - interfaces[ioif].gpio_g_in, - interfaces[ioif].gpio_g_out, - interfaces[ioif].gpio_b)); - - gpio_in_pins |= interfaces[ioif].gpio_g_in; - gpio_out_pins |= interfaces[ioif].gpio_g_out; - gpio_pb_pins |= interfaces[ioif].gpio_b; - - DBG(printk("GPIO pins: available after: g_in=0x%08x g_out=0x%08x pb=0x%02x\n", - gpio_in_pins, gpio_out_pins, gpio_pb_pins)); - - local_irq_restore(flags); - - notify_watchers(); -} - -/* Create a bitmask from bit 0 (inclusive) to bit stop_bit - (non-inclusive). stop_bit == 0 returns 0x0 */ -static inline unsigned int create_mask(const unsigned stop_bit) -{ - /* Avoid overflow */ - if (stop_bit >= 32) { - return 0xffffffff; - } - return (1<<stop_bit)-1; -} - - -/* port can be 'a', 'b' or 'g' */ -int cris_io_interface_allocate_pins(const enum cris_io_interface ioif, - const char port, - const unsigned start_bit, - const unsigned stop_bit) -{ - unsigned int i; - unsigned int mask = 0; - unsigned int tmp_mask; - unsigned long int flags; - enum cris_io_interface *owners; - - (void)cris_io_interface_init(); - - DBG(printk("cris_io_interface_allocate_pins: if=%d port=%c start=%u stop=%u\n", - ioif, port, start_bit, stop_bit)); - - if (!((start_bit <= stop_bit) && - ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) || - ((port == 'g') && (stop_bit < 32))))) { - return -EINVAL; - } - - mask = create_mask(stop_bit + 1); - tmp_mask = create_mask(start_bit); - mask &= ~tmp_mask; - - DBG(printk("cris_io_interface_allocate_pins: port=%c start=%u stop=%u mask=0x%08x\n", - port, start_bit, stop_bit, mask)); - - local_irq_save(flags); - - switch (port) { - case 'a': - if ((gpio_pa_pins & mask) != mask) { - local_irq_restore(flags); - return -EBUSY; - } - owners = gpio_pa_owners; - gpio_pa_pins &= ~mask; - break; - case 'b': - if ((gpio_pb_pins & mask) != mask) { - local_irq_restore(flags); - return -EBUSY; - } - owners = gpio_pb_owners; - gpio_pb_pins &= ~mask; - break; - case 'g': - if (((gpio_in_pins & mask) != mask) || - ((gpio_out_pins & mask) != mask)) { - local_irq_restore(flags); - return -EBUSY; - } - owners = gpio_pg_owners; - gpio_in_pins &= ~mask; - gpio_out_pins &= ~mask; - break; - default: - local_irq_restore(flags); - return -EINVAL; - } - - for (i = start_bit; i <= stop_bit; i++) { - owners[i] = ioif; - } - local_irq_restore(flags); - - notify_watchers(); - return 0; -} - - -/* port can be 'a', 'b' or 'g' */ -int cris_io_interface_free_pins(const enum cris_io_interface ioif, - const char port, - const unsigned start_bit, - const unsigned stop_bit) -{ - unsigned int i; - unsigned int mask = 0; - unsigned int tmp_mask; - unsigned long int flags; - enum cris_io_interface *owners; - - (void)cris_io_interface_init(); - - if (!((start_bit <= stop_bit) && - ((((port == 'a') || (port == 'b')) && (stop_bit < 8)) || - ((port == 'g') && (stop_bit < 32))))) { - return -EINVAL; - } - - mask = create_mask(stop_bit + 1); - tmp_mask = create_mask(start_bit); - mask &= ~tmp_mask; - - DBG(printk("cris_io_interface_free_pins: port=%c start=%u stop=%u mask=0x%08x\n", - port, start_bit, stop_bit, mask)); - - local_irq_save(flags); - - switch (port) { - case 'a': - if ((~gpio_pa_pins & mask) != mask) { - local_irq_restore(flags); - printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins"); - } - owners = gpio_pa_owners; - break; - case 'b': - if ((~gpio_pb_pins & mask) != mask) { - local_irq_restore(flags); - printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins"); - } - owners = gpio_pb_owners; - break; - case 'g': - if (((~gpio_in_pins & mask) != mask) || - ((~gpio_out_pins & mask) != mask)) { - local_irq_restore(flags); - printk(KERN_CRIT "cris_io_interface_free_pins: Freeing free pins"); - } - owners = gpio_pg_owners; - break; - default: - owners = NULL; /* Cannot happen. Shut up, gcc! */ - } - - for (i = start_bit; i <= stop_bit; i++) { - if (owners[i] != ioif) { - printk(KERN_CRIT "cris_io_interface_free_pins: Freeing unowned pins"); - } - } - - /* All was ok, change data. */ - switch (port) { - case 'a': - gpio_pa_pins |= mask; - break; - case 'b': - gpio_pb_pins |= mask; - break; - case 'g': - gpio_in_pins |= mask; - gpio_out_pins |= mask; - break; - } - - for (i = start_bit; i <= stop_bit; i++) { - owners[i] = if_unclaimed; - } - local_irq_restore(flags); - notify_watchers(); - - return 0; -} - - -int cris_io_interface_register_watcher(void (*notify)(const unsigned int gpio_in_available, - const unsigned int gpio_out_available, - const unsigned char pa_available, - const unsigned char pb_available)) -{ - struct watcher *w; - - (void)cris_io_interface_init(); - - if (NULL == notify) { - return -EINVAL; - } - w = kmalloc(sizeof(*w), GFP_KERNEL); - if (!w) { - return -ENOMEM; - } - w->notify = notify; - w->next = watchers; - watchers = w; - - w->notify((const unsigned int)gpio_in_pins, - (const unsigned int)gpio_out_pins, - (const unsigned char)gpio_pa_pins, - (const unsigned char)gpio_pb_pins); - - return 0; -} - -void cris_io_interface_delete_watcher(void (*notify)(const unsigned int gpio_in_available, - const unsigned int gpio_out_available, - const unsigned char pa_available, - const unsigned char pb_available)) -{ - struct watcher *w = watchers, *prev = NULL; - - (void)cris_io_interface_init(); - - while ((NULL != w) && (w->notify != notify)){ - prev = w; - w = w->next; - } - if (NULL != w) { - if (NULL != prev) { - prev->next = w->next; - } else { - watchers = w->next; - } - kfree(w); - return; - } - printk(KERN_WARNING "cris_io_interface_delete_watcher: Deleting unknown watcher 0x%p\n", notify); -} - - -static int cris_io_interface_init(void) -{ - static int first = 1; - int i; - - if (!first) { - return 0; - } - first = 0; - - for (i = 0; i<8; i++) { - gpio_pa_owners[i] = if_unclaimed; - gpio_pb_owners[i] = if_unclaimed; - gpio_pg_owners[i] = if_unclaimed; - } - for (; i<32; i++) { - gpio_pg_owners[i] = if_unclaimed; - } - return 0; -} - - -module_init(cris_io_interface_init); - - -EXPORT_SYMBOL(cris_request_io_interface); -EXPORT_SYMBOL(cris_free_io_interface); -EXPORT_SYMBOL(cris_io_interface_allocate_pins); -EXPORT_SYMBOL(cris_io_interface_free_pins); -EXPORT_SYMBOL(cris_io_interface_register_watcher); -EXPORT_SYMBOL(cris_io_interface_delete_watcher); diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c deleted file mode 100644 index df11e383acdd..000000000000 --- a/arch/cris/arch-v10/kernel/irq.c +++ /dev/null @@ -1,236 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/kernel/irq.c - * - * Copyright (c) 2000-2002 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - * - * This file contains the interrupt vectors and some - * helper functions - * - */ - -#include <asm/irq.h> -#include <asm/current.h> -#include <linux/irq.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/init.h> - -#define crisv10_mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr)); -#define crisv10_unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr)); - -extern void kgdb_init(void); -extern void breakpoint(void); - -/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is - * global just so that the kernel gdb can use it. - */ - -void -set_int_vector(int n, irqvectptr addr) -{ - etrax_irv->v[n + 0x20] = (irqvectptr)addr; -} - -/* the breakpoint vector is obviously not made just like the normal irq handlers - * but needs to contain _code_ to jump to addr. - * - * the BREAK n instruction jumps to IBR + n * 8 - */ - -void -set_break_vector(int n, irqvectptr addr) -{ - unsigned short *jinstr = (unsigned short *)&etrax_irv->v[n*2]; - unsigned long *jaddr = (unsigned long *)(jinstr + 1); - - /* if you don't know what this does, do not touch it! */ - - *jinstr = 0x0d3f; - *jaddr = (unsigned long)addr; - - /* 00000026 <clrlop+1a> 3f0d82000000 jump 0x82 */ -} - -/* - * This builds up the IRQ handler stubs using some ugly macros in irq.h - * - * These macros create the low-level assembly IRQ routines that do all - * the operations that are needed. They are also written to be fast - and to - * disable interrupts as little as humanly possible. - * - */ - -/* IRQ0 and 1 are special traps */ -void hwbreakpoint(void); -void IRQ1_interrupt(void); -BUILD_TIMER_IRQ(2, 0x04) /* the timer interrupt is somewhat special */ -BUILD_IRQ(3, 0x08) -BUILD_IRQ(4, 0x10) -BUILD_IRQ(5, 0x20) -BUILD_IRQ(6, 0x40) -BUILD_IRQ(7, 0x80) -BUILD_IRQ(8, 0x100) -BUILD_IRQ(9, 0x200) -BUILD_IRQ(10, 0x400) -BUILD_IRQ(11, 0x800) -BUILD_IRQ(12, 0x1000) -BUILD_IRQ(13, 0x2000) -void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */ -void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */ -BUILD_IRQ(16, 0x10000 | 0x20000) /* ethernet tx interrupt needs to block rx */ -BUILD_IRQ(17, 0x20000 | 0x10000) /* ...and vice versa */ -BUILD_IRQ(18, 0x40000) -BUILD_IRQ(19, 0x80000) -BUILD_IRQ(20, 0x100000) -BUILD_IRQ(21, 0x200000) -BUILD_IRQ(22, 0x400000) -BUILD_IRQ(23, 0x800000) -BUILD_IRQ(24, 0x1000000) -BUILD_IRQ(25, 0x2000000) -/* IRQ 26-30 are reserved */ -BUILD_IRQ(31, 0x80000000) - -/* - * Pointers to the low-level handlers - */ - -static void (*interrupt[NR_IRQS])(void) = { - NULL, NULL, IRQ2_interrupt, IRQ3_interrupt, - IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt, - IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt, - IRQ12_interrupt, IRQ13_interrupt, NULL, NULL, - IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt, - IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt, - IRQ24_interrupt, IRQ25_interrupt, NULL, NULL, NULL, NULL, NULL, - IRQ31_interrupt -}; - -static void enable_crisv10_irq(struct irq_data *data) -{ - crisv10_unmask_irq(data->irq); -} - -static void disable_crisv10_irq(struct irq_data *data) -{ - crisv10_mask_irq(data->irq); -} - -static struct irq_chip crisv10_irq_type = { - .name = "CRISv10", - .irq_shutdown = disable_crisv10_irq, - .irq_enable = enable_crisv10_irq, - .irq_disable = disable_crisv10_irq, -}; - -void weird_irq(void); -void system_call(void); /* from entry.S */ -void do_sigtrap(void); /* from entry.S */ -void gdb_handle_breakpoint(void); /* from entry.S */ - -extern void do_IRQ(int irq, struct pt_regs * regs); - -/* Handle multiple IRQs */ -void do_multiple_IRQ(struct pt_regs* regs) -{ - int bit; - unsigned masked; - unsigned mask; - unsigned ethmask = 0; - - /* Get interrupts to mask and handle */ - mask = masked = *R_VECT_MASK_RD; - - /* Never mask timer IRQ */ - mask &= ~(IO_MASK(R_VECT_MASK_RD, timer0)); - - /* - * If either ethernet interrupt (rx or tx) is active then block - * the other one too. Unblock afterwards also. - */ - if (mask & - (IO_STATE(R_VECT_MASK_RD, dma0, active) | - IO_STATE(R_VECT_MASK_RD, dma1, active))) { - ethmask = (IO_MASK(R_VECT_MASK_RD, dma0) | - IO_MASK(R_VECT_MASK_RD, dma1)); - } - - /* Block them */ - *R_VECT_MASK_CLR = (mask | ethmask); - - /* An extra irq_enter here to prevent softIRQs to run after - * each do_IRQ. This will decrease the interrupt latency. - */ - irq_enter(); - - /* Handle all IRQs */ - for (bit = 2; bit < 32; bit++) { - if (masked & (1 << bit)) { - do_IRQ(bit, regs); - } - } - - /* This irq_exit() will trigger the soft IRQs. */ - irq_exit(); - - /* Unblock the IRQs again */ - *R_VECT_MASK_SET = (masked | ethmask); -} - -/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and - setting the irq vector table. -*/ - -void __init init_IRQ(void) -{ - int i; - - /* clear all interrupt masks */ - *R_IRQ_MASK0_CLR = 0xffffffff; - *R_IRQ_MASK1_CLR = 0xffffffff; - *R_IRQ_MASK2_CLR = 0xffffffff; - *R_VECT_MASK_CLR = 0xffffffff; - - for (i = 0; i < 256; i++) - etrax_irv->v[i] = weird_irq; - - /* Initialize IRQ handler descriptors. */ - for(i = 2; i < NR_IRQS; i++) { - irq_set_chip_and_handler(i, &crisv10_irq_type, - handle_simple_irq); - set_int_vector(i, interrupt[i]); - } - - /* the entries in the break vector contain actual code to be - executed by the associated break handler, rather than just a jump - address. therefore we need to setup a default breakpoint handler - for all breakpoints */ - for (i = 0; i < 16; i++) - set_break_vector(i, do_sigtrap); - - /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */ - set_int_vector(15, multiple_interrupt); - - /* 0 and 1 which are special breakpoint/NMI traps */ - set_int_vector(0, hwbreakpoint); - set_int_vector(1, IRQ1_interrupt); - - /* and irq 14 which is the mmu bus fault handler */ - set_int_vector(14, mmu_bus_fault); - - /* setup the system-call trap, which is reached by BREAK 13 */ - set_break_vector(13, system_call); - - /* setup a breakpoint handler for debugging used for both user and - kernel mode debugging (which is why it is not inside an ifdef - CONFIG_ETRAX_KGDB) */ - set_break_vector(8, gdb_handle_breakpoint); - -#ifdef CONFIG_ETRAX_KGDB - /* setup kgdb if its enabled, and break into the debugger */ - kgdb_init(); - breakpoint(); -#endif -} diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c deleted file mode 100644 index 79b13564d15c..000000000000 --- a/arch/cris/arch-v10/kernel/kgdb.c +++ /dev/null @@ -1,1128 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/*!************************************************************************** -*! -*! FILE NAME : kgdb.c -*! -*! DESCRIPTION: Implementation of the gdb stub with respect to ETRAX 100. -*! It is a mix of arch/m68k/kernel/kgdb.c and cris_stub.c. -*! -*!--------------------------------------------------------------------------- -*! HISTORY -*! -*! DATE NAME CHANGES -*! ---- ---- ------- -*! Apr 26 1999 Hendrik Ruijter Initial version. -*! May 6 1999 Hendrik Ruijter Removed call to strlen in libc and removed -*! struct assignment as it generates calls to -*! memcpy in libc. -*! Jun 17 1999 Hendrik Ruijter Added gdb 4.18 support. 'X', 'qC' and 'qL'. -*! Jul 21 1999 Bjorn Wesen eLinux port -*! -*!--------------------------------------------------------------------------- -*! -*! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN -*! -*!**************************************************************************/ -/* @(#) cris_stub.c 1.3 06/17/99 */ - -/* - * kgdb usage notes: - * ----------------- - * - * If you select CONFIG_ETRAX_KGDB in the configuration, the kernel will be - * built with different gcc flags: "-g" is added to get debug infos, and - * "-fomit-frame-pointer" is omitted to make debugging easier. Since the - * resulting kernel will be quite big (approx. > 7 MB), it will be stripped - * before compresion. Such a kernel will behave just as usually, except if - * given a "debug=<device>" command line option. (Only serial devices are - * allowed for <device>, i.e. no printers or the like; possible values are - * machine depedend and are the same as for the usual debug device, the one - * for logging kernel messages.) If that option is given and the device can be - * initialized, the kernel will connect to the remote gdb in trap_init(). The - * serial parameters are fixed to 8N1 and 115200 bps, for easyness of - * implementation. - * - * To start a debugging session, start that gdb with the debugging kernel - * image (the one with the symbols, vmlinux.debug) named on the command line. - * This file will be used by gdb to get symbol and debugging infos about the - * kernel. Next, select remote debug mode by - * target remote <device> - * where <device> is the name of the serial device over which the debugged - * machine is connected. Maybe you have to adjust the baud rate by - * set remotebaud <rate> - * or also other parameters with stty: - * shell stty ... </dev/... - * If the kernel to debug has already booted, it waited for gdb and now - * connects, and you'll see a breakpoint being reported. If the kernel isn't - * running yet, start it now. The order of gdb and the kernel doesn't matter. - * Another thing worth knowing about in the getting-started phase is how to - * debug the remote protocol itself. This is activated with - * set remotedebug 1 - * gdb will then print out each packet sent or received. You'll also get some - * messages about the gdb stub on the console of the debugged machine. - * - * If all that works, you can use lots of the usual debugging techniques on - * the kernel, e.g. inspecting and changing variables/memory, setting - * breakpoints, single stepping and so on. It's also possible to interrupt the - * debugged kernel by pressing C-c in gdb. Have fun! :-) - * - * The gdb stub is entered (and thus the remote gdb gets control) in the - * following situations: - * - * - If breakpoint() is called. This is just after kgdb initialization, or if - * a breakpoint() call has been put somewhere into the kernel source. - * (Breakpoints can of course also be set the usual way in gdb.) - * In eLinux, we call breakpoint() in init/main.c after IRQ initialization. - * - * - If there is a kernel exception, i.e. bad_super_trap() or die_if_kernel() - * are entered. All the CPU exceptions are mapped to (more or less..., see - * the hard_trap_info array below) appropriate signal, which are reported - * to gdb. die_if_kernel() is usually called after some kind of access - * error and thus is reported as SIGSEGV. - * - * - When panic() is called. This is reported as SIGABRT. - * - * - If C-c is received over the serial line, which is treated as - * SIGINT. - * - * Of course, all these signals are just faked for gdb, since there is no - * signal concept as such for the kernel. It also isn't possible --obviously-- - * to set signal handlers from inside gdb, or restart the kernel with a - * signal. - * - * Current limitations: - * - * - While the kernel is stopped, interrupts are disabled for safety reasons - * (i.e., variables not changing magically or the like). But this also - * means that the clock isn't running anymore, and that interrupts from the - * hardware may get lost/not be served in time. This can cause some device - * errors... - * - * - When single-stepping, only one instruction of the current thread is - * executed, but interrupts are allowed for that time and will be serviced - * if pending. Be prepared for that. - * - * - All debugging happens in kernel virtual address space. There's no way to - * access physical memory not mapped in kernel space, or to access user - * space. A way to work around this is using get_user_long & Co. in gdb - * expressions, but only for the current process. - * - * - Interrupting the kernel only works if interrupts are currently allowed, - * and the interrupt of the serial line isn't blocked by some other means - * (IPL too high, disabled, ...) - * - * - The gdb stub is currently not reentrant, i.e. errors that happen therein - * (e.g. accessing invalid memory) may not be caught correctly. This could - * be removed in future by introducing a stack of struct registers. - * - */ - -/* - * To enable debugger support, two things need to happen. One, a - * call to kgdb_init() is necessary in order to allow any breakpoints - * or error conditions to be properly intercepted and reported to gdb. - * Two, a breakpoint needs to be generated to begin communication. This - * is most easily accomplished by a call to breakpoint(). - * - * The following gdb commands are supported: - * - * command function Return value - * - * g return the value of the CPU registers hex data or ENN - * G set the value of the CPU registers OK or ENN - * - * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN - * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN - * - * c Resume at current address SNN ( signal NN) - * cAA..AA Continue at address AA..AA SNN - * - * s Step one instruction SNN - * sAA..AA Step one instruction from AA..AA SNN - * - * k kill - * - * ? What was the last sigval ? SNN (signal NN) - * - * bBB..BB Set baud rate to BB..BB OK or BNN, then sets - * baud rate - * - * All commands and responses are sent with a packet which includes a - * checksum. A packet consists of - * - * $<packet info>#<checksum>. - * - * where - * <packet info> :: <characters representing the command or response> - * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> - * - * When a packet is received, it is first acknowledged with either '+' or '-'. - * '+' indicates a successful transfer. '-' indicates a failed transfer. - * - * Example: - * - * Host: Reply: - * $m0,10#2a +$00010203040506070809101112131415#42 - * - */ - - -#include <linux/string.h> -#include <linux/signal.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/linkage.h> -#include <linux/reboot.h> - -#include <asm/setup.h> -#include <asm/ptrace.h> - -#include <arch/svinto.h> -#include <asm/irq.h> - -static int kgdb_started = 0; - -/********************************* Register image ****************************/ -/* Use the order of registers as defined in "AXIS ETRAX CRIS Programmer's - Reference", p. 1-1, with the additional register definitions of the - ETRAX 100LX in cris-opc.h. - There are 16 general 32-bit registers, R0-R15, where R14 is the stack - pointer, SP, and R15 is the program counter, PC. - There are 16 special registers, P0-P15, where three of the unimplemented - registers, P0, P4 and P8, are reserved as zero-registers. A read from - any of these registers returns zero and a write has no effect. */ - -typedef -struct register_image -{ - /* Offset */ - unsigned int r0; /* 0x00 */ - unsigned int r1; /* 0x04 */ - unsigned int r2; /* 0x08 */ - unsigned int r3; /* 0x0C */ - unsigned int r4; /* 0x10 */ - unsigned int r5; /* 0x14 */ - unsigned int r6; /* 0x18 */ - unsigned int r7; /* 0x1C */ - unsigned int r8; /* 0x20 Frame pointer */ - unsigned int r9; /* 0x24 */ - unsigned int r10; /* 0x28 */ - unsigned int r11; /* 0x2C */ - unsigned int r12; /* 0x30 */ - unsigned int r13; /* 0x34 */ - unsigned int sp; /* 0x38 Stack pointer */ - unsigned int pc; /* 0x3C Program counter */ - - unsigned char p0; /* 0x40 8-bit zero-register */ - unsigned char vr; /* 0x41 Version register */ - - unsigned short p4; /* 0x42 16-bit zero-register */ - unsigned short ccr; /* 0x44 Condition code register */ - - unsigned int mof; /* 0x46 Multiply overflow register */ - - unsigned int p8; /* 0x4A 32-bit zero-register */ - unsigned int ibr; /* 0x4E Interrupt base register */ - unsigned int irp; /* 0x52 Interrupt return pointer */ - unsigned int srp; /* 0x56 Subroutine return pointer */ - unsigned int bar; /* 0x5A Breakpoint address register */ - unsigned int dccr; /* 0x5E Double condition code register */ - unsigned int brp; /* 0x62 Breakpoint return pointer (pc in caller) */ - unsigned int usp; /* 0x66 User mode stack pointer */ -} registers; - -/* Serial port, reads one character. ETRAX 100 specific. from debugport.c */ -int getDebugChar (void); - -/* Serial port, writes one character. ETRAX 100 specific. from debugport.c */ -void putDebugChar (int val); - -void enableDebugIRQ (void); - -/******************** Prototypes for global functions. ***********************/ - -/* The string str is prepended with the GDB printout token and sent. */ -void putDebugString (const unsigned char *str, int length); /* used by etrax100ser.c */ - -/* The hook for both static (compiled) and dynamic breakpoints set by GDB. - ETRAX 100 specific. */ -void handle_breakpoint (void); /* used by irq.c */ - -/* The hook for an interrupt generated by GDB. ETRAX 100 specific. */ -void handle_interrupt (void); /* used by irq.c */ - -/* A static breakpoint to be used at startup. */ -void breakpoint (void); /* called by init/main.c */ - -/* From osys_int.c, executing_task contains the number of the current - executing task in osys. Does not know of object-oriented threads. */ -extern unsigned char executing_task; - -/* The number of characters used for a 64 bit thread identifier. */ -#define HEXCHARS_IN_THREAD_ID 16 - -/********************************** Packet I/O ******************************/ -/* BUFMAX defines the maximum number of characters in - inbound/outbound buffers */ -#define BUFMAX 512 - -/* Run-length encoding maximum length. Send 64 at most. */ -#define RUNLENMAX 64 - -/* The inbound/outbound buffers used in packet I/O */ -static char remcomInBuffer[BUFMAX]; -static char remcomOutBuffer[BUFMAX]; - -/* Error and warning messages. */ -enum error_type -{ - SUCCESS, E01, E02, E03, E04, E05, E06, E07, E08 -}; -static char *error_message[] = -{ - "", - "E01 Set current or general thread - H[c,g] - internal error.", - "E02 Change register content - P - cannot change read-only register.", - "E03 Thread is not alive.", /* T, not used. */ - "E04 The command is not supported - [s,C,S,!,R,d,r] - internal error.", - "E05 Change register content - P - the register is not implemented..", - "E06 Change memory content - M - internal error.", - "E07 Change register content - P - the register is not stored on the stack", - "E08 Invalid parameter" -}; -/********************************* Register image ****************************/ -/* Use the order of registers as defined in "AXIS ETRAX CRIS Programmer's - Reference", p. 1-1, with the additional register definitions of the - ETRAX 100LX in cris-opc.h. - There are 16 general 32-bit registers, R0-R15, where R14 is the stack - pointer, SP, and R15 is the program counter, PC. - There are 16 special registers, P0-P15, where three of the unimplemented - registers, P0, P4 and P8, are reserved as zero-registers. A read from - any of these registers returns zero and a write has no effect. */ -enum register_name -{ - R0, R1, R2, R3, - R4, R5, R6, R7, - R8, R9, R10, R11, - R12, R13, SP, PC, - P0, VR, P2, P3, - P4, CCR, P6, MOF, - P8, IBR, IRP, SRP, - BAR, DCCR, BRP, USP -}; - -/* The register sizes of the registers in register_name. An unimplemented register - is designated by size 0 in this array. */ -static int register_size[] = -{ - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - 1, 1, 0, 0, - 2, 2, 0, 4, - 4, 4, 4, 4, - 4, 4, 4, 4 -}; - -/* Contains the register image of the executing thread in the assembler - part of the code in order to avoid horrible addressing modes. */ -registers cris_reg; - -/* FIXME: Should this be used? Delete otherwise. */ -/* Contains the assumed consistency state of the register image. Uses the - enum error_type for state information. */ -static int consistency_status = SUCCESS; - -/********************************** Handle exceptions ************************/ -/* The variable cris_reg contains the register image associated with the - current_thread_c variable. It is a complete register image created at - entry. The reg_g contains a register image of a task where the general - registers are taken from the stack and all special registers are taken - from the executing task. It is associated with current_thread_g and used - in order to provide access mainly for 'g', 'G' and 'P'. -*/ - -/********************************** Breakpoint *******************************/ -/* Use an internal stack in the breakpoint and interrupt response routines */ -#define INTERNAL_STACK_SIZE 1024 -char internal_stack[INTERNAL_STACK_SIZE]; - -/* Due to the breakpoint return pointer, a state variable is needed to keep - track of whether it is a static (compiled) or dynamic (gdb-invoked) - breakpoint to be handled. A static breakpoint uses the content of register - BRP as it is whereas a dynamic breakpoint requires subtraction with 2 - in order to execute the instruction. The first breakpoint is static. */ -static unsigned char __used is_dyn_brkp; - -/********************************* String library ****************************/ -/* Single-step over library functions creates trap loops. */ - -/* Copy char s2[] to s1[]. */ -static char* -gdb_cris_strcpy (char *s1, const char *s2) -{ - char *s = s1; - - for (s = s1; (*s++ = *s2++) != '\0'; ) - ; - return (s1); -} - -/* Find length of s[]. */ -static int -gdb_cris_strlen (const char *s) -{ - const char *sc; - - for (sc = s; *sc != '\0'; sc++) - ; - return (sc - s); -} - -/* Find first occurrence of c in s[n]. */ -static void* -gdb_cris_memchr (const void *s, int c, int n) -{ - const unsigned char uc = c; - const unsigned char *su; - - for (su = s; 0 < n; ++su, --n) - if (*su == uc) - return ((void *)su); - return (NULL); -} -/******************************* Standard library ****************************/ -/* Single-step over library functions creates trap loops. */ -/* Convert string to long. */ -static int -gdb_cris_strtol (const char *s, char **endptr, int base) -{ - char *s1; - char *sd; - int x = 0; - - for (s1 = (char*)s; (sd = gdb_cris_memchr(hex_asc, *s1, base)) != NULL; ++s1) - x = x * base + (sd - hex_asc); - - if (endptr) - { - /* Unconverted suffix is stored in endptr unless endptr is NULL. */ - *endptr = s1; - } - - return x; -} - -/********************************** Packet I/O ******************************/ - -/* Convert the memory, pointed to by mem into hexadecimal representation. - Put the result in buf, and return a pointer to the last character - in buf (null). */ - -static char * -mem2hex(char *buf, unsigned char *mem, int count) -{ - int i; - int ch; - - if (mem == NULL) { - /* Bogus read from m0. FIXME: What constitutes a valid address? */ - for (i = 0; i < count; i++) { - *buf++ = '0'; - *buf++ = '0'; - } - } else { - /* Valid mem address. */ - for (i = 0; i < count; i++) { - ch = *mem++; - buf = hex_byte_pack(buf, ch); - } - } - - /* Terminate properly. */ - *buf = '\0'; - return (buf); -} - -/* Put the content of the array, in binary representation, pointed to by buf - into memory pointed to by mem, and return a pointer to the character after - the last byte written. - Gdb will escape $, #, and the escape char (0x7d). */ -static unsigned char* -bin2mem (unsigned char *mem, unsigned char *buf, int count) -{ - int i; - unsigned char *next; - for (i = 0; i < count; i++) { - /* Check for any escaped characters. Be paranoid and - only unescape chars that should be escaped. */ - if (*buf == 0x7d) { - next = buf + 1; - if (*next == 0x3 || *next == 0x4 || *next == 0x5D) /* #, $, ESC */ - { - buf++; - *buf += 0x20; - } - } - *mem++ = *buf++; - } - return (mem); -} - -/* Await the sequence $<data>#<checksum> and store <data> in the array buffer - returned. */ -static void -getpacket (char *buffer) -{ - unsigned char checksum; - unsigned char xmitcsum; - int i; - int count; - char ch; - do { - while ((ch = getDebugChar ()) != '$') - /* Wait for the start character $ and ignore all other characters */; - checksum = 0; - xmitcsum = -1; - count = 0; - /* Read until a # or the end of the buffer is reached */ - while (count < BUFMAX - 1) { - ch = getDebugChar (); - if (ch == '#') - break; - checksum = checksum + ch; - buffer[count] = ch; - count = count + 1; - } - buffer[count] = '\0'; - - if (ch == '#') { - xmitcsum = hex_to_bin(getDebugChar()) << 4; - xmitcsum += hex_to_bin(getDebugChar()); - if (checksum != xmitcsum) { - /* Wrong checksum */ - putDebugChar ('-'); - } - else { - /* Correct checksum */ - putDebugChar ('+'); - /* If sequence characters are received, reply with them */ - if (buffer[2] == ':') { - putDebugChar (buffer[0]); - putDebugChar (buffer[1]); - /* Remove the sequence characters from the buffer */ - count = gdb_cris_strlen (buffer); - for (i = 3; i <= count; i++) - buffer[i - 3] = buffer[i]; - } - } - } - } while (checksum != xmitcsum); -} - -/* Send $<data>#<checksum> from the <data> in the array buffer. */ - -static void -putpacket(char *buffer) -{ - int checksum; - int runlen; - int encode; - - do { - char *src = buffer; - putDebugChar ('$'); - checksum = 0; - while (*src) { - /* Do run length encoding */ - putDebugChar (*src); - checksum += *src; - runlen = 0; - while (runlen < RUNLENMAX && *src == src[runlen]) { - runlen++; - } - if (runlen > 3) { - /* Got a useful amount */ - putDebugChar ('*'); - checksum += '*'; - encode = runlen + ' ' - 4; - putDebugChar (encode); - checksum += encode; - src += runlen; - } - else { - src++; - } - } - putDebugChar('#'); - putDebugChar(hex_asc_hi(checksum)); - putDebugChar(hex_asc_lo(checksum)); - } while(kgdb_started && (getDebugChar() != '+')); -} - -/* The string str is prepended with the GDB printout token and sent. Required - in traditional implementations. */ -void -putDebugString (const unsigned char *str, int length) -{ - remcomOutBuffer[0] = 'O'; - mem2hex(&remcomOutBuffer[1], (unsigned char *)str, length); - putpacket(remcomOutBuffer); -} - -/********************************* Register image ****************************/ -/* Write a value to a specified register in the register image of the current - thread. Returns status code SUCCESS, E02, E05 or E08. */ -static int -write_register (int regno, char *val) -{ - int status = SUCCESS; - registers *current_reg = &cris_reg; - - if (regno >= R0 && regno <= PC) { - /* 32-bit register with simple offset. */ - if (hex2bin((unsigned char *)current_reg + regno * sizeof(unsigned int), - val, sizeof(unsigned int))) - status = E08; - } - else if (regno == P0 || regno == VR || regno == P4 || regno == P8) { - /* Do not support read-only registers. */ - status = E02; - } - else if (regno == CCR) { - /* 16 bit register with complex offset. (P4 is read-only, P6 is not implemented, - and P7 (MOF) is 32 bits in ETRAX 100LX. */ - if (hex2bin((unsigned char *)&(current_reg->ccr) + (regno-CCR) * sizeof(unsigned short), - val, sizeof(unsigned short))) - status = E08; - } - else if (regno >= MOF && regno <= USP) { - /* 32 bit register with complex offset. (P8 has been taken care of.) */ - if (hex2bin((unsigned char *)&(current_reg->ibr) + (regno-IBR) * sizeof(unsigned int), - val, sizeof(unsigned int))) - status = E08; - } - else { - /* Do not support nonexisting or unimplemented registers (P2, P3, and P6). */ - status = E05; - } - return status; -} - -/* Read a value from a specified register in the register image. Returns the - value in the register or -1 for non-implemented registers. - Should check consistency_status after a call which may be E05 after changes - in the implementation. */ -static int -read_register (char regno, unsigned int *valptr) -{ - registers *current_reg = &cris_reg; - - if (regno >= R0 && regno <= PC) { - /* 32-bit register with simple offset. */ - *valptr = *(unsigned int *)((char *)current_reg + regno * sizeof(unsigned int)); - return SUCCESS; - } - else if (regno == P0 || regno == VR) { - /* 8 bit register with complex offset. */ - *valptr = (unsigned int)(*(unsigned char *) - ((char *)&(current_reg->p0) + (regno-P0) * sizeof(char))); - return SUCCESS; - } - else if (regno == P4 || regno == CCR) { - /* 16 bit register with complex offset. */ - *valptr = (unsigned int)(*(unsigned short *) - ((char *)&(current_reg->p4) + (regno-P4) * sizeof(unsigned short))); - return SUCCESS; - } - else if (regno >= MOF && regno <= USP) { - /* 32 bit register with complex offset. */ - *valptr = *(unsigned int *)((char *)&(current_reg->p8) - + (regno-P8) * sizeof(unsigned int)); - return SUCCESS; - } - else { - /* Do not support nonexisting or unimplemented registers (P2, P3, and P6). */ - consistency_status = E05; - return E05; - } -} - -/********************************** Handle exceptions ************************/ -/* Build and send a response packet in order to inform the host the - stub is stopped. TAAn...:r...;n...:r...;n...:r...; - AA = signal number - n... = register number (hex) - r... = register contents - n... = `thread' - r... = thread process ID. This is a hex integer. - n... = other string not starting with valid hex digit. - gdb should ignore this n,r pair and go on to the next. - This way we can extend the protocol. */ -static void -stub_is_stopped(int sigval) -{ - char *ptr = remcomOutBuffer; - int regno; - - unsigned int reg_cont; - int status; - - /* Send trap type (converted to signal) */ - - *ptr++ = 'T'; - ptr = hex_byte_pack(ptr, sigval); - - /* Send register contents. We probably only need to send the - * PC, frame pointer and stack pointer here. Other registers will be - * explicitly asked for. But for now, send all. - */ - - for (regno = R0; regno <= USP; regno++) { - /* Store n...:r...; for the registers in the buffer. */ - - status = read_register (regno, ®_cont); - - if (status == SUCCESS) { - ptr = hex_byte_pack(ptr, regno); - *ptr++ = ':'; - - ptr = mem2hex(ptr, (unsigned char *)®_cont, - register_size[regno]); - *ptr++ = ';'; - } - - } - - /* null-terminate and send it off */ - - *ptr = 0; - - putpacket (remcomOutBuffer); -} - -/* Performs a complete re-start from scratch. */ -static void -kill_restart (void) -{ - machine_restart(""); -} - -/* All expected commands are sent from remote.c. Send a response according - to the description in remote.c. */ -void -handle_exception (int sigval) -{ - /* Send response. */ - - stub_is_stopped (sigval); - - for (;;) { - remcomOutBuffer[0] = '\0'; - getpacket (remcomInBuffer); - switch (remcomInBuffer[0]) { - case 'g': - /* Read registers: g - Success: Each byte of register data is described by two hex digits. - Registers are in the internal order for GDB, and the bytes - in a register are in the same order the machine uses. - Failure: void. */ - - mem2hex(remcomOutBuffer, (char *)&cris_reg, sizeof(registers)); - break; - - case 'G': - /* Write registers. GXX..XX - Each byte of register data is described by two hex digits. - Success: OK - Failure: E08. */ - if (hex2bin((char *)&cris_reg, &remcomInBuffer[1], sizeof(registers))) - gdb_cris_strcpy (remcomOutBuffer, error_message[E08]); - else - gdb_cris_strcpy (remcomOutBuffer, "OK"); - break; - - case 'P': - /* Write register. Pn...=r... - Write register n..., hex value without 0x, with value r..., - which contains a hex value without 0x and two hex digits - for each byte in the register (target byte order). P1f=11223344 means - set register 31 to 44332211. - Success: OK - Failure: E02, E05, E08 */ - { - char *suffix; - int regno = gdb_cris_strtol (&remcomInBuffer[1], &suffix, 16); - int status; - status = write_register (regno, suffix+1); - - switch (status) { - case E02: - /* Do not support read-only registers. */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E02]); - break; - case E05: - /* Do not support non-existing registers. */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E05]); - break; - case E07: - /* Do not support non-existing registers on the stack. */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E07]); - break; - case E08: - /* Invalid parameter. */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E08]); - break; - default: - /* Valid register number. */ - gdb_cris_strcpy (remcomOutBuffer, "OK"); - break; - } - } - break; - - case 'm': - /* Read from memory. mAA..AA,LLLL - AA..AA is the address and LLLL is the length. - Success: XX..XX is the memory content. Can be fewer bytes than - requested if only part of the data may be read. m6000120a,6c means - retrieve 108 byte from base address 6000120a. - Failure: void. */ - { - char *suffix; - unsigned char *addr = (unsigned char *)gdb_cris_strtol(&remcomInBuffer[1], - &suffix, 16); int length = gdb_cris_strtol(suffix+1, 0, 16); - - mem2hex(remcomOutBuffer, addr, length); - } - break; - - case 'X': - /* Write to memory. XAA..AA,LLLL:XX..XX - AA..AA is the start address, LLLL is the number of bytes, and - XX..XX is the binary data. - Success: OK - Failure: void. */ - case 'M': - /* Write to memory. MAA..AA,LLLL:XX..XX - AA..AA is the start address, LLLL is the number of bytes, and - XX..XX is the hexadecimal data. - Success: OK - Failure: E08. */ - { - char *lenptr; - char *dataptr; - unsigned char *addr = (unsigned char *)gdb_cris_strtol(&remcomInBuffer[1], - &lenptr, 16); - int length = gdb_cris_strtol(lenptr+1, &dataptr, 16); - if (*lenptr == ',' && *dataptr == ':') { - if (remcomInBuffer[0] == 'M') { - if (hex2bin(addr, dataptr + 1, length)) - gdb_cris_strcpy (remcomOutBuffer, error_message[E08]); - else - gdb_cris_strcpy (remcomOutBuffer, "OK"); - } else /* X */ { - bin2mem(addr, dataptr + 1, length); - gdb_cris_strcpy (remcomOutBuffer, "OK"); - } - } else { - gdb_cris_strcpy (remcomOutBuffer, error_message[E06]); - } - } - break; - - case 'c': - /* Continue execution. cAA..AA - AA..AA is the address where execution is resumed. If AA..AA is - omitted, resume at the present address. - Success: return to the executing thread. - Failure: will never know. */ - if (remcomInBuffer[1] != '\0') { - cris_reg.pc = gdb_cris_strtol (&remcomInBuffer[1], 0, 16); - } - enableDebugIRQ(); - return; - - case 's': - /* Step. sAA..AA - AA..AA is the address where execution is resumed. If AA..AA is - omitted, resume at the present address. Success: return to the - executing thread. Failure: will never know. - - Should never be invoked. The single-step is implemented on - the host side. If ever invoked, it is an internal error E04. */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E04]); - putpacket (remcomOutBuffer); - return; - - case '?': - /* The last signal which caused a stop. ? - Success: SAA, where AA is the signal number. - Failure: void. */ - remcomOutBuffer[0] = 'S'; - remcomOutBuffer[1] = hex_asc_hi(sigval); - remcomOutBuffer[2] = hex_asc_lo(sigval); - remcomOutBuffer[3] = 0; - break; - - case 'D': - /* Detach from host. D - Success: OK, and return to the executing thread. - Failure: will never know */ - putpacket ("OK"); - return; - - case 'k': - case 'r': - /* kill request or reset request. - Success: restart of target. - Failure: will never know. */ - kill_restart (); - break; - - case 'C': - case 'S': - case '!': - case 'R': - case 'd': - /* Continue with signal sig. Csig;AA..AA - Step with signal sig. Ssig;AA..AA - Use the extended remote protocol. ! - Restart the target system. R0 - Toggle debug flag. d - Search backwards. tAA:PP,MM - Not supported: E04 */ - gdb_cris_strcpy (remcomOutBuffer, error_message[E04]); - break; - - default: - /* The stub should ignore other request and send an empty - response ($#<checksum>). This way we can extend the protocol and GDB - can tell whether the stub it is talking to uses the old or the new. */ - remcomOutBuffer[0] = 0; - break; - } - putpacket(remcomOutBuffer); - } -} - -/********************************** Breakpoint *******************************/ -/* The hook for both a static (compiled) and a dynamic breakpoint set by GDB. - An internal stack is used by the stub. The register image of the caller is - stored in the structure register_image. - Interactive communication with the host is handled by handle_exception and - finally the register image is restored. */ - -void kgdb_handle_breakpoint(void); - -asm ("\n" -" .global kgdb_handle_breakpoint\n" -"kgdb_handle_breakpoint:\n" -";;\n" -";; Response to the break-instruction\n" -";;\n" -";; Create a register image of the caller\n" -";;\n" -" move $dccr,[cris_reg+0x5E] ; Save the flags in DCCR before disable interrupts\n" -" di ; Disable interrupts\n" -" move.d $r0,[cris_reg] ; Save R0\n" -" move.d $r1,[cris_reg+0x04] ; Save R1\n" -" move.d $r2,[cris_reg+0x08] ; Save R2\n" -" move.d $r3,[cris_reg+0x0C] ; Save R3\n" -" move.d $r4,[cris_reg+0x10] ; Save R4\n" -" move.d $r5,[cris_reg+0x14] ; Save R5\n" -" move.d $r6,[cris_reg+0x18] ; Save R6\n" -" move.d $r7,[cris_reg+0x1C] ; Save R7\n" -" move.d $r8,[cris_reg+0x20] ; Save R8\n" -" move.d $r9,[cris_reg+0x24] ; Save R9\n" -" move.d $r10,[cris_reg+0x28] ; Save R10\n" -" move.d $r11,[cris_reg+0x2C] ; Save R11\n" -" move.d $r12,[cris_reg+0x30] ; Save R12\n" -" move.d $r13,[cris_reg+0x34] ; Save R13\n" -" move.d $sp,[cris_reg+0x38] ; Save SP (R14)\n" -";; Due to the old assembler-versions BRP might not be recognized\n" -" .word 0xE670 ; move brp,$r0\n" -" subq 2,$r0 ; Set to address of previous instruction.\n" -" move.d $r0,[cris_reg+0x3c] ; Save the address in PC (R15)\n" -" clear.b [cris_reg+0x40] ; Clear P0\n" -" move $vr,[cris_reg+0x41] ; Save special register P1\n" -" clear.w [cris_reg+0x42] ; Clear P4\n" -" move $ccr,[cris_reg+0x44] ; Save special register CCR\n" -" move $mof,[cris_reg+0x46] ; P7\n" -" clear.d [cris_reg+0x4A] ; Clear P8\n" -" move $ibr,[cris_reg+0x4E] ; P9,\n" -" move $irp,[cris_reg+0x52] ; P10,\n" -" move $srp,[cris_reg+0x56] ; P11,\n" -" move $bar,[cris_reg+0x5A] ; P12,\n" -" ; P13, register DCCR already saved\n" -";; Due to the old assembler-versions BRP might not be recognized\n" -" .word 0xE670 ; move brp,r0\n" -";; Static (compiled) breakpoints must return to the next instruction in order\n" -";; to avoid infinite loops. Dynamic (gdb-invoked) must restore the instruction\n" -";; in order to execute it when execution is continued.\n" -" test.b [is_dyn_brkp] ; Is this a dynamic breakpoint?\n" -" beq is_static ; No, a static breakpoint\n" -" nop\n" -" subq 2,$r0 ; rerun the instruction the break replaced\n" -"is_static:\n" -" moveq 1,$r1\n" -" move.b $r1,[is_dyn_brkp] ; Set the state variable to dynamic breakpoint\n" -" move.d $r0,[cris_reg+0x62] ; Save the return address in BRP\n" -" move $usp,[cris_reg+0x66] ; USP\n" -";;\n" -";; Handle the communication\n" -";;\n" -" move.d internal_stack+1020,$sp ; Use the internal stack which grows upward\n" -" moveq 5,$r10 ; SIGTRAP\n" -" jsr handle_exception ; Interactive routine\n" -";;\n" -";; Return to the caller\n" -";;\n" -" move.d [cris_reg],$r0 ; Restore R0\n" -" move.d [cris_reg+0x04],$r1 ; Restore R1\n" -" move.d [cris_reg+0x08],$r2 ; Restore R2\n" -" move.d [cris_reg+0x0C],$r3 ; Restore R3\n" -" move.d [cris_reg+0x10],$r4 ; Restore R4\n" -" move.d [cris_reg+0x14],$r5 ; Restore R5\n" -" move.d [cris_reg+0x18],$r6 ; Restore R6\n" -" move.d [cris_reg+0x1C],$r7 ; Restore R7\n" -" move.d [cris_reg+0x20],$r8 ; Restore R8\n" -" move.d [cris_reg+0x24],$r9 ; Restore R9\n" -" move.d [cris_reg+0x28],$r10 ; Restore R10\n" -" move.d [cris_reg+0x2C],$r11 ; Restore R11\n" -" move.d [cris_reg+0x30],$r12 ; Restore R12\n" -" move.d [cris_reg+0x34],$r13 ; Restore R13\n" -";;\n" -";; FIXME: Which registers should be restored?\n" -";;\n" -" move.d [cris_reg+0x38],$sp ; Restore SP (R14)\n" -" move [cris_reg+0x56],$srp ; Restore the subroutine return pointer.\n" -" move [cris_reg+0x5E],$dccr ; Restore DCCR\n" -" move [cris_reg+0x66],$usp ; Restore USP\n" -" jump [cris_reg+0x62] ; A jump to the content in register BRP works.\n" -" nop ;\n" -"\n"); - -/* The hook for an interrupt generated by GDB. An internal stack is used - by the stub. The register image of the caller is stored in the structure - register_image. Interactive communication with the host is handled by - handle_exception and finally the register image is restored. Due to the - old assembler which does not recognise the break instruction and the - breakpoint return pointer hex-code is used. */ - -void kgdb_handle_serial(void); - -asm ("\n" -" .global kgdb_handle_serial\n" -"kgdb_handle_serial:\n" -";;\n" -";; Response to a serial interrupt\n" -";;\n" -"\n" -" move $dccr,[cris_reg+0x5E] ; Save the flags in DCCR\n" -" di ; Disable interrupts\n" -" move.d $r0,[cris_reg] ; Save R0\n" -" move.d $r1,[cris_reg+0x04] ; Save R1\n" -" move.d $r2,[cris_reg+0x08] ; Save R2\n" -" move.d $r3,[cris_reg+0x0C] ; Save R3\n" -" move.d $r4,[cris_reg+0x10] ; Save R4\n" -" move.d $r5,[cris_reg+0x14] ; Save R5\n" -" move.d $r6,[cris_reg+0x18] ; Save R6\n" -" move.d $r7,[cris_reg+0x1C] ; Save R7\n" -" move.d $r8,[cris_reg+0x20] ; Save R8\n" -" move.d $r9,[cris_reg+0x24] ; Save R9\n" -" move.d $r10,[cris_reg+0x28] ; Save R10\n" -" move.d $r11,[cris_reg+0x2C] ; Save R11\n" -" move.d $r12,[cris_reg+0x30] ; Save R12\n" -" move.d $r13,[cris_reg+0x34] ; Save R13\n" -" move.d $sp,[cris_reg+0x38] ; Save SP (R14)\n" -" move $irp,[cris_reg+0x3c] ; Save the address in PC (R15)\n" -" clear.b [cris_reg+0x40] ; Clear P0\n" -" move $vr,[cris_reg+0x41] ; Save special register P1,\n" -" clear.w [cris_reg+0x42] ; Clear P4\n" -" move $ccr,[cris_reg+0x44] ; Save special register CCR\n" -" move $mof,[cris_reg+0x46] ; P7\n" -" clear.d [cris_reg+0x4A] ; Clear P8\n" -" move $ibr,[cris_reg+0x4E] ; P9,\n" -" move $irp,[cris_reg+0x52] ; P10,\n" -" move $srp,[cris_reg+0x56] ; P11,\n" -" move $bar,[cris_reg+0x5A] ; P12,\n" -" ; P13, register DCCR already saved\n" -";; Due to the old assembler-versions BRP might not be recognized\n" -" .word 0xE670 ; move brp,r0\n" -" move.d $r0,[cris_reg+0x62] ; Save the return address in BRP\n" -" move $usp,[cris_reg+0x66] ; USP\n" -"\n" -";; get the serial character (from debugport.c) and check if it is a ctrl-c\n" -"\n" -" jsr getDebugChar\n" -" cmp.b 3, $r10\n" -" bne goback\n" -" nop\n" -"\n" -" move.d [cris_reg+0x5E], $r10 ; Get DCCR\n" -" btstq 8, $r10 ; Test the U-flag.\n" -" bmi goback\n" -" nop\n" -"\n" -";;\n" -";; Handle the communication\n" -";;\n" -" move.d internal_stack+1020,$sp ; Use the internal stack\n" -" moveq 2,$r10 ; SIGINT\n" -" jsr handle_exception ; Interactive routine\n" -"\n" -"goback:\n" -";;\n" -";; Return to the caller\n" -";;\n" -" move.d [cris_reg],$r0 ; Restore R0\n" -" move.d [cris_reg+0x04],$r1 ; Restore R1\n" -" move.d [cris_reg+0x08],$r2 ; Restore R2\n" -" move.d [cris_reg+0x0C],$r3 ; Restore R3\n" -" move.d [cris_reg+0x10],$r4 ; Restore R4\n" -" move.d [cris_reg+0x14],$r5 ; Restore R5\n" -" move.d [cris_reg+0x18],$r6 ; Restore R6\n" -" move.d [cris_reg+0x1C],$r7 ; Restore R7\n" -" move.d [cris_reg+0x20],$r8 ; Restore R8\n" -" move.d [cris_reg+0x24],$r9 ; Restore R9\n" -" move.d [cris_reg+0x28],$r10 ; Restore R10\n" -" move.d [cris_reg+0x2C],$r11 ; Restore R11\n" -" move.d [cris_reg+0x30],$r12 ; Restore R12\n" -" move.d [cris_reg+0x34],$r13 ; Restore R13\n" -";;\n" -";; FIXME: Which registers should be restored?\n" -";;\n" -" move.d [cris_reg+0x38],$sp ; Restore SP (R14)\n" -" move [cris_reg+0x56],$srp ; Restore the subroutine return pointer.\n" -" move [cris_reg+0x5E],$dccr ; Restore DCCR\n" -" move [cris_reg+0x66],$usp ; Restore USP\n" -" reti ; Return from the interrupt routine\n" -" nop\n" -"\n"); - -/* Use this static breakpoint in the start-up only. */ - -void -breakpoint(void) -{ - kgdb_started = 1; - is_dyn_brkp = 0; /* This is a static, not a dynamic breakpoint. */ - __asm__ volatile ("break 8"); /* Jump to handle_breakpoint. */ -} - -/* initialize kgdb. doesn't break into the debugger, but sets up irq and ports */ - -void -kgdb_init(void) -{ - /* could initialize debug port as well but it's done in head.S already... */ - - /* breakpoint handler is now set in irq.c */ - set_int_vector(8, kgdb_handle_serial); - - enableDebugIRQ(); -} - -/****************************** End of file **********************************/ diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c deleted file mode 100644 index 16848b2c61c8..000000000000 --- a/arch/cris/arch-v10/kernel/process.c +++ /dev/null @@ -1,180 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/kernel/process.c - * - * Copyright (C) 1995 Linus Torvalds - * Copyright (C) 2000-2002 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - * Mikael Starvik (starvik@axis.com) - * - * This file handles the architecture-dependent parts of process handling.. - */ - -#include <linux/sched.h> -#include <linux/sched/debug.h> -#include <linux/sched/task.h> -#include <linux/sched/task_stack.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <linux/fs.h> -#include <arch/svinto.h> -#include <linux/init.h> -#include <arch/system.h> -#include <linux/ptrace.h> - -#ifdef CONFIG_ETRAX_GPIO -void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */ -#endif - -/* - * We use this if we don't have any better - * idle routine.. - */ -void default_idle(void) -{ -#ifdef CONFIG_ETRAX_GPIO - etrax_gpio_wake_up_check(); -#endif - local_irq_enable(); -} - -/* if the watchdog is enabled, we can simply disable interrupts and go - * into an eternal loop, and the watchdog will reset the CPU after 0.1s - * if on the other hand the watchdog wasn't enabled, we just enable it and wait - */ - -void hard_reset_now (void) -{ - /* - * Don't declare this variable elsewhere. We don't want any other - * code to know about it than the watchdog handler in entry.S and - * this code, implementing hard reset through the watchdog. - */ -#if defined(CONFIG_ETRAX_WATCHDOG) - extern int cause_of_death; -#endif - - printk("*** HARD RESET ***\n"); - local_irq_disable(); - -#if defined(CONFIG_ETRAX_WATCHDOG) - cause_of_death = 0xbedead; -#else - /* Since we dont plan to keep on resetting the watchdog, - the key can be arbitrary hence three */ - *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, 3) | - IO_STATE(R_WATCHDOG, enable, start); -#endif - - while(1) /* waiting for RETRIBUTION! */ ; -} - -/* setup the child's kernel stack with a pt_regs and switch_stack on it. - * it will be un-nested during _resume and _ret_from_sys_call when the - * new thread is scheduled. - * - * also setup the thread switching structure which is used to keep - * thread-specific data during _resumes. - * - */ -asmlinkage void ret_from_fork(void); -asmlinkage void ret_from_kernel_thread(void); - -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long arg, struct task_struct *p) -{ - struct pt_regs *childregs = task_pt_regs(p); - struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1; - - /* put the pt_regs structure at the end of the new kernel stack page and fix it up - * remember that the task_struct doubles as the kernel stack for the task - */ - - if (unlikely(p->flags & PF_KTHREAD)) { - memset(swstack, 0, - sizeof(struct switch_stack) + sizeof(struct pt_regs)); - swstack->r1 = usp; - swstack->r2 = arg; - childregs->dccr = 1 << I_DCCR_BITNR; - swstack->return_ip = (unsigned long) ret_from_kernel_thread; - p->thread.ksp = (unsigned long) swstack; - p->thread.usp = 0; - return 0; - } - *childregs = *current_pt_regs(); /* struct copy of pt_regs */ - - childregs->r10 = 0; /* child returns 0 after a fork/clone */ - - /* put the switch stack right below the pt_regs */ - - swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */ - - /* we want to return into ret_from_sys_call after the _resume */ - - swstack->return_ip = (unsigned long) ret_from_fork; /* Will call ret_from_sys_call */ - - /* fix the user-mode stackpointer */ - - p->thread.usp = usp ?: rdusp(); - - /* and the kernel-mode one */ - - p->thread.ksp = (unsigned long) swstack; - -#ifdef DEBUG - printk("copy_thread: new regs at 0x%p, as shown below:\n", childregs); - show_registers(childregs); -#endif - - return 0; -} - -unsigned long get_wchan(struct task_struct *p) -{ -#if 0 - /* YURGH. TODO. */ - - unsigned long ebp, esp, eip; - unsigned long stack_page; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - stack_page = (unsigned long)p; - esp = p->thread.esp; - if (!stack_page || esp < stack_page || esp > 8188+stack_page) - return 0; - /* include/asm-i386/system.h:switch_to() pushes ebp last. */ - ebp = *(unsigned long *) esp; - do { - if (ebp < stack_page || ebp > 8184+stack_page) - return 0; - eip = *(unsigned long *) (ebp+4); - if (!in_sched_functions(eip)) - return eip; - ebp = *(unsigned long *) ebp; - } while (count++ < 16); -#endif - return 0; -} -#undef last_sched -#undef first_sched - -void show_regs(struct pt_regs * regs) -{ - unsigned long usp = rdusp(); - - show_regs_print_info(KERN_DEFAULT); - - printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n", - regs->irp, regs->srp, regs->dccr, usp, regs->mof ); - printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", - regs->r0, regs->r1, regs->r2, regs->r3); - printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", - regs->r4, regs->r5, regs->r6, regs->r7); - printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", - regs->r8, regs->r9, regs->r10, regs->r11); - printk("r12: %08lx r13: %08lx oR10: %08lx\n", - regs->r12, regs->r13, regs->orig_r10); -} - diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c deleted file mode 100644 index b89f57ae096e..000000000000 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2000-2003, Axis Communications AB. - */ - -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/sched/task_stack.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/errno.h> -#include <linux/ptrace.h> -#include <linux/user.h> -#include <linux/signal.h> -#include <linux/security.h> - -#include <linux/uaccess.h> -#include <asm/page.h> -#include <asm/pgtable.h> -#include <asm/processor.h> - -/* - * Determines which bits in DCCR the user has access to. - * 1 = access, 0 = no access. - */ -#define DCCR_MASK 0x0000001f /* XNZVC */ - -/* - * Get contents of register REGNO in task TASK. - */ -inline long get_reg(struct task_struct *task, unsigned int regno) -{ - /* USP is a special case, it's not in the pt_regs struct but - * in the tasks thread struct - */ - - if (regno == PT_USP) - return task->thread.usp; - else if (regno < PT_MAX) - return ((unsigned long *)task_pt_regs(task))[regno]; - else - return 0; -} - -/* - * Write contents of register REGNO in task TASK. - */ -inline int put_reg(struct task_struct *task, unsigned int regno, - unsigned long data) -{ - if (regno == PT_USP) - task->thread.usp = data; - else if (regno < PT_MAX) - ((unsigned long *)task_pt_regs(task))[regno] = data; - else - return -1; - return 0; -} - -/* - * Called by kernel/ptrace.c when detaching. - * - * Make sure the single step bit is not set. - */ -void -ptrace_disable(struct task_struct *child) -{ - /* Todo - pending singlesteps? */ - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); -} - -/* - * Note that this implementation of ptrace behaves differently from vanilla - * ptrace. Contrary to what the man page says, in the PTRACE_PEEKTEXT, - * PTRACE_PEEKDATA, and PTRACE_PEEKUSER requests the data variable is not - * ignored. Instead, the data variable is expected to point at a location - * (in user space) where the result of the ptrace call is written (instead of - * being returned). - */ -long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - int ret; - unsigned int regno = addr >> 2; - unsigned long __user *datap = (unsigned long __user *)data; - - switch (request) { - /* Read word at location address. */ - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - ret = generic_ptrace_peekdata(child, addr, data); - break; - - /* Read the word at location address in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp; - - ret = -EIO; - if ((addr & 3) || regno > PT_MAX) - break; - - tmp = get_reg(child, regno); - ret = put_user(tmp, datap); - break; - } - - /* Write the word at location address. */ - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - ret = generic_ptrace_pokedata(child, addr, data); - break; - - /* Write the word at location address in the USER area. */ - case PTRACE_POKEUSR: - ret = -EIO; - if ((addr & 3) || regno > PT_MAX) - break; - - if (regno == PT_DCCR) { - /* don't allow the tracing process to change stuff like - * interrupt enable, kernel/user bit, dma enables etc. - */ - data &= DCCR_MASK; - data |= get_reg(child, PT_DCCR) & ~DCCR_MASK; - } - if (put_reg(child, regno, data)) - break; - ret = 0; - break; - - /* Get all GP registers from the child. */ - case PTRACE_GETREGS: { - int i; - unsigned long tmp; - - ret = 0; - for (i = 0; i <= PT_MAX; i++) { - tmp = get_reg(child, i); - - if (put_user(tmp, datap)) { - ret = -EFAULT; - break; - } - - datap++; - } - - break; - } - - /* Set all GP registers in the child. */ - case PTRACE_SETREGS: { - int i; - unsigned long tmp; - - ret = 0; - for (i = 0; i <= PT_MAX; i++) { - if (get_user(tmp, datap)) { - ret = -EFAULT; - break; - } - - if (i == PT_DCCR) { - tmp &= DCCR_MASK; - tmp |= get_reg(child, PT_DCCR) & ~DCCR_MASK; - } - - put_reg(child, i, tmp); - datap++; - } - - break; - } - - default: - ret = ptrace_request(child, request, addr, data); - break; - } - - return ret; -} - -void do_syscall_trace(void) -{ - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; - - if (!(current->ptrace & PT_PTRACED)) - return; - - /* the 0x80 provides a way for the tracing parent to distinguish - between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - - /* - * This isn't the same as continuing with a signal, but it will do for - * normal use. - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } -} diff --git a/arch/cris/arch-v10/kernel/setup.c b/arch/cris/arch-v10/kernel/setup.c deleted file mode 100644 index 8e4fc248f96f..000000000000 --- a/arch/cris/arch-v10/kernel/setup.c +++ /dev/null @@ -1,107 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * - * linux/arch/cris/arch-v10/kernel/setup.c - * - * Copyright (C) 1995 Linus Torvalds - * Copyright (c) 2001-2002 Axis Communications AB - */ - -/* - * This file handles the architecture-dependent parts of initialization - */ - -#include <linux/seq_file.h> -#include <linux/proc_fs.h> -#include <linux/delay.h> -#include <linux/param.h> -#include <arch/system.h> - -#ifdef CONFIG_PROC_FS -#define HAS_FPU 0x0001 -#define HAS_MMU 0x0002 -#define HAS_ETHERNET100 0x0004 -#define HAS_TOKENRING 0x0008 -#define HAS_SCSI 0x0010 -#define HAS_ATA 0x0020 -#define HAS_USB 0x0040 -#define HAS_IRQ_BUG 0x0080 -#define HAS_MMU_BUG 0x0100 - -static struct cpu_info { - char *model; - unsigned short cache; - unsigned short flags; -} cpu_info[] = { - /* The first four models will never ever run this code and are - only here for display. */ - { "ETRAX 1", 0, 0 }, - { "ETRAX 2", 0, 0 }, - { "ETRAX 3", 0, HAS_TOKENRING }, - { "ETRAX 4", 0, HAS_TOKENRING | HAS_SCSI }, - { "Unknown", 0, 0 }, - { "Unknown", 0, 0 }, - { "Unknown", 0, 0 }, - { "Simulator", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA }, - { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_IRQ_BUG }, - { "ETRAX 100", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA }, - { "ETRAX 100LX", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU | HAS_MMU_BUG }, - { "ETRAX 100LX v2", 8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU }, - { "Unknown", 0, 0 } /* This entry MUST be the last */ -}; - -int show_cpuinfo(struct seq_file *m, void *v) -{ - unsigned long revision; - struct cpu_info *info; - - /* read the version register in the CPU and print some stuff */ - - revision = rdvr(); - - if (revision >= ARRAY_SIZE(cpu_info)) - info = &cpu_info[ARRAY_SIZE(cpu_info) - 1]; - else - info = &cpu_info[revision]; - - seq_printf(m, - "processor\t: 0\n" - "cpu\t\t: CRIS\n" - "cpu revision\t: %lu\n" - "cpu model\t: %s\n" - "cache size\t: %d kB\n" - "fpu\t\t: %s\n" - "mmu\t\t: %s\n" - "mmu DMA bug\t: %s\n" - "ethernet\t: %s Mbps\n" - "token ring\t: %s\n" - "scsi\t\t: %s\n" - "ata\t\t: %s\n" - "usb\t\t: %s\n" - "bogomips\t: %lu.%02lu\n", - - revision, - info->model, - info->cache, - info->flags & HAS_FPU ? "yes" : "no", - info->flags & HAS_MMU ? "yes" : "no", - info->flags & HAS_MMU_BUG ? "yes" : "no", - info->flags & HAS_ETHERNET100 ? "10/100" : "10", - info->flags & HAS_TOKENRING ? "4/16 Mbps" : "no", - info->flags & HAS_SCSI ? "yes" : "no", - info->flags & HAS_ATA ? "yes" : "no", - info->flags & HAS_USB ? "yes" : "no", - (loops_per_jiffy * HZ + 500) / 500000, - ((loops_per_jiffy * HZ + 500) / 5000) % 100); - - return 0; -} - -#endif /* CONFIG_PROC_FS */ - -void -show_etrax_copyright(void) -{ - printk(KERN_INFO - "Linux/CRIS port on ETRAX 100LX (c) 2001 Axis Communications AB\n"); -} diff --git a/arch/cris/arch-v10/kernel/shadows.c b/arch/cris/arch-v10/kernel/shadows.c deleted file mode 100644 index 2e9565e868f2..000000000000 --- a/arch/cris/arch-v10/kernel/shadows.c +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Various shadow registers. Defines for these are in include/asm-etrax100/io.h - */ - -/* Shadows for internal Etrax-registers */ - -unsigned long genconfig_shadow; -unsigned long gen_config_ii_shadow; -unsigned long port_g_data_shadow; -unsigned char port_pa_dir_shadow; -unsigned char port_pa_data_shadow; -unsigned char port_pb_i2c_shadow; -unsigned char port_pb_config_shadow; -unsigned char port_pb_dir_shadow; -unsigned char port_pb_data_shadow; -unsigned long r_timer_ctrl_shadow; - -/* Shadows for external I/O port registers. - * These are only usable if there actually IS a latch connected - * to the corresponding external chip-select pin. - * - * A common usage is that CSP0 controls LEDs and CSP4 video chips. - */ - -unsigned long port_cse1_shadow; -unsigned long port_csp0_shadow; -unsigned long port_csp4_shadow; - -/* Corresponding addresses for the ports. - * These are initialized in arch/cris/mm/init.c using ioremap. - */ - -volatile unsigned long *port_cse1_addr; -volatile unsigned long *port_csp0_addr; -volatile unsigned long *port_csp4_addr; - diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c deleted file mode 100644 index 2beffc37faf8..000000000000 --- a/arch/cris/arch-v10/kernel/signal.c +++ /dev/null @@ -1,440 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/kernel/signal.c - * - * Based on arch/i386/kernel/signal.c by - * Copyright (C) 1991, 1992 Linus Torvalds - * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson * - * - * Ideas also taken from arch/arm. - * - * Copyright (C) 2000-2007 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - * - */ - -#include <linux/sched.h> -#include <linux/sched/task_stack.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/kernel.h> -#include <linux/signal.h> -#include <linux/errno.h> -#include <linux/wait.h> -#include <linux/ptrace.h> -#include <linux/unistd.h> -#include <linux/stddef.h> - -#include <asm/processor.h> -#include <asm/ucontext.h> -#include <linux/uaccess.h> -#include <arch/system.h> - -#define DEBUG_SIG 0 - -/* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */ -/* manipulate regs so that upon return, it will be re-executed */ - -/* We rely on that pc points to the instruction after "break 13", so the - * library must never do strange things like putting it in a delay slot. - */ -#define RESTART_CRIS_SYS(regs) regs->r10 = regs->orig_r10; regs->irp -= 2; - -void do_signal(int canrestart, struct pt_regs *regs); - -/* - * Do a signal return; undo the signal stack. - */ - -struct sigframe { - struct sigcontext sc; - unsigned long extramask[_NSIG_WORDS-1]; - unsigned char retcode[8]; /* trampoline code */ -}; - -struct rt_sigframe { - struct siginfo *pinfo; - void *puc; - struct siginfo info; - struct ucontext uc; - unsigned char retcode[8]; /* trampoline code */ -}; - - -static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) -{ - unsigned int err = 0; - unsigned long old_usp; - - /* Always make any pending restarted system calls return -EINTR */ - current->restart_block.fn = do_no_restart_syscall; - - /* restore the regs from &sc->regs (same as sc, since regs is first) - * (sc is already checked for VERIFY_READ since the sigframe was - * checked in sys_sigreturn previously) - */ - - if (__copy_from_user(regs, sc, sizeof(struct pt_regs))) - goto badframe; - - /* make sure the U-flag is set so user-mode cannot fool us */ - - regs->dccr |= 1 << 8; - - /* restore the old USP as it was before we stacked the sc etc. - * (we cannot just pop the sigcontext since we aligned the sp and - * stuff after pushing it) - */ - - err |= __get_user(old_usp, &sc->usp); - - wrusp(old_usp); - - /* TODO: the other ports use regs->orig_XX to disable syscall checks - * after this completes, but we don't use that mechanism. maybe we can - * use it now ? - */ - - return err; - -badframe: - return 1; -} - -asmlinkage int sys_sigreturn(void) -{ - struct pt_regs *regs = current_pt_regs(); - struct sigframe __user *frame = (struct sigframe *)rdusp(); - sigset_t set; - - /* - * Since we stacked the signal on a dword boundary, - * then frame should be dword aligned here. If it's - * not, then the user is trying to mess with us. - */ - if (((long)frame) & 3) - goto badframe; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__get_user(set.sig[0], &frame->sc.oldmask) - || (_NSIG_WORDS > 1 - && __copy_from_user(&set.sig[1], frame->extramask, - sizeof(frame->extramask)))) - goto badframe; - - set_current_blocked(&set); - - if (restore_sigcontext(regs, &frame->sc)) - goto badframe; - - /* TODO: SIGTRAP when single-stepping as in arm ? */ - - return regs->r10; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int sys_rt_sigreturn(void) -{ - struct pt_regs *regs = current_pt_regs(); - struct rt_sigframe __user *frame = (struct rt_sigframe *)rdusp(); - sigset_t set; - - /* - * Since we stacked the signal on a dword boundary, - * then frame should be dword aligned here. If it's - * not, then the user is trying to mess with us. - */ - if (((long)frame) & 3) - goto badframe; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) - goto badframe; - - set_current_blocked(&set); - - if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) - goto badframe; - - if (restore_altstack(&frame->uc.uc_stack)) - goto badframe; - - return regs->r10; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -/* - * Set up a signal frame. - */ - -static int setup_sigcontext(struct sigcontext __user *sc, - struct pt_regs *regs, unsigned long mask) -{ - int err = 0; - unsigned long usp = rdusp(); - - /* copy the regs. they are first in sc so we can use sc directly */ - - err |= __copy_to_user(sc, regs, sizeof(struct pt_regs)); - - /* Set the frametype to CRIS_FRAME_NORMAL for the execution of - the signal handler. The frametype will be restored to its previous - value in restore_sigcontext. */ - regs->frametype = CRIS_FRAME_NORMAL; - - /* then some other stuff */ - - err |= __put_user(mask, &sc->oldmask); - - err |= __put_user(usp, &sc->usp); - - return err; -} - -/* Figure out where we want to put the new signal frame - * - usually on the stack. */ - -static inline void __user * -get_sigframe(struct ksignal *ksig, size_t frame_size) -{ - unsigned long sp = sigsp(rdusp(), ksig); - - /* make sure the frame is dword-aligned */ - - sp &= ~3; - - return (void __user*)(sp - frame_size); -} - -/* grab and setup a signal frame. - * - * basically we stack a lot of state info, and arrange for the - * user-mode program to return to the kernel using either a - * trampoline which performs the syscall sigreturn, or a provided - * user-mode trampoline. - */ - -static int setup_frame(struct ksignal *ksig, sigset_t *set, - struct pt_regs *regs) -{ - struct sigframe __user *frame; - unsigned long return_ip; - int err = 0; - - frame = get_sigframe(ksig, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return -EFAULT; - - err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); - if (err) - return -EFAULT; - - if (_NSIG_WORDS > 1) { - err |= __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - } - if (err) - return -EFAULT; - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ksig->ka.sa.sa_flags & SA_RESTORER) { - return_ip = (unsigned long)ksig->ka.sa.sa_restorer; - } else { - /* trampoline - the desired return ip is the retcode itself */ - return_ip = (unsigned long)&frame->retcode; - /* This is movu.w __NR_sigreturn, r9; break 13; */ - err |= __put_user(0x9c5f, (short __user*)(frame->retcode+0)); - err |= __put_user(__NR_sigreturn, (short __user*)(frame->retcode+2)); - err |= __put_user(0xe93d, (short __user*)(frame->retcode+4)); - } - - if (err) - return -EFAULT; - - /* Set up registers for signal handler */ - - regs->irp = (unsigned long) ksig->ka.sa.sa_handler; /* what we enter NOW */ - regs->srp = return_ip; /* what we enter LATER */ - regs->r10 = ksig->sig; /* first argument is signo */ - - /* actually move the usp to reflect the stacked frame */ - - wrusp((unsigned long)frame); - - return 0; -} - -static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, - struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - unsigned long return_ip; - int err = 0; - - frame = get_sigframe(ksig, sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - return -EFAULT; - - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); - err |= copy_siginfo_to_user(&frame->info, &ksig->info); - if (err) - return -EFAULT; - - /* Clear all the bits of the ucontext we don't use. */ - err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); - - err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); - - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - - err |= __save_altstack(&frame->uc.uc_stack, rdusp()); - - if (err) - return -EFAULT; - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ksig->ka.sa.sa_flags & SA_RESTORER) { - return_ip = (unsigned long)ksig->ka.sa.sa_restorer; - } else { - /* trampoline - the desired return ip is the retcode itself */ - return_ip = (unsigned long)&frame->retcode; - /* This is movu.w __NR_rt_sigreturn, r9; break 13; */ - err |= __put_user(0x9c5f, (short __user *)(frame->retcode+0)); - err |= __put_user(__NR_rt_sigreturn, - (short __user *)(frame->retcode+2)); - err |= __put_user(0xe93d, (short __user *)(frame->retcode+4)); - } - - if (err) - return -EFAULT; - - /* Set up registers for signal handler */ - - /* What we enter NOW */ - regs->irp = (unsigned long) ksig->ka.sa.sa_handler; - /* What we enter LATER */ - regs->srp = return_ip; - /* First argument is signo */ - regs->r10 = ksig->sig; - /* Second argument is (siginfo_t *) */ - regs->r11 = (unsigned long)&frame->info; - /* Third argument is unused */ - regs->r12 = 0; - - /* Actually move the usp to reflect the stacked frame */ - wrusp((unsigned long)frame); - - return 0; -} - -/* - * OK, we're invoking a handler - */ - -static inline void handle_signal(int canrestart, struct ksignal *ksig, - struct pt_regs *regs) -{ - sigset_t *oldset = sigmask_to_save(); - int ret; - - /* Are we from a system call? */ - if (canrestart) { - /* If so, check system call restarting.. */ - switch (regs->r10) { - case -ERESTART_RESTARTBLOCK: - case -ERESTARTNOHAND: - /* ERESTARTNOHAND means that the syscall should - * only be restarted if there was no handler for - * the signal, and since we only get here if there - * is a handler, we don't restart */ - regs->r10 = -EINTR; - break; - case -ERESTARTSYS: - /* ERESTARTSYS means to restart the syscall if - * there is no handler or the handler was - * registered with SA_RESTART */ - if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { - regs->r10 = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - /* ERESTARTNOINTR means that the syscall should - * be called again after the signal handler returns. */ - RESTART_CRIS_SYS(regs); - } - } - - /* Set up the stack frame */ - if (ksig->ka.sa.sa_flags & SA_SIGINFO) - ret = setup_rt_frame(ksig, oldset, regs); - else - ret = setup_frame(ksig, oldset, regs); - - signal_setup_done(ret, ksig, 0); -} - -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - * - * Also note that the regs structure given here as an argument, is the latest - * pushed pt_regs. It may or may not be the same as the first pushed registers - * when the initial usermode->kernelmode transition took place. Therefore - * we can use user_mode(regs) to see if we came directly from kernel or user - * mode below. - */ - -void do_signal(int canrestart, struct pt_regs *regs) -{ - struct ksignal ksig; - - /* - * We want the common case to go fast, which - * is why we may in certain cases get here from - * kernel mode. Just return without doing anything - * if so. - */ - if (!user_mode(regs)) - return; - - if (get_signal(&ksig)) { - /* Whee! Actually deliver the signal. */ - handle_signal(canrestart, &ksig, regs); - return; - } - - /* Did we come from a system call? */ - if (canrestart) { - /* Restart the system call - no handlers present */ - if (regs->r10 == -ERESTARTNOHAND || - regs->r10 == -ERESTARTSYS || - regs->r10 == -ERESTARTNOINTR) { - RESTART_CRIS_SYS(regs); - } - if (regs->r10 == -ERESTART_RESTARTBLOCK) { - regs->r9 = __NR_restart_syscall; - regs->irp -= 2; - } - } - - /* if there's no signal to deliver, we just put the saved sigmask - * back */ - restore_saved_sigmask(); -} diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c deleted file mode 100644 index 3d78373db254..000000000000 --- a/arch/cris/arch-v10/kernel/time.c +++ /dev/null @@ -1,268 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/arch-v10/kernel/time.c - * - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * Copyright (C) 1999-2002 Axis Communications AB - * - */ - -#include <linux/timex.h> -#include <linux/time.h> -#include <linux/jiffies.h> -#include <linux/interrupt.h> -#include <linux/swap.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/mm.h> -#include <asm/types.h> -#include <asm/signal.h> -#include <asm/io.h> -#include <asm/delay.h> -#include <asm/irq_regs.h> - -/* define this if you need to use print_timestamp */ -/* it will make jiffies at 96 hz instead of 100 hz though */ -#undef USE_CASCADE_TIMERS - -unsigned long get_ns_in_jiffie(void) -{ - unsigned char timer_count, t1; - unsigned short presc_count; - unsigned long ns; - unsigned long flags; - - local_irq_save(flags); - timer_count = *R_TIMER0_DATA; - presc_count = *R_TIM_PRESC_STATUS; - /* presc_count might be wrapped */ - t1 = *R_TIMER0_DATA; - - if (timer_count != t1){ - /* it wrapped, read prescaler again... */ - presc_count = *R_TIM_PRESC_STATUS; - timer_count = t1; - } - local_irq_restore(flags); - if (presc_count >= PRESCALE_VALUE/2 ){ - presc_count = PRESCALE_VALUE - presc_count + PRESCALE_VALUE/2; - } else { - presc_count = PRESCALE_VALUE - presc_count - PRESCALE_VALUE/2; - } - - ns = ( (TIMER0_DIV - timer_count) * ((1000000000/HZ)/TIMER0_DIV )) + - ( (presc_count) * (1000000000/PRESCALE_FREQ)); - return ns; -} - -static u32 cris_v10_gettimeoffset(void) -{ - u32 count; - - /* The timer interrupt comes from Etrax timer 0. In order to get - * better precision, we check the current value. It might have - * underflowed already though. - */ - count = *R_TIMER0_DATA; - - /* Convert timer value to nsec */ - return (TIMER0_DIV - count) * (NSEC_PER_SEC/HZ)/TIMER0_DIV; -} - -/* Excerpt from the Etrax100 HSDD about the built-in watchdog: - * - * 3.10.4 Watchdog timer - - * When the watchdog timer is started, it generates an NMI if the watchdog - * isn't restarted or stopped within 0.1 s. If it still isn't restarted or - * stopped after an additional 3.3 ms, the watchdog resets the chip. - * The watchdog timer is stopped after reset. The watchdog timer is controlled - * by the R_WATCHDOG register. The R_WATCHDOG register contains an enable bit - * and a 3-bit key value. The effect of writing to the R_WATCHDOG register is - * described in the table below: - * - * Watchdog Value written: - * state: To enable: To key: Operation: - * -------- ---------- ------- ---------- - * stopped 0 X No effect. - * stopped 1 key_val Start watchdog with key = key_val. - * started 0 ~key Stop watchdog - * started 1 ~key Restart watchdog with key = ~key. - * started X new_key_val Change key to new_key_val. - * - * Note: '~' is the bitwise NOT operator. - * - */ - -/* right now, starting the watchdog is the same as resetting it */ -#define start_watchdog reset_watchdog - -#ifdef CONFIG_ETRAX_WATCHDOG -static int watchdog_key = 0; /* arbitrary number */ -#endif - -/* number of pages to consider "out of memory". it is normal that the memory - * is used though, so put this really low. - */ - -#define WATCHDOG_MIN_FREE_PAGES 8 - -void reset_watchdog(void) -{ -#if defined(CONFIG_ETRAX_WATCHDOG) - /* only keep watchdog happy as long as we have memory left! */ - if(nr_free_pages() > WATCHDOG_MIN_FREE_PAGES) { - /* reset the watchdog with the inverse of the old key */ - watchdog_key ^= 0x7; /* invert key, which is 3 bits */ - *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) | - IO_STATE(R_WATCHDOG, enable, start); - } -#endif -} - -/* stop the watchdog - we still need the correct key */ - -void stop_watchdog(void) -{ -#ifdef CONFIG_ETRAX_WATCHDOG - watchdog_key ^= 0x7; /* invert key, which is 3 bits */ - *R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) | - IO_STATE(R_WATCHDOG, enable, stop); -#endif -} - - -extern void cris_do_profile(struct pt_regs *regs); - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "xtime_update()" routine every clocktick - */ -static inline irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - struct pt_regs *regs = get_irq_regs(); - /* acknowledge the timer irq */ - -#ifdef USE_CASCADE_TIMERS - *R_TIMER_CTRL = - IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) | - IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) | - IO_STATE( R_TIMER_CTRL, i1, clr) | - IO_STATE( R_TIMER_CTRL, tm1, run) | - IO_STATE( R_TIMER_CTRL, clksel1, cascade0) | - IO_STATE( R_TIMER_CTRL, i0, clr) | - IO_STATE( R_TIMER_CTRL, tm0, run) | - IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz); -#else - *R_TIMER_CTRL = r_timer_ctrl_shadow | IO_STATE(R_TIMER_CTRL, i0, clr); -#endif - - /* reset watchdog otherwise it resets us! */ - reset_watchdog(); - - /* Update statistics. */ - update_process_times(user_mode(regs)); - - /* call the real timer interrupt handler */ - xtime_update(1); - - cris_do_profile(regs); /* Save profiling information */ - return IRQ_HANDLED; -} - -/* timer is IRQF_SHARED so drivers can add stuff to the timer irq chain */ - -static struct irqaction irq2 = { - .handler = timer_interrupt, - .flags = IRQF_SHARED, - .name = "timer", -}; - -void __init time_init(void) -{ - arch_gettimeoffset = cris_v10_gettimeoffset; - - /* probe for the RTC and read it if it exists - * Before the RTC can be probed the loops_per_usec variable needs - * to be initialized to make usleep work. A better value for - * loops_per_usec is calculated by the kernel later once the - * clock has started. - */ - loops_per_usec = 50; - - /* Setup the etrax timers - * Base frequency is 25000 hz, divider 250 -> 100 HZ - * In normal mode, we use timer0, so timer1 is free. In cascade - * mode (which we sometimes use for debugging) both timers are used. - * Remember that linux/timex.h contains #defines that rely on the - * timer settings below (hz and divide factor) !!! - */ - -#ifdef USE_CASCADE_TIMERS - *R_TIMER_CTRL = - IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) | - IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) | - IO_STATE( R_TIMER_CTRL, i1, nop) | - IO_STATE( R_TIMER_CTRL, tm1, stop_ld) | - IO_STATE( R_TIMER_CTRL, clksel1, cascade0) | - IO_STATE( R_TIMER_CTRL, i0, nop) | - IO_STATE( R_TIMER_CTRL, tm0, stop_ld) | - IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz); - - *R_TIMER_CTRL = r_timer_ctrl_shadow = - IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) | - IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) | - IO_STATE( R_TIMER_CTRL, i1, nop) | - IO_STATE( R_TIMER_CTRL, tm1, run) | - IO_STATE( R_TIMER_CTRL, clksel1, cascade0) | - IO_STATE( R_TIMER_CTRL, i0, nop) | - IO_STATE( R_TIMER_CTRL, tm0, run) | - IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz); -#else - *R_TIMER_CTRL = - IO_FIELD(R_TIMER_CTRL, timerdiv1, 192) | - IO_FIELD(R_TIMER_CTRL, timerdiv0, TIMER0_DIV) | - IO_STATE(R_TIMER_CTRL, i1, nop) | - IO_STATE(R_TIMER_CTRL, tm1, stop_ld) | - IO_STATE(R_TIMER_CTRL, clksel1, c19k2Hz) | - IO_STATE(R_TIMER_CTRL, i0, nop) | - IO_STATE(R_TIMER_CTRL, tm0, stop_ld) | - IO_STATE(R_TIMER_CTRL, clksel0, flexible); - - *R_TIMER_CTRL = r_timer_ctrl_shadow = - IO_FIELD(R_TIMER_CTRL, timerdiv1, 192) | - IO_FIELD(R_TIMER_CTRL, timerdiv0, TIMER0_DIV) | - IO_STATE(R_TIMER_CTRL, i1, nop) | - IO_STATE(R_TIMER_CTRL, tm1, run) | - IO_STATE(R_TIMER_CTRL, clksel1, c19k2Hz) | - IO_STATE(R_TIMER_CTRL, i0, nop) | - IO_STATE(R_TIMER_CTRL, tm0, run) | - IO_STATE(R_TIMER_CTRL, clksel0, flexible); - - *R_TIMER_PRESCALE = PRESCALE_VALUE; -#endif - - /* unmask the timer irq */ - *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer0, set); - - /* now actually register the irq handler that calls timer_interrupt() */ - setup_irq(2, &irq2); /* irq 2 is the timer0 irq in etrax */ - - /* enable watchdog if we should use one */ -#if defined(CONFIG_ETRAX_WATCHDOG) - printk("Enabling watchdog...\n"); - start_watchdog(); - - /* If we use the hardware watchdog, we want to trap it as an NMI - and dump registers before it resets us. For this to happen, we - must set the "m" NMI enable flag (which once set, is unset only - when an NMI is taken). - - The same goes for the external NMI, but that doesn't have any - driver or infrastructure support yet. */ - asm ("setf m"); - - *R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, watchdog_nmi, set); - *R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, nmi, set); -#endif -} diff --git a/arch/cris/arch-v10/kernel/traps.c b/arch/cris/arch-v10/kernel/traps.c deleted file mode 100644 index 876d45b957f4..000000000000 --- a/arch/cris/arch-v10/kernel/traps.c +++ /dev/null @@ -1,134 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Helper functions for trap handlers - * - * Copyright (C) 2000-2007, Axis Communications AB. - * - * Authors: Bjorn Wesen - * Hans-Peter Nilsson - * - */ - -#include <linux/ptrace.h> -#include <linux/uaccess.h> -#include <linux/sched/debug.h> - -#include <arch/sv_addr_ag.h> -#include <arch/system.h> - -void -show_registers(struct pt_regs *regs) -{ - /* - * It's possible to use either the USP register or current->thread.usp. - * USP might not correspond to the current process for all cases this - * function is called, and current->thread.usp isn't up to date for the - * current process. Experience shows that using USP is the way to go. - */ - unsigned long usp = rdusp(); - - printk("IRP: %08lx SRP: %08lx DCCR: %08lx USP: %08lx MOF: %08lx\n", - regs->irp, regs->srp, regs->dccr, usp, regs->mof); - - printk(" r0: %08lx r1: %08lx r2: %08lx r3: %08lx\n", - regs->r0, regs->r1, regs->r2, regs->r3); - - printk(" r4: %08lx r5: %08lx r6: %08lx r7: %08lx\n", - regs->r4, regs->r5, regs->r6, regs->r7); - - printk(" r8: %08lx r9: %08lx r10: %08lx r11: %08lx\n", - regs->r8, regs->r9, regs->r10, regs->r11); - - printk("r12: %08lx r13: %08lx oR10: %08lx sp: %08lx\n", - regs->r12, regs->r13, regs->orig_r10, (long unsigned)regs); - - printk("R_MMU_CAUSE: %08lx\n", (unsigned long)*R_MMU_CAUSE); - - printk("Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, (unsigned long)current); - - /* - * When in-kernel, we also print out the stack and code at the - * time of the fault.. - */ - if (!user_mode(regs)) { - int i; - - show_stack(NULL, (unsigned long *)usp); - - /* - * If the previous stack-dump wasn't a kernel one, dump the - * kernel stack now. - */ - if (usp != 0) - show_stack(NULL, NULL); - - printk("\nCode: "); - - if (regs->irp < PAGE_OFFSET) - goto bad_value; - - /* - * Quite often the value at regs->irp doesn't point to the - * interesting instruction, which often is the previous - * instruction. So dump at an offset large enough that the - * instruction decoding should be in sync at the interesting - * point, but small enough to fit on a row. The regs->irp - * location is pointed out in a ksymoops-friendly way by - * wrapping the byte for that address in parenthesises. - */ - for (i = -12; i < 12; i++) { - unsigned char c; - - if (__get_user(c, &((unsigned char *)regs->irp)[i])) { -bad_value: - printk(" Bad IP value."); - break; - } - - if (i == 0) - printk("(%02x) ", c); - else - printk("%02x ", c); - } - printk("\n"); - } -} - -void -arch_enable_nmi(void) -{ - asm volatile ("setf m"); -} - -extern void (*nmi_handler)(struct pt_regs *); -void handle_nmi(struct pt_regs *regs) -{ - if (nmi_handler) - nmi_handler(regs); - - /* Wait until nmi is no longer active. (We enable NMI immediately after - returning from this function, and we don't want it happening while - exiting from the NMI interrupt handler.) */ - while (*R_IRQ_MASK0_RD & IO_STATE(R_IRQ_MASK0_RD, nmi_pin, active)) - ; -} - -#ifdef CONFIG_DEBUG_BUGVERBOSE -void -handle_BUG(struct pt_regs *regs) -{ - struct bug_frame f; - unsigned char c; - unsigned long irp = regs->irp; - - if (__copy_from_user(&f, (const void __user *)(irp - 8), sizeof f)) - return; - if (f.prefix != BUG_PREFIX || f.magic != BUG_MAGIC) - return; - if (__get_user(c, f.filename)) - f.filename = "<bad filename>"; - - printk("kernel BUG at %s:%d!\n", f.filename, f.line); -} -#endif diff --git a/arch/cris/arch-v10/lib/Makefile b/arch/cris/arch-v10/lib/Makefile deleted file mode 100644 index 725153edb764..000000000000 --- a/arch/cris/arch-v10/lib/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for Etrax-specific library files.. -# - -lib-y = checksum.o checksumcopy.o string.o usercopy.o memset.o csumcpfruser.o - diff --git a/arch/cris/arch-v10/lib/checksum.S b/arch/cris/arch-v10/lib/checksum.S deleted file mode 100644 index a3b96391706f..000000000000 --- a/arch/cris/arch-v10/lib/checksum.S +++ /dev/null @@ -1,119 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * A fast checksum routine using movem - * Copyright (c) 1998-2001 Axis Communications AB - * - * csum_partial(const unsigned char * buff, int len, unsigned int sum) - */ - - .globl csum_partial -csum_partial: - - ;; r10 - src - ;; r11 - length - ;; r12 - checksum - - ;; check for breakeven length between movem and normal word looping versions - ;; we also do _NOT_ want to compute a checksum over more than the - ;; actual length when length < 40 - - cmpu.w 80,$r11 - blo _word_loop - nop - - ;; need to save the registers we use below in the movem loop - ;; this overhead is why we have a check above for breakeven length - ;; only r0 - r8 have to be saved, the other ones are clobber-able - ;; according to the ABI - - subq 9*4,$sp - movem $r8,[$sp] - - ;; do a movem checksum - - subq 10*4,$r11 ; update length for the first loop - -_mloop: movem [$r10+],$r9 ; read 10 longwords - - ;; perform dword checksumming on the 10 longwords - - add.d $r0,$r12 - ax - add.d $r1,$r12 - ax - add.d $r2,$r12 - ax - add.d $r3,$r12 - ax - add.d $r4,$r12 - ax - add.d $r5,$r12 - ax - add.d $r6,$r12 - ax - add.d $r7,$r12 - ax - add.d $r8,$r12 - ax - add.d $r9,$r12 - - ;; fold the carry into the checksum, to avoid having to loop the carry - ;; back into the top - - ax - addq 0,$r12 - - subq 10*4,$r11 - bge _mloop - nop - - addq 10*4,$r11 ; compensate for last loop underflowing length - - movem [$sp+],$r8 ; restore regs - -_word_loop: - ;; only fold if there is anything to fold. - - cmpq 0,$r12 - beq _no_fold - - ;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below. - ;; r9 and r13 can be used as temporaries. - - moveq -1,$r9 ; put 0xffff in r9, faster than move.d 0xffff,r9 - lsrq 16,$r9 - - move.d $r12,$r13 - lsrq 16,$r13 ; r13 = checksum >> 16 - and.d $r9,$r12 ; checksum = checksum & 0xffff - add.d $r13,$r12 ; checksum += r13 - -_no_fold: - cmpq 2,$r11 - blt _no_words - nop - - ;; checksum the rest of the words - - subq 2,$r11 - -_wloop: subq 2,$r11 - bge _wloop - addu.w [$r10+],$r12 - - addq 2,$r11 - -_no_words: - ;; see if we have one odd byte more - cmpq 1,$r11 - beq _do_byte - nop - ret - move.d $r12, $r10 - -_do_byte: - ;; copy and checksum the last byte - addu.b [$r10],$r12 - ret - move.d $r12, $r10 - diff --git a/arch/cris/arch-v10/lib/checksumcopy.S b/arch/cris/arch-v10/lib/checksumcopy.S deleted file mode 100644 index b21449cb1ad3..000000000000 --- a/arch/cris/arch-v10/lib/checksumcopy.S +++ /dev/null @@ -1,127 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * A fast checksum+copy routine using movem - * Copyright (c) 1998, 2001 Axis Communications AB - * - * Authors: Bjorn Wesen - * - * csum_partial_copy_nocheck(const char *src, char *dst, - * int len, unsigned int sum) - */ - - .globl csum_partial_copy_nocheck -csum_partial_copy_nocheck: - - ;; r10 - src - ;; r11 - dst - ;; r12 - length - ;; r13 - checksum - - ;; check for breakeven length between movem and normal word looping versions - ;; we also do _NOT_ want to compute a checksum over more than the - ;; actual length when length < 40 - - cmpu.w 80, $r12 - blo _word_loop - nop - - ;; need to save the registers we use below in the movem loop - ;; this overhead is why we have a check above for breakeven length - ;; only r0 - r8 have to be saved, the other ones are clobber-able - ;; according to the ABI - - subq 9*4, $sp - movem $r8, [$sp] - - ;; do a movem copy and checksum - - subq 10*4, $r12 ; update length for the first loop - -_mloop: movem [$r10+],$r9 ; read 10 longwords -1: ;; A failing userspace access will have this as PC. - movem $r9,[$r11+] ; write 10 longwords - - ;; perform dword checksumming on the 10 longwords - - add.d $r0,$r13 - ax - add.d $r1,$r13 - ax - add.d $r2,$r13 - ax - add.d $r3,$r13 - ax - add.d $r4,$r13 - ax - add.d $r5,$r13 - ax - add.d $r6,$r13 - ax - add.d $r7,$r13 - ax - add.d $r8,$r13 - ax - add.d $r9,$r13 - - ;; fold the carry into the checksum, to avoid having to loop the carry - ;; back into the top - - ax - addq 0,$r13 - - subq 10*4,$r12 - bge _mloop - nop - - addq 10*4,$r12 ; compensate for last loop underflowing length - - movem [$sp+],$r8 ; restore regs - -_word_loop: - ;; only fold if there is anything to fold. - - cmpq 0,$r13 - beq _no_fold - - ;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below - ;; r9 can be used as temporary. - - move.d $r13,$r9 - lsrq 16,$r9 ; r0 = checksum >> 16 - and.d 0xffff,$r13 ; checksum = checksum & 0xffff - add.d $r9,$r13 ; checksum += r0 - -_no_fold: - cmpq 2,$r12 - blt _no_words - nop - - ;; copy and checksum the rest of the words - - subq 2,$r12 - -_wloop: move.w [$r10+],$r9 -2: ;; A failing userspace access will have this as PC. - addu.w $r9,$r13 - subq 2,$r12 - bge _wloop - move.w $r9,[$r11+] - - addq 2,$r12 - -_no_words: - ;; see if we have one odd byte more - cmpq 1,$r12 - beq _do_byte - nop - ret - move.d $r13, $r10 - -_do_byte: - ;; copy and checksum the last byte - move.b [$r10],$r9 -3: ;; A failing userspace access will have this as PC. - addu.b $r9,$r13 - move.b $r9,[$r11] - ret - move.d $r13, $r10 diff --git a/arch/cris/arch-v10/lib/csumcpfruser.S b/arch/cris/arch-v10/lib/csumcpfruser.S deleted file mode 100644 index beb8992ed478..000000000000 --- a/arch/cris/arch-v10/lib/csumcpfruser.S +++ /dev/null @@ -1,65 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Add-on to transform csum_partial_copy_nocheck in checksumcopy.S into - * csum_partial_copy_from_user by adding exception records. - * - * Copyright (C) 2001 Axis Communications AB. - * - * Author: Hans-Peter Nilsson. - */ - -#include <asm/errno.h> - -/* Same function body, but a different name. If we just added exception - records to _csum_partial_copy_nocheck and made it generic, we wouldn't - know a user fault from a kernel fault and we would have overhead in - each kernel caller for the error-pointer argument. - - unsigned int csum_partial_copy_from_user - (const char *src, char *dst, int len, unsigned int sum, int *errptr); - - Note that the errptr argument is only set if we encounter an error. - It is conveniently located on the stack, so the normal function body - does not have to handle it. */ - -#define csum_partial_copy_nocheck csum_partial_copy_from_user - -/* There are local labels numbered 1, 2 and 3 present to mark the - different from-user accesses. */ -#include "checksumcopy.S" - - .section .fixup,"ax" - -;; Here from the movem loop; restore stack. -4: - movem [$sp+],$r8 -;; r12 is already decremented. Add back chunk_size-2. - addq 40-2,$r12 - -;; Here from the word loop; r12 is off by 2; add it back. -5: - addq 2,$r12 - -;; Here from a failing single byte. -6: - -;; Signal in *errptr that we had a failing access. - moveq -EFAULT,$r9 - move.d $r9,[[$sp]] - -;; Clear the rest of the destination area using memset. Preserve the -;; checksum for the readable bytes. - push $srp - push $r13 - move.d $r11,$r10 - clear.d $r11 - jsr memset - pop $r10 - jump [$sp+] - - .previous - .section __ex_table,"a" - .dword 1b,4b - .dword 2b,5b - .dword 3b,6b - .previous diff --git a/arch/cris/arch-v10/lib/dram_init.S b/arch/cris/arch-v10/lib/dram_init.S deleted file mode 100644 index fd7437577938..000000000000 --- a/arch/cris/arch-v10/lib/dram_init.S +++ /dev/null @@ -1,147 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * DRAM/SDRAM initialization - alter with care - * This file is intended to be included from other assembler files - * - * Note: This file may not modify r9 because r9 is used to carry - * information from the decompressor to the kernel - * - * Copyright (C) 2000-2012 Axis Communications AB - * - */ - -/* Just to be certain the config file is included, we include it here - * explicitly instead of depending on it being included in the file that - * uses this code. - */ - - - ;; WARNING! The registers r8 and r9 are used as parameters carrying - ;; information from the decompressor (if the kernel was compressed). - ;; They should not be used in the code below. - - move.d CONFIG_ETRAX_DEF_R_WAITSTATES, $r0 - move.d $r0, [R_WAITSTATES] - - move.d CONFIG_ETRAX_DEF_R_BUS_CONFIG, $r0 - move.d $r0, [R_BUS_CONFIG] - -#ifndef CONFIG_ETRAX_SDRAM - move.d CONFIG_ETRAX_DEF_R_DRAM_CONFIG, $r0 - move.d $r0, [R_DRAM_CONFIG] - - move.d CONFIG_ETRAX_DEF_R_DRAM_TIMING, $r0 - move.d $r0, [R_DRAM_TIMING] -#else - ;; Samsung SDRAMs seem to require to be initialized twice to work properly. - moveq 2, $r6 -_sdram_init: - - ; Refer to ETRAX 100LX Designers Reference for a description of SDRAM initialization - - ; Bank configuration - move.d CONFIG_ETRAX_DEF_R_SDRAM_CONFIG, $r0 - move.d $r0, [R_SDRAM_CONFIG] - - ; Calculate value of mrs_data - ; CAS latency = 2 && bus_width = 32 => 0x40 - ; CAS latency = 3 && bus_width = 32 => 0x60 - ; CAS latency = 2 && bus_width = 16 => 0x20 - ; CAS latency = 3 && bus_width = 16 => 0x30 - - ; Check if value is already supplied in kernel config - move.d CONFIG_ETRAX_DEF_R_SDRAM_TIMING, $r2 - and.d 0x00ff0000, $r2 - bne _set_timing - lsrq 16, $r2 - - move.d 0x40, $r2 ; Assume 32 bits and CAS latency = 2 - move.d CONFIG_ETRAX_DEF_R_SDRAM_TIMING, $r1 - move.d $r1, $r3 - and.d 0x03, $r1 ; Get CAS latency - and.d 0x1000, $r3 ; 50 or 100 MHz? - beq _speed_50 - nop -_speed_100: - cmp.d 0x00, $r1 ; CAS latency = 2? - beq _bw_check - nop - or.d 0x20, $r2 ; CAS latency = 3 - ba _bw_check - nop -_speed_50: - cmp.d 0x01, $r1 ; CAS latency = 2? - beq _bw_check - nop - or.d 0x20, $r2 ; CAS latency = 3 -_bw_check: - move.d CONFIG_ETRAX_DEF_R_SDRAM_CONFIG, $r1 - and.d 0x800000, $r1 ; DRAM width is bit 23 - bne _set_timing - nop - lsrq 1, $r2 ; 16 bits. Shift down value. - - ; Set timing parameters. Starts master clock -_set_timing: - move.d CONFIG_ETRAX_DEF_R_SDRAM_TIMING, $r1 - and.d 0x8000f9ff, $r1 ; Make sure mrs data and command is 0 - or.d 0x80000000, $r1 ; Make sure sdram enable bit is set - move.d $r1, $r5 - or.d 0x0000c000, $r1 ; ref = disable - lslq 16, $r2 ; mrs data starts at bit 16 - or.d $r2, $r1 - move.d $r1, [R_SDRAM_TIMING] - - ; Wait 200us - move.d 10000, $r2 -1: bne 1b - subq 1, $r2 - - ; Issue initialization command sequence - move.d _sdram_commands_start, $r2 - and.d 0x000fffff, $r2 ; Make sure commands are read from flash - move.d _sdram_commands_end, $r3 - and.d 0x000fffff, $r3 -1: clear.d $r4 - move.b [$r2+], $r4 - lslq 9, $r4 ; Command starts at bit 9 - or.d $r1, $r4 - move.d $r4, [R_SDRAM_TIMING] - nop ; Wait five nop cycles between each command - nop - nop - nop - nop - cmp.d $r2, $r3 - bne 1b - nop - move.d $r5, [R_SDRAM_TIMING] - subq 1, $r6 - bne _sdram_init - nop - ba _sdram_commands_end - nop - -_sdram_commands_start: - .byte 3 ; Precharge - .byte 0 ; nop - .byte 2 ; refresh - .byte 0 ; nop - .byte 2 ; refresh - .byte 0 ; nop - .byte 2 ; refresh - .byte 0 ; nop - .byte 2 ; refresh - .byte 0 ; nop - .byte 2 ; refresh - .byte 0 ; nop - .byte 2 ; refresh - .byte 0 ; nop - .byte 2 ; refresh - .byte 0 ; nop - .byte 2 ; refresh - .byte 0 ; nop - .byte 1 ; mrs - .byte 0 ; nop -_sdram_commands_end: -#endif diff --git a/arch/cris/arch-v10/lib/hw_settings.S b/arch/cris/arch-v10/lib/hw_settings.S deleted file mode 100644 index 0d449852517e..000000000000 --- a/arch/cris/arch-v10/lib/hw_settings.S +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * This table is used by some tools to extract hardware parameters. - * The table should be included in the kernel and the decompressor. - * Don't forget to update the tools if you change this table. - * - * Copyright (C) 2001 Axis Communications AB - * - * Authors: Mikael Starvik (starvik@axis.com) - */ - -#define PA_SET_VALUE ((CONFIG_ETRAX_DEF_R_PORT_PA_DIR << 8) | \ - (CONFIG_ETRAX_DEF_R_PORT_PA_DATA)) -#define PB_SET_VALUE ((CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG << 16) | \ - (CONFIG_ETRAX_DEF_R_PORT_PB_DIR << 8) | \ - (CONFIG_ETRAX_DEF_R_PORT_PB_DATA)) - - .ascii "HW_PARAM_MAGIC" ; Magic number - .dword 0xc0004000 ; Kernel start address - - ; Debug port -#ifdef CONFIG_ETRAX_DEBUG_PORT0 - .dword 0 -#elif defined(CONFIG_ETRAX_DEBUG_PORT1) - .dword 1 -#elif defined(CONFIG_ETRAX_DEBUG_PORT2) - .dword 2 -#elif defined(CONFIG_ETRAX_DEBUG_PORT3) - .dword 3 -#else - .dword 4 ; No debug -#endif - - ; SDRAM or EDO DRAM? -#ifdef CONFIG_ETRAX_SDRAM - .dword 1 -#else - .dword 0 -#endif - - ; Register values - .dword R_WAITSTATES - .dword CONFIG_ETRAX_DEF_R_WAITSTATES - .dword R_BUS_CONFIG - .dword CONFIG_ETRAX_DEF_R_BUS_CONFIG -#ifdef CONFIG_ETRAX_SDRAM - .dword R_SDRAM_CONFIG - .dword CONFIG_ETRAX_DEF_R_SDRAM_CONFIG - .dword R_SDRAM_TIMING - .dword CONFIG_ETRAX_DEF_R_SDRAM_TIMING -#else - .dword R_DRAM_CONFIG - .dword CONFIG_ETRAX_DEF_R_DRAM_CONFIG - .dword R_DRAM_TIMING - .dword CONFIG_ETRAX_DEF_R_DRAM_TIMING -#endif - .dword R_PORT_PA_SET - .dword PA_SET_VALUE - .dword R_PORT_PB_SET - .dword PB_SET_VALUE - .dword 0 ; No more register values diff --git a/arch/cris/arch-v10/lib/memset.c b/arch/cris/arch-v10/lib/memset.c deleted file mode 100644 index c94ea9b3ec29..000000000000 --- a/arch/cris/arch-v10/lib/memset.c +++ /dev/null @@ -1,259 +0,0 @@ -/* A memset for CRIS. - Copyright (C) 1999-2005 Axis Communications. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Neither the name of Axis Communications nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS - COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. */ - -/* FIXME: This file should really only be used for reference, as the - result is somewhat depending on gcc generating what we expect rather - than what we describe. An assembly file should be used instead. */ - -/* Note the multiple occurrence of the expression "12*4", including the - asm. It is hard to get it into the asm in a good way. Thus better to - expose the problem everywhere: no macro. */ - -/* Assuming one cycle per dword written or read (ok, not really true; the - world is not ideal), and one cycle per instruction, then 43+3*(n/48-1) - <= 24+24*(n/48-1) so n >= 45.7; n >= 0.9; we win on the first full - 48-byte block to set. */ - -#define MEMSET_BY_BLOCK_THRESHOLD (1 * 48) - -/* No name ambiguities in this file. */ -__asm__ (".syntax no_register_prefix"); - -void *memset(void *pdst, int c, unsigned int plen) -{ - /* Now we want the parameters in special registers. Make sure the - compiler does something usable with this. */ - - register char *return_dst __asm__ ("r10") = pdst; - register int n __asm__ ("r12") = plen; - register int lc __asm__ ("r11") = c; - - /* Most apps use memset sanely. Memsetting about 3..4 bytes or less get - penalized here compared to the generic implementation. */ - - /* This is fragile performancewise at best. Check with newer GCC - releases, if they compile cascaded "x |= x << 8" to sane code. */ - __asm__("movu.b %0,r13 \n\ - lslq 8,r13 \n\ - move.b %0,r13 \n\ - move.d r13,%0 \n\ - lslq 16,r13 \n\ - or.d r13,%0" - : "=r" (lc) /* Inputs. */ - : "0" (lc) /* Outputs. */ - : "r13"); /* Trash. */ - - { - register char *dst __asm__ ("r13") = pdst; - - if (((unsigned long) pdst & 3) != 0 - /* Oops! n = 0 must be a valid call, regardless of alignment. */ - && n >= 3) - { - if ((unsigned long) dst & 1) - { - *dst = (char) lc; - n--; - dst++; - } - - if ((unsigned long) dst & 2) - { - *(short *) dst = lc; - n -= 2; - dst += 2; - } - } - - /* Decide which setting method to use. */ - if (n >= MEMSET_BY_BLOCK_THRESHOLD) - { - /* It is not optimal to tell the compiler about clobbering any - registers; that will move the saving/restoring of those registers - to the function prologue/epilogue, and make non-block sizes - suboptimal. */ - __asm__ volatile - ("\ - ;; GCC does promise correct register allocations, but let's \n\ - ;; make sure it keeps its promises. \n\ - .ifnc %0-%1-%4,$r13-$r12-$r11 \n\ - .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\ - .endif \n\ - \n\ - ;; Save the registers we'll clobber in the movem process \n\ - ;; on the stack. Don't mention them to gcc, it will only be \n\ - ;; upset. \n\ - subq 11*4,sp \n\ - movem r10,[sp] \n\ - \n\ - move.d r11,r0 \n\ - move.d r11,r1 \n\ - move.d r11,r2 \n\ - move.d r11,r3 \n\ - move.d r11,r4 \n\ - move.d r11,r5 \n\ - move.d r11,r6 \n\ - move.d r11,r7 \n\ - move.d r11,r8 \n\ - move.d r11,r9 \n\ - move.d r11,r10 \n\ - \n\ - ;; Now we've got this: \n\ - ;; r13 - dst \n\ - ;; r12 - n \n\ - \n\ - ;; Update n for the first loop \n\ - subq 12*4,r12 \n\ -0: \n\ -" -#ifdef __arch_common_v10_v32 - /* Cater to branch offset difference between v32 and v10. We - assume the branch below has an 8-bit offset. */ -" setf\n" -#endif -" subq 12*4,r12 \n\ - bge 0b \n\ - movem r11,[r13+] \n\ - \n\ - ;; Compensate for last loop underflowing n. \n\ - addq 12*4,r12 \n\ - \n\ - ;; Restore registers from stack. \n\ - movem [sp+],r10" - - /* Outputs. */ - : "=r" (dst), "=r" (n) - - /* Inputs. */ - : "0" (dst), "1" (n), "r" (lc)); - } - - /* An ad-hoc unroll, used for 4*12-1..16 bytes. */ - while (n >= 16) - { - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - n -= 16; - } - - switch (n) - { - case 0: - break; - - case 1: - *dst = (char) lc; - break; - - case 2: - *(short *) dst = (short) lc; - break; - - case 3: - *(short *) dst = (short) lc; dst += 2; - *dst = (char) lc; - break; - - case 4: - *(long *) dst = lc; - break; - - case 5: - *(long *) dst = lc; dst += 4; - *dst = (char) lc; - break; - - case 6: - *(long *) dst = lc; dst += 4; - *(short *) dst = (short) lc; - break; - - case 7: - *(long *) dst = lc; dst += 4; - *(short *) dst = (short) lc; dst += 2; - *dst = (char) lc; - break; - - case 8: - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; - break; - - case 9: - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *dst = (char) lc; - break; - - case 10: - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *(short *) dst = (short) lc; - break; - - case 11: - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *(short *) dst = (short) lc; dst += 2; - *dst = (char) lc; - break; - - case 12: - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; - break; - - case 13: - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *dst = (char) lc; - break; - - case 14: - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *(short *) dst = (short) lc; - break; - - case 15: - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *(long *) dst = lc; dst += 4; - *(short *) dst = (short) lc; dst += 2; - *dst = (char) lc; - break; - } - } - - return return_dst; -} diff --git a/arch/cris/arch-v10/lib/string.c b/arch/cris/arch-v10/lib/string.c deleted file mode 100644 index c7bd6ebdc93c..000000000000 --- a/arch/cris/arch-v10/lib/string.c +++ /dev/null @@ -1,236 +0,0 @@ -/* A memcpy for CRIS. - Copyright (C) 1994-2005 Axis Communications. - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Neither the name of Axis Communications nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS - COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. */ - -/* FIXME: This file should really only be used for reference, as the - result is somewhat depending on gcc generating what we expect rather - than what we describe. An assembly file should be used instead. */ - -#include <stddef.h> - -/* Break even between movem and move16 is really at 38.7 * 2, but - modulo 44, so up to the next multiple of 44, we use ordinary code. */ -#define MEMCPY_BY_BLOCK_THRESHOLD (44 * 2) - -/* No name ambiguities in this file. */ -__asm__ (".syntax no_register_prefix"); - -void * -memcpy(void *pdst, const void *psrc, size_t pn) -{ - /* Now we want the parameters put in special registers. - Make sure the compiler is able to make something useful of this. - As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop). - - If gcc was allright, it really would need no temporaries, and no - stack space to save stuff on. */ - - register void *return_dst __asm__ ("r10") = pdst; - register unsigned char *dst __asm__ ("r13") = pdst; - register unsigned const char *src __asm__ ("r11") = psrc; - register int n __asm__ ("r12") = pn; - - /* When src is aligned but not dst, this makes a few extra needless - cycles. I believe it would take as many to check that the - re-alignment was unnecessary. */ - if (((unsigned long) dst & 3) != 0 - /* Don't align if we wouldn't copy more than a few bytes; so we - don't have to check further for overflows. */ - && n >= 3) - { - if ((unsigned long) dst & 1) - { - n--; - *dst = *src; - src++; - dst++; - } - - if ((unsigned long) dst & 2) - { - n -= 2; - *(short *) dst = *(short *) src; - src += 2; - dst += 2; - } - } - - /* Decide which copying method to use. */ - if (n >= MEMCPY_BY_BLOCK_THRESHOLD) - { - /* It is not optimal to tell the compiler about clobbering any - registers; that will move the saving/restoring of those registers - to the function prologue/epilogue, and make non-movem sizes - suboptimal. */ - __asm__ volatile - ("\ - ;; GCC does promise correct register allocations, but let's \n\ - ;; make sure it keeps its promises. \n\ - .ifnc %0-%1-%2,$r13-$r11-$r12 \n\ - .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\ - .endif \n\ - \n\ - ;; Save the registers we'll use in the movem process \n\ - ;; on the stack. \n\ - subq 11*4,sp \n\ - movem r10,[sp] \n\ - \n\ - ;; Now we've got this: \n\ - ;; r11 - src \n\ - ;; r13 - dst \n\ - ;; r12 - n \n\ - \n\ - ;; Update n for the first loop. \n\ - subq 44,r12 \n\ -0: \n\ -" -#ifdef __arch_common_v10_v32 - /* Cater to branch offset difference between v32 and v10. We - assume the branch below has an 8-bit offset. */ -" setf\n" -#endif -" movem [r11+],r10 \n\ - subq 44,r12 \n\ - bge 0b \n\ - movem r10,[r13+] \n\ - \n\ - ;; Compensate for last loop underflowing n. \n\ - addq 44,r12 \n\ - \n\ - ;; Restore registers from stack. \n\ - movem [sp+],r10" - - /* Outputs. */ - : "=r" (dst), "=r" (src), "=r" (n) - - /* Inputs. */ - : "0" (dst), "1" (src), "2" (n)); - } - - while (n >= 16) - { - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - - n -= 16; - } - - switch (n) - { - case 0: - break; - - case 1: - *dst = *src; - break; - - case 2: - *(short *) dst = *(short *) src; - break; - - case 3: - *(short *) dst = *(short *) src; dst += 2; src += 2; - *dst = *src; - break; - - case 4: - *(long *) dst = *(long *) src; - break; - - case 5: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *dst = *src; - break; - - case 6: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(short *) dst = *(short *) src; - break; - - case 7: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(short *) dst = *(short *) src; dst += 2; src += 2; - *dst = *src; - break; - - case 8: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; - break; - - case 9: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *dst = *src; - break; - - case 10: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(short *) dst = *(short *) src; - break; - - case 11: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(short *) dst = *(short *) src; dst += 2; src += 2; - *dst = *src; - break; - - case 12: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; - break; - - case 13: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *dst = *src; - break; - - case 14: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(short *) dst = *(short *) src; - break; - - case 15: - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(long *) dst = *(long *) src; dst += 4; src += 4; - *(short *) dst = *(short *) src; dst += 2; src += 2; - *dst = *src; - break; - } - - return return_dst; -} diff --git a/arch/cris/arch-v10/lib/usercopy.c b/arch/cris/arch-v10/lib/usercopy.c deleted file mode 100644 index 3f1e2f4680f7..000000000000 --- a/arch/cris/arch-v10/lib/usercopy.c +++ /dev/null @@ -1,511 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * User address space access functions. - * The non-inlined parts of asm-cris/uaccess.h are here. - * - * Copyright (C) 2000, Axis Communications AB. - * - * Written by Hans-Peter Nilsson. - * Pieces used from memcpy, originally by Kenny Ranerup long time ago. - */ - -#include <linux/uaccess.h> - -/* Asm:s have been tweaked (within the domain of correctness) to give - satisfactory results for "gcc version 2.96 20000427 (experimental)". - - Check regularly... - - Note that the PC saved at a bus-fault is the address *after* the - faulting instruction, which means the branch-target for instructions in - delay-slots for taken branches. Note also that the postincrement in - the instruction is performed regardless of bus-fault; the register is - seen updated in fault handlers. - - Oh, and on the code formatting issue, to whomever feels like "fixing - it" to Conformity: I'm too "lazy", but why don't you go ahead and "fix" - string.c too. I just don't think too many people will hack this file - for the code format to be an issue. */ - - -/* Copy to userspace. This is based on the memcpy used for - kernel-to-kernel copying; see "string.c". */ - -unsigned long __copy_user(void __user *pdst, const void *psrc, unsigned long pn) -{ - /* We want the parameters put in special registers. - Make sure the compiler is able to make something useful of this. - As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop). - - FIXME: Comment for old gcc version. Check. - If gcc was alright, it really would need no temporaries, and no - stack space to save stuff on. */ - - register char *dst __asm__ ("r13") = pdst; - register const char *src __asm__ ("r11") = psrc; - register int n __asm__ ("r12") = pn; - register int retn __asm__ ("r10") = 0; - - - /* When src is aligned but not dst, this makes a few extra needless - cycles. I believe it would take as many to check that the - re-alignment was unnecessary. */ - if (((unsigned long) dst & 3) != 0 - /* Don't align if we wouldn't copy more than a few bytes; so we - don't have to check further for overflows. */ - && n >= 3) - { - if ((unsigned long) dst & 1) - { - __asm_copy_to_user_1 (dst, src, retn); - n--; - } - - if ((unsigned long) dst & 2) - { - __asm_copy_to_user_2 (dst, src, retn); - n -= 2; - } - } - - /* Decide which copying method to use. */ - if (n >= 44*2) /* Break even between movem and - move16 is at 38.7*2, but modulo 44. */ - { - /* For large copies we use 'movem'. */ - - /* It is not optimal to tell the compiler about clobbering any - registers; that will move the saving/restoring of those registers - to the function prologue/epilogue, and make non-movem sizes - suboptimal. - - This method is not foolproof; it assumes that the "asm reg" - declarations at the beginning of the function really are used - here (beware: they may be moved to temporary registers). - This way, we do not have to save/move the registers around into - temporaries; we can safely use them straight away. - - If you want to check that the allocation was right; then - check the equalities in the first comment. It should say - "r13=r13, r11=r11, r12=r12". */ - __asm__ volatile ("\ - .ifnc %0%1%2%3,$r13$r11$r12$r10 \n\ - .err \n\ - .endif \n\ - \n\ - ;; Save the registers we'll use in the movem process \n\ - ;; on the stack. \n\ - subq 11*4,$sp \n\ - movem $r10,[$sp] \n\ - \n\ - ;; Now we've got this: \n\ - ;; r11 - src \n\ - ;; r13 - dst \n\ - ;; r12 - n \n\ - \n\ - ;; Update n for the first loop \n\ - subq 44,$r12 \n\ - \n\ -; Since the noted PC of a faulting instruction in a delay-slot of a taken \n\ -; branch, is that of the branch target, we actually point at the from-movem \n\ -; for this case. There is no ambiguity here; if there was a fault in that \n\ -; instruction (meaning a kernel oops), the faulted PC would be the address \n\ -; after *that* movem. \n\ - \n\ -0: \n\ - movem [$r11+],$r10 \n\ - subq 44,$r12 \n\ - bge 0b \n\ - movem $r10,[$r13+] \n\ -1: \n\ - addq 44,$r12 ;; compensate for last loop underflowing n \n\ - \n\ - ;; Restore registers from stack \n\ - movem [$sp+],$r10 \n\ -2: \n\ - .section .fixup,\"ax\" \n\ - \n\ -; To provide a correct count in r10 of bytes that failed to be copied, \n\ -; we jump back into the loop if the loop-branch was taken. There is no \n\ -; performance penalty for sany use; the program will segfault soon enough.\n\ - \n\ -3: \n\ - move.d [$sp],$r10 \n\ - addq 44,$r10 \n\ - move.d $r10,[$sp] \n\ - jump 0b \n\ -4: \n\ - movem [$sp+],$r10 \n\ - addq 44,$r10 \n\ - addq 44,$r12 \n\ - jump 2b \n\ - \n\ - .previous \n\ - .section __ex_table,\"a\" \n\ - .dword 0b,3b \n\ - .dword 1b,4b \n\ - .previous" - - /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn) - /* Inputs */ : "0" (dst), "1" (src), "2" (n), "3" (retn)); - - } - - /* Either we directly start copying, using dword copying in a loop, or - we copy as much as possible with 'movem' and then the last block (<44 - bytes) is copied here. This will work since 'movem' will have - updated SRC, DST and N. */ - - while (n >= 16) - { - __asm_copy_to_user_16 (dst, src, retn); - n -= 16; - } - - /* Having a separate by-four loops cuts down on cache footprint. - FIXME: Test with and without; increasing switch to be 0..15. */ - while (n >= 4) - { - __asm_copy_to_user_4 (dst, src, retn); - n -= 4; - } - - switch (n) - { - case 0: - break; - case 1: - __asm_copy_to_user_1 (dst, src, retn); - break; - case 2: - __asm_copy_to_user_2 (dst, src, retn); - break; - case 3: - __asm_copy_to_user_3 (dst, src, retn); - break; - } - - return retn; -} -EXPORT_SYMBOL(__copy_user); - -/* Copy from user to kernel. The return-value is the number of bytes that were - inaccessible. */ - -unsigned long __copy_user_in(void *pdst, const void __user *psrc, - unsigned long pn) -{ - /* We want the parameters put in special registers. - Make sure the compiler is able to make something useful of this. - As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop). - - FIXME: Comment for old gcc version. Check. - If gcc was alright, it really would need no temporaries, and no - stack space to save stuff on. */ - - register char *dst __asm__ ("r13") = pdst; - register const char *src __asm__ ("r11") = psrc; - register int n __asm__ ("r12") = pn; - register int retn __asm__ ("r10") = 0; - - /* The best reason to align src is that we then know that a read-fault - was for aligned bytes; there's no 1..3 remaining good bytes to - pickle. */ - if (((unsigned long) src & 3) != 0) - { - if (((unsigned long) src & 1) && n != 0) - { - __asm_copy_from_user_1 (dst, src, retn); - n--; - if (retn) - goto exception; - } - - if (((unsigned long) src & 2) && n >= 2) - { - __asm_copy_from_user_2 (dst, src, retn); - n -= 2; - if (retn) - goto exception; - } - } - - /* Decide which copying method to use. */ - if (n >= 44*2) /* Break even between movem and - move16 is at 38.7*2, but modulo 44. - FIXME: We use move4 now. */ - { - /* For large copies we use 'movem' */ - - /* It is not optimal to tell the compiler about clobbering any - registers; that will move the saving/restoring of those registers - to the function prologue/epilogue, and make non-movem sizes - suboptimal. - - This method is not foolproof; it assumes that the "asm reg" - declarations at the beginning of the function really are used - here (beware: they may be moved to temporary registers). - This way, we do not have to save/move the registers around into - temporaries; we can safely use them straight away. - - If you want to check that the allocation was right; then - check the equalities in the first comment. It should say - "r13=r13, r11=r11, r12=r12" */ - __asm__ volatile ("\n\ - .ifnc %0%1%2%3,$r13$r11$r12$r10 \n\ - .err \n\ - .endif \n\ - \n\ - ;; Save the registers we'll use in the movem process \n\ - ;; on the stack. \n\ - subq 11*4,$sp \n\ - movem $r10,[$sp] \n\ - \n\ - ;; Now we've got this: \n\ - ;; r11 - src \n\ - ;; r13 - dst \n\ - ;; r12 - n \n\ - \n\ - ;; Update n for the first loop \n\ - subq 44,$r12 \n\ -0: \n\ - movem [$r11+],$r10 \n\ -1: \n\ - subq 44,$r12 \n\ - bge 0b \n\ - movem $r10,[$r13+] \n\ - \n\ - addq 44,$r12 ;; compensate for last loop underflowing n \n\ - \n\ - ;; Restore registers from stack \n\ - movem [$sp+],$r10 \n\ -4: \n\ - .section .fixup,\"ax\" \n\ - \n\ -;; Do not jump back into the loop if we fail. For some uses, we get a \n\ -;; page fault somewhere on the line. Without checking for page limits, \n\ -;; we don't know where, but we need to copy accurately and keep an \n\ -;; accurate count; not just clear the whole line. To do that, we fall \n\ -;; down in the code below, proceeding with smaller amounts. It should \n\ -;; be kept in mind that we have to cater to code like what at one time \n\ -;; was in fs/super.c: \n\ -;; i = size - copy_from_user((void *)page, data, size); \n\ -;; which would cause repeated faults while clearing the remainder of \n\ -;; the SIZE bytes at PAGE after the first fault. \n\ -;; A caveat here is that we must not fall through from a failing page \n\ -;; to a valid page. \n\ - \n\ -3: \n\ - movem [$sp+],$r10 \n\ - addq 44,$r12 ;; Get back count before faulting point. \n\ - subq 44,$r11 ;; Get back pointer to faulting movem-line. \n\ - jump 4b ;; Fall through, pretending the fault didn't happen.\n\ - \n\ - .previous \n\ - .section __ex_table,\"a\" \n\ - .dword 1b,3b \n\ - .previous" - - /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn) - /* Inputs */ : "0" (dst), "1" (src), "2" (n), "3" (retn)); - - } - - /* Either we directly start copying here, using dword copying in a loop, - or we copy as much as possible with 'movem' and then the last block - (<44 bytes) is copied here. This will work since 'movem' will have - updated src, dst and n. (Except with failing src.) - - Since we want to keep src accurate, we can't use - __asm_copy_from_user_N with N != (1, 2, 4); it updates dst and - retn, but not src (by design; it's value is ignored elsewhere). */ - - while (n >= 4) - { - __asm_copy_from_user_4 (dst, src, retn); - n -= 4; - - if (retn) - goto exception; - } - - /* If we get here, there were no memory read faults. */ - switch (n) - { - /* These copies are at least "naturally aligned" (so we don't have - to check each byte), due to the src alignment code before the - movem loop. The *_3 case *will* get the correct count for retn. */ - case 0: - /* This case deliberately left in (if you have doubts check the - generated assembly code). */ - break; - case 1: - __asm_copy_from_user_1 (dst, src, retn); - break; - case 2: - __asm_copy_from_user_2 (dst, src, retn); - break; - case 3: - __asm_copy_from_user_3 (dst, src, retn); - break; - } - - /* If we get here, retn correctly reflects the number of failing - bytes. */ - return retn; - -exception: - return retn + n; -} -EXPORT_SYMBOL(__copy_user_in); - -/* Zero userspace. */ -unsigned long __do_clear_user(void __user *pto, unsigned long pn) -{ - /* We want the parameters put in special registers. - Make sure the compiler is able to make something useful of this. - As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop). - - FIXME: Comment for old gcc version. Check. - If gcc was alright, it really would need no temporaries, and no - stack space to save stuff on. */ - - register char *dst __asm__ ("r13") = pto; - register int n __asm__ ("r12") = pn; - register int retn __asm__ ("r10") = 0; - - - if (((unsigned long) dst & 3) != 0 - /* Don't align if we wouldn't copy more than a few bytes. */ - && n >= 3) - { - if ((unsigned long) dst & 1) - { - __asm_clear_1 (dst, retn); - n--; - } - - if ((unsigned long) dst & 2) - { - __asm_clear_2 (dst, retn); - n -= 2; - } - } - - /* Decide which copying method to use. - FIXME: This number is from the "ordinary" kernel memset. */ - if (n >= (1*48)) - { - /* For large clears we use 'movem' */ - - /* It is not optimal to tell the compiler about clobbering any - call-saved registers; that will move the saving/restoring of - those registers to the function prologue/epilogue, and make - non-movem sizes suboptimal. - - This method is not foolproof; it assumes that the "asm reg" - declarations at the beginning of the function really are used - here (beware: they may be moved to temporary registers). - This way, we do not have to save/move the registers around into - temporaries; we can safely use them straight away. - - If you want to check that the allocation was right; then - check the equalities in the first comment. It should say - something like "r13=r13, r11=r11, r12=r12". */ - __asm__ volatile ("\n\ - .ifnc %0%1%2,$r13$r12$r10 \n\ - .err \n\ - .endif \n\ - \n\ - ;; Save the registers we'll clobber in the movem process \n\ - ;; on the stack. Don't mention them to gcc, it will only be \n\ - ;; upset. \n\ - subq 11*4,$sp \n\ - movem $r10,[$sp] \n\ - \n\ - clear.d $r0 \n\ - clear.d $r1 \n\ - clear.d $r2 \n\ - clear.d $r3 \n\ - clear.d $r4 \n\ - clear.d $r5 \n\ - clear.d $r6 \n\ - clear.d $r7 \n\ - clear.d $r8 \n\ - clear.d $r9 \n\ - clear.d $r10 \n\ - clear.d $r11 \n\ - \n\ - ;; Now we've got this: \n\ - ;; r13 - dst \n\ - ;; r12 - n \n\ - \n\ - ;; Update n for the first loop \n\ - subq 12*4,$r12 \n\ -0: \n\ - subq 12*4,$r12 \n\ - bge 0b \n\ - movem $r11,[$r13+] \n\ -1: \n\ - addq 12*4,$r12 ;; compensate for last loop underflowing n\n\ - \n\ - ;; Restore registers from stack \n\ - movem [$sp+],$r10 \n\ -2: \n\ - .section .fixup,\"ax\" \n\ -3: \n\ - move.d [$sp],$r10 \n\ - addq 12*4,$r10 \n\ - move.d $r10,[$sp] \n\ - clear.d $r10 \n\ - jump 0b \n\ - \n\ -4: \n\ - movem [$sp+],$r10 \n\ - addq 12*4,$r10 \n\ - addq 12*4,$r12 \n\ - jump 2b \n\ - \n\ - .previous \n\ - .section __ex_table,\"a\" \n\ - .dword 0b,3b \n\ - .dword 1b,4b \n\ - .previous" - - /* Outputs */ : "=r" (dst), "=r" (n), "=r" (retn) - /* Inputs */ : "0" (dst), "1" (n), "2" (retn) - /* Clobber */ : "r11"); - } - - while (n >= 16) - { - __asm_clear_16 (dst, retn); - n -= 16; - } - - /* Having a separate by-four loops cuts down on cache footprint. - FIXME: Test with and without; increasing switch to be 0..15. */ - while (n >= 4) - { - __asm_clear_4 (dst, retn); - n -= 4; - } - - switch (n) - { - case 0: - break; - case 1: - __asm_clear_1 (dst, retn); - break; - case 2: - __asm_clear_2 (dst, retn); - break; - case 3: - __asm_clear_3 (dst, retn); - break; - } - - return retn; -} -EXPORT_SYMBOL(__do_clear_user); diff --git a/arch/cris/arch-v10/mm/Makefile b/arch/cris/arch-v10/mm/Makefile deleted file mode 100644 index 588b4baee85e..000000000000 --- a/arch/cris/arch-v10/mm/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# -# Makefile for the linux cris-specific parts of the memory manager. -# - -obj-y := fault.o init.o tlb.o - diff --git a/arch/cris/arch-v10/mm/fault.c b/arch/cris/arch-v10/mm/fault.c deleted file mode 100644 index e6c225169642..000000000000 --- a/arch/cris/arch-v10/mm/fault.c +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/mm/fault.c - * - * Low level bus fault handler - * - * - * Copyright (C) 2000-2007 Axis Communications AB - * - * Authors: Bjorn Wesen - * - */ - -#include <linux/mm.h> -#include <linux/uaccess.h> -#include <asm/pgtable.h> -#include <arch/svinto.h> -#include <asm/mmu_context.h> - -/* debug of low-level TLB reload */ -#undef DEBUG - -#ifdef DEBUG -#define D(x) x -#else -#define D(x) -#endif - -extern const struct exception_table_entry - *search_exception_tables(unsigned long addr); - -asmlinkage void do_page_fault(unsigned long address, struct pt_regs *regs, - int protection, int writeaccess); - -/* fast TLB-fill fault handler - * this is called from entry.S with interrupts disabled - */ - -void -handle_mmu_bus_fault(struct pt_regs *regs) -{ - int cause; - int select; -#ifdef DEBUG - int index; - int page_id; - int acc, inv; -#endif - pgd_t* pgd = (pgd_t*)per_cpu(current_pgd, smp_processor_id()); - pmd_t *pmd; - pte_t pte; - int miss, we, writeac; - unsigned long address; - unsigned long flags; - - cause = *R_MMU_CAUSE; - - address = cause & PAGE_MASK; /* get faulting address */ - select = *R_TLB_SELECT; - -#ifdef DEBUG - page_id = IO_EXTRACT(R_MMU_CAUSE, page_id, cause); - acc = IO_EXTRACT(R_MMU_CAUSE, acc_excp, cause); - inv = IO_EXTRACT(R_MMU_CAUSE, inv_excp, cause); - index = IO_EXTRACT(R_TLB_SELECT, index, select); -#endif - miss = IO_EXTRACT(R_MMU_CAUSE, miss_excp, cause); - we = IO_EXTRACT(R_MMU_CAUSE, we_excp, cause); - writeac = IO_EXTRACT(R_MMU_CAUSE, wr_rd, cause); - - D(printk("bus_fault from IRP 0x%lx: addr 0x%lx, miss %d, inv %d, we %d, acc %d, dx %d pid %d\n", - regs->irp, address, miss, inv, we, acc, index, page_id)); - - /* leave it to the MM system fault handler */ - if (miss) - do_page_fault(address, regs, 0, writeac); - else - do_page_fault(address, regs, 1, we); - - /* Reload TLB with new entry to avoid an extra miss exception. - * do_page_fault may have flushed the TLB so we have to restore - * the MMU registers. - */ - local_irq_save(flags); - pmd = (pmd_t *)(pgd + pgd_index(address)); - if (pmd_none(*pmd)) - goto exit; - pte = *pte_offset_kernel(pmd, address); - if (!pte_present(pte)) - goto exit; - *R_TLB_SELECT = select; - *R_TLB_HI = cause; - *R_TLB_LO = pte_val(pte); -exit: - local_irq_restore(flags); -} diff --git a/arch/cris/arch-v10/mm/init.c b/arch/cris/arch-v10/mm/init.c deleted file mode 100644 index 4da99a0e3b57..000000000000 --- a/arch/cris/arch-v10/mm/init.c +++ /dev/null @@ -1,256 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/arch-v10/mm/init.c - * - */ -#include <linux/mmzone.h> -#include <linux/init.h> -#include <linux/bootmem.h> -#include <linux/mm.h> -#include <asm/pgtable.h> -#include <asm/page.h> -#include <asm/types.h> -#include <asm/mmu.h> -#include <asm/io.h> -#include <asm/mmu_context.h> -#include <arch/svinto.h> - -extern void tlb_init(void); - -/* - * The kernel is already mapped with a kernel segment at kseg_c so - * we don't need to map it with a page table. However head.S also - * temporarily mapped it at kseg_4 so we should set up the ksegs again, - * clear the TLB and do some other paging setup stuff. - */ - -void __init -paging_init(void) -{ - int i; - unsigned long zones_size[MAX_NR_ZONES]; - - printk("Setting up paging and the MMU.\n"); - - /* clear out the init_mm.pgd that will contain the kernel's mappings */ - - for(i = 0; i < PTRS_PER_PGD; i++) - swapper_pg_dir[i] = __pgd(0); - - /* make sure the current pgd table points to something sane - * (even if it is most probably not used until the next - * switch_mm) - */ - - per_cpu(current_pgd, smp_processor_id()) = init_mm.pgd; - - /* initialise the TLB (tlb.c) */ - - tlb_init(); - - /* see README.mm for details on the KSEG setup */ - -#ifdef CONFIG_CRIS_LOW_MAP - /* Etrax-100 LX version 1 has a bug so that we cannot map anything - * across the 0x80000000 boundary, so we need to shrink the user-virtual - * area to 0x50000000 instead of 0xb0000000 and map things slightly - * different. The unused areas are marked as paged so that we can catch - * freak kernel accesses there. - * - * The ARTPEC chip is mapped at 0xa so we pass that segment straight - * through. We cannot vremap it because the vmalloc area is below 0x8 - * and Juliette needs an uncached area above 0x8. - * - * Same thing with 0xc and 0x9, which is memory-mapped I/O on some boards. - * We map them straight over in LOW_MAP, but use vremap in LX version 2. - */ - -#define CACHED_BOOTROM (KSEG_F | 0x08000000UL) - - *R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, seg ) | /* bootrom */ - IO_STATE(R_MMU_KSEG, seg_e, page ) | - IO_STATE(R_MMU_KSEG, seg_d, page ) | - IO_STATE(R_MMU_KSEG, seg_c, page ) | - IO_STATE(R_MMU_KSEG, seg_b, seg ) | /* kernel reg area */ - IO_STATE(R_MMU_KSEG, seg_a, page ) | - IO_STATE(R_MMU_KSEG, seg_9, seg ) | /* LED's on some boards */ - IO_STATE(R_MMU_KSEG, seg_8, seg ) | /* CSE0/1, flash and I/O */ - IO_STATE(R_MMU_KSEG, seg_7, page ) | /* kernel vmalloc area */ - IO_STATE(R_MMU_KSEG, seg_6, seg ) | /* kernel DRAM area */ - IO_STATE(R_MMU_KSEG, seg_5, seg ) | /* cached flash */ - IO_STATE(R_MMU_KSEG, seg_4, page ) | /* user area */ - IO_STATE(R_MMU_KSEG, seg_3, page ) | /* user area */ - IO_STATE(R_MMU_KSEG, seg_2, page ) | /* user area */ - IO_STATE(R_MMU_KSEG, seg_1, page ) | /* user area */ - IO_STATE(R_MMU_KSEG, seg_0, page ) ); /* user area */ - - *R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x3 ) | - IO_FIELD(R_MMU_KBASE_HI, base_e, 0x0 ) | - IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) | - IO_FIELD(R_MMU_KBASE_HI, base_c, 0x0 ) | - IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) | - IO_FIELD(R_MMU_KBASE_HI, base_a, 0x0 ) | - IO_FIELD(R_MMU_KBASE_HI, base_9, 0x9 ) | - IO_FIELD(R_MMU_KBASE_HI, base_8, 0x8 ) ); - - *R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_6, 0x4 ) | - IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_4, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_3, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) ); -#else - /* This code is for the corrected Etrax-100 LX version 2... */ - -#define CACHED_BOOTROM (KSEG_A | 0x08000000UL) - - *R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, seg ) | /* cached flash */ - IO_STATE(R_MMU_KSEG, seg_e, seg ) | /* uncached flash */ - IO_STATE(R_MMU_KSEG, seg_d, page ) | /* vmalloc area */ - IO_STATE(R_MMU_KSEG, seg_c, seg ) | /* kernel area */ - IO_STATE(R_MMU_KSEG, seg_b, seg ) | /* kernel reg area */ - IO_STATE(R_MMU_KSEG, seg_a, seg ) | /* bootrom */ - IO_STATE(R_MMU_KSEG, seg_9, page ) | /* user area */ - IO_STATE(R_MMU_KSEG, seg_8, page ) | - IO_STATE(R_MMU_KSEG, seg_7, page ) | - IO_STATE(R_MMU_KSEG, seg_6, page ) | - IO_STATE(R_MMU_KSEG, seg_5, page ) | - IO_STATE(R_MMU_KSEG, seg_4, page ) | - IO_STATE(R_MMU_KSEG, seg_3, page ) | - IO_STATE(R_MMU_KSEG, seg_2, page ) | - IO_STATE(R_MMU_KSEG, seg_1, page ) | - IO_STATE(R_MMU_KSEG, seg_0, page ) ); - - *R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x0 ) | - IO_FIELD(R_MMU_KBASE_HI, base_e, 0x8 ) | - IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) | - IO_FIELD(R_MMU_KBASE_HI, base_c, 0x4 ) | - IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) | - IO_FIELD(R_MMU_KBASE_HI, base_a, 0x3 ) | - IO_FIELD(R_MMU_KBASE_HI, base_9, 0x0 ) | - IO_FIELD(R_MMU_KBASE_HI, base_8, 0x0 ) ); - - *R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_6, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_4, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_3, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) | - IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) ); -#endif - - *R_MMU_CONTEXT = ( IO_FIELD(R_MMU_CONTEXT, page_id, 0 ) ); - - /* The MMU has been enabled ever since head.S but just to make - * it totally obvious we do it here as well. - */ - - *R_MMU_CTRL = ( IO_STATE(R_MMU_CTRL, inv_excp, enable ) | - IO_STATE(R_MMU_CTRL, acc_excp, enable ) | - IO_STATE(R_MMU_CTRL, we_excp, enable ) ); - - *R_MMU_ENABLE = IO_STATE(R_MMU_ENABLE, mmu_enable, enable); - - /* - * initialize the bad page table and bad page to point - * to a couple of allocated pages - */ - - empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE); - memset((void *)empty_zero_page, 0, PAGE_SIZE); - - /* All pages are DMA'able in Etrax, so put all in the DMA'able zone */ - - zones_size[0] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT; - - for (i = 1; i < MAX_NR_ZONES; i++) - zones_size[i] = 0; - - /* Use free_area_init_node instead of free_area_init, because the former - * is designed for systems where the DRAM starts at an address substantially - * higher than 0, like us (we start at PAGE_OFFSET). This saves space in the - * mem_map page array. - */ - - free_area_init_node(0, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0); -} - -/* Initialize remaps of some I/O-ports. It is important that this - * is called before any driver is initialized. - */ - -static int -__init init_ioremap(void) -{ - - /* Give the external I/O-port addresses their values */ - -#ifdef CONFIG_CRIS_LOW_MAP - /* Simply a linear map (see the KSEG map above in paging_init) */ - port_cse1_addr = (volatile unsigned long *)(MEM_CSE1_START | - MEM_NON_CACHEABLE); - port_csp0_addr = (volatile unsigned long *)(MEM_CSP0_START | - MEM_NON_CACHEABLE); - port_csp4_addr = (volatile unsigned long *)(MEM_CSP4_START | - MEM_NON_CACHEABLE); -#else - /* Note that nothing blows up just because we do this remapping - * it's ok even if the ports are not used or connected - * to anything (or connected to a non-I/O thing) */ - port_cse1_addr = (volatile unsigned long *) - ioremap((unsigned long)(MEM_CSE1_START | MEM_NON_CACHEABLE), 16); - port_csp0_addr = (volatile unsigned long *) - ioremap((unsigned long)(MEM_CSP0_START | MEM_NON_CACHEABLE), 16); - port_csp4_addr = (volatile unsigned long *) - ioremap((unsigned long)(MEM_CSP4_START | MEM_NON_CACHEABLE), 16); -#endif - return 0; -} - -__initcall(init_ioremap); - -/* Helper function for the two below */ - -static inline void -flush_etrax_cacherange(void *startadr, int length) -{ - /* CACHED_BOOTROM is mapped to the boot-rom area (cached) which - * we can use to get fast dummy-reads of cachelines - */ - - volatile short *flushadr = (volatile short *)(((unsigned long)startadr & ~PAGE_MASK) | - CACHED_BOOTROM); - - length = length > 8192 ? 8192 : length; /* No need to flush more than cache size */ - - while(length > 0) { - *flushadr; /* dummy read to flush */ - flushadr += (32/sizeof(short)); /* a cacheline is 32 bytes */ - length -= 32; - } -} - -/* Due to a bug in Etrax100(LX) all versions, receiving DMA buffers - * will occasionally corrupt certain CPU writes if the DMA buffers - * happen to be hot in the cache. - * - * As a workaround, we have to flush the relevant parts of the cache - * before (re) inserting any receiving descriptor into the DMA HW. - */ - -void -prepare_rx_descriptor(struct etrax_dma_descr *desc) -{ - flush_etrax_cacherange((void *)desc->buf, desc->sw_len ? desc->sw_len : 65536); -} - -/* Do the same thing but flush the entire cache */ - -void -flush_etrax_cache(void) -{ - flush_etrax_cacherange(0, 8192); -} diff --git a/arch/cris/arch-v10/mm/tlb.c b/arch/cris/arch-v10/mm/tlb.c deleted file mode 100644 index 7f1f752f2445..000000000000 --- a/arch/cris/arch-v10/mm/tlb.c +++ /dev/null @@ -1,179 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/cris/arch-v10/mm/tlb.c - * - * Low level TLB handling - * - * - * Copyright (C) 2000-2007 Axis Communications AB - * - * Authors: Bjorn Wesen (bjornw@axis.com) - * - */ - -#include <linux/mm_types.h> - -#include <asm/tlb.h> -#include <asm/mmu_context.h> -#include <arch/svinto.h> - -#define D(x) - -/* The TLB can host up to 64 different mm contexts at the same time. - * The running context is R_MMU_CONTEXT, and each TLB entry contains a - * page_id that has to match to give a hit. In page_id_map, we keep track - * of which mm's we have assigned which page_id's, so that we know when - * to invalidate TLB entries. - * - * The last page_id is never running - it is used as an invalid page_id - * so we can make TLB entries that will never match. - * - * Notice that we need to make the flushes atomic, otherwise an interrupt - * handler that uses vmalloced memory might cause a TLB load in the middle - * of a flush causing. - */ - -/* invalidate all TLB entries */ - -void -flush_tlb_all(void) -{ - int i; - unsigned long flags; - - /* the vpn of i & 0xf is so we dont write similar TLB entries - * in the same 4-way entry group. details... - */ - - local_irq_save(flags); - for(i = 0; i < NUM_TLB_ENTRIES; i++) { - *R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) ); - *R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) | - IO_FIELD(R_TLB_HI, vpn, i & 0xf ) ); - - *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) | - IO_STATE(R_TLB_LO, valid, no ) | - IO_STATE(R_TLB_LO, kernel,no ) | - IO_STATE(R_TLB_LO, we, no ) | - IO_FIELD(R_TLB_LO, pfn, 0 ) ); - } - local_irq_restore(flags); - D(printk("tlb: flushed all\n")); -} - -/* invalidate the selected mm context only */ - -void -flush_tlb_mm(struct mm_struct *mm) -{ - int i; - int page_id = mm->context.page_id; - unsigned long flags; - - D(printk("tlb: flush mm context %d (%p)\n", page_id, mm)); - - if(page_id == NO_CONTEXT) - return; - - /* mark the TLB entries that match the page_id as invalid. - * here we could also check the _PAGE_GLOBAL bit and NOT flush - * global pages. is it worth the extra I/O ? - */ - - local_irq_save(flags); - for(i = 0; i < NUM_TLB_ENTRIES; i++) { - *R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i); - if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) { - *R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) | - IO_FIELD(R_TLB_HI, vpn, i & 0xf ) ); - - *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) | - IO_STATE(R_TLB_LO, valid, no ) | - IO_STATE(R_TLB_LO, kernel,no ) | - IO_STATE(R_TLB_LO, we, no ) | - IO_FIELD(R_TLB_LO, pfn, 0 ) ); - } - } - local_irq_restore(flags); -} - -/* invalidate a single page */ - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) -{ - struct mm_struct *mm = vma->vm_mm; - int page_id = mm->context.page_id; - int i; - unsigned long flags; - - D(printk("tlb: flush page %p in context %d (%p)\n", addr, page_id, mm)); - - if(page_id == NO_CONTEXT) - return; - - addr &= PAGE_MASK; /* perhaps not necessary */ - - /* invalidate those TLB entries that match both the mm context - * and the virtual address requested - */ - - local_irq_save(flags); - for(i = 0; i < NUM_TLB_ENTRIES; i++) { - unsigned long tlb_hi; - *R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i); - tlb_hi = *R_TLB_HI; - if (IO_EXTRACT(R_TLB_HI, page_id, tlb_hi) == page_id && - (tlb_hi & PAGE_MASK) == addr) { - *R_TLB_HI = IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) | - addr; /* same addr as before works. */ - - *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) | - IO_STATE(R_TLB_LO, valid, no ) | - IO_STATE(R_TLB_LO, kernel,no ) | - IO_STATE(R_TLB_LO, we, no ) | - IO_FIELD(R_TLB_LO, pfn, 0 ) ); - } - } - local_irq_restore(flags); -} - -/* - * Initialize the context related info for a new mm_struct - * instance. - */ - -int -init_new_context(struct task_struct *tsk, struct mm_struct *mm) -{ - mm->context.page_id = NO_CONTEXT; - return 0; -} - -/* called in schedule() just before actually doing the switch_to */ - -void switch_mm(struct mm_struct *prev, struct mm_struct *next, - struct task_struct *tsk) -{ - if (prev != next) { - /* make sure we have a context */ - get_mmu_context(next); - - /* remember the pgd for the fault handlers - * this is similar to the pgd register in some other CPU's. - * we need our own copy of it because current and active_mm - * might be invalid at points where we still need to derefer - * the pgd. - */ - - per_cpu(current_pgd, smp_processor_id()) = next->pgd; - - /* switch context in the MMU */ - - D(printk(KERN_DEBUG "switching mmu_context to %d (%p)\n", - next->context, next)); - - *R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, - page_id, next->context.page_id); - } -} - diff --git a/arch/cris/arch-v10/output_arch.ld b/arch/cris/arch-v10/output_arch.ld deleted file mode 100644 index 2f3288006991..000000000000 --- a/arch/cris/arch-v10/output_arch.ld +++ /dev/null @@ -1,2 +0,0 @@ -/* At the time of this writing, there's no equivalent ld option. */ -OUTPUT_ARCH (cris) |