--- /dev/null
+00-INDEX
+ - This file
+
+cache-lock.txt
+ - HOWTO for blackfin cache locking.
+
+cachefeatures.txt
+ - Supported cache features.
+
+Filesystems
+ - Requirements for mounting the root file system.
--- /dev/null
+/*
+ * File: Documentation/blackfin/Filesystems
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Rev: $Id: Filesystems 2384 2006-11-01 04:12:43Z magicyang $
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ */
+
+ How to mount the root file system in uClinux/Blackfin
+ -----------------------------------------------------
+
+1 Mounting EXT3 File system.
+ ------------------------
+
+ Creating an EXT3 File system for uClinux/Blackfin:
+
+
+Please follow the steps to form the EXT3 File system and mount the same as root
+file system.
+
+a Make an ext3 file system as large as you want the final root file
+ system.
+
+ mkfs.ext3 /dev/ram0 <your-rootfs-size-in-1k-blocks>
+
+b Mount this Empty file system on a free directory as:
+
+ mount -t ext3 /dev/ram0 ./test
+ where ./test is the empty directory.
+
+c Copy your root fs directory that you have so carefully made over.
+
+ cp -af /tmp/my_final_rootfs_files/* ./test
+
+ (For ex: cp -af uClinux-dist/romfs/* ./test)
+
+d If you have done everything right till now you should be able to see
+ the required "root" dir's (that's etc, root, bin, lib, sbin...)
+
+e Now unmount the file system
+
+ umount ./test
+
+f Create the root file system image.
+
+ dd if=/dev/ram0 bs=1k count=<your-rootfs-size-in-1k-blocks> \
+ > ext3fs.img
+
+
+Now you have to tell the kernel that will be mounting this file system as
+rootfs.
+So do a make menuconfig under kernel and select the Ext3 journaling file system
+support under File system --> submenu.
+
+
+2. Mounting EXT2 File system.
+ -------------------------
+
+By default the ext2 file system image will be created if you invoke make from
+the top uClinux-dist directory.
+
+
+3. Mounting CRAMFS File System
+ ----------------------------
+
+To create a CRAMFS file system image execute the command
+
+ mkfs.cramfs ./test cramfs.img
+
+ where ./test is the target directory.
+
+
+4. Mounting ROMFS File System
+ --------------------------
+
+To create a ROMFS file system image execute the command
+
+ genromfs -v -V "ROMdisk" -f romfs.img -d ./test
+
+ where ./test is the target directory
+
+
+5. Mounting the JFFS2 Filesystem
+ -----------------------------
+
+To create a compressed JFFS filesystem (JFFS2), please execute the command
+
+ mkfs.jffs2 -d ./test -o jffs2.img
+
+ where ./test is the target directory.
+
+However, please make sure the following is in your kernel config.
+
+/*
+ * RAM/ROM/Flash chip drivers
+ */
+#define CONFIG_MTD_CFI 1
+#define CONFIG_MTD_ROM 1
+/*
+ * Mapping drivers for chip access
+ */
+#define CONFIG_MTD_COMPLEX_MAPPINGS 1
+#define CONFIG_MTD_BF533 1
+#undef CONFIG_MTD_UCLINUX
+
+Through the u-boot boot loader, use the jffs2.img in the corresponding
+partition made in linux-2.6.x/drivers/mtd/maps/bf533_flash.c.
+
+NOTE - Currently the Flash driver is available only for EZKIT. Watch out for a
+ STAMP driver soon.
+
+
+6. Mounting the NFS File system
+ -----------------------------
+
+ For mounting the NFS please do the following in the kernel config.
+
+ In Networking Support --> Networking options --> TCP/IP networking -->
+ IP: kernel level autoconfiguration
+
+ Enable BOOTP Support.
+
+ In Kernel hacking --> Compiled-in kernel boot parameter add the following
+
+ root=/dev/nfs rw ip=bootp
+
+ In File system --> Network File system, Enable
+
+ NFS file system support --> NFSv3 client support
+ Root File system on NFS
+
+ in uClibc menuconfig, do the following
+ In Networking Support
+ enable Remote Procedure Call (RPC) support
+ Full RPC Support
+
+ On the Host side, ensure that /etc/dhcpd.conf looks something like this
+
+ ddns-update-style ad-hoc;
+ allow bootp;
+ subnet 10.100.4.0 netmask 255.255.255.0 {
+ default-lease-time 122209600;
+ max-lease-time 31557600;
+ group {
+ host bf533 {
+ hardware ethernet 00:CF:52:49:C3:01;
+ fixed-address 10.100.4.50;
+ option root-path "/home/nfsmount";
+ }
+ }
+
+ ensure that /etc/exports looks something like this
+ /home/nfsmount *(rw,no_root_squash,no_all_squash)
+
+ run the following commands as root (may differ depending on your
+ distribution) :
+ - service nfs start
+ - service portmap start
+ - service dhcpd start
+ - /usr/sbin/exportfs
--- /dev/null
+/*
+ * File: Documentation/blackfin/cache-lock.txt
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Rev: $Id: cache-lock.txt 2384 2006-11-01 04:12:43Z magicyang $
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ */
+
+How to lock your code in cache in uClinux/blackfin
+--------------------------------------------------
+
+There are only a few steps required to lock your code into the cache.
+Currently you can lock the code by Way.
+
+Below are the interface provided for locking the cache.
+
+
+1. cache_grab_lock(int Ways);
+
+This function grab the lock for locking your code into the cache specified
+by Ways.
+
+
+2. cache_lock(int Ways);
+
+This function should be called after your critical code has been executed.
+Once the critical code exits, the code is now loaded into the cache. This
+function locks the code into the cache.
+
+
+So, the example sequence will be:
+
+ cache_grab_lock(WAY0_L); /* Grab the lock */
+
+ critical_code(); /* Execute the code of interest */
+
+ cache_lock(WAY0_L); /* Lock the cache */
+
+Where WAY0_L signifies WAY0 locking.
--- /dev/null
+/*
+ * File: Documentation/blackfin/cachefeatures.txt
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Rev: $Id: cachefeatures.txt 2384 2006-11-01 04:12:43Z magicyang $
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ */
+
+ - Instruction and Data cache initialization.
+ icache_init();
+ dcache_init();
+
+ - Instruction and Data cache Invalidation Routines, when flushing the
+ same is not required.
+ _icache_invalidate();
+ _dcache_invalidate();
+
+ Also, for invalidating the entire instruction and data cache, the below
+ routines are provided (another method for invalidation, refer page no 267 and 287 of
+ ADSP-BF533 Hardware Reference manual)
+
+ invalidate_entire_dcache();
+ invalidate_entire_icache();
+
+ -External Flushing of Instruction and data cache routines.
+
+ flush_instruction_cache();
+ flush_data_cache();
+
+ - Internal Flushing of Instruction and Data Cache.
+
+ icplb_flush();
+ dcplb_flush();
+
+ - Locking the cache.
+
+ cache_grab_lock();
+ cache_lock();
+
+ Please refer linux-2.6.x/Documentation/blackfin/cache-lock.txt for how to
+ lock the cache.
+
+ Locking the cache is optional feature.
+
+ - Miscellaneous cache functions.
+
+ flush_cache_all();
+ flush_cache_mm();
+ invalidate_dcache_range();
+ flush_dcache_range();
+ flush_dcache_page();
+ flush_cache_range();
+ flush_cache_page();
+ invalidate_dcache_range();
+ flush_page_to_ram();
+
M: rpurdie@rpsys.net
S: Maintained
+BLACKFIN ARCHITECTURE
+P: Aubrey Li
+M: aubrey.li@analog.com
+P: Bernd Schmidt
+M: bernd.schmidt@analog.com
+P: Bryan Wu
+M: bryan.wu@analog.com
+P: Grace Pan
+M: grace.pan@analog.com
+P: Michael Hennerich
+M: michael.hennerich@analog.com
+P: Mike Frysinger
+M: michael.frysinger@analog.com
+P: Jane Lv
+M: jane.lv@analog.com
+P: Jerry Zeng
+M: jerry.zeng@analog.com
+P: Jie Zhang
+M: jie.zhang@analog.com
+P: Robin Getz
+M: robin.getz@analog.com
+P: Roy Huang
+M: roy.huang@analog.com
+P: Sonic Zhang
+M: sonic.zhang@analog.com
+P: Yi Li
+M: yi.li@analog.com
+L: uclinux-dist-devel@blackfin.uclinux.org
+W: http://blackfin.uclinux.org
+S: Supported
+
+BLACKFIN SERIAL DRIVER
+P: Aubrey Li
+M: aubrey.li@analog.com
+L: uclinux-dist-devel@blackfin.uclinux.org
+W: http://blackfin.uclinux.org
+S: Supported
+
BAYCOM/HDLCDRV DRIVERS FOR AX.25
P: Thomas Sailer
M: t.sailer@alumni.ethz.ch
--- /dev/null
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/kconfig-language.txt.
+#
+
+mainmenu "uClinux/Blackfin (w/o MMU) Kernel Configuration"
+
+config MMU
+ bool
+ default n
+
+config FPU
+ bool
+ default n
+
+config RWSEM_GENERIC_SPINLOCK
+ bool
+ default y
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+ default n
+
+config BLACKFIN
+ bool
+ default y
+
+config BFIN
+ bool
+ default y
+
+config SEMAPHORE_SLEEPERS
+ bool
+ default y
+
+config GENERIC_FIND_NEXT_BIT
+ bool
+ default y
+
+config GENERIC_HWEIGHT
+ bool
+ default y
+
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+config GENERIC_IRQ_PROBE
+ bool
+ default y
+
+config GENERIC_TIME
+ bool
+ default n
+
+config GENERIC_CALIBRATE_DELAY
+ bool
+ default y
+
+config FORCE_MAX_ZONEORDER
+ int
+ default "14"
+
+config GENERIC_CALIBRATE_DELAY
+ bool
+ default y
+
+config IRQCHIP_DEMUX_GPIO
+ bool
+ default y
+
+source "init/Kconfig"
+source "kernel/Kconfig.preempt"
+
+menu "Blackfin Processor Options"
+
+comment "Processor and Board Settings"
+
+choice
+ prompt "CPU"
+ default BF533
+
+config BF531
+ bool "BF531"
+ help
+ BF531 Processor Support.
+
+config BF532
+ bool "BF532"
+ help
+ BF532 Processor Support.
+
+config BF533
+ bool "BF533"
+ help
+ BF533 Processor Support.
+
+config BF534
+ bool "BF534"
+ help
+ BF534 Processor Support.
+
+config BF536
+ bool "BF536"
+ help
+ BF536 Processor Support.
+
+config BF537
+ bool "BF537"
+ help
+ BF537 Processor Support.
+
+config BF561
+ bool "BF561"
+ help
+ Not Supported Yet - Work in progress - BF561 Processor Support.
+
+endchoice
+
+choice
+ prompt "Silicon Rev"
+ default BF_REV_0_2 if BF537
+ default BF_REV_0_3 if BF533
+
+config BF_REV_0_2
+ bool "0.2"
+ depends on (BF537 || BF536 || BF534)
+
+config BF_REV_0_3
+ bool "0.3"
+ depends on (BF561 || BF537 || BF536 || BF534 || BF533 || BF532 || BF531)
+
+config BF_REV_0_4
+ bool "0.4"
+ depends on (BF561 || BF533 || BF532 || BF531)
+
+config BF_REV_0_5
+ bool "0.5"
+ depends on (BF561 || BF533 || BF532 || BF531)
+
+endchoice
+
+config BFIN_DUAL_CORE
+ bool
+ depends on (BF561)
+ default y
+
+config BFIN_SINGLE_CORE
+ bool
+ depends on !BFIN_DUAL_CORE
+ default y
+
+choice
+ prompt "System type"
+ default BFIN533_STAMP
+ help
+ Do NOT change the board here. Please use the top level
+ configuration to ensure that all the other settings are
+ correct.
+
+config BFIN533_EZKIT
+ bool "BF533-EZKIT"
+ depends on (BF533 || BF532 || BF531)
+ help
+ BF533-EZKIT-LITE board Support.
+
+config BFIN533_STAMP
+ bool "BF533-STAMP"
+ depends on (BF533 || BF532 || BF531)
+ help
+ BF533-STAMP board Support.
+
+config BFIN537_STAMP
+ bool "BF537-STAMP"
+ depends on (BF537 || BF536 || BF534)
+ help
+ BF537-STAMP board Support.
+
+config BFIN533_BLUETECHNIX_CM
+ bool "Bluetechnix CM-BF533"
+ depends on (BF533)
+ help
+ CM-BF533 support for EVAL- and DEV-Board.
+
+config BFIN537_BLUETECHNIX_CM
+ bool "Bluetechnix CM-BF537"
+ depends on (BF537)
+ help
+ CM-BF537 support for EVAL- and DEV-Board.
+
+config BFIN561_BLUETECHNIX_CM
+ bool "BF561-CM"
+ depends on (BF561)
+ help
+ CM-BF561 support for EVAL- and DEV-Board.
+
+config BFIN561_EZKIT
+ bool "BF561-EZKIT"
+ depends on (BF561)
+ help
+ BF561-EZKIT-LITE board Support.
+
+config PNAV10
+ bool "PNAV 1.0 board"
+ depends on (BF537)
+ help
+ PNAV 1.0 board Support.
+
+config GENERIC_BOARD
+ bool "Custom"
+ depends on (BF537 || BF536 \
+ || BF534 || BF561 || BF535 || BF533 || BF532 || BF531)
+ help
+ GENERIC or Custom board Support.
+
+endchoice
+
+config MEM_GENERIC_BOARD
+ bool
+ depends on GENERIC_BOARD
+ default y
+
+config MEM_MT48LC64M4A2FB_7E
+ bool
+ depends on (BFIN533_STAMP)
+ default y
+
+config MEM_MT48LC16M16A2TG_75
+ bool
+ depends on (BFIN533_EZKIT || BFIN561_EZKIT \
+ || BFIN533_BLUETECHNIX_CM || BFIN537_BLUETECHNIX_CM)
+ default y
+
+config MEM_MT48LC32M8A2_75
+ bool
+ depends on (BFIN537_STAMP || PNAV10)
+ default y
+
+config MEM_MT48LC8M32B2B5_7
+ bool
+ depends on (BFIN561_BLUETECHNIX_CM)
+ default y
+
+config BFIN_SHARED_FLASH_ENET
+ bool
+ depends on (BFIN533_STAMP)
+ default y
+
+source "arch/blackfin/mach-bf533/Kconfig"
+source "arch/blackfin/mach-bf561/Kconfig"
+source "arch/blackfin/mach-bf537/Kconfig"
+
+menu "Board customizations"
+
+config CMDLINE_BOOL
+ bool "Default bootloader kernel arguments"
+
+config CMDLINE
+ string "Initial kernel command string"
+ depends on CMDLINE_BOOL
+ default "console=ttyBF0,57600"
+ help
+ If you don't have a boot loader capable of passing a command line string
+ to the kernel, you may specify one here. As a minimum, you should specify
+ the memory size and the root device (e.g., mem=8M, root=/dev/nfs).
+
+comment "Board Setup"
+
+config CLKIN_HZ
+ int "Crystal Frequency in Hz"
+ default "11059200" if BFIN533_STAMP
+ default "27000000" if BFIN533_EZKIT
+ default "25000000" if BFIN537_STAMP
+ default "30000000" if BFIN561_EZKIT
+ default "24576000" if PNAV10
+ help
+ The frequency of CLKIN crystal oscillator on the board in Hz.
+
+config MEM_SIZE
+ int "SDRAM Memory Size in MBytes"
+ default 32 if BFIN533_EZKIT
+ default 64 if BFIN537_STAMP
+ default 64 if BFIN561_EZKIT
+ default 128 if BFIN533_STAMP
+ default 64 if PNAV10
+
+config MEM_ADD_WIDTH
+ int "SDRAM Memory Address Width"
+ default 9 if BFIN533_EZKIT
+ default 9 if BFIN561_EZKIT
+ default 10 if BFIN537_STAMP
+ default 11 if BFIN533_STAMP
+ default 10 if PNAV10
+
+config ENET_FLASH_PIN
+ int "PF port/pin used for flash and ethernet sharing"
+ depends on (BFIN533_STAMP)
+ default 0
+ help
+ PF port/pin used for flash and ethernet sharing to allow other PF
+ pins to be used on other platforms without having to touch common
+ code.
+ For example: PF0 --> 0,PF1 --> 1,PF2 --> 2, etc.
+
+config BOOT_LOAD
+ hex "Kernel load address for booting"
+ default "0x1000"
+ help
+ This option allows you to set the load address of the kernel.
+ This can be useful if you are on a board which has a small amount
+ of memory or you wish to reserve some memory at the beginning of
+ the address space.
+
+ Note that you generally want to keep this value at or above 4k
+ (0x1000) as this will allow the kernel to capture NULL pointer
+ references.
+
+comment "LED Status Indicators"
+ depends on (BFIN533_STAMP || BFIN533_BLUETECHNIX_CM)
+
+config BFIN_ALIVE_LED
+ bool "Enable Board Alive"
+ depends on (BFIN533_STAMP || BFIN533_BLUETECHNIX_CM)
+ default n
+ help
+ Blink the LEDs you select when the kernel is running. Helps detect
+ a hung kernel.
+
+config BFIN_ALIVE_LED_NUM
+ int "LED"
+ depends on BFIN_ALIVE_LED
+ range 1 3 if BFIN533_STAMP
+ default "3" if BFIN533_STAMP
+ help
+ Select the LED (marked on the board) for you to blink.
+
+config BFIN_IDLE_LED
+ bool "Enable System Load/Idle LED"
+ depends on (BFIN533_STAMP || BFIN533_BLUETECHNIX_CM)
+ default n
+ help
+ Blinks the LED you select when to determine kernel load.
+
+config BFIN_IDLE_LED_NUM
+ int "LED"
+ depends on BFIN_IDLE_LED
+ range 1 3 if BFIN533_STAMP
+ default "2" if BFIN533_STAMP
+ help
+ Select the LED (marked on the board) for you to blink.
+
+#
+# Sorry - but you need to put the hex address here -
+#
+
+# Flag Data register
+config BFIN_ALIVE_LED_PORT
+ hex
+ default 0xFFC00700 if (BFIN533_STAMP)
+
+# Peripheral Flag Direction Register
+config BFIN_ALIVE_LED_DPORT
+ hex
+ default 0xFFC00730 if (BFIN533_STAMP)
+
+config BFIN_ALIVE_LED_PIN
+ hex
+ default 0x04 if (BFIN533_STAMP && BFIN_ALIVE_LED_NUM = 1)
+ default 0x08 if (BFIN533_STAMP && BFIN_ALIVE_LED_NUM = 2)
+ default 0x10 if (BFIN533_STAMP && BFIN_ALIVE_LED_NUM = 3)
+
+config BFIN_IDLE_LED_PORT
+ hex
+ default 0xFFC00700 if (BFIN533_STAMP)
+
+# Peripheral Flag Direction Register
+config BFIN_IDLE_LED_DPORT
+ hex
+ default 0xFFC00730 if (BFIN533_STAMP)
+
+config BFIN_IDLE_LED_PIN
+ hex
+ default 0x04 if (BFIN533_STAMP && BFIN_IDLE_LED_NUM = 1)
+ default 0x08 if (BFIN533_STAMP && BFIN_IDLE_LED_NUM = 2)
+ default 0x10 if (BFIN533_STAMP && BFIN_IDLE_LED_NUM = 3)
+
+comment "Console UART Setup"
+
+choice
+ prompt "Baud Rate"
+ default BAUD_57600
+config BAUD_9600
+ bool "9600"
+config BAUD_19200
+ bool "19200"
+config BAUD_38400
+ bool "38400"
+config BAUD_57600
+ bool "57600"
+config BAUD_115200
+ bool "115200"
+endchoice
+
+choice
+ prompt "Parity"
+ default BAUD_NO_PARITY
+config BAUD_NO_PARITY
+ bool "No Parity"
+config BAUD_PARITY
+ bool "Parity"
+endchoice
+
+choice
+ prompt "Stop Bits"
+ default BAUD_1_STOPBIT
+config BAUD_1_STOPBIT
+ bool "1"
+config BAUD_2_STOPBIT
+ bool "2"
+endchoice
+
+endmenu
+
+
+menu "Blackfin Kernel Optimizations"
+
+comment "Timer Tick"
+
+source kernel/Kconfig.hz
+
+comment "Memory Optimizations"
+
+config I_ENTRY_L1
+ bool "Locate interrupt entry code in L1 Memory"
+ default y
+ help
+ If enabled interrupt entry code (STORE/RESTORE CONTEXT) is linked
+ into L1 instruction memory.(less latency)
+
+config EXCPT_IRQ_SYSC_L1
+ bool "Locate entire ASM lowlevel excepetion / interrupt - Syscall and CPLB handler code in L1 Memory"
+ default y
+ help
+ If enabled entire ASM lowlevel exception and interrupt entry code (STORE/RESTORE CONTEXT) is linked
+ into L1 instruction memory.(less latency)
+
+config DO_IRQ_L1
+ bool "Locate frequently called do_irq dispatcher function in L1 Memory"
+ default y
+ help
+ If enabled frequently called do_irq dispatcher function is linked
+ into L1 instruction memory.(less latency)
+
+config CORE_TIMER_IRQ_L1
+ bool "Locate frequently called timer_interrupt() function in L1 Memory"
+ default y
+ help
+ If enabled frequently called timer_interrupt() function is linked
+ into L1 instruction memory.(less latency)
+
+config IDLE_L1
+ bool "Locate frequently idle function in L1 Memory"
+ default y
+ help
+ If enabled frequently called idle function is linked
+ into L1 instruction memory.(less latency)
+
+config SCHEDULE_L1
+ bool "Locate kernel schedule function in L1 Memory"
+ default y
+ help
+ If enabled frequently called kernel schedule is linked
+ into L1 instruction memory.(less latency)
+
+config ARITHMETIC_OPS_L1
+ bool "Locate kernel owned arithmetic functions in L1 Memory"
+ default y
+ help
+ If enabled arithmetic functions are linked
+ into L1 instruction memory.(less latency)
+
+config ACCESS_OK_L1
+ bool "Locate access_ok function in L1 Memory"
+ default y
+ help
+ If enabled access_ok function is linked
+ into L1 instruction memory.(less latency)
+
+config MEMSET_L1
+ bool "Locate memset function in L1 Memory"
+ default y
+ help
+ If enabled memset function is linked
+ into L1 instruction memory.(less latency)
+
+config MEMCPY_L1
+ bool "Locate memcpy function in L1 Memory"
+ default y
+ help
+ If enabled memcpy function is linked
+ into L1 instruction memory.(less latency)
+
+config SYS_BFIN_SPINLOCK_L1
+ bool "Locate sys_bfin_spinlock function in L1 Memory"
+ default y
+ help
+ If enabled sys_bfin_spinlock function is linked
+ into L1 instruction memory.(less latency)
+
+config IP_CHECKSUM_L1
+ bool "Locate IP Checksum function in L1 Memory"
+ default n
+ help
+ If enabled IP Checksum function is linked
+ into L1 instruction memory.(less latency)
+
+config CACHELINE_ALIGNED_L1
+ bool "Locate cacheline_aligned data to L1 Data Memory"
+ default y
+ depends on !BF531
+ help
+ If enabled cacheline_anligned data is linked
+ into L1 data memory.(less latency)
+
+config SYSCALL_TAB_L1
+ bool "Locate Syscall Table L1 Data Memory"
+ default n
+ depends on !BF531
+ help
+ If enabled the Syscall LUT is linked
+ into L1 data memory.(less latency)
+
+config CPLB_SWITCH_TAB_L1
+ bool "Locate CPLB Switch Tables L1 Data Memory"
+ default n
+ depends on !BF531
+ help
+ If enabled the CPLB Switch Tables are linked
+ into L1 data memory.(less latency)
+
+endmenu
+
+
+choice
+ prompt "Kernel executes from"
+ help
+ Choose the memory type that the kernel will be running in.
+
+config RAMKERNEL
+ bool "RAM"
+ help
+ The kernel will be resident in RAM when running.
+
+config ROMKERNEL
+ bool "ROM"
+ help
+ The kernel will be resident in FLASH/ROM when running.
+
+endchoice
+
+source "mm/Kconfig"
+
+config LARGE_ALLOCS
+ bool "Allow allocating large blocks (> 1MB) of memory"
+ help
+ Allow the slab memory allocator to keep chains for very large
+ memory sizes - upto 32MB. You may need this if your system has
+ a lot of RAM, and you need to able to allocate very large
+ contiguous chunks. If unsure, say N.
+
+config BFIN_DMA_5XX
+ bool "Enable DMA Support"
+ depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561)
+ default y
+ help
+ DMA driver for BF5xx.
+
+choice
+ prompt "Uncached SDRAM region"
+ default DMA_UNCACHED_1M
+ depends BFIN_DMA_5XX
+config DMA_UNCACHED_2M
+ bool "Enable 2M DMA region"
+config DMA_UNCACHED_1M
+ bool "Enable 1M DMA region"
+config DMA_UNCACHED_NONE
+ bool "Disable DMA region"
+endchoice
+
+
+comment "Cache Support"
+config BLKFIN_CACHE
+ bool "Enable ICACHE"
+config BLKFIN_DCACHE
+ bool "Enable DCACHE"
+config BLKFIN_DCACHE_BANKA
+ bool "Enable only 16k BankA DCACHE - BankB is SRAM"
+ depends on BLKFIN_DCACHE && !BF531
+ default n
+config BLKFIN_CACHE_LOCK
+ bool "Enable Cache Locking"
+
+choice
+ prompt "Policy"
+ depends on BLKFIN_DCACHE
+ default BLKFIN_WB
+config BLKFIN_WB
+ bool "Write back"
+ help
+ Write Back Policy:
+ Cached data will be written back to SDRAM only when needed.
+ This can give a nice increase in performance, but beware of
+ broken drivers that do not properly invalidate/flush their
+ cache.
+
+ Write Through Policy:
+ Cached data will always be written back to SDRAM when the
+ cache is updated. This is a completely safe setting, but
+ performance is worse than Write Back.
+
+ If you are unsure of the options and you want to be safe,
+ then go with Write Through.
+
+config BLKFIN_WT
+ bool "Write through"
+ help
+ Write Back Policy:
+ Cached data will be written back to SDRAM only when needed.
+ This can give a nice increase in performance, but beware of
+ broken drivers that do not properly invalidate/flush their
+ cache.
+
+ Write Through Policy:
+ Cached data will always be written back to SDRAM when the
+ cache is updated. This is a completely safe setting, but
+ performance is worse than Write Back.
+
+ If you are unsure of the options and you want to be safe,
+ then go with Write Through.
+
+endchoice
+
+config L1_MAX_PIECE
+ int "Set the max L1 SRAM pieces"
+ default 16
+ help
+ Set the max memory pieces for the L1 SRAM allocation algorithm.
+ Min value is 16. Max value is 1024.
+
+menu "Clock Settings"
+
+
+config BFIN_KERNEL_CLOCK
+ bool "Re-program Clocks while Kernel boots?"
+ default n
+ help
+ This option decides if kernel clocks are re-programed from the
+ bootloader settings. If the clocks are not set, the SDRAM settings
+ are also not changed, and the Bootloader does 100% of the hardware
+ configuration.
+
+config VCO_MULT
+ int "VCO Multiplier"
+ depends on BFIN_KERNEL_CLOCK
+ default "22" if BFIN533_EZKIT
+ default "45" if BFIN533_STAMP
+ default "20" if BFIN537_STAMP
+ default "22" if BFIN533_BLUETECHNIX_CM
+ default "20" if BFIN537_BLUETECHNIX_CM
+ default "20" if BFIN561_BLUETECHNIX_CM
+ default "20" if BFIN561_EZKIT
+
+config CCLK_DIV
+ int "Core Clock Divider"
+ depends on BFIN_KERNEL_CLOCK
+ default 1 if BFIN533_EZKIT
+ default 1 if BFIN533_STAMP
+ default 1 if BFIN537_STAMP
+ default 1 if BFIN533_BLUETECHNIX_CM
+ default 1 if BFIN537_BLUETECHNIX_CM
+ default 1 if BFIN561_BLUETECHNIX_CM
+ default 1 if BFIN561_EZKIT
+
+config SCLK_DIV
+ int "System Clock Divider"
+ depends on BFIN_KERNEL_CLOCK
+ default 5 if BFIN533_EZKIT
+ default 5 if BFIN533_STAMP
+ default 4 if BFIN537_STAMP
+ default 5 if BFIN533_BLUETECHNIX_CM
+ default 4 if BFIN537_BLUETECHNIX_CM
+ default 4 if BFIN561_BLUETECHNIX_CM
+ default 5 if BFIN561_EZKIT
+
+config CLKIN_HALF
+ bool "Half ClockIn"
+ depends on BFIN_KERNEL_CLOCK
+ default n
+
+config PLL_BYPASS
+ bool "Bypass PLL"
+ depends on BFIN_KERNEL_CLOCK
+ default n
+
+endmenu
+
+comment "Asynchonous Memory Configuration"
+
+menu "EBIU_AMBCTL Global Control"
+config C_AMCKEN
+ bool "Enable CLKOUT"
+ default y
+
+config C_CDPRIO
+ bool "DMA has priority over core for ext. accesses"
+ default n
+
+config C_B0PEN
+ depends on BF561
+ bool "Bank 0 16 bit packing enable"
+ default y
+
+config C_B1PEN
+ depends on BF561
+ bool "Bank 1 16 bit packing enable"
+ default y
+
+config C_B2PEN
+ depends on BF561
+ bool "Bank 2 16 bit packing enable"
+ default y
+
+config C_B3PEN
+ depends on BF561
+ bool "Bank 3 16 bit packing enable"
+ default n
+
+choice
+ prompt"Enable Asynchonous Memory Banks"
+ default C_AMBEN_ALL
+
+config C_AMBEN
+ bool "Disable All Banks"
+
+config C_AMBEN_B0
+ bool "Enable Bank 0"
+
+config C_AMBEN_B0_B1
+ bool "Enable Bank 0 & 1"
+
+config C_AMBEN_B0_B1_B2
+ bool "Enable Bank 0 & 1 & 2"
+
+config C_AMBEN_ALL
+ bool "Enable All Banks"
+endchoice
+endmenu
+
+menu "EBIU_AMBCTL Control"
+config BANK_0
+ hex "Bank 0"
+ default 0x7BB0
+
+config BANK_1
+ hex "Bank 1"
+ default 0x7BB0
+
+config BANK_2
+ hex "Bank 2"
+ default 0x7BB0
+
+config BANK_3
+ hex "Bank 3"
+ default 0x99B3
+endmenu
+
+endmenu
+
+#############################################################################
+menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
+
+config PCI
+ bool "PCI support"
+ help
+ Support for PCI bus.
+
+source "drivers/pci/Kconfig"
+
+config HOTPLUG
+ bool "Support for hot-pluggable device"
+ help
+ Say Y here if you want to plug devices into your computer while
+ the system is running, and be able to use them quickly. In many
+ cases, the devices can likewise be unplugged at any time too.
+
+ One well known example of this is PCMCIA- or PC-cards, credit-card
+ size devices such as network cards, modems or hard drives which are
+ plugged into slots found on all modern laptop computers. Another
+ example, used on modern desktops as well as laptops, is USB.
+
+ Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
+ software (at <http://linux-hotplug.sourceforge.net/>) and install it.
+ Then your kernel will automatically call out to a user mode "policy
+ agent" (/sbin/hotplug) to load modules and set up software needed
+ to use devices as you hotplug them.
+
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+menu "Executable file formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+menu "Power management options"
+source "kernel/power/Kconfig"
+
+choice
+ prompt "Select PM Wakeup Event Source"
+ default PM_WAKEUP_GPIO_BY_SIC_IWR
+ depends on PM
+ help
+ If you have a GPIO already configured as input with the corresponding PORTx_MASK
+ bit set - "Specify Wakeup Event by SIC_IWR value"
+
+config PM_WAKEUP_GPIO_BY_SIC_IWR
+ bool "Specify Wakeup Event by SIC_IWR value"
+config PM_WAKEUP_BY_GPIO
+ bool "Cause Wakeup Event by GPIO"
+config PM_WAKEUP_GPIO_API
+ bool "Configure Wakeup Event by PM GPIO API"
+
+endchoice
+
+config PM_WAKEUP_SIC_IWR
+ hex "Wakeup Events (SIC_IWR)"
+ depends on PM_WAKEUP_GPIO_BY_SIC_IWR
+ default 0x80000000 if (BF537 || BF536 || BF534)
+ default 0x100000 if (BF533 || BF532 || BF531)
+
+config PM_WAKEUP_GPIO_NUMBER
+ int "Wakeup GPIO number"
+ range 0 47
+ depends on PM_WAKEUP_BY_GPIO
+ default 2 if BFIN537_STAMP
+
+choice
+ prompt "GPIO Polarity"
+ depends on PM_WAKEUP_BY_GPIO
+ default PM_WAKEUP_GPIO_POLAR_H
+config PM_WAKEUP_GPIO_POLAR_H
+ bool "Active High"
+config PM_WAKEUP_GPIO_POLAR_L
+ bool "Active Low"
+config PM_WAKEUP_GPIO_POLAR_EDGE_F
+ bool "Falling EDGE"
+config PM_WAKEUP_GPIO_POLAR_EDGE_R
+ bool "Rising EDGE"
+config PM_WAKEUP_GPIO_POLAR_EDGE_B
+ bool "Both EDGE"
+endchoice
+
+endmenu
+
+if (BF537 || BF533)
+
+menu "CPU Frequency scaling"
+
+source "drivers/cpufreq/Kconfig"
+
+config CPU_FREQ
+ bool
+ default n
+ help
+ If you want to enable this option, you should select the
+ DPMC driver from Character Devices.
+endmenu
+
+endif
+
+source "net/Kconfig"
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/blackfin/oprofile/Kconfig"
+
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config DEBUG_HWERR
+ bool "Hardware error interrupt debugging"
+ depends on DEBUG_KERNEL
+ help
+ When enabled, the hardware error interrupt is never disabled, and
+ will happen immediately when an error condition occurs. This comes
+ at a slight cost in code size, but is necessary if you are getting
+ hardware error interrupts and need to know where they are coming
+ from.
+
+config DEBUG_ICACHE_CHECK
+ bool "Check Instruction cache coherancy"
+ depends on DEBUG_KERNEL
+ depends on DEBUG_HWERR
+ help
+ Say Y here if you are getting wierd unexplained errors. This will
+ ensure that icache is what SDRAM says it should be, by doing a
+ byte wise comparision between SDRAM and instruction cache. This
+ also relocates the irq_panic() function to L1 memory, (which is
+ un-cached).
+
+config DEBUG_KERNEL_START
+ bool "Debug Kernel Startup"
+ depends on DEBUG_KERNEL
+ help
+ Say Y here to put in an mini-execption handler before the kernel
+ replaces the bootloader exception handler. This will stop kernels
+ from dieing at startup with no visible error messages.
+
+config DEBUG_SERIAL_EARLY_INIT
+ bool "Initialize serial driver early"
+ default n
+ depends on SERIAL_BFIN
+ help
+ Say Y here if you want to get kernel output early when kernel
+ crashes before the normal console initialization. If this option
+ is enable, console output will always go to the ttyBF0, no matter
+ what kernel boot paramters you set.
+
+config DEBUG_HUNT_FOR_ZERO
+ bool "Catch NULL pointer reads/writes"
+ default y
+ help
+ Say Y here to catch reads/writes to anywhere in the memory range
+ from 0x0000 - 0x0FFF (the first 4k) of memory. This is useful in
+ catching common programming errors such as NULL pointer dereferences.
+
+ Misbehaving applications will be killed (generate a SEGV) while the
+ kernel will trigger a panic.
+
+ Enabling this option will take up an extra entry in CPLB table.
+ Otherwise, there is no extra overhead.
+
+config DEBUG_BFIN_NO_KERN_HWTRACE
+ bool "Trace user apps (turn off hwtrace in kernel)"
+ default n
+ help
+ Some pieces of the kernel contain a lot of flow changes which can
+ quickly fill up the hardware trace buffer. When debugging crashes,
+ the hardware trace may indicate that the problem lies in kernel
+ space when in reality an application is buggy.
+
+ Say Y here to disable hardware tracing in some known "jumpy" pieces
+ of code so that the trace buffer will extend further back.
+
+config DUAL_CORE_TEST_MODULE
+ tristate "Dual Core Test Module"
+ depends on (BF561)
+ default n
+ help
+ Say Y here to build-in dual core test module for dual core test.
+
+config CPLB_INFO
+ bool "Display the CPLB information"
+ help
+ Display the CPLB information.
+
+config ACCESS_CHECK
+ bool "Check the user pointer address"
+ default y
+ help
+ Usually the pointer transfer from user space is checked to see if its
+ address is in the kernel space.
+
+ Say N here to disable that check to improve the performance.
+
+endmenu
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
--- /dev/null
+#
+# arch/blackfin/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+
+
+CROSS_COMPILE ?= bfin-uclinux-
+LDFLAGS_vmlinux := -X
+OBJCOPYFLAGS := -O binary -R .note -R .comment -S
+GZFLAGS := -9
+
+CFLAGS_MODULE += -mlong-calls
+KALLSYMS += --symbol-prefix=_
+
+
+# setup the machine name and the machine dependent settings
+machine-$(CONFIG_BF531) := bf533
+machine-$(CONFIG_BF532) := bf533
+machine-$(CONFIG_BF533) := bf533
+machine-$(CONFIG_BF534) := bf537
+machine-$(CONFIG_BF536) := bf537
+machine-$(CONFIG_BF537) := bf537
+machine-$(CONFIG_BF561) := bf561
+MACHINE := $(machine-y)
+export MACHINE
+
+
+head-y := arch/$(ARCH)/mach-$(MACHINE)/head.o arch/$(ARCH)/kernel/init_task.o
+
+core-y += arch/$(ARCH)/kernel/ arch/$(ARCH)/mm/ arch/$(ARCH)/mach-common/
+
+# If we have a machine-specific directory, then include it in the build.
+ifneq ($(machine-y),)
+core-y += arch/$(ARCH)/mach-$(MACHINE)/
+core-y += arch/$(ARCH)/mach-$(MACHINE)/boards/
+endif
+
+libs-y += arch/$(ARCH)/lib/
+
+drivers-$(CONFIG_OPROFILE) += arch/$(ARCH)/oprofile/
+
+
+
+# Update machine arch symlinks if something which affects
+# them changed. We use .mach to indicate when they were updated
+# last, otherwise make uses the target directory mtime.
+
+include/asm-blackfin/.mach: $(wildcard include/config/arch/*.h) include/config/auto.conf
+ @echo ' SYMLINK include/asm-$(ARCH)/mach-$(MACHINE) -> include/asm-$(ARCH)/mach'
+ifneq ($(KBUILD_SRC),)
+ $(Q)mkdir -p include/asm-$(ARCH)
+ $(Q)ln -fsn $(srctree)/include/asm-$(ARCH)/mach-$(MACHINE) include/asm-$(ARCH)/mach
+else
+ $(Q)ln -fsn mach-$(MACHINE) include/asm-$(ARCH)/mach
+endif
+ @touch $@
+
+CLEAN_FILES += \
+ include/asm-$(ARCH)/asm-offsets.h \
+ arch/$(ARCH)/kernel/asm-offsets.s \
+ include/asm-$(ARCH)/mach \
+ include/asm-$(ARCH)/.mach
+
+archprepare: include/asm-blackfin/.mach
+archclean:
+ $(Q)$(MAKE) $(clean)=$(boot)
+
+
+all: vmImage
+boot := arch/$(ARCH)/boot
+BOOT_TARGETS = vmImage
+.PHONY: $(BOOT_TARGETS)
+$(BOOT_TARGETS): vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+define archhelp
+ echo '* vmImage - Kernel-only image for U-Boot (arch/$(ARCH)/boot/vmImage)'
+endef
--- /dev/null
+#
+# arch/blackfin/boot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+targets := vmImage
+extra-y += vmlinux.bin vmlinux.gz
+
+quiet_cmd_uimage = UIMAGE $@
+ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(ARCH) -O linux -T kernel \
+ -C gzip -a $(CONFIG_BOOT_LOAD) -e $(CONFIG_BOOT_LOAD) -n 'Linux-$(KERNELRELEASE)' \
+ -d $< $@
+
+$(obj)/vmlinux.bin: vmlinux FORCE
+ $(call if_changed,objcopy)
+
+$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE
+ $(call if_changed,gzip)
+
+$(obj)/vmImage: $(obj)/vmlinux.gz
+ $(call if_changed,uimage)
+ @echo 'Kernel: $@ is ready'
--- /dev/null
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.20
+#
+# CONFIG_MMU is not set
+# CONFIG_FPU is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_BFIN=y
+CONFIG_SEMAPHORE_SLEEPERS=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_UCLINUX=y
+CONFIG_FORCE_MAX_ZONEORDER=14
+CONFIG_IRQCHIP_DEMUX_GPIO=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SYSVIPC=y
+# CONFIG_IPC_NS is not set
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_UTS_NS is not set
+# CONFIG_AUDIT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_LIMIT_PAGECACHE is not set
+CONFIG_BUDDY=y
+# CONFIG_NP2 is not set
+CONFIG_SLAB=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_RT_MUTEXES=y
+CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
+# CONFIG_SLOB is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Block layer
+#
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# Blackfin Processor Options
+#
+
+#
+# Processor and Board Settings
+#
+# CONFIG_BF531 is not set
+# CONFIG_BF532 is not set
+# CONFIG_BF533 is not set
+# CONFIG_BF534 is not set
+# CONFIG_BF535 is not set
+# CONFIG_BF536 is not set
+CONFIG_BF537=y
+# CONFIG_BF561 is not set
+CONFIG_BF_REV_0_2=y
+# CONFIG_BF_REV_0_3 is not set
+# CONFIG_BF_REV_0_4 is not set
+# CONFIG_BF_REV_0_5 is not set
+CONFIG_BLACKFIN=y
+CONFIG_BFIN_SINGLE_CORE=y
+# CONFIG_BFIN533_EZKIT is not set
+# CONFIG_BFIN533_STAMP is not set
+CONFIG_BFIN537_STAMP=y
+# CONFIG_BFIN533_BLUETECHNIX_CM is not set
+# CONFIG_BFIN537_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_BLUETECHNIX_CM is not set
+# CONFIG_BFIN561_EZKIT is not set
+# CONFIG_PNAV10 is not set
+# CONFIG_GENERIC_BOARD is not set
+CONFIG_MEM_MT48LC32M8A2_75=y
+CONFIG_IRQ_PLL_WAKEUP=7
+
+#
+# BF537 Specific Configuration
+#
+
+#
+# PORT F/G Selection
+#
+CONFIG_BF537_PORT_F=y
+# CONFIG_BF537_PORT_G is not set
+# CONFIG_BF537_PORT_H is not set
+
+#
+# Interrupt Priority Assignment
+#
+
+#
+# Priority
+#
+CONFIG_IRQ_DMA_ERROR=7
+CONFIG_IRQ_ERROR=7
+CONFIG_IRQ_RTC=8
+CONFIG_IRQ_PPI=8
+CONFIG_IRQ_SPORT0_RX=9
+CONFIG_IRQ_SPORT0_TX=9
+CONFIG_IRQ_SPORT1_RX=9
+CONFIG_IRQ_SPORT1_TX=9
+CONFIG_IRQ_TWI=10
+CONFIG_IRQ_SPI=10
+CONFIG_IRQ_UART0_RX=10
+CONFIG_IRQ_UART0_TX=10
+CONFIG_IRQ_UART1_RX=10
+CONFIG_IRQ_UART1_TX=10
+CONFIG_IRQ_CAN_RX=11
+CONFIG_IRQ_CAN_TX=11
+CONFIG_IRQ_MAC_RX=11
+CONFIG_IRQ_MAC_TX=11
+CONFIG_IRQ_TMR0=12
+CONFIG_IRQ_TMR1=12
+CONFIG_IRQ_TMR2=12
+CONFIG_IRQ_TMR3=12
+CONFIG_IRQ_TMR4=12
+CONFIG_IRQ_TMR5=12
+CONFIG_IRQ_TMR6=12
+CONFIG_IRQ_TMR7=12
+CONFIG_IRQ_PROG_INTA=12
+CONFIG_IRQ_PORTG_INTB=12
+CONFIG_IRQ_MEM_DMA0=13
+CONFIG_IRQ_MEM_DMA1=13
+CONFIG_IRQ_WATCH=13
+
+#
+# Board customizations
+#
+
+#
+# Board Setup
+#
+CONFIG_CLKIN_HZ=25000000
+CONFIG_MEM_SIZE=64
+CONFIG_MEM_ADD_WIDTH=10
+CONFIG_BOOT_LOAD=0x1000
+
+#
+# Console UART Setup
+#
+# CONFIG_BAUD_9600 is not set
+# CONFIG_BAUD_19200 is not set
+# CONFIG_BAUD_38400 is not set
+CONFIG_BAUD_57600=y
+# CONFIG_BAUD_115200 is not set
+CONFIG_BAUD_NO_PARITY=y
+# CONFIG_BAUD_PARITY is not set
+CONFIG_BAUD_1_STOPBIT=y
+# CONFIG_BAUD_2_STOPBIT is not set
+
+#
+# Blackfin Kernel Optimizations
+#
+
+#
+# Timer Tick
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+
+#
+# Memory Optimizations
+#
+CONFIG_I_ENTRY_L1=y
+CONFIG_RAMKERNEL=y
+# CONFIG_ROMKERNEL is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+# CONFIG_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_LARGE_ALLOCS=y
+CONFIG_BFIN_DMA_5XX=y
+# CONFIG_DMA_UNCACHED_2M is not set
+CONFIG_DMA_UNCACHED_1M=y
+# CONFIG_DMA_UNCACHED_NONE is not set
+
+#
+# Cache Support
+#
+CONFIG_BLKFIN_CACHE=y
+CONFIG_BLKFIN_DCACHE=y
+# CONFIG_BLKFIN_CACHE_LOCK is not set
+# CONFIG_BLKFIN_WB is not set
+CONFIG_BLKFIN_WT=y
+CONFIG_L1_MAX_PIECE=16
+
+#
+# Clock Settings
+#
+# CONFIG_BFIN_KERNEL_CLOCK is not set
+
+#
+# Asynchonous Memory Configuration
+#
+
+#
+# EBIU_AMBCTL Global Control
+#
+CONFIG_C_AMCKEN=y
+CONFIG_C_CDPRIO=y
+# CONFIG_C_AMBEN is not set
+# CONFIG_C_AMBEN_B0 is not set
+# CONFIG_C_AMBEN_B0_B1 is not set
+# CONFIG_C_AMBEN_B0_B1_B2 is not set
+CONFIG_C_AMBEN_ALL=y
+
+#
+# EBIU_AMBCTL Control
+#
+CONFIG_BANK_0=0x7BB0
+CONFIG_BANK_1=0x7BB0
+CONFIG_BANK_2=0x7BB0
+CONFIG_BANK_3=0x99B3
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF_FDPIC=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_BINFMT_ZFLAT=y
+# CONFIG_BINFMT_SHARED_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_LEGACY=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_PM_SYSFS_DEPRECATED is not set
+CONFIG_PM_WAKEUP_GPIO_BY_SIC_IWR=y
+# CONFIG_PM_WAKEUP_BY_GPIO is not set
+# CONFIG_PM_WAKEUP_GPIO_API is not set
+CONFIG_PM_WAKEUP_SIC_IWR=0x80000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NETDEBUG is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+# CONFIG_NETLABEL is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+
+#
+# DCCP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_DCCP is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+
+#
+# TIPC Configuration (EXPERIMENTAL)
+#
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+CONFIG_IRDA=m
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=m
+CONFIG_IRCOMM=m
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+CONFIG_IRDA_CACHE_LAST_LSAP=y
+# CONFIG_IRDA_FAST_RR is not set
+# CONFIG_IRDA_DEBUG is not set
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+CONFIG_IRTTY_SIR=m
+
+#
+# Dongle support
+#
+# CONFIG_DONGLE is not set
+
+#
+# Old SIR device drivers
+#
+# CONFIG_IRPORT_SIR is not set
+
+#
+# Old Serial dongle support
+#
+
+#
+# FIR device drivers
+#
+# CONFIG_BT is not set
+# CONFIG_IEEE80211 is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# Connector - unified userspace <-> kernelspace linker
+#
+# CONFIG_CONNECTOR is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_MW320D=m
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=m
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_BF5xx=m
+CONFIG_BFIN_FLASH_SIZE=0x400000
+CONFIG_EBIU_FLASH_BASE=0x20000000
+
+#
+# FLASH_EBIU_AMBCTL Control
+#
+CONFIG_BFIN_FLASH_BANK_0=0x7BB0
+CONFIG_BFIN_FLASH_BANK_1=0x7BB0
+CONFIG_BFIN_FLASH_BANK_2=0x7BB0
+CONFIG_BFIN_FLASH_BANK_3=0x7BB0
+CONFIG_MTD_UCLINUX=y
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND_BFIN=m
+CONFIG_BFIN_NAND_BASE=0x20212000
+CONFIG_BFIN_NAND_CLE=2
+CONFIG_BFIN_NAND_ALE=1
+CONFIG_BFIN_NAND_READY=3
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+
+#
+# OneNAND Flash Device Drivers
+#
+# CONFIG_MTD_ONENAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Misc devices
+#
+# CONFIG_TIFM_CORE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_NETLINK is not set
+
+#
+# Serial ATA (prod) and Parallel ATA (experimental) drivers
+#
+# CONFIG_ATA is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# PHY device support
+#
+# CONFIG_PHYLIB is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_SMC91X is not set
+CONFIG_BFIN_MAC=y
+CONFIG_BFIN_MAC_USE_L1=y
+CONFIG_BFIN_TX_DESC_NUM=10
+CONFIG_BFIN_RX_DESC_NUM=20
+# CONFIG_BFIN_MAC_RMII is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_BF53X_PFBUTTONS is not set
+CONFIG_TWI_KEYPAD=m
+CONFIG_BFIN_TWIKEYPAD_IRQ_PFX=72
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_AD9960 is not set
+# CONFIG_SPI_ADC_BF533 is not set
+# CONFIG_BF533_PFLAGS is not set
+# CONFIG_BF5xx_PPIFCD is not set
+# CONFIG_BF5xx_TIMERS is not set
+# CONFIG_BF5xx_PPI is not set
+CONFIG_BFIN_SPORT=y
+# CONFIG_BFIN_TIMER_LATENCY is not set
+CONFIG_TWI_LCD=m
+CONFIG_TWI_LCD_SLAVE_ADDR=34
+# CONFIG_AD5304 is not set
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_BFIN=y
+CONFIG_SERIAL_BFIN_CONSOLE=y
+CONFIG_SERIAL_BFIN_DMA=y
+# CONFIG_SERIAL_BFIN_PIO is not set
+CONFIG_SERIAL_BFIN_UART0=y
+# CONFIG_BFIN_UART0_CTSRTS is not set
+# CONFIG_SERIAL_BFIN_UART1 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_BFIN_SPORT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_LEGACY_PTYS is not set
+
+#
+# CAN, the car bus and industrial fieldbus
+#
+CONFIG_CAN4LINUX=y
+
+#
+# linux embedded drivers
+#
+# CONFIG_CAN_MCF5282 is not set
+# CONFIG_CAN_UNCTWINCAN is not set
+CONFIG_CAN_BLACKFIN=m
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_GEN_RTC is not set
+CONFIG_BLACKFIN_DPMC=y
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_BFIN_GPIO is not set
+CONFIG_I2C_BFIN_TWI=m
+CONFIG_TWICLK_KHZ=50
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+CONFIG_SENSORS_AD5252=m
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_BFIN=y
+
+#
+# SPI Protocol Masters
+#
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Hardware Monitoring support
+#
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB=m
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_BFIN_7171=m
+CONFIG_FB_BFIN_7393=m
+CONFIG_NTSC=y
+# CONFIG_PAL is not set
+# CONFIG_NTSC_640x480 is not set
+# CONFIG_PAL_640x480 is not set
+# CONFIG_NTSC_YCBCR is not set
+# CONFIG_PAL_YCBCR is not set
+CONFIG_ADV7393_1XMEM=y
+# CONFIG_ADV7393_2XMEM is not set
+CONFIG_FB_BF537_LQ035=m
+CONFIG_LQ035_SLAVE_ADDR=0x58
+# CONFIG_FB_BFIN_LANDSCAPE is not set
+# CONFIG_FB_BFIN_BGR is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
+
+#
+# Sound
+#
+CONFIG_SOUND=m
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+
+#
+# HID Devices
+#
+CONFIG_HID=y
+
+#
+# USB support
+#
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_SPI_MMC is not set
+# CONFIG_MMC is not set
+
+#
+# LED devices
+#
+# CONFIG_NEW_LEDS is not set
+
+#
+# LED drivers
+#
+
+#
+# LED Triggers
+#
+
+#
+# InfiniBand support
+#
+
+#
+# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
+#
+
+#
+# Real Time Clock
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+CONFIG_RTC_DRV_BFIN=y
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# Virtualization
+#
+
+#
+# PBX support
+#
+# CONFIG_PBX is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_YAFFS_FS=m
+CONFIG_YAFFS_YAFFS1=y
+# CONFIG_YAFFS_DOES_ECC is not set
+CONFIG_YAFFS_YAFFS2=y
+CONFIG_YAFFS_AUTO_YAFFS2=y
+# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set
+CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=10
+# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set
+# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set
+CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+# CONFIG_9P_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=m
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_HUNT_FOR_ZERO=y
+# CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
+# CONFIG_BOOTPARAM is not set
+# CONFIG_NO_KERNEL_MSG is not set
+CONFIG_CPLB_INFO=y
+# CONFIG_NO_ACCESS_CHECK is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+CONFIG_SECURITY=y
+# CONFIG_SECURITY_NETWORK is not set
+CONFIG_SECURITY_CAPABILITIES=y
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_PLIST=y
+CONFIG_IOMAP_COPY=y
--- /dev/null
+#
+# arch/blackfin/kernel/Makefile
+#
+
+extra-y := init_task.o vmlinux.lds
+
+obj-y := \
+ entry.o process.o bfin_ksyms.o ptrace.o setup.o signal.o \
+ sys_bfin.o time.o traps.o irqchip.o dma-mapping.o bfin_gpio.o \
+ flat.o
+
+obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_BFIN_DMA_5XX) += bfin_dma_5xx.o
+obj-$(CONFIG_DUAL_CORE_TEST_MODULE) += dualcore_test.o
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/asm-offsets.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: generate definitions needed by assembly language modules.
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+#include <asm/irq.h>
+#include <asm/thread_info.h>
+
+#define DEFINE(sym, val) \
+ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+
+int main(void)
+{
+ /* offsets into the task struct */
+ DEFINE(TASK_STATE, offsetof(struct task_struct, state));
+ DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+ DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
+ DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
+ DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+ DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, thread_info));
+ DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+ DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
+ DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, pending));
+
+ /* offsets into the irq_cpustat_t struct */
+ DEFINE(CPUSTAT_SOFTIRQ_PENDING,
+ offsetof(irq_cpustat_t, __softirq_pending));
+
+ /* offsets into the thread struct */
+ DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+ DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
+ DEFINE(THREAD_SR, offsetof(struct thread_struct, seqstat));
+ DEFINE(PT_SR, offsetof(struct thread_struct, seqstat));
+ DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
+ DEFINE(THREAD_PC, offsetof(struct thread_struct, pc));
+ DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE);
+
+ /* offsets into the pt_regs */
+ DEFINE(PT_ORIG_P0, offsetof(struct pt_regs, orig_p0));
+ DEFINE(PT_ORIG_PC, offsetof(struct pt_regs, orig_pc));
+ DEFINE(PT_R0, offsetof(struct pt_regs, r0));
+ DEFINE(PT_R1, offsetof(struct pt_regs, r1));
+ DEFINE(PT_R2, offsetof(struct pt_regs, r2));
+ DEFINE(PT_R3, offsetof(struct pt_regs, r3));
+ DEFINE(PT_R4, offsetof(struct pt_regs, r4));
+ DEFINE(PT_R5, offsetof(struct pt_regs, r5));
+ DEFINE(PT_R6, offsetof(struct pt_regs, r6));
+ DEFINE(PT_R7, offsetof(struct pt_regs, r7));
+
+ DEFINE(PT_P0, offsetof(struct pt_regs, p0));
+ DEFINE(PT_P1, offsetof(struct pt_regs, p1));
+ DEFINE(PT_P2, offsetof(struct pt_regs, p2));
+ DEFINE(PT_P3, offsetof(struct pt_regs, p3));
+ DEFINE(PT_P4, offsetof(struct pt_regs, p4));
+ DEFINE(PT_P5, offsetof(struct pt_regs, p5));
+
+ DEFINE(PT_FP, offsetof(struct pt_regs, fp));
+ DEFINE(PT_USP, offsetof(struct pt_regs, usp));
+ DEFINE(PT_I0, offsetof(struct pt_regs, i0));
+ DEFINE(PT_I1, offsetof(struct pt_regs, i1));
+ DEFINE(PT_I2, offsetof(struct pt_regs, i2));
+ DEFINE(PT_I3, offsetof(struct pt_regs, i3));
+ DEFINE(PT_M0, offsetof(struct pt_regs, m0));
+ DEFINE(PT_M1, offsetof(struct pt_regs, m1));
+ DEFINE(PT_M2, offsetof(struct pt_regs, m2));
+ DEFINE(PT_M3, offsetof(struct pt_regs, m3));
+ DEFINE(PT_L0, offsetof(struct pt_regs, l0));
+ DEFINE(PT_L1, offsetof(struct pt_regs, l1));
+ DEFINE(PT_L2, offsetof(struct pt_regs, l2));
+ DEFINE(PT_L3, offsetof(struct pt_regs, l3));
+ DEFINE(PT_B0, offsetof(struct pt_regs, b0));
+ DEFINE(PT_B1, offsetof(struct pt_regs, b1));
+ DEFINE(PT_B2, offsetof(struct pt_regs, b2));
+ DEFINE(PT_B3, offsetof(struct pt_regs, b3));
+ DEFINE(PT_A0X, offsetof(struct pt_regs, a0x));
+ DEFINE(PT_A0W, offsetof(struct pt_regs, a0w));
+ DEFINE(PT_A1X, offsetof(struct pt_regs, a1x));
+ DEFINE(PT_A1W, offsetof(struct pt_regs, a1w));
+ DEFINE(PT_LC0, offsetof(struct pt_regs, lc0));
+ DEFINE(PT_LC1, offsetof(struct pt_regs, lc1));
+ DEFINE(PT_LT0, offsetof(struct pt_regs, lt0));
+ DEFINE(PT_LT1, offsetof(struct pt_regs, lt1));
+ DEFINE(PT_LB0, offsetof(struct pt_regs, lb0));
+ DEFINE(PT_LB1, offsetof(struct pt_regs, lb1));
+ DEFINE(PT_ASTAT, offsetof(struct pt_regs, astat));
+ DEFINE(PT_RESERVED, offsetof(struct pt_regs, reserved));
+ DEFINE(PT_RETS, offsetof(struct pt_regs, rets));
+ DEFINE(PT_PC, offsetof(struct pt_regs, pc));
+ DEFINE(PT_RETX, offsetof(struct pt_regs, retx));
+ DEFINE(PT_RETN, offsetof(struct pt_regs, retn));
+ DEFINE(PT_RETE, offsetof(struct pt_regs, rete));
+ DEFINE(PT_SEQSTAT, offsetof(struct pt_regs, seqstat));
+ DEFINE(PT_SYSCFG, offsetof(struct pt_regs, syscfg));
+ DEFINE(PT_IPEND, offsetof(struct pt_regs, ipend));
+ DEFINE(SIZEOF_PTREGS, sizeof(struct pt_regs));
+ DEFINE(PT_TEXT_ADDR, sizeof(struct pt_regs)); /* Needed by gdb */
+ DEFINE(PT_TEXT_END_ADDR, 4 + sizeof(struct pt_regs));/* Needed by gdb */
+ DEFINE(PT_DATA_ADDR, 8 + sizeof(struct pt_regs)); /* Needed by gdb */
+ DEFINE(PT_FDPIC_EXEC, 12 + sizeof(struct pt_regs)); /* Needed by gdb */
+ DEFINE(PT_FDPIC_INTERP, 16 + sizeof(struct pt_regs));/* Needed by gdb */
+
+ /* signal defines */
+ DEFINE(SIGSEGV, SIGSEGV);
+ DEFINE(SIGTRAP, SIGTRAP);
+
+ return 0;
+}
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/bfin_dma_5xx.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+
+#include <asm/dma.h>
+#include <asm/cacheflush.h>
+
+/* Remove unused code not exported by symbol or internally called */
+#define REMOVE_DEAD_CODE
+
+/**************************************************************************
+ * Global Variables
+***************************************************************************/
+
+static struct dma_channel dma_ch[MAX_BLACKFIN_DMA_CHANNEL];
+#if defined (CONFIG_BF561)
+static struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA1_0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_7_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_11_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_7_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_11_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA1_S1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA2_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA2_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA2_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA2_S1_NEXT_DESC_PTR,
+ (struct dma_register *) IMDMA_D0_NEXT_DESC_PTR,
+ (struct dma_register *) IMDMA_S0_NEXT_DESC_PTR,
+ (struct dma_register *) IMDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) IMDMA_S1_NEXT_DESC_PTR,
+};
+#else
+static struct dma_register *base_addr[MAX_BLACKFIN_DMA_CHANNEL] = {
+ (struct dma_register *) DMA0_NEXT_DESC_PTR,
+ (struct dma_register *) DMA1_NEXT_DESC_PTR,
+ (struct dma_register *) DMA2_NEXT_DESC_PTR,
+ (struct dma_register *) DMA3_NEXT_DESC_PTR,
+ (struct dma_register *) DMA4_NEXT_DESC_PTR,
+ (struct dma_register *) DMA5_NEXT_DESC_PTR,
+ (struct dma_register *) DMA6_NEXT_DESC_PTR,
+ (struct dma_register *) DMA7_NEXT_DESC_PTR,
+#if (defined(CONFIG_BF537) || defined(CONFIG_BF534) || defined(CONFIG_BF536))
+ (struct dma_register *) DMA8_NEXT_DESC_PTR,
+ (struct dma_register *) DMA9_NEXT_DESC_PTR,
+ (struct dma_register *) DMA10_NEXT_DESC_PTR,
+ (struct dma_register *) DMA11_NEXT_DESC_PTR,
+#endif
+ (struct dma_register *) MDMA_D0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S0_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_D1_NEXT_DESC_PTR,
+ (struct dma_register *) MDMA_S1_NEXT_DESC_PTR,
+};
+#endif
+
+/*------------------------------------------------------------------------------
+ * Set the Buffer Clear bit in the Configuration register of specific DMA
+ * channel. This will stop the descriptor based DMA operation.
+ *-----------------------------------------------------------------------------*/
+static void clear_dma_buffer(unsigned int channel)
+{
+ dma_ch[channel].regs->cfg |= RESTART;
+ SSYNC();
+ dma_ch[channel].regs->cfg &= ~RESTART;
+ SSYNC();
+}
+
+int __init blackfin_dma_init(void)
+{
+ int i;
+
+ printk(KERN_INFO "Blackfin DMA Controller\n");
+
+ for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
+ dma_ch[i].chan_status = DMA_CHANNEL_FREE;
+ dma_ch[i].regs = base_addr[i];
+ mutex_init(&(dma_ch[i].dmalock));
+ }
+
+ return 0;
+}
+
+arch_initcall(blackfin_dma_init);
+
+/*
+ * Form the channel find the irq number for that channel.
+ */
+#if !defined(CONFIG_BF561)
+
+static int bf533_channel2irq(unsigned int channel)
+{
+ int ret_irq = -1;
+
+ switch (channel) {
+ case CH_PPI:
+ ret_irq = IRQ_PPI;
+ break;
+
+#if (defined(CONFIG_BF537) || defined(CONFIG_BF534) || defined(CONFIG_BF536))
+ case CH_EMAC_RX:
+ ret_irq = IRQ_MAC_RX;
+ break;
+
+ case CH_EMAC_TX:
+ ret_irq = IRQ_MAC_TX;
+ break;
+
+ case CH_UART1_RX:
+ ret_irq = IRQ_UART1_RX;
+ break;
+
+ case CH_UART1_TX:
+ ret_irq = IRQ_UART1_TX;
+ break;
+#endif
+
+ case CH_SPORT0_RX:
+ ret_irq = IRQ_SPORT0_RX;
+ break;
+
+ case CH_SPORT0_TX:
+ ret_irq = IRQ_SPORT0_TX;
+ break;
+
+ case CH_SPORT1_RX:
+ ret_irq = IRQ_SPORT1_RX;
+ break;
+
+ case CH_SPORT1_TX:
+ ret_irq = IRQ_SPORT1_TX;
+ break;
+
+ case CH_SPI:
+ ret_irq = IRQ_SPI;
+ break;
+
+ case CH_UART_RX:
+ ret_irq = IRQ_UART_RX;
+ break;
+
+ case CH_UART_TX:
+ ret_irq = IRQ_UART_TX;
+ break;
+
+ case CH_MEM_STREAM0_SRC:
+ case CH_MEM_STREAM0_DEST:
+ ret_irq = IRQ_MEM_DMA0;
+ break;
+
+ case CH_MEM_STREAM1_SRC:
+ case CH_MEM_STREAM1_DEST:
+ ret_irq = IRQ_MEM_DMA1;
+ break;
+ }
+ return ret_irq;
+}
+
+# define channel2irq(channel) bf533_channel2irq(channel)
+
+#else
+
+static int bf561_channel2irq(unsigned int channel)
+{
+ int ret_irq = -1;
+
+ switch (channel) {
+ case CH_PPI0:
+ ret_irq = IRQ_PPI0;
+ break;
+ case CH_PPI1:
+ ret_irq = IRQ_PPI1;
+ break;
+ case CH_SPORT0_RX:
+ ret_irq = IRQ_SPORT0_RX;
+ break;
+ case CH_SPORT0_TX:
+ ret_irq = IRQ_SPORT0_TX;
+ break;
+ case CH_SPORT1_RX:
+ ret_irq = IRQ_SPORT1_RX;
+ break;
+ case CH_SPORT1_TX:
+ ret_irq = IRQ_SPORT1_TX;
+ break;
+ case CH_SPI:
+ ret_irq = IRQ_SPI;
+ break;
+ case CH_UART_RX:
+ ret_irq = IRQ_UART_RX;
+ break;
+ case CH_UART_TX:
+ ret_irq = IRQ_UART_TX;
+ break;
+
+ case CH_MEM_STREAM0_SRC:
+ case CH_MEM_STREAM0_DEST:
+ ret_irq = IRQ_MEM_DMA0;
+ break;
+ case CH_MEM_STREAM1_SRC:
+ case CH_MEM_STREAM1_DEST:
+ ret_irq = IRQ_MEM_DMA1;
+ break;
+ case CH_MEM_STREAM2_SRC:
+ case CH_MEM_STREAM2_DEST:
+ ret_irq = IRQ_MEM_DMA2;
+ break;
+ case CH_MEM_STREAM3_SRC:
+ case CH_MEM_STREAM3_DEST:
+ ret_irq = IRQ_MEM_DMA3;
+ break;
+
+ case CH_IMEM_STREAM0_SRC:
+ case CH_IMEM_STREAM0_DEST:
+ ret_irq = IRQ_IMEM_DMA0;
+ break;
+ case CH_IMEM_STREAM1_SRC:
+ case CH_IMEM_STREAM1_DEST:
+ ret_irq = IRQ_IMEM_DMA1;
+ break;
+ }
+ return ret_irq;
+}
+
+# define channel2irq(channel) bf561_channel2irq(channel)
+
+#endif
+
+/*------------------------------------------------------------------------------
+ * Request the specific DMA channel from the system.
+ *-----------------------------------------------------------------------------*/
+int request_dma(unsigned int channel, char *device_id)
+{
+
+ pr_debug("request_dma() : BEGIN \n");
+ mutex_lock(&(dma_ch[channel].dmalock));
+
+ if ((dma_ch[channel].chan_status == DMA_CHANNEL_REQUESTED)
+ || (dma_ch[channel].chan_status == DMA_CHANNEL_ENABLED)) {
+ mutex_unlock(&(dma_ch[channel].dmalock));
+ pr_debug("DMA CHANNEL IN USE \n");
+ return -EBUSY;
+ } else {
+ dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
+ pr_debug("DMA CHANNEL IS ALLOCATED \n");
+ }
+
+ mutex_unlock(&(dma_ch[channel].dmalock));
+
+ dma_ch[channel].device_id = device_id;
+ dma_ch[channel].irq_callback = NULL;
+
+ /* This is to be enabled by putting a restriction -
+ * you have to request DMA, before doing any operations on
+ * descriptor/channel
+ */
+ pr_debug("request_dma() : END \n");
+ return channel;
+}
+EXPORT_SYMBOL(request_dma);
+
+int set_dma_callback(unsigned int channel, dma_interrupt_t callback, void *data)
+{
+ int ret_irq = 0;
+
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ if (callback != NULL) {
+ int ret_val;
+ ret_irq = channel2irq(channel);
+
+ dma_ch[channel].data = data;
+
+ ret_val =
+ request_irq(ret_irq, (void *)callback, IRQF_DISABLED,
+ dma_ch[channel].device_id, data);
+ if (ret_val) {
+ printk(KERN_NOTICE
+ "Request irq in DMA engine failed.\n");
+ return -EPERM;
+ }
+ dma_ch[channel].irq_callback = callback;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(set_dma_callback);
+
+void free_dma(unsigned int channel)
+{
+ int ret_irq;
+
+ pr_debug("freedma() : BEGIN \n");
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ /* Halt the DMA */
+ disable_dma(channel);
+ clear_dma_buffer(channel);
+
+ if (dma_ch[channel].irq_callback != NULL) {
+ ret_irq = channel2irq(channel);
+ free_irq(ret_irq, dma_ch[channel].data);
+ }
+
+ /* Clear the DMA Variable in the Channel */
+ mutex_lock(&(dma_ch[channel].dmalock));
+ dma_ch[channel].chan_status = DMA_CHANNEL_FREE;
+ mutex_unlock(&(dma_ch[channel].dmalock));
+
+ pr_debug("freedma() : END \n");
+}
+EXPORT_SYMBOL(free_dma);
+
+void dma_enable_irq(unsigned int channel)
+{
+ int ret_irq;
+
+ pr_debug("dma_enable_irq() : BEGIN \n");
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ ret_irq = channel2irq(channel);
+ enable_irq(ret_irq);
+}
+EXPORT_SYMBOL(dma_enable_irq);
+
+void dma_disable_irq(unsigned int channel)
+{
+ int ret_irq;
+
+ pr_debug("dma_disable_irq() : BEGIN \n");
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ ret_irq = channel2irq(channel);
+ disable_irq(ret_irq);
+}
+EXPORT_SYMBOL(dma_disable_irq);
+
+int dma_channel_active(unsigned int channel)
+{
+ if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+EXPORT_SYMBOL(dma_channel_active);
+
+/*------------------------------------------------------------------------------
+* stop the specific DMA channel.
+*-----------------------------------------------------------------------------*/
+void disable_dma(unsigned int channel)
+{
+ pr_debug("stop_dma() : BEGIN \n");
+
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ dma_ch[channel].regs->cfg &= ~DMAEN; /* Clean the enable bit */
+ SSYNC();
+ dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
+ /* Needs to be enabled Later */
+ pr_debug("stop_dma() : END \n");
+ return;
+}
+EXPORT_SYMBOL(disable_dma);
+
+void enable_dma(unsigned int channel)
+{
+ pr_debug("enable_dma() : BEGIN \n");
+
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED;
+ dma_ch[channel].regs->curr_x_count = 0;
+ dma_ch[channel].regs->curr_y_count = 0;
+
+ dma_ch[channel].regs->cfg |= DMAEN; /* Set the enable bit */
+ SSYNC();
+ pr_debug("enable_dma() : END \n");
+ return;
+}
+EXPORT_SYMBOL(enable_dma);
+
+/*------------------------------------------------------------------------------
+* Set the Start Address register for the specific DMA channel
+* This function can be used for register based DMA,
+* to setup the start address
+* addr: Starting address of the DMA Data to be transferred.
+*-----------------------------------------------------------------------------*/
+void set_dma_start_addr(unsigned int channel, unsigned long addr)
+{
+ pr_debug("set_dma_start_addr() : BEGIN \n");
+
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ dma_ch[channel].regs->start_addr = addr;
+ SSYNC();
+ pr_debug("set_dma_start_addr() : END\n");
+}
+EXPORT_SYMBOL(set_dma_start_addr);
+
+void set_dma_next_desc_addr(unsigned int channel, unsigned long addr)
+{
+ pr_debug("set_dma_next_desc_addr() : BEGIN \n");
+
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ dma_ch[channel].regs->next_desc_ptr = addr;
+ SSYNC();
+ pr_debug("set_dma_start_addr() : END\n");
+}
+EXPORT_SYMBOL(set_dma_next_desc_addr);
+
+void set_dma_x_count(unsigned int channel, unsigned short x_count)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ dma_ch[channel].regs->x_count = x_count;
+ SSYNC();
+}
+EXPORT_SYMBOL(set_dma_x_count);
+
+void set_dma_y_count(unsigned int channel, unsigned short y_count)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ dma_ch[channel].regs->y_count = y_count;
+ SSYNC();
+}
+EXPORT_SYMBOL(set_dma_y_count);
+
+void set_dma_x_modify(unsigned int channel, short x_modify)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ dma_ch[channel].regs->x_modify = x_modify;
+ SSYNC();
+}
+EXPORT_SYMBOL(set_dma_x_modify);
+
+void set_dma_y_modify(unsigned int channel, short y_modify)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ dma_ch[channel].regs->y_modify = y_modify;
+ SSYNC();
+}
+EXPORT_SYMBOL(set_dma_y_modify);
+
+void set_dma_config(unsigned int channel, unsigned short config)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ dma_ch[channel].regs->cfg = config;
+ SSYNC();
+}
+EXPORT_SYMBOL(set_dma_config);
+
+unsigned short
+set_bfin_dma_config(char direction, char flow_mode,
+ char intr_mode, char dma_mode, char width)
+{
+ unsigned short config;
+
+ config =
+ ((direction << 1) | (width << 2) | (dma_mode << 4) |
+ (intr_mode << 6) | (flow_mode << 12) | RESTART);
+ return config;
+}
+EXPORT_SYMBOL(set_bfin_dma_config);
+
+void set_dma_sg(unsigned int channel, struct dmasg * sg, int nr_sg)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ dma_ch[channel].regs->cfg |= ((nr_sg & 0x0F) << 8);
+
+ dma_ch[channel].regs->next_desc_ptr = (unsigned int)sg;
+
+ SSYNC();
+}
+EXPORT_SYMBOL(set_dma_sg);
+
+/*------------------------------------------------------------------------------
+ * Get the DMA status of a specific DMA channel from the system.
+ *-----------------------------------------------------------------------------*/
+unsigned short get_dma_curr_irqstat(unsigned int channel)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ return dma_ch[channel].regs->irq_status;
+}
+EXPORT_SYMBOL(get_dma_curr_irqstat);
+
+/*------------------------------------------------------------------------------
+ * Clear the DMA_DONE bit in DMA status. Stop the DMA completion interrupt.
+ *-----------------------------------------------------------------------------*/
+void clear_dma_irqstat(unsigned int channel)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+ dma_ch[channel].regs->irq_status |= 3;
+}
+EXPORT_SYMBOL(clear_dma_irqstat);
+
+/*------------------------------------------------------------------------------
+ * Get current DMA xcount of a specific DMA channel from the system.
+ *-----------------------------------------------------------------------------*/
+unsigned short get_dma_curr_xcount(unsigned int channel)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ return dma_ch[channel].regs->curr_x_count;
+}
+EXPORT_SYMBOL(get_dma_curr_xcount);
+
+/*------------------------------------------------------------------------------
+ * Get current DMA ycount of a specific DMA channel from the system.
+ *-----------------------------------------------------------------------------*/
+unsigned short get_dma_curr_ycount(unsigned int channel)
+{
+ BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
+ && channel < MAX_BLACKFIN_DMA_CHANNEL));
+
+ return dma_ch[channel].regs->curr_y_count;
+}
+EXPORT_SYMBOL(get_dma_curr_ycount);
+
+void *dma_memcpy(void *dest, const void *src, size_t size)
+{
+ int direction; /* 1 - address decrease, 0 - address increase */
+ int flag_align; /* 1 - address aligned, 0 - address unaligned */
+ int flag_2D; /* 1 - 2D DMA needed, 0 - 1D DMA needed */
+
+ if (size <= 0)
+ return NULL;
+
+ if ((unsigned long)src < memory_end)
+ blackfin_dcache_flush_range((unsigned int)src,
+ (unsigned int)(src + size));
+
+ bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
+
+ if ((unsigned long)src < (unsigned long)dest)
+ direction = 1;
+ else
+ direction = 0;
+
+ if ((((unsigned long)dest % 2) == 0) && (((unsigned long)src % 2) == 0)
+ && ((size % 2) == 0))
+ flag_align = 1;
+ else
+ flag_align = 0;
+
+ if (size > 0x10000) /* size > 64K */
+ flag_2D = 1;
+ else
+ flag_2D = 0;
+
+ /* Setup destination and source start address */
+ if (direction) {
+ if (flag_align) {
+ bfin_write_MDMA_D0_START_ADDR(dest + size - 2);
+ bfin_write_MDMA_S0_START_ADDR(src + size - 2);
+ } else {
+ bfin_write_MDMA_D0_START_ADDR(dest + size - 1);
+ bfin_write_MDMA_S0_START_ADDR(src + size - 1);
+ }
+ } else {
+ bfin_write_MDMA_D0_START_ADDR(dest);
+ bfin_write_MDMA_S0_START_ADDR(src);
+ }
+
+ /* Setup destination and source xcount */
+ if (flag_2D) {
+ if (flag_align) {
+ bfin_write_MDMA_D0_X_COUNT(1024 / 2);
+ bfin_write_MDMA_S0_X_COUNT(1024 / 2);
+ } else {
+ bfin_write_MDMA_D0_X_COUNT(1024);
+ bfin_write_MDMA_S0_X_COUNT(1024);
+ }
+ bfin_write_MDMA_D0_Y_COUNT(size >> 10);
+ bfin_write_MDMA_S0_Y_COUNT(size >> 10);
+ } else {
+ if (flag_align) {
+ bfin_write_MDMA_D0_X_COUNT(size / 2);
+ bfin_write_MDMA_S0_X_COUNT(size / 2);
+ } else {
+ bfin_write_MDMA_D0_X_COUNT(size);
+ bfin_write_MDMA_S0_X_COUNT(size);
+ }
+ }
+
+ /* Setup destination and source xmodify and ymodify */
+ if (direction) {
+ if (flag_align) {
+ bfin_write_MDMA_D0_X_MODIFY(-2);
+ bfin_write_MDMA_S0_X_MODIFY(-2);
+ if (flag_2D) {
+ bfin_write_MDMA_D0_Y_MODIFY(-2);
+ bfin_write_MDMA_S0_Y_MODIFY(-2);
+ }
+ } else {
+ bfin_write_MDMA_D0_X_MODIFY(-1);
+ bfin_write_MDMA_S0_X_MODIFY(-1);
+ if (flag_2D) {
+ bfin_write_MDMA_D0_Y_MODIFY(-1);
+ bfin_write_MDMA_S0_Y_MODIFY(-1);
+ }
+ }
+ } else {
+ if (flag_align) {
+ bfin_write_MDMA_D0_X_MODIFY(2);
+ bfin_write_MDMA_S0_X_MODIFY(2);
+ if (flag_2D) {
+ bfin_write_MDMA_D0_Y_MODIFY(2);
+ bfin_write_MDMA_S0_Y_MODIFY(2);
+ }
+ } else {
+ bfin_write_MDMA_D0_X_MODIFY(1);
+ bfin_write_MDMA_S0_X_MODIFY(1);
+ if (flag_2D) {
+ bfin_write_MDMA_D0_Y_MODIFY(1);
+ bfin_write_MDMA_S0_Y_MODIFY(1);
+ }
+ }
+ }
+
+ /* Enable source DMA */
+ if (flag_2D) {
+ if (flag_align) {
+ bfin_write_MDMA_S0_CONFIG(DMAEN | DMA2D | WDSIZE_16);
+ bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | DMA2D | WDSIZE_16);
+ } else {
+ bfin_write_MDMA_S0_CONFIG(DMAEN | DMA2D);
+ bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | DMA2D);
+ }
+ } else {
+ if (flag_align) {
+ bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
+ bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
+ } else {
+ bfin_write_MDMA_S0_CONFIG(DMAEN);
+ bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN);
+ }
+ }
+
+ while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
+ ;
+
+ bfin_write_MDMA_D0_IRQ_STATUS(bfin_read_MDMA_D0_IRQ_STATUS() |
+ (DMA_DONE | DMA_ERR));
+
+ bfin_write_MDMA_S0_CONFIG(0);
+ bfin_write_MDMA_D0_CONFIG(0);
+
+ if ((unsigned long)dest < memory_end)
+ blackfin_dcache_invalidate_range((unsigned int)dest,
+ (unsigned int)(dest + size));
+
+ return dest;
+}
+EXPORT_SYMBOL(dma_memcpy);
+
+void *safe_dma_memcpy(void *dest, const void *src, size_t size)
+{
+ int flags = 0;
+ void *addr;
+ local_irq_save(flags);
+ addr = dma_memcpy(dest, src, size);
+ local_irq_restore(flags);
+ return addr;
+}
+EXPORT_SYMBOL(safe_dma_memcpy);
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/bfin_gpio.c
+ * Based on:
+ * Author: Michael Hennerich (hennerich@blackfin.uclinux.org)
+ *
+ * Created:
+ * Description: GPIO Abstraction Layer
+ *
+ * Modified:
+ * Copyright 2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+* Number BF537/6/4 BF561 BF533/2/1
+*
+* GPIO_0 PF0 PF0 PF0
+* GPIO_1 PF1 PF1 PF1
+* GPIO_2 PF2 PF2 PF2
+* GPIO_3 PF3 PF3 PF3
+* GPIO_4 PF4 PF4 PF4
+* GPIO_5 PF5 PF5 PF5
+* GPIO_6 PF6 PF6 PF6
+* GPIO_7 PF7 PF7 PF7
+* GPIO_8 PF8 PF8 PF8
+* GPIO_9 PF9 PF9 PF9
+* GPIO_10 PF10 PF10 PF10
+* GPIO_11 PF11 PF11 PF11
+* GPIO_12 PF12 PF12 PF12
+* GPIO_13 PF13 PF13 PF13
+* GPIO_14 PF14 PF14 PF14
+* GPIO_15 PF15 PF15 PF15
+* GPIO_16 PG0 PF16
+* GPIO_17 PG1 PF17
+* GPIO_18 PG2 PF18
+* GPIO_19 PG3 PF19
+* GPIO_20 PG4 PF20
+* GPIO_21 PG5 PF21
+* GPIO_22 PG6 PF22
+* GPIO_23 PG7 PF23
+* GPIO_24 PG8 PF24
+* GPIO_25 PG9 PF25
+* GPIO_26 PG10 PF26
+* GPIO_27 PG11 PF27
+* GPIO_28 PG12 PF28
+* GPIO_29 PG13 PF29
+* GPIO_30 PG14 PF30
+* GPIO_31 PG15 PF31
+* GPIO_32 PH0 PF32
+* GPIO_33 PH1 PF33
+* GPIO_34 PH2 PF34
+* GPIO_35 PH3 PF35
+* GPIO_36 PH4 PF36
+* GPIO_37 PH5 PF37
+* GPIO_38 PH6 PF38
+* GPIO_39 PH7 PF39
+* GPIO_40 PH8 PF40
+* GPIO_41 PH9 PF41
+* GPIO_42 PH10 PF42
+* GPIO_43 PH11 PF43
+* GPIO_44 PH12 PF44
+* GPIO_45 PH13 PF45
+* GPIO_46 PH14 PF46
+* GPIO_47 PH15 PF47
+*/
+
+#include <linux/module.h>
+#include <linux/err.h>
+#include <asm/blackfin.h>
+#include <asm/gpio.h>
+#include <linux/irq.h>
+
+#ifdef BF533_FAMILY
+static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+ (struct gpio_port_t *) FIO_FLAG_D,
+};
+#endif
+
+#ifdef BF537_FAMILY
+static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+ (struct gpio_port_t *) PORTFIO,
+ (struct gpio_port_t *) PORTGIO,
+ (struct gpio_port_t *) PORTHIO,
+};
+
+static unsigned short *port_fer[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+ (unsigned short *) PORTF_FER,
+ (unsigned short *) PORTG_FER,
+ (unsigned short *) PORTH_FER,
+};
+
+#endif
+
+#ifdef BF561_FAMILY
+static struct gpio_port_t *gpio_bankb[gpio_bank(MAX_BLACKFIN_GPIOS)] = {
+ (struct gpio_port_t *) FIO0_FLAG_D,
+ (struct gpio_port_t *) FIO1_FLAG_D,
+ (struct gpio_port_t *) FIO2_FLAG_D,
+};
+#endif
+
+static unsigned short reserved_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+#ifdef CONFIG_PM
+static unsigned short wakeup_map[gpio_bank(MAX_BLACKFIN_GPIOS)];
+static unsigned char wakeup_flags_map[MAX_BLACKFIN_GPIOS];
+static struct gpio_port_s gpio_bank_saved[gpio_bank(MAX_BLACKFIN_GPIOS)];
+
+#ifdef BF533_FAMILY
+static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB};
+#endif
+
+#ifdef BF537_FAMILY
+static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG_INTB, IRQ_PORTG_INTB, IRQ_MAC_TX};
+#endif
+
+#ifdef BF561_FAMILY
+static unsigned int sic_iwr_irqs[gpio_bank(MAX_BLACKFIN_GPIOS)] = {IRQ_PROG0_INTB, IRQ_PROG1_INTB, IRQ_PROG2_INTB};
+#endif
+
+#endif /* CONFIG_PM */
+
+inline int check_gpio(unsigned short gpio)
+{
+ if (gpio > MAX_BLACKFIN_GPIOS)
+ return -EINVAL;
+ return 0;
+}
+
+#ifdef BF537_FAMILY
+void port_setup(unsigned short gpio, unsigned short usage)
+{
+ if (usage == GPIO_USAGE) {
+ if (*port_fer[gpio_bank(gpio)] & gpio_bit(gpio))
+ printk(KERN_WARNING "bfin-gpio: Possible Conflict with Peripheral "
+ "usage and GPIO %d detected!\n", gpio);
+ *port_fer[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+ } else
+ *port_fer[gpio_bank(gpio)] |= gpio_bit(gpio);
+ SSYNC();
+}
+#else
+# define port_setup(...) do { } while (0)
+#endif
+
+
+void default_gpio(unsigned short gpio)
+{
+ unsigned short bank,bitmask;
+
+ bank = gpio_bank(gpio);
+ bitmask = gpio_bit(gpio);
+
+ gpio_bankb[bank]->maska_clear = bitmask;
+ gpio_bankb[bank]->maskb_clear = bitmask;
+ SSYNC();
+ gpio_bankb[bank]->inen &= ~bitmask;
+ gpio_bankb[bank]->dir &= ~bitmask;
+ gpio_bankb[bank]->polar &= ~bitmask;
+ gpio_bankb[bank]->both &= ~bitmask;
+ gpio_bankb[bank]->edge &= ~bitmask;
+}
+
+
+int __init bfin_gpio_init(void)
+{
+ int i;
+
+ printk(KERN_INFO "Blackfin GPIO Controller\n");
+
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE)
+ reserved_map[gpio_bank(i)] = 0;
+
+#if defined(BF537_FAMILY) && (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
+# if defined(CONFIG_BFIN_MAC_RMII)
+ reserved_map[PORT_H] = 0xC373;
+# else
+ reserved_map[PORT_H] = 0xFFFF;
+# endif
+#endif
+
+ return 0;
+}
+
+arch_initcall(bfin_gpio_init);
+
+
+/***********************************************************
+*
+* FUNCTIONS: Blackfin General Purpose Ports Access Functions
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+*
+*
+* DESCRIPTION: These functions abstract direct register access
+* to Blackfin processor General Purpose
+* Ports Regsiters
+*
+* CAUTION: These functions do not belong to the GPIO Driver API
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+
+/* Set a specific bit */
+
+#define SET_GPIO(name) \
+void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \
+{ \
+ unsigned long flags; \
+ BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \
+ local_irq_save(flags); \
+ if (arg) \
+ gpio_bankb[gpio_bank(gpio)]->name |= gpio_bit(gpio); \
+ else \
+ gpio_bankb[gpio_bank(gpio)]->name &= ~gpio_bit(gpio); \
+ local_irq_restore(flags); \
+} \
+EXPORT_SYMBOL(set_gpio_ ## name);
+
+SET_GPIO(dir)
+SET_GPIO(inen)
+SET_GPIO(polar)
+SET_GPIO(edge)
+SET_GPIO(both)
+
+
+#define SET_GPIO_SC(name) \
+void set_gpio_ ## name(unsigned short gpio, unsigned short arg) \
+{ \
+ BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))); \
+ if (arg) \
+ gpio_bankb[gpio_bank(gpio)]->name ## _set = gpio_bit(gpio); \
+ else \
+ gpio_bankb[gpio_bank(gpio)]->name ## _clear = gpio_bit(gpio); \
+} \
+EXPORT_SYMBOL(set_gpio_ ## name);
+
+SET_GPIO_SC(maska)
+SET_GPIO_SC(maskb)
+
+#if defined(ANOMALY_05000311)
+void set_gpio_data(unsigned short gpio, unsigned short arg)
+{
+ unsigned long flags;
+ BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+ local_irq_save(flags);
+ if (arg)
+ gpio_bankb[gpio_bank(gpio)]->data_set = gpio_bit(gpio);
+ else
+ gpio_bankb[gpio_bank(gpio)]->data_clear = gpio_bit(gpio);
+ bfin_read_CHIPID();
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(set_gpio_data);
+#else
+SET_GPIO_SC(data)
+#endif
+
+
+#if defined(ANOMALY_05000311)
+void set_gpio_toggle(unsigned short gpio)
+{
+ unsigned long flags;
+ BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+ local_irq_save(flags);
+ gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
+ bfin_read_CHIPID();
+ local_irq_restore(flags);
+}
+#else
+void set_gpio_toggle(unsigned short gpio)
+{
+ BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+ gpio_bankb[gpio_bank(gpio)]->toggle = gpio_bit(gpio);
+}
+#endif
+EXPORT_SYMBOL(set_gpio_toggle);
+
+
+/*Set current PORT date (16-bit word)*/
+
+#define SET_GPIO_P(name) \
+void set_gpiop_ ## name(unsigned short gpio, unsigned short arg) \
+{ \
+ gpio_bankb[gpio_bank(gpio)]->name = arg; \
+} \
+EXPORT_SYMBOL(set_gpiop_ ## name);
+
+SET_GPIO_P(dir)
+SET_GPIO_P(inen)
+SET_GPIO_P(polar)
+SET_GPIO_P(edge)
+SET_GPIO_P(both)
+SET_GPIO_P(maska)
+SET_GPIO_P(maskb)
+
+
+#if defined(ANOMALY_05000311)
+void set_gpiop_data(unsigned short gpio, unsigned short arg)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+ gpio_bankb[gpio_bank(gpio)]->data = arg;
+ bfin_read_CHIPID();
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(set_gpiop_data);
+#else
+SET_GPIO_P(data)
+#endif
+
+
+
+/* Get a specific bit */
+
+#define GET_GPIO(name) \
+unsigned short get_gpio_ ## name(unsigned short gpio) \
+{ \
+ return (0x01 & (gpio_bankb[gpio_bank(gpio)]->name >> gpio_sub_n(gpio))); \
+} \
+EXPORT_SYMBOL(get_gpio_ ## name);
+
+GET_GPIO(dir)
+GET_GPIO(inen)
+GET_GPIO(polar)
+GET_GPIO(edge)
+GET_GPIO(both)
+GET_GPIO(maska)
+GET_GPIO(maskb)
+
+
+#if defined(ANOMALY_05000311)
+unsigned short get_gpio_data(unsigned short gpio)
+{
+ unsigned long flags;
+ unsigned short ret;
+ BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+ local_irq_save(flags);
+ ret = 0x01 & (gpio_bankb[gpio_bank(gpio)]->data >> gpio_sub_n(gpio));
+ bfin_read_CHIPID();
+ local_irq_restore(flags);
+ return ret;
+}
+EXPORT_SYMBOL(get_gpio_data);
+#else
+GET_GPIO(data)
+#endif
+
+/*Get current PORT date (16-bit word)*/
+
+#define GET_GPIO_P(name) \
+unsigned short get_gpiop_ ## name(unsigned short gpio) \
+{ \
+ return (gpio_bankb[gpio_bank(gpio)]->name);\
+} \
+EXPORT_SYMBOL(get_gpiop_ ## name);
+
+GET_GPIO_P(dir)
+GET_GPIO_P(inen)
+GET_GPIO_P(polar)
+GET_GPIO_P(edge)
+GET_GPIO_P(both)
+GET_GPIO_P(maska)
+GET_GPIO_P(maskb)
+
+#if defined(ANOMALY_05000311)
+unsigned short get_gpiop_data(unsigned short gpio)
+{
+ unsigned long flags;
+ unsigned short ret;
+ local_irq_save(flags);
+ ret = gpio_bankb[gpio_bank(gpio)]->data;
+ bfin_read_CHIPID();
+ local_irq_restore(flags);
+ return ret;
+}
+EXPORT_SYMBOL(get_gpiop_data);
+#else
+GET_GPIO_P(data)
+#endif
+
+#ifdef CONFIG_PM
+/***********************************************************
+*
+* FUNCTIONS: Blackfin PM Setup API
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+* type -
+* PM_WAKE_RISING
+* PM_WAKE_FALLING
+* PM_WAKE_HIGH
+* PM_WAKE_LOW
+* PM_WAKE_BOTH_EDGES
+*
+* DESCRIPTION: Blackfin PM Driver API
+*
+* CAUTION:
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+int gpio_pm_wakeup_request(unsigned short gpio, unsigned char type)
+{
+ unsigned long flags;
+
+ if ((check_gpio(gpio) < 0) || !type)
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ wakeup_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+ wakeup_flags_map[gpio] = type;
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_pm_wakeup_request);
+
+void gpio_pm_wakeup_free(unsigned short gpio)
+{
+ unsigned long flags;
+
+ if (check_gpio(gpio) < 0)
+ return;
+
+ local_irq_save(flags);
+
+ wakeup_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_pm_wakeup_free);
+
+static int bfin_gpio_wakeup_type(unsigned short gpio, unsigned char type)
+{
+ port_setup(gpio, GPIO_USAGE);
+ set_gpio_dir(gpio, 0);
+ set_gpio_inen(gpio, 1);
+
+ if (type & (PM_WAKE_RISING | PM_WAKE_FALLING))
+ set_gpio_edge(gpio, 1);
+ else
+ set_gpio_edge(gpio, 0);
+
+ if ((type & (PM_WAKE_BOTH_EDGES)) == (PM_WAKE_BOTH_EDGES))
+ set_gpio_both(gpio, 1);
+ else
+ set_gpio_both(gpio, 0);
+
+ if ((type & (PM_WAKE_FALLING | PM_WAKE_LOW)))
+ set_gpio_polar(gpio, 1);
+ else
+ set_gpio_polar(gpio, 0);
+
+ SSYNC();
+
+ return 0;
+}
+
+u32 gpio_pm_setup(void)
+{
+ u32 sic_iwr = 0;
+ u16 bank, mask, i, gpio;
+
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE) {
+ mask = wakeup_map[gpio_bank(i)];
+ bank = gpio_bank(i);
+
+ gpio_bank_saved[bank].maskb = gpio_bankb[bank]->maskb;
+ gpio_bankb[bank]->maskb = 0;
+
+ if (mask) {
+#ifdef BF537_FAMILY
+ gpio_bank_saved[bank].fer = *port_fer[bank];
+#endif
+ gpio_bank_saved[bank].inen = gpio_bankb[bank]->inen;
+ gpio_bank_saved[bank].polar = gpio_bankb[bank]->polar;
+ gpio_bank_saved[bank].dir = gpio_bankb[bank]->dir;
+ gpio_bank_saved[bank].edge = gpio_bankb[bank]->edge;
+ gpio_bank_saved[bank].both = gpio_bankb[bank]->both;
+
+ gpio = i;
+
+ while (mask) {
+ if (mask & 1) {
+ bfin_gpio_wakeup_type(gpio, wakeup_flags_map[gpio]);
+ set_gpio_data(gpio, 0); /*Clear*/
+ }
+ gpio++;
+ mask >>= 1;
+ }
+
+ sic_iwr |= 1 << (sic_iwr_irqs[bank] - (IRQ_CORETMR + 1));
+ gpio_bankb[bank]->maskb_set = wakeup_map[gpio_bank(i)];
+ }
+ }
+
+ if (sic_iwr)
+ return sic_iwr;
+ else
+ return IWR_ENABLE_ALL;
+}
+
+
+void gpio_pm_restore(void)
+{
+ u16 bank, mask, i;
+
+ for (i = 0; i < MAX_BLACKFIN_GPIOS; i+=GPIO_BANKSIZE) {
+ mask = wakeup_map[gpio_bank(i)];
+ bank = gpio_bank(i);
+
+ if (mask) {
+#ifdef BF537_FAMILY
+ *port_fer[bank] = gpio_bank_saved[bank].fer;
+#endif
+ gpio_bankb[bank]->inen = gpio_bank_saved[bank].inen;
+ gpio_bankb[bank]->dir = gpio_bank_saved[bank].dir;
+ gpio_bankb[bank]->polar = gpio_bank_saved[bank].polar;
+ gpio_bankb[bank]->edge = gpio_bank_saved[bank].edge;
+ gpio_bankb[bank]->both = gpio_bank_saved[bank].both;
+ }
+
+ gpio_bankb[bank]->maskb = gpio_bank_saved[bank].maskb;
+ }
+}
+
+#endif
+
+/***********************************************************
+*
+* FUNCTIONS: Blackfin GPIO Driver
+*
+* INPUTS/OUTPUTS:
+* gpio - GPIO Number between 0 and MAX_BLACKFIN_GPIOS
+*
+*
+* DESCRIPTION: Blackfin GPIO Driver API
+*
+* CAUTION:
+*************************************************************
+* MODIFICATION HISTORY :
+**************************************************************/
+
+int gpio_request(unsigned short gpio, const char *label)
+{
+ unsigned long flags;
+
+ if (check_gpio(gpio) < 0)
+ return -EINVAL;
+
+ local_irq_save(flags);
+
+ if (unlikely(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio))) {
+ printk(KERN_ERR "bfin-gpio: GPIO %d is already reserved!\n", gpio);
+ dump_stack();
+ local_irq_restore(flags);
+ return -EBUSY;
+ }
+ reserved_map[gpio_bank(gpio)] |= gpio_bit(gpio);
+
+ local_irq_restore(flags);
+
+ port_setup(gpio, GPIO_USAGE);
+
+ return 0;
+}
+EXPORT_SYMBOL(gpio_request);
+
+
+void gpio_free(unsigned short gpio)
+{
+ unsigned long flags;
+
+ if (check_gpio(gpio) < 0)
+ return;
+
+ local_irq_save(flags);
+
+ if (unlikely(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)))) {
+ printk(KERN_ERR "bfin-gpio: GPIO %d wasn't reserved!\n", gpio);
+ dump_stack();
+ local_irq_restore(flags);
+ return;
+ }
+
+ default_gpio(gpio);
+
+ reserved_map[gpio_bank(gpio)] &= ~gpio_bit(gpio);
+
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_free);
+
+
+void gpio_direction_input(unsigned short gpio)
+{
+ unsigned long flags;
+
+ BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+
+ local_irq_save(flags);
+ gpio_bankb[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio);
+ gpio_bankb[gpio_bank(gpio)]->inen |= gpio_bit(gpio);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+void gpio_direction_output(unsigned short gpio)
+{
+ unsigned long flags;
+
+ BUG_ON(!(reserved_map[gpio_bank(gpio)] & gpio_bit(gpio)));
+
+ local_irq_save(flags);
+ gpio_bankb[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio);
+ gpio_bankb[gpio_bank(gpio)]->dir |= gpio_bit(gpio);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL(gpio_direction_output);
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/bfin_ksyms.c
+ * Based on: none - original work
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <asm/irq.h>
+#include <asm/checksum.h>
+#include <asm/cacheflush.h>
+#include <asm/uaccess.h>
+
+/* platform dependent support */
+
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(strcmp);
+EXPORT_SYMBOL(strncmp);
+EXPORT_SYMBOL(dump_thread);
+
+EXPORT_SYMBOL(ip_fast_csum);
+
+EXPORT_SYMBOL(kernel_thread);
+
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__down_interruptible);
+
+EXPORT_SYMBOL(is_in_rom);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy);
+
+/* The following are special because they're not called
+ * explicitly (the C compiler generates them). Fortunately,
+ * their interface isn't gonna change any time soon now, so
+ * it's OK to leave it out of version control.
+ */
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(get_wchan);
+
+/*
+ * libgcc functions - functions that are used internally by the
+ * compiler... (prototypes are not correct though, but that
+ * doesn't really matter since they're not versioned).
+ */
+extern void __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __smulsi3_highpart(void);
+extern void __umulsi3_highpart(void);
+extern void __divsi3(void);
+extern void __lshrdi3(void);
+extern void __modsi3(void);
+extern void __muldi3(void);
+extern void __udivsi3(void);
+extern void __umodsi3(void);
+
+/* gcc lib functions */
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__umulsi3_highpart);
+EXPORT_SYMBOL(__smulsi3_highpart);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(outsl);
+EXPORT_SYMBOL(insl);
+EXPORT_SYMBOL(irq_flags);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(blackfin_dcache_invalidate_range);
+EXPORT_SYMBOL(blackfin_icache_dcache_flush_range);
+EXPORT_SYMBOL(blackfin_icache_flush_range);
+EXPORT_SYMBOL(blackfin_dcache_flush_range);
+EXPORT_SYMBOL(blackfin_dflush_page);
+
+EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(__init_begin);
+EXPORT_SYMBOL(__init_end);
+EXPORT_SYMBOL(_ebss_l1);
+EXPORT_SYMBOL(_stext_l1);
+EXPORT_SYMBOL(_etext_l1);
+EXPORT_SYMBOL(_sdata_l1);
+EXPORT_SYMBOL(_ebss_b_l1);
+EXPORT_SYMBOL(_sdata_b_l1);
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/dma-mapping.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: Dynamic DMA mapping support.
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/bootmem.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/bfin-global.h>
+
+static spinlock_t dma_page_lock;
+static unsigned int *dma_page;
+static unsigned int dma_pages;
+static unsigned long dma_base;
+static unsigned long dma_size;
+static unsigned int dma_initialized;
+
+void dma_alloc_init(unsigned long start, unsigned long end)
+{
+ spin_lock_init(&dma_page_lock);
+ dma_initialized = 0;
+
+ dma_page = (unsigned int *)__get_free_page(GFP_KERNEL);
+ memset(dma_page, 0, PAGE_SIZE);
+ dma_base = PAGE_ALIGN(start);
+ dma_size = PAGE_ALIGN(end) - PAGE_ALIGN(start);
+ dma_pages = dma_size >> PAGE_SHIFT;
+ memset((void *)dma_base, 0, DMA_UNCACHED_REGION);
+ dma_initialized = 1;
+
+ printk(KERN_INFO "%s: dma_page @ 0x%p - %d pages at 0x%08lx\n", __FUNCTION__,
+ dma_page, dma_pages, dma_base);
+}
+
+static inline unsigned int get_pages(size_t size)
+{
+ return ((size - 1) >> PAGE_SHIFT) + 1;
+}
+
+static unsigned long __alloc_dma_pages(unsigned int pages)
+{
+ unsigned long ret = 0, flags;
+ int i, count = 0;
+
+ if (dma_initialized == 0)
+ dma_alloc_init(_ramend - DMA_UNCACHED_REGION, _ramend);
+
+ spin_lock_irqsave(&dma_page_lock, flags);
+
+ for (i = 0; i < dma_pages;) {
+ if (dma_page[i++] == 0) {
+ if (++count == pages) {
+ while (count--)
+ dma_page[--i] = 1;
+ ret = dma_base + (i << PAGE_SHIFT);
+ break;
+ }
+ } else
+ count = 0;
+ }
+ spin_unlock_irqrestore(&dma_page_lock, flags);
+ return ret;
+}
+
+static void __free_dma_pages(unsigned long addr, unsigned int pages)
+{
+ unsigned long page = (addr - dma_base) >> PAGE_SHIFT;
+ unsigned long flags;
+ int i;
+
+ if ((page + pages) > dma_pages) {
+ printk(KERN_ERR "%s: freeing outside range.\n", __FUNCTION__);
+ BUG();
+ }
+
+ spin_lock_irqsave(&dma_page_lock, flags);
+ for (i = page; i < page + pages; i++) {
+ dma_page[i] = 0;
+ }
+ spin_unlock_irqrestore(&dma_page_lock, flags);
+}
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t * dma_handle, gfp_t gfp)
+{
+ void *ret;
+
+ ret = (void *)__alloc_dma_pages(get_pages(size));
+
+ if (ret) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_phys(ret);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void
+dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+ dma_addr_t dma_handle)
+{
+ __free_dma_pages((unsigned long)vaddr, get_pages(size));
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+/*
+ * Dummy functions defined for some existing drivers
+ */
+
+dma_addr_t
+dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+
+ invalidate_dcache_range((unsigned long)ptr,
+ (unsigned long)ptr + size);
+
+ return (dma_addr_t) ptr;
+}
+EXPORT_SYMBOL(dma_map_single);
+
+int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ for (i = 0; i < nents; i++)
+ invalidate_dcache_range(sg_dma_address(&sg[i]),
+ sg_dma_address(&sg[i]) +
+ sg_dma_len(&sg[i]));
+
+ return nents;
+}
+EXPORT_SYMBOL(dma_map_sg);
+
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+EXPORT_SYMBOL(dma_unmap_single);
+
+void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+ int nhwentries, enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+EXPORT_SYMBOL(dma_unmap_sg);
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/dualcore_test.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: Small test code for CoreB on a BF561
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+
+static int *testarg = (int*)0xfeb00000;
+
+static int test_init(void)
+{
+ *testarg = 1;
+ printk("Dual core test module inserted: set testarg = [%d]\n @ [%p]\n",
+ *testarg, testarg);
+ return 0;
+}
+
+static void test_exit(void)
+{
+ printk("Dual core test module removed: testarg = [%d]\n", *testarg);
+}
+
+module_init(test_init);
+module_exit(test_exit);
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/entry.S
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/asm-offsets.h>
+
+#include <asm/mach-common/context.S>
+
+#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
+.section .l1.text
+#else
+.text
+#endif
+
+ENTRY(_ret_from_fork)
+ SP += -12;
+ call _schedule_tail;
+ SP += 12;
+ r0 = [sp + PT_IPEND];
+ cc = bittst(r0,1);
+ if cc jump .Lin_kernel;
+ RESTORE_CONTEXT
+ rti;
+.Lin_kernel:
+ bitclr(r0,1);
+ [sp + PT_IPEND] = r0;
+ /* do a 'fake' RTI by jumping to [RETI]
+ * to avoid clearing supervisor mode in child
+ */
+ RESTORE_ALL_SYS
+ p0 = reti;
+ jump (p0);
+
+ENTRY(_sys_fork)
+ r0 = -EINVAL;
+ rts;
+
+ENTRY(_sys_vfork)
+ r0 = sp;
+ r0 += 24;
+ [--sp] = rets;
+ SP += -12;
+ call _bfin_vfork;
+ SP += 12;
+ rets = [sp++];
+ rts;
+
+ENTRY(_sys_clone)
+ r0 = sp;
+ r0 += 24;
+ [--sp] = rets;
+ SP += -12;
+ call _bfin_clone;
+ SP += 12;
+ rets = [sp++];
+ rts;
+
+ENTRY(_sys_rt_sigreturn)
+ r0 = sp;
+ r0 += 24;
+ [--sp] = rets;
+ SP += -12;
+ call _do_rt_sigreturn;
+ SP += 12;
+ rets = [sp++];
+ rts;
--- /dev/null
+/*
+ * arch/blackfin/kernel/flat.c
+ *
+ * Copyright (C) 2007 Analog Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/flat.h>
+
+#define FLAT_BFIN_RELOC_TYPE_16_BIT 0
+#define FLAT_BFIN_RELOC_TYPE_16H_BIT 1
+#define FLAT_BFIN_RELOC_TYPE_32_BIT 2
+
+unsigned long bfin_get_addr_from_rp(unsigned long *ptr,
+ unsigned long relval,
+ unsigned long flags,
+ unsigned long *persistent)
+{
+ unsigned short *usptr = (unsigned short *)ptr;
+ int type = (relval >> 26) & 7;
+ unsigned long val;
+
+ switch (type) {
+ case FLAT_BFIN_RELOC_TYPE_16_BIT:
+ case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+ usptr = (unsigned short *)ptr;
+ pr_debug("*usptr = %x", get_unaligned(usptr));
+ val = get_unaligned(usptr);
+ val += *persistent;
+ break;
+
+ case FLAT_BFIN_RELOC_TYPE_32_BIT:
+ pr_debug("*ptr = %lx", get_unaligned(ptr));
+ val = get_unaligned(ptr);
+ break;
+
+ default:
+ pr_debug("BINFMT_FLAT: Unknown relocation type %x\n",
+ type);
+
+ return 0;
+ }
+
+ /*
+ * Stack-relative relocs contain the offset into the stack, we
+ * have to add the stack's start address here and return 1 from
+ * flat_addr_absolute to prevent the normal address calculations
+ */
+ if (relval & (1 << 29))
+ return val + current->mm->context.end_brk;
+
+ if ((flags & FLAT_FLAG_GOTPIC) == 0)
+ val = htonl(val);
+ return val;
+}
+EXPORT_SYMBOL(bfin_get_addr_from_rp);
+
+/*
+ * Insert the address ADDR into the symbol reference at RP;
+ * RELVAL is the raw relocation-table entry from which RP is derived
+ */
+void bfin_put_addr_at_rp(unsigned long *ptr, unsigned long addr,
+ unsigned long relval)
+{
+ unsigned short *usptr = (unsigned short *)ptr;
+ int type = (relval >> 26) & 7;
+
+ switch (type) {
+ case FLAT_BFIN_RELOC_TYPE_16_BIT:
+ put_unaligned(addr, usptr);
+ pr_debug("new value %x at %p", get_unaligned(usptr),
+ usptr);
+ break;
+
+ case FLAT_BFIN_RELOC_TYPE_16H_BIT:
+ put_unaligned(addr >> 16, usptr);
+ pr_debug("new value %x", get_unaligned(usptr));
+ break;
+
+ case FLAT_BFIN_RELOC_TYPE_32_BIT:
+ put_unaligned(addr, ptr);
+ pr_debug("new ptr =%lx", get_unaligned(ptr));
+ break;
+ }
+}
+EXPORT_SYMBOL(bfin_put_addr_at_rp);
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/init_task.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+
+struct mm_struct init_mm = INIT_MM(init_mm);
+EXPORT_SYMBOL(init_mm);
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry.
+ */
+union thread_union init_thread_union
+ __attribute__ ((__section__(".data.init_task"))) = {
+INIT_THREAD_INFO(init_task)};
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/irqchip.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the simple DMA Implementation for Blackfin
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/seq_file.h>
+#include <linux/kallsyms.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+static unsigned long irq_err_count;
+static spinlock_t irq_controller_lock;
+
+/*
+ * Dummy mask/unmask handler
+ */
+void dummy_mask_unmask_irq(unsigned int irq)
+{
+}
+
+void ack_bad_irq(unsigned int irq)
+{
+ irq_err_count += 1;
+ printk(KERN_ERR "IRQ: spurious interrupt %d\n", irq);
+}
+EXPORT_SYMBOL(ack_bad_irq);
+
+static struct irq_chip bad_chip = {
+ .ack = dummy_mask_unmask_irq,
+ .mask = dummy_mask_unmask_irq,
+ .unmask = dummy_mask_unmask_irq,
+};
+
+static struct irq_desc bad_irq_desc = {
+ .chip = &bad_chip,
+ .handle_irq = handle_bad_irq,
+ .depth = 1,
+};
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *) v;
+ struct irqaction *action;
+ unsigned long flags;
+
+ if (i < NR_IRQS) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+ goto unlock;
+
+ seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
+ seq_printf(p, " %s", action->name);
+ for (action = action->next; action; action = action->next)
+ seq_printf(p, ", %s", action->name);
+
+ seq_putc(p, '\n');
+ unlock:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ } else if (i == NR_IRQS) {
+ seq_printf(p, "Err: %10lu\n", irq_err_count);
+ }
+ return 0;
+}
+
+/*
+ * do_IRQ handles all hardware IRQ's. Decoded IRQs should not
+ * come via this function. Instead, they should provide their
+ * own 'handler'
+ */
+
+#ifdef CONFIG_DO_IRQ_L1
+asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)__attribute__((l1_text));
+#endif
+
+asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+ struct pt_regs *old_regs;
+ struct irq_desc *desc = irq_desc + irq;
+ unsigned short pending, other_ints;
+
+ old_regs = set_irq_regs(regs);
+
+ /*
+ * Some hardware gives randomly wrong interrupts. Rather
+ * than crashing, do something sensible.
+ */
+ if (irq >= NR_IRQS)
+ desc = &bad_irq_desc;
+
+ irq_enter();
+
+ generic_handle_irq(irq);
+
+ /* If we're the only interrupt running (ignoring IRQ15 which is for
+ syscalls), lower our priority to IRQ14 so that softirqs run at
+ that level. If there's another, lower-level interrupt, irq_exit
+ will defer softirqs to that. */
+ CSYNC();
+ pending = bfin_read_IPEND() & ~0x8000;
+ other_ints = pending & (pending - 1);
+ if (other_ints == 0)
+ lower_to_irq14();
+ irq_exit();
+
+ set_irq_regs(old_regs);
+}
+
+void __init init_IRQ(void)
+{
+ struct irq_desc *desc;
+ int irq;
+
+ spin_lock_init(&irq_controller_lock);
+ for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++) {
+ *desc = bad_irq_desc;
+ }
+
+ init_arch_irq();
+}
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/module.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <asm/dma.h>
+#include <asm/cacheflush.h>
+
+/*
+ * handle arithmetic relocations.
+ * See binutils/bfd/elf32-bfin.c for more details
+ */
+#define RELOC_STACK_SIZE 100
+static uint32_t reloc_stack[RELOC_STACK_SIZE];
+static unsigned int reloc_stack_tos;
+
+#define is_reloc_stack_empty() ((reloc_stack_tos > 0)?0:1)
+
+static void reloc_stack_push(uint32_t value)
+{
+ reloc_stack[reloc_stack_tos++] = value;
+}
+
+static uint32_t reloc_stack_pop(void)
+{
+ return reloc_stack[--reloc_stack_tos];
+}
+
+static uint32_t reloc_stack_operate(unsigned int oper, struct module *mod)
+{
+ uint32_t value;
+
+ switch (oper) {
+ case R_add:
+ value = reloc_stack[reloc_stack_tos - 2] +
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_sub:
+ value = reloc_stack[reloc_stack_tos - 2] -
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_mult:
+ value = reloc_stack[reloc_stack_tos - 2] *
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_div:
+ value = reloc_stack[reloc_stack_tos - 2] /
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_mod:
+ value = reloc_stack[reloc_stack_tos - 2] %
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_lshift:
+ value = reloc_stack[reloc_stack_tos - 2] <<
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_rshift:
+ value = reloc_stack[reloc_stack_tos - 2] >>
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_and:
+ value = reloc_stack[reloc_stack_tos - 2] &
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_or:
+ value = reloc_stack[reloc_stack_tos - 2] |
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_xor:
+ value = reloc_stack[reloc_stack_tos - 2] ^
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_land:
+ value = reloc_stack[reloc_stack_tos - 2] &&
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_lor:
+ value = reloc_stack[reloc_stack_tos - 2] ||
+ reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 2;
+ break;
+ case R_neg:
+ value = -reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos--;
+ break;
+ case R_comp:
+ value = ~reloc_stack[reloc_stack_tos - 1];
+ reloc_stack_tos -= 1;
+ break;
+ default:
+ printk(KERN_WARNING "module %s: unhandled reloction\n",
+ mod->name);
+ return 0;
+ }
+
+ /* now push the new value back on stack */
+ reloc_stack_push(value);
+
+ return value;
+}
+
+void *module_alloc(unsigned long size)
+{
+ if (size == 0)
+ return NULL;
+ return vmalloc(size);
+}
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+ vfree(module_region);
+}
+
+/* Transfer the section to the L1 memory */
+int
+module_frob_arch_sections(Elf_Ehdr * hdr, Elf_Shdr * sechdrs,
+ char *secstrings, struct module *mod)
+{
+ Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+ void *dest = NULL;
+
+ for (s = sechdrs; s < sechdrs_end; ++s) {
+ if ((strcmp(".l1.text", secstrings + s->sh_name) == 0) ||
+ ((strcmp(".text", secstrings + s->sh_name)==0) &&
+ (hdr->e_flags & FLG_CODE_IN_L1) && (s->sh_size > 0))) {
+ mod->arch.text_l1 = s;
+ dest = l1_inst_sram_alloc(s->sh_size);
+ if (dest == NULL) {
+ printk(KERN_ERR
+ "module %s: L1 instruction memory allocation failed\n",
+ mod->name);
+ return -1;
+ }
+ dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
+ s->sh_flags &= ~SHF_ALLOC;
+ s->sh_addr = (unsigned long)dest;
+ }
+ if ((strcmp(".l1.data", secstrings + s->sh_name) == 0)||
+ ((strcmp(".data", secstrings + s->sh_name)==0) &&
+ (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
+ mod->arch.data_a_l1 = s;
+ dest = l1_data_sram_alloc(s->sh_size);
+ if (dest == NULL) {
+ printk(KERN_ERR
+ "module %s: L1 data memory allocation failed\n",
+ mod->name);
+ return -1;
+ }
+ memcpy(dest, (void *)s->sh_addr, s->sh_size);
+ s->sh_flags &= ~SHF_ALLOC;
+ s->sh_addr = (unsigned long)dest;
+ }
+ if (strcmp(".l1.bss", secstrings + s->sh_name) == 0 ||
+ ((strcmp(".bss", secstrings + s->sh_name)==0) &&
+ (hdr->e_flags & FLG_DATA_IN_L1) && (s->sh_size > 0))) {
+ mod->arch.bss_a_l1 = s;
+ dest = l1_data_sram_alloc(s->sh_size);
+ if (dest == NULL) {
+ printk(KERN_ERR
+ "module %s: L1 data memory allocation failed\n",
+ mod->name);
+ return -1;
+ }
+ memset(dest, 0, s->sh_size);
+ s->sh_flags &= ~SHF_ALLOC;
+ s->sh_addr = (unsigned long)dest;
+ }
+ if (strcmp(".l1.data.B", secstrings + s->sh_name) == 0) {
+ mod->arch.data_b_l1 = s;
+ dest = l1_data_B_sram_alloc(s->sh_size);
+ if (dest == NULL) {
+ printk(KERN_ERR
+ "module %s: L1 data memory allocation failed\n",
+ mod->name);
+ return -1;
+ }
+ memcpy(dest, (void *)s->sh_addr, s->sh_size);
+ s->sh_flags &= ~SHF_ALLOC;
+ s->sh_addr = (unsigned long)dest;
+ }
+ if (strcmp(".l1.bss.B", secstrings + s->sh_name) == 0) {
+ mod->arch.bss_b_l1 = s;
+ dest = l1_data_B_sram_alloc(s->sh_size);
+ if (dest == NULL) {
+ printk(KERN_ERR
+ "module %s: L1 data memory allocation failed\n",
+ mod->name);
+ return -1;
+ }
+ memset(dest, 0, s->sh_size);
+ s->sh_flags &= ~SHF_ALLOC;
+ s->sh_addr = (unsigned long)dest;
+ }
+ }
+ return 0;
+}
+
+int
+apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relsec, struct module *me)
+{
+ printk(KERN_ERR "module %s: .rel unsupported\n", me->name);
+ return -ENOEXEC;
+}
+
+/*************************************************************************/
+/* FUNCTION : apply_relocate_add */
+/* ABSTRACT : Blackfin specific relocation handling for the loadable */
+/* modules. Modules are expected to be .o files. */
+/* Arithmetic relocations are handled. */
+/* We do not expect LSETUP to be split and hence is not */
+/* handled. */
+/* R_byte and R_byte2 are also not handled as the gas */
+/* does not generate it. */
+/*************************************************************************/
+int
+apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
+ unsigned int symindex, unsigned int relsec,
+ struct module *mod)
+{
+ unsigned int i;
+ unsigned short tmp;
+ Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+ Elf32_Sym *sym;
+ uint32_t *location32;
+ uint16_t *location16;
+ uint32_t value;
+
+ pr_debug("Applying relocate section %u to %u\n", relsec,
+ sechdrs[relsec].sh_info);
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+ /* This is where to make the change */
+ location16 =
+ (uint16_t *) (sechdrs[sechdrs[relsec].sh_info].sh_addr +
+ rel[i].r_offset);
+ location32 = (uint32_t *) location16;
+ /* This is the symbol it is referring to. Note that all
+ undefined symbols have been resolved. */
+ sym = (Elf32_Sym *) sechdrs[symindex].sh_addr
+ + ELF32_R_SYM(rel[i].r_info);
+ if (is_reloc_stack_empty()) {
+ value = sym->st_value;
+ } else {
+ value = reloc_stack_pop();
+ }
+ value += rel[i].r_addend;
+ pr_debug("location is %x, value is %x type is %d \n",
+ (unsigned int) location32, value,
+ ELF32_R_TYPE(rel[i].r_info));
+
+ switch (ELF32_R_TYPE(rel[i].r_info)) {
+
+ case R_pcrel24:
+ case R_pcrel24_jump_l:
+ /* Add the value, subtract its postition */
+ location16 =
+ (uint16_t *) (sechdrs[sechdrs[relsec].sh_info].
+ sh_addr + rel[i].r_offset - 2);
+ location32 = (uint32_t *) location16;
+ value -= (uint32_t) location32;
+ value >>= 1;
+ pr_debug("value is %x, before %x-%x after %x-%x\n", value,
+ *location16, *(location16 + 1),
+ (*location16 & 0xff00) | (value >> 16 & 0x00ff),
+ value & 0xffff);
+ *location16 =
+ (*location16 & 0xff00) | (value >> 16 & 0x00ff);
+ *(location16 + 1) = value & 0xffff;
+ break;
+ case R_pcrel12_jump:
+ case R_pcrel12_jump_s:
+ value -= (uint32_t) location32;
+ value >>= 1;
+ *location16 = (value & 0xfff);
+ break;
+ case R_pcrel10:
+ value -= (uint32_t) location32;
+ value >>= 1;
+ *location16 = (value & 0x3ff);
+ break;
+ case R_luimm16:
+ pr_debug("before %x after %x\n", *location16,
+ (value & 0xffff));
+ tmp = (value & 0xffff);
+ if((unsigned long)location16 >= L1_CODE_START) {
+ dma_memcpy(location16, &tmp, 2);
+ } else
+ *location16 = tmp;
+ break;
+ case R_huimm16:
+ pr_debug("before %x after %x\n", *location16,
+ ((value >> 16) & 0xffff));
+ tmp = ((value >> 16) & 0xffff);
+ if((unsigned long)location16 >= L1_CODE_START) {
+ dma_memcpy(location16, &tmp, 2);
+ } else
+ *location16 = tmp;
+ break;
+ case R_rimm16:
+ *location16 = (value & 0xffff);
+ break;
+ case R_byte4_data:
+ pr_debug("before %x after %x\n", *location32, value);
+ *location32 = value;
+ break;
+ case R_push:
+ reloc_stack_push(value);
+ break;
+ case R_const:
+ reloc_stack_push(rel[i].r_addend);
+ break;
+ case R_add:
+ case R_sub:
+ case R_mult:
+ case R_div:
+ case R_mod:
+ case R_lshift:
+ case R_rshift:
+ case R_and:
+ case R_or:
+ case R_xor:
+ case R_land:
+ case R_lor:
+ case R_neg:
+ case R_comp:
+ reloc_stack_operate(ELF32_R_TYPE(rel[i].r_info), mod);
+ break;
+ default:
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+ mod->name, ELF32_R_TYPE(rel[i].r_info));
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+int
+module_finalize(const Elf_Ehdr * hdr,
+ const Elf_Shdr * sechdrs, struct module *mod)
+{
+ unsigned int i, strindex = 0, symindex = 0;
+ char *secstrings;
+
+ secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ for (i = 1; i < hdr->e_shnum; i++) {
+ /* Internal symbols and strings. */
+ if (sechdrs[i].sh_type == SHT_SYMTAB) {
+ symindex = i;
+ strindex = sechdrs[i].sh_link;
+ }
+ }
+
+ for (i = 1; i < hdr->e_shnum; i++) {
+ const char *strtab = (char *)sechdrs[strindex].sh_addr;
+ unsigned int info = sechdrs[i].sh_info;
+
+ /* Not a valid relocation section? */
+ if (info >= hdr->e_shnum)
+ continue;
+
+ if ((sechdrs[i].sh_type == SHT_RELA) &&
+ ((strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0)||
+ ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
+ (hdr->e_flags & FLG_CODE_IN_L1)))) {
+ apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
+ symindex, i, mod);
+ }
+ }
+ return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+ if ((mod->arch.text_l1) && (mod->arch.text_l1->sh_addr))
+ l1_inst_sram_free((void*)mod->arch.text_l1->sh_addr);
+ if ((mod->arch.data_a_l1) && (mod->arch.data_a_l1->sh_addr))
+ l1_data_sram_free((void*)mod->arch.data_a_l1->sh_addr);
+ if ((mod->arch.bss_a_l1) && (mod->arch.bss_a_l1->sh_addr))
+ l1_data_sram_free((void*)mod->arch.bss_a_l1->sh_addr);
+ if ((mod->arch.data_b_l1) && (mod->arch.data_b_l1->sh_addr))
+ l1_data_B_sram_free((void*)mod->arch.data_b_l1->sh_addr);
+ if ((mod->arch.bss_b_l1) && (mod->arch.bss_b_l1->sh_addr))
+ l1_data_B_sram_free((void*)mod->arch.bss_b_l1->sh_addr);
+}
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/process.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: Blackfin architecture-dependent process handling.
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <linux/unistd.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+
+#include <asm/blackfin.h>
+#include <asm/uaccess.h>
+
+#define LED_ON 0
+#define LED_OFF 1
+
+asmlinkage void ret_from_fork(void);
+
+/* Points to the SDRAM backup memory for the stack that is currently in
+ * L1 scratchpad memory.
+ */
+void *current_l1_stack_save;
+
+/* The number of tasks currently using a L1 stack area. The SRAM is
+ * allocated/deallocated whenever this changes from/to zero.
+ */
+int nr_l1stack_tasks;
+
+/* Start and length of the area in L1 scratchpad memory which we've allocated
+ * for process stacks.
+ */
+void *l1_stack_base;
+unsigned long l1_stack_len;
+
+/*
+ * Powermanagement idle function, if any..
+ */
+void (*pm_idle)(void) = NULL;
+EXPORT_SYMBOL(pm_idle);
+
+void (*pm_power_off)(void) = NULL;
+EXPORT_SYMBOL(pm_power_off);
+
+/*
+ * We are using a different LED from the one used to indicate timer interrupt.
+ */
+#if defined(CONFIG_BFIN_IDLE_LED)
+static inline void leds_switch(int flag)
+{
+ unsigned short tmp = 0;
+
+ tmp = bfin_read_CONFIG_BFIN_IDLE_LED_PORT();
+ SSYNC();
+
+ if (flag == LED_ON)
+ tmp &= ~CONFIG_BFIN_IDLE_LED_PIN; /* light on */
+ else
+ tmp |= CONFIG_BFIN_IDLE_LED_PIN; /* light off */
+
+ bfin_write_CONFIG_BFIN_IDLE_LED_PORT(tmp);
+ SSYNC();
+
+}
+#else
+static inline void leds_switch(int flag)
+{
+}
+#endif
+
+/*
+ * The idle loop on BFIN
+ */
+#ifdef CONFIG_IDLE_L1
+void default_idle(void)__attribute__((l1_text));
+void cpu_idle(void)__attribute__((l1_text));
+#endif
+
+void default_idle(void)
+{
+ while (!need_resched()) {
+ leds_switch(LED_OFF);
+ local_irq_disable();
+ if (likely(!need_resched()))
+ idle_with_irq_disabled();
+ local_irq_enable();
+ leds_switch(LED_ON);
+ }
+}
+
+void (*idle)(void) = default_idle;
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+ /* endless idle loop with no priority at all */
+ while (1) {
+ idle();
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+ }
+}
+
+void machine_restart(char *__unused)
+{
+#if defined(CONFIG_BLKFIN_CACHE)
+ bfin_write_IMEM_CONTROL(0x01);
+ SSYNC();
+#endif
+ bfin_reset();
+ /* Dont do anything till the reset occurs */
+ while (1) {
+ SSYNC();
+ }
+}
+
+void machine_halt(void)
+{
+ for (;;)
+ asm volatile ("idle");
+}
+
+void machine_power_off(void)
+{
+ for (;;)
+ asm volatile ("idle");
+}
+
+void show_regs(struct pt_regs *regs)
+{
+ printk(KERN_NOTICE "\n");
+ printk(KERN_NOTICE
+ "PC: %08lu Status: %04lu SysStatus: %04lu RETS: %08lu\n",
+ regs->pc, regs->astat, regs->seqstat, regs->rets);
+ printk(KERN_NOTICE
+ "A0.x: %08lx A0.w: %08lx A1.x: %08lx A1.w: %08lx\n",
+ regs->a0x, regs->a0w, regs->a1x, regs->a1w);
+ printk(KERN_NOTICE "P0: %08lx P1: %08lx P2: %08lx P3: %08lx\n",
+ regs->p0, regs->p1, regs->p2, regs->p3);
+ printk(KERN_NOTICE "P4: %08lx P5: %08lx\n", regs->p4, regs->p5);
+ printk(KERN_NOTICE "R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n",
+ regs->r0, regs->r1, regs->r2, regs->r3);
+ printk(KERN_NOTICE "R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n",
+ regs->r4, regs->r5, regs->r6, regs->r7);
+
+ if (!(regs->ipend))
+ printk("USP: %08lx\n", rdusp());
+}
+
+/* Fill in the fpu structure for a core dump. */
+
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpregs)
+{
+ return 1;
+}
+
+/*
+ * This gets run with P1 containing the
+ * function to call, and R1 containing
+ * the "args". Note P0 is clobbered on the way here.
+ */
+void kernel_thread_helper(void);
+__asm__(".section .text\n"
+ ".align 4\n"
+ "_kernel_thread_helper:\n\t"
+ "\tsp += -12;\n\t"
+ "\tr0 = r1;\n\t" "\tcall (p1);\n\t" "\tcall _do_exit;\n" ".previous");
+
+/*
+ * Create a kernel thread.
+ */
+pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
+{
+ struct pt_regs regs;
+
+ memset(®s, 0, sizeof(regs));
+
+ regs.r1 = (unsigned long)arg;
+ regs.p1 = (unsigned long)fn;
+ regs.pc = (unsigned long)kernel_thread_helper;
+ regs.orig_p0 = -1;
+ /* Set bit 2 to tell ret_from_fork we should be returning to kernel
+ mode. */
+ regs.ipend = 0x8002;
+ __asm__ __volatile__("%0 = syscfg;":"=da"(regs.syscfg):);
+ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL,
+ NULL);
+}
+
+void flush_thread(void)
+{
+}
+
+asmlinkage int bfin_vfork(struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL,
+ NULL);
+}
+
+asmlinkage int bfin_clone(struct pt_regs *regs)
+{
+ unsigned long clone_flags;
+ unsigned long newsp;
+
+ /* syscall2 puts clone_flags in r0 and usp in r1 */
+ clone_flags = regs->r0;
+ newsp = regs->r1;
+ if (!newsp)
+ newsp = rdusp();
+ else
+ newsp -= 12;
+ return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
+}
+
+int
+copy_thread(int nr, unsigned long clone_flags,
+ unsigned long usp, unsigned long topstk,
+ struct task_struct *p, struct pt_regs *regs)
+{
+ struct pt_regs *childregs;
+
+ childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
+ *childregs = *regs;
+ childregs->r0 = 0;
+
+ p->thread.usp = usp;
+ p->thread.ksp = (unsigned long)childregs;
+ p->thread.pc = (unsigned long)ret_from_fork;
+
+ return 0;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs *regs, struct user *dump)
+{
+ dump->magic = CMAGIC;
+ dump->start_code = 0;
+ dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
+ dump->u_tsize = ((unsigned long)current->mm->end_code) >> PAGE_SHIFT;
+ dump->u_dsize = ((unsigned long)(current->mm->brk +
+ (PAGE_SIZE - 1))) >> PAGE_SHIFT;
+ dump->u_dsize -= dump->u_tsize;
+ dump->u_ssize = 0;
+
+ if (dump->start_stack < TASK_SIZE)
+ dump->u_ssize =
+ ((unsigned long)(TASK_SIZE -
+ dump->start_stack)) >> PAGE_SHIFT;
+
+ dump->u_ar0 = (struct user_regs_struct *)((int)&dump->regs - (int)dump);
+
+ dump->regs.r0 = regs->r0;
+ dump->regs.r1 = regs->r1;
+ dump->regs.r2 = regs->r2;
+ dump->regs.r3 = regs->r3;
+ dump->regs.r4 = regs->r4;
+ dump->regs.r5 = regs->r5;
+ dump->regs.r6 = regs->r6;
+ dump->regs.r7 = regs->r7;
+ dump->regs.p0 = regs->p0;
+ dump->regs.p1 = regs->p1;
+ dump->regs.p2 = regs->p2;
+ dump->regs.p3 = regs->p3;
+ dump->regs.p4 = regs->p4;
+ dump->regs.p5 = regs->p5;
+ dump->regs.orig_p0 = regs->orig_p0;
+ dump->regs.a0w = regs->a0w;
+ dump->regs.a1w = regs->a1w;
+ dump->regs.a0x = regs->a0x;
+ dump->regs.a1x = regs->a1x;
+ dump->regs.rets = regs->rets;
+ dump->regs.astat = regs->astat;
+ dump->regs.pc = regs->pc;
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+
+asmlinkage int sys_execve(char *name, char **argv, char **envp)
+{
+ int error;
+ char *filename;
+ struct pt_regs *regs = (struct pt_regs *)((&name) + 6);
+
+ lock_kernel();
+ filename = getname(name);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, argv, envp, regs);
+ putname(filename);
+ out:
+ unlock_kernel();
+ return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long fp, pc;
+ unsigned long stack_page;
+ int count = 0;
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+
+ stack_page = (unsigned long)p;
+ fp = p->thread.usp;
+ do {
+ if (fp < stack_page + sizeof(struct thread_info) ||
+ fp >= 8184 + stack_page)
+ return 0;
+ pc = ((unsigned long *)fp)[1];
+ if (!in_sched_functions(pc))
+ return pc;
+ fp = *(unsigned long *)fp;
+ }
+ while (count++ < 16);
+ return 0;
+}
+
+#if defined(CONFIG_ACCESS_CHECK)
+int _access_ok(unsigned long addr, unsigned long size)
+{
+
+ if (addr > (addr + size))
+ return 0;
+ if (segment_eq(get_fs(),KERNEL_DS))
+ return 1;
+#ifdef CONFIG_MTD_UCLINUX
+ if (addr >= memory_start && (addr + size) <= memory_end)
+ return 1;
+ if (addr >= memory_mtd_end && (addr + size) <= physical_mem_end)
+ return 1;
+#else
+ if (addr >= memory_start && (addr + size) <= physical_mem_end)
+ return 1;
+#endif
+ if (addr >= (unsigned long)__init_begin &&
+ addr + size <= (unsigned long)__init_end)
+ return 1;
+ if (addr >= L1_SCRATCH_START
+ && addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH)
+ return 1;
+#if L1_CODE_LENGTH != 0
+ if (addr >= L1_CODE_START + (_etext_l1 - _stext_l1)
+ && addr + size <= L1_CODE_START + L1_CODE_LENGTH)
+ return 1;
+#endif
+#if L1_DATA_A_LENGTH != 0
+ if (addr >= L1_DATA_A_START + (_ebss_l1 - _sdata_l1)
+ && addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH)
+ return 1;
+#endif
+#if L1_DATA_B_LENGTH != 0
+ if (addr >= L1_DATA_B_START
+ && addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH)
+ return 1;
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(_access_ok);
+#endif /* CONFIG_ACCESS_CHECK */
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/ptrace.c
+ * Based on: Taken from linux/kernel/ptrace.c
+ * Author: linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
+ *
+ * Created: 1/23/92
+ * Description:
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/signal.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/asm-offsets.h>
+#include <asm/dma.h>
+
+#define MAX_SHARED_LIBS 3
+#define TEXT_OFFSET 0
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/* determines which bits in the SYSCFG reg the user has access to. */
+/* 1 = access 0 = no access */
+#define SYSCFG_MASK 0x0007 /* SYSCFG reg */
+/* sets the trace bits. */
+#define TRACE_BITS 0x0001
+
+/* Find the stack offset for a register, relative to thread.esp0. */
+#define PT_REG(reg) ((long)&((struct pt_regs *)0)->reg)
+
+/*
+ * Get the address of the live pt_regs for the specified task.
+ * These are saved onto the top kernel stack when the process
+ * is not running.
+ *
+ * Note: if a user thread is execve'd from kernel space, the
+ * kernel stack will not be empty on entry to the kernel, so
+ * ptracing these tasks will fail.
+ */
+static inline struct pt_regs *get_user_regs(struct task_struct *task)
+{
+ return (struct pt_regs *)
+ ((unsigned long)task->thread_info +
+ (THREAD_SIZE - sizeof(struct pt_regs)));
+}
+
+/*
+ * Get all user integer registers.
+ */
+static inline int ptrace_getregs(struct task_struct *tsk, void __user * uregs)
+{
+ struct pt_regs *regs = get_user_regs(tsk);
+ return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
+}
+
+/* Mapping from PT_xxx to the stack offset at which the register is
+ * saved. Notice that usp has no stack-slot and needs to be treated
+ * specially (see get_reg/put_reg below).
+ */
+
+/*
+ * Get contents of register REGNO in task TASK.
+ */
+static inline long get_reg(struct task_struct *task, int regno)
+{
+ unsigned char *reg_ptr;
+
+ struct pt_regs *regs =
+ (struct pt_regs *)((unsigned long)task->thread_info +
+ (THREAD_SIZE - sizeof(struct pt_regs)));
+ reg_ptr = (char *)regs;
+
+ switch (regno) {
+ case PT_USP:
+ return task->thread.usp;
+ default:
+ if (regno <= 216)
+ return *(long *)(reg_ptr + regno);
+ }
+ /* slight mystery ... never seems to come here but kernel misbehaves without this code! */
+
+ printk(KERN_WARNING "Request to get for unknown register %d\n", regno);
+ return 0;
+}
+
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+static inline int
+put_reg(struct task_struct *task, int regno, unsigned long data)
+{
+ char * reg_ptr;
+
+ struct pt_regs *regs =
+ (struct pt_regs *)((unsigned long)task->thread_info +
+ (THREAD_SIZE - sizeof(struct pt_regs)));
+ reg_ptr = (char *)regs;
+
+ switch (regno) {
+ case PT_PC:
+ /*********************************************************************/
+ /* At this point the kernel is most likely in exception. */
+ /* The RETX register will be used to populate the pc of the process. */
+ /*********************************************************************/
+ regs->retx = data;
+ regs->pc = data;
+ break;
+ case PT_RETX:
+ break; /* regs->retx = data; break; */
+ case PT_USP:
+ regs->usp = data;
+ task->thread.usp = data;
+ break;
+ default:
+ if (regno <= 216)
+ *(long *)(reg_ptr + regno) = data;
+ }
+ return 0;
+}
+
+/*
+ * check that an address falls within the bounds of the target process's memory mappings
+ */
+static inline int is_user_addr_valid(struct task_struct *child,
+ unsigned long start, unsigned long len)
+{
+ struct vm_list_struct *vml;
+ struct sram_list_struct *sraml;
+
+ for (vml = child->mm->context.vmlist; vml; vml = vml->next)
+ if (start >= vml->vma->vm_start && start + len <= vml->vma->vm_end)
+ return 0;
+
+ for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next)
+ if (start >= (unsigned long)sraml->addr
+ && start + len <= (unsigned long)sraml->addr + sraml->length)
+ return 0;
+
+ return -EIO;
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+ unsigned long tmp;
+ /* make sure the single step bit is not set. */
+ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
+ put_reg(child, PT_SR, tmp);
+}
+
+long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+{
+ int ret;
+ int add = 0;
+
+ switch (request) {
+ /* when I and D space are separate, these will need to be fixed. */
+ case PTRACE_PEEKDATA:
+ pr_debug("ptrace: PEEKDATA\n");
+ add = MAX_SHARED_LIBS * 4; /* space between text and data */
+ /* fall through */
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ {
+ unsigned long tmp = 0;
+ int copied;
+
+ ret = -EIO;
+ pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + add %d %ld\n", addr, add,
+ sizeof(data));
+ if (is_user_addr_valid(child, addr + add, sizeof(tmp)) < 0)
+ break;
+ pr_debug("ptrace: user address is valid\n");
+
+#if L1_CODE_LENGTH != 0
+ if (addr + add >= L1_CODE_START
+ && addr + add + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) {
+ safe_dma_memcpy (&tmp, (const void *)(addr + add), sizeof(tmp));
+ copied = sizeof(tmp);
+ } else
+#endif
+ copied =
+ access_process_vm(child, addr + add, &tmp,
+ sizeof(tmp), 0);
+ pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp);
+ if (copied != sizeof(tmp))
+ break;
+ ret = put_user(tmp, (unsigned long *)data);
+ break;
+ }
+
+ /* read the word at location addr in the USER area. */
+ case PTRACE_PEEKUSR:
+ {
+ unsigned long tmp;
+ ret = -EIO;
+ tmp = 0;
+ if ((addr & 3) || (addr > (sizeof(struct pt_regs) + 16))) {
+ printk(KERN_WARNING "ptrace error : PEEKUSR : temporarily returning "
+ "0 - %x sizeof(pt_regs) is %lx\n",
+ (int)addr, sizeof(struct pt_regs));
+ break;
+ }
+ if (addr == sizeof(struct pt_regs)) {
+ /* PT_TEXT_ADDR */
+ tmp = child->mm->start_code + TEXT_OFFSET;
+ } else if (addr == (sizeof(struct pt_regs) + 4)) {
+ /* PT_TEXT_END_ADDR */
+ tmp = child->mm->end_code;
+ } else if (addr == (sizeof(struct pt_regs) + 8)) {
+ /* PT_DATA_ADDR */
+ tmp = child->mm->start_data;
+#ifdef CONFIG_BINFMT_ELF_FDPIC
+ } else if (addr == (sizeof(struct pt_regs) + 12)) {
+ tmp = child->mm->context.exec_fdpic_loadmap;
+ } else if (addr == (sizeof(struct pt_regs) + 16)) {
+ tmp = child->mm->context.interp_fdpic_loadmap;
+#endif
+ } else {
+ tmp = get_reg(child, addr);
+ }
+ ret = put_user(tmp, (unsigned long *)data);
+ break;
+ }
+
+ /* when I and D space are separate, this will have to be fixed. */
+ case PTRACE_POKEDATA:
+ printk(KERN_NOTICE "ptrace: PTRACE_PEEKDATA\n");
+ /* fall through */
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ {
+ int copied;
+
+ ret = -EIO;
+ pr_debug("ptrace: POKETEXT at addr 0x%08lx + add %d %ld bytes %lx\n",
+ addr, add, sizeof(data), data);
+ if (is_user_addr_valid(child, addr + add, sizeof(data)) < 0)
+ break;
+ pr_debug("ptrace: user address is valid\n");
+
+#if L1_CODE_LENGTH != 0
+ if (addr + add >= L1_CODE_START
+ && addr + add + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) {
+ safe_dma_memcpy ((void *)(addr + add), &data, sizeof(data));
+ copied = sizeof(data);
+ } else
+#endif
+ copied =
+ access_process_vm(child, addr + add, &data,
+ sizeof(data), 1);
+ pr_debug("ptrace: copied size %d\n", copied);
+ if (copied != sizeof(data))
+ break;
+ ret = 0;
+ break;
+ }
+
+ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ ret = -EIO;
+ if ((addr & 3) || (addr > (sizeof(struct pt_regs) + 16))) {
+ printk(KERN_WARNING "ptrace error : POKEUSR: temporarily returning 0\n");
+ break;
+ }
+
+ if (addr >= (sizeof(struct pt_regs))) {
+ ret = 0;
+ break;
+ }
+ if (addr == PT_SYSCFG) {
+ data &= SYSCFG_MASK;
+ data |= get_reg(child, PT_SYSCFG);
+ }
+ ret = put_reg(child, addr, data);
+ break;
+
+ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+ case PTRACE_CONT:
+ { /* restart after signal. */
+ long tmp;
+
+ pr_debug("ptrace_cont\n");
+
+ ret = -EIO;
+ if (!valid_signal(data))
+ break;
+ if (request == PTRACE_SYSCALL)
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ else
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
+ child->exit_code = data;
+ /* make sure the single step bit is not set. */
+ tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS);
+ put_reg(child, PT_SYSCFG, tmp);
+ pr_debug("before wake_up_process\n");
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+ /*
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
+ * exit.
+ */
+ case PTRACE_KILL:
+ {
+ long tmp;
+ ret = 0;
+ if (child->exit_state == EXIT_ZOMBIE) /* already dead */
+ break;
+ child->exit_code = SIGKILL;
+ /* make sure the single step bit is not set. */
+ tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS);
+ put_reg(child, PT_SYSCFG, tmp);
+ wake_up_process(child);
+ break;
+ }
+
+ case PTRACE_SINGLESTEP:
+ { /* set the trap flag. */
+ long tmp;
+
+ pr_debug("single step\n");
+ ret = -EIO;
+ if (!valid_signal(data))
+ break;
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+
+ tmp = get_reg(child, PT_SYSCFG) | (TRACE_BITS);
+ put_reg(child, PT_SYSCFG, tmp);
+
+ child->exit_code = data;
+ /* give it a chance to run. */
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+ case PTRACE_DETACH:
+ { /* detach a process that was attached. */
+ ret = ptrace_detach(child, data);
+ break;
+ }
+
+ case PTRACE_GETREGS:
+ {
+
+ /* Get all gp regs from the child. */
+ ret = ptrace_getregs(child, (void __user *)data);
+ break;
+ }
+
+ case PTRACE_SETREGS:
+ {
+ printk(KERN_NOTICE
+ "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n");
+ /* Set all gp regs in the child. */
+ ret = 0;
+ break;
+ }
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ break;
+ }
+
+ return ret;
+}
+
+asmlinkage void 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. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/setup.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/delay.h>
+#include <linux/console.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+
+#include <linux/ext2_fs.h>
+#include <linux/cramfs_fs.h>
+#include <linux/romfs_fs.h>
+
+#include <asm/cacheflush.h>
+#include <asm/blackfin.h>
+#include <asm/cplbinit.h>
+
+unsigned long memory_start, memory_end, physical_mem_end;
+unsigned long reserved_mem_dcache_on;
+unsigned long reserved_mem_icache_on;
+EXPORT_SYMBOL(memory_start);
+EXPORT_SYMBOL(memory_end);
+EXPORT_SYMBOL(physical_mem_end);
+EXPORT_SYMBOL(_ramend);
+
+#ifdef CONFIG_MTD_UCLINUX
+unsigned long memory_mtd_end, memory_mtd_start, mtd_size;
+unsigned long _ebss;
+EXPORT_SYMBOL(memory_mtd_end);
+EXPORT_SYMBOL(memory_mtd_start);
+EXPORT_SYMBOL(mtd_size);
+#endif
+
+char command_line[COMMAND_LINE_SIZE];
+
+#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
+static void generate_cpl_tables(void);
+#endif
+
+void __init bf53x_cache_init(void)
+{
+#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
+ generate_cpl_tables();
+#endif
+
+#ifdef CONFIG_BLKFIN_CACHE
+ bfin_icache_init();
+ printk(KERN_INFO "Instruction Cache Enabled\n");
+#endif
+
+#ifdef CONFIG_BLKFIN_DCACHE
+ bfin_dcache_init();
+ printk(KERN_INFO "Data Cache Enabled"
+# if defined CONFIG_BLKFIN_WB
+ " (write-back)"
+# elif defined CONFIG_BLKFIN_WT
+ " (write-through)"
+# endif
+ "\n");
+#endif
+}
+
+void bf53x_relocate_l1_mem(void)
+{
+ unsigned long l1_code_length;
+ unsigned long l1_data_a_length;
+ unsigned long l1_data_b_length;
+
+ l1_code_length = _etext_l1 - _stext_l1;
+ if (l1_code_length > L1_CODE_LENGTH)
+ l1_code_length = L1_CODE_LENGTH;
+ /* cannot complain as printk is not available as yet.
+ * But we can continue booting and complain later!
+ */
+
+ /* Copy _stext_l1 to _etext_l1 to L1 instruction SRAM */
+ dma_memcpy(_stext_l1, _l1_lma_start, l1_code_length);
+
+ l1_data_a_length = _ebss_l1 - _sdata_l1;
+ if (l1_data_a_length > L1_DATA_A_LENGTH)
+ l1_data_a_length = L1_DATA_A_LENGTH;
+
+ /* Copy _sdata_l1 to _ebss_l1 to L1 data bank A SRAM */
+ dma_memcpy(_sdata_l1, _l1_lma_start + l1_code_length, l1_data_a_length);
+
+ l1_data_b_length = _ebss_b_l1 - _sdata_b_l1;
+ if (l1_data_b_length > L1_DATA_B_LENGTH)
+ l1_data_b_length = L1_DATA_B_LENGTH;
+
+ /* Copy _sdata_b_l1 to _ebss_b_l1 to L1 data bank B SRAM */
+ dma_memcpy(_sdata_b_l1, _l1_lma_start + l1_code_length +
+ l1_data_a_length, l1_data_b_length);
+
+}
+
+/*
+ * Initial parsing of the command line. Currently, we support:
+ * - Controlling the linux memory size: mem=xxx[KMG]
+ * - Controlling the physical memory size: max_mem=xxx[KMG][$][#]
+ * $ -> reserved memory is dcacheable
+ * # -> reserved memory is icacheable
+ */
+static __init void parse_cmdline_early(char *cmdline_p)
+{
+ char c = ' ', *to = cmdline_p;
+ unsigned int memsize;
+ for (;;) {
+ if (c == ' ') {
+
+ if (!memcmp(to, "mem=", 4)) {
+ to += 4;
+ memsize = memparse(to, &to);
+ if (memsize)
+ _ramend = memsize;
+
+ } else if (!memcmp(to, "max_mem=", 8)) {
+ to += 8;
+ memsize = memparse(to, &to);
+ if (memsize) {
+ physical_mem_end = memsize;
+ if (*to != ' ') {
+ if (*to == '$'
+ || *(to + 1) == '$')
+ reserved_mem_dcache_on =
+ 1;
+ if (*to == '#'
+ || *(to + 1) == '#')
+ reserved_mem_icache_on =
+ 1;
+ }
+ }
+ }
+
+ }
+ c = *(to++);
+ if (!c)
+ break;
+ }
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+ int bootmap_size;
+ unsigned long l1_length, sclk, cclk;
+#ifdef CONFIG_MTD_UCLINUX
+ unsigned long mtd_phys = 0;
+#endif
+
+ cclk = get_cclk();
+ sclk = get_sclk();
+
+#if !defined(CONFIG_BFIN_KERNEL_CLOCK) && defined(ANOMALY_05000273)
+ if (cclk == sclk)
+ panic("ANOMALY 05000273, SCLK can not be same as CCLK");
+#endif
+
+#if defined(ANOMALY_05000266)
+ bfin_read_IMDMA_D0_IRQ_STATUS();
+ bfin_read_IMDMA_D1_IRQ_STATUS();
+#endif
+
+#ifdef DEBUG_SERIAL_EARLY_INIT
+ bfin_console_init(); /* early console registration */
+ /* this give a chance to get printk() working before crash. */
+#endif
+
+#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
+ /* we need to initialize the Flashrom device here since we might
+ * do things with flash early on in the boot
+ */
+ flash_probe();
+#endif
+
+#if defined(CONFIG_CMDLINE_BOOL)
+ memset(command_line, 0, sizeof(command_line));
+ strncpy(&command_line[0], CONFIG_CMDLINE, sizeof(command_line));
+ command_line[sizeof(command_line) - 1] = 0;
+#endif
+
+ /* Keep a copy of command line */
+ *cmdline_p = &command_line[0];
+ memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+ boot_command_line[COMMAND_LINE_SIZE - 1] = 0;
+
+ /* setup memory defaults from the user config */
+ physical_mem_end = 0;
+ _ramend = CONFIG_MEM_SIZE * 1024 * 1024;
+
+ parse_cmdline_early(&command_line[0]);
+
+ if (physical_mem_end == 0)
+ physical_mem_end = _ramend;
+
+ /* by now the stack is part of the init task */
+ memory_end = _ramend - DMA_UNCACHED_REGION;
+
+ _ramstart = (unsigned long)__bss_stop;
+ memory_start = PAGE_ALIGN(_ramstart);
+
+#if defined(CONFIG_MTD_UCLINUX)
+ /* generic memory mapped MTD driver */
+ memory_mtd_end = memory_end;
+
+ mtd_phys = _ramstart;
+ mtd_size = PAGE_ALIGN(*((unsigned long *)(mtd_phys + 8)));
+
+# if defined(CONFIG_EXT2_FS) || defined(CONFIG_EXT3_FS)
+ if (*((unsigned short *)(mtd_phys + 0x438)) == EXT2_SUPER_MAGIC)
+ mtd_size =
+ PAGE_ALIGN(*((unsigned long *)(mtd_phys + 0x404)) << 10);
+# endif
+
+# if defined(CONFIG_CRAMFS)
+ if (*((unsigned long *)(mtd_phys)) == CRAMFS_MAGIC)
+ mtd_size = PAGE_ALIGN(*((unsigned long *)(mtd_phys + 0x4)));
+# endif
+
+# if defined(CONFIG_ROMFS_FS)
+ if (((unsigned long *)mtd_phys)[0] == ROMSB_WORD0
+ && ((unsigned long *)mtd_phys)[1] == ROMSB_WORD1)
+ mtd_size =
+ PAGE_ALIGN(be32_to_cpu(((unsigned long *)mtd_phys)[2]));
+# if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
+ /* Due to a Hardware Anomaly we need to limit the size of usable
+ * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
+ * 05000263 - Hardware loop corrupted when taking an ICPLB exception
+ */
+# if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
+ if (memory_end >= 56 * 1024 * 1024)
+ memory_end = 56 * 1024 * 1024;
+# else
+ if (memory_end >= 60 * 1024 * 1024)
+ memory_end = 60 * 1024 * 1024;
+# endif /* CONFIG_DEBUG_HUNT_FOR_ZERO */
+# endif /* ANOMALY_05000263 */
+# endif /* CONFIG_ROMFS_FS */
+
+ memory_end -= mtd_size;
+
+ if (mtd_size == 0) {
+ console_init();
+ panic("Don't boot kernel without rootfs attached.\n");
+ }
+
+ /* Relocate MTD image to the top of memory after the uncached memory area */
+ dma_memcpy((char *)memory_end, __bss_stop, mtd_size);
+
+ memory_mtd_start = memory_end;
+ _ebss = memory_mtd_start; /* define _ebss for compatible */
+#endif /* CONFIG_MTD_UCLINUX */
+
+#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
+ /* Due to a Hardware Anomaly we need to limit the size of usable
+ * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
+ * 05000263 - Hardware loop corrupted when taking an ICPLB exception
+ */
+#if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
+ if (memory_end >= 56 * 1024 * 1024)
+ memory_end = 56 * 1024 * 1024;
+#else
+ if (memory_end >= 60 * 1024 * 1024)
+ memory_end = 60 * 1024 * 1024;
+#endif /* CONFIG_DEBUG_HUNT_FOR_ZERO */
+ printk(KERN_NOTICE "Warning: limiting memory to %liMB due to hardware anomaly 05000263\n", memory_end >> 20);
+#endif /* ANOMALY_05000263 */
+
+#if !defined(CONFIG_MTD_UCLINUX)
+ memory_end -= SIZE_4K; /*In case there is no valid CPLB behind memory_end make sure we don't get to close*/
+#endif
+ init_mm.start_code = (unsigned long)_stext;
+ init_mm.end_code = (unsigned long)_etext;
+ init_mm.end_data = (unsigned long)_edata;
+ init_mm.brk = (unsigned long)0;
+
+ init_leds();
+
+ printk(KERN_INFO "Blackfin support (C) 2004-2007 Analog Devices, Inc.\n");
+ printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid());
+ if (bfin_revid() != bfin_compiled_revid())
+ printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n",
+ bfin_compiled_revid(), bfin_revid());
+ if (bfin_revid() < SUPPORTED_REVID)
+ printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n",
+ CPU, bfin_revid());
+ printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n");
+
+ printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu Mhz System Clock\n",
+ cclk / 1000000, sclk / 1000000);
+
+#if defined(ANOMALY_05000273)
+ if ((cclk >> 1) <= sclk)
+ printk("\n\n\nANOMALY_05000273: CCLK must be >= 2*SCLK !!!\n\n\n");
+#endif
+
+ printk(KERN_INFO "Board Memory: %ldMB\n", physical_mem_end >> 20);
+ printk(KERN_INFO "Kernel Managed Memory: %ldMB\n", _ramend >> 20);
+
+ printk(KERN_INFO "Memory map:\n"
+ KERN_INFO " text = 0x%p-0x%p\n"
+ KERN_INFO " init = 0x%p-0x%p\n"
+ KERN_INFO " data = 0x%p-0x%p\n"
+ KERN_INFO " stack = 0x%p-0x%p\n"
+ KERN_INFO " bss = 0x%p-0x%p\n"
+ KERN_INFO " available = 0x%p-0x%p\n"
+#ifdef CONFIG_MTD_UCLINUX
+ KERN_INFO " rootfs = 0x%p-0x%p\n"
+#endif
+#if DMA_UNCACHED_REGION > 0
+ KERN_INFO " DMA Zone = 0x%p-0x%p\n"
+#endif
+ , _stext, _etext,
+ __init_begin, __init_end,
+ _sdata, _edata,
+ (void*)&init_thread_union, (void*)((int)(&init_thread_union) + 0x2000),
+ __bss_start, __bss_stop,
+ (void*)_ramstart, (void*)memory_end
+#ifdef CONFIG_MTD_UCLINUX
+ , (void*)memory_mtd_start, (void*)(memory_mtd_start + mtd_size)
+#endif
+#if DMA_UNCACHED_REGION > 0
+ , (void*)(_ramend - DMA_UNCACHED_REGION), (void*)(_ramend)
+#endif
+ );
+
+ /*
+ * give all the memory to the bootmap allocator, tell it to put the
+ * boot mem_map at the start of memory
+ */
+ bootmap_size = init_bootmem_node(NODE_DATA(0), memory_start >> PAGE_SHIFT, /* map goes here */
+ PAGE_OFFSET >> PAGE_SHIFT,
+ memory_end >> PAGE_SHIFT);
+ /*
+ * free the usable memory, we have to make sure we do not free
+ * the bootmem bitmap so we then reserve it after freeing it :-)
+ */
+ free_bootmem(memory_start, memory_end - memory_start);
+
+ reserve_bootmem(memory_start, bootmap_size);
+ /*
+ * get kmalloc into gear
+ */
+ paging_init();
+
+ /* check the size of the l1 area */
+ l1_length = _etext_l1 - _stext_l1;
+ if (l1_length > L1_CODE_LENGTH)
+ panic("L1 memory overflow\n");
+
+ l1_length = _ebss_l1 - _sdata_l1;
+ if (l1_length > L1_DATA_A_LENGTH)
+ panic("L1 memory overflow\n");
+
+ bf53x_cache_init();
+
+#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)
+# if defined(CONFIG_BFIN_SHARED_FLASH_ENET) && defined(CONFIG_BFIN533_STAMP)
+ /* setup BF533_STAMP CPLD to route AMS3 to Ethernet MAC */
+ bfin_write_FIO_DIR(bfin_read_FIO_DIR() | (1 << CONFIG_ENET_FLASH_PIN));
+ bfin_write_FIO_FLAG_S(1 << CONFIG_ENET_FLASH_PIN);
+ SSYNC();
+# endif
+# if defined (CONFIG_BFIN561_EZKIT)
+ bfin_write_FIO0_DIR(bfin_read_FIO0_DIR() | (1 << 12));
+ SSYNC();
+# endif /* defined (CONFIG_BFIN561_EZKIT) */
+#endif
+
+ printk(KERN_INFO "Hardware Trace Enabled\n");
+ bfin_write_TBUFCTL(0x03);
+}
+
+#if defined(CONFIG_BF561)
+static struct cpu cpu[2];
+#else
+static struct cpu cpu[1];
+#endif
+static int __init topology_init(void)
+{
+#if defined (CONFIG_BF561)
+ register_cpu(&cpu[0], 0);
+ register_cpu(&cpu[1], 1);
+ return 0;
+#else
+ return register_cpu(cpu, 0);
+#endif
+}
+
+subsys_initcall(topology_init);
+
+#if defined(CONFIG_BLKFIN_DCACHE) || defined(CONFIG_BLKFIN_CACHE)
+u16 lock_kernel_check(u32 start, u32 end)
+{
+ if ((start <= (u32) _stext && end >= (u32) _end)
+ || (start >= (u32) _stext && end <= (u32) _end))
+ return IN_KERNEL;
+ return 0;
+}
+
+static unsigned short __init
+fill_cplbtab(struct cplb_tab *table,
+ unsigned long start, unsigned long end,
+ unsigned long block_size, unsigned long cplb_data)
+{
+ int i;
+
+ switch (block_size) {
+ case SIZE_4M:
+ i = 3;
+ break;
+ case SIZE_1M:
+ i = 2;
+ break;
+ case SIZE_4K:
+ i = 1;
+ break;
+ case SIZE_1K:
+ default:
+ i = 0;
+ break;
+ }
+
+ cplb_data = (cplb_data & ~(3 << 16)) | (i << 16);
+
+ while ((start < end) && (table->pos < table->size)) {
+
+ table->tab[table->pos++] = start;
+
+ if (lock_kernel_check(start, start + block_size) == IN_KERNEL)
+ table->tab[table->pos++] =
+ cplb_data | CPLB_LOCK | CPLB_DIRTY;
+ else
+ table->tab[table->pos++] = cplb_data;
+
+ start += block_size;
+ }
+ return 0;
+}
+
+static unsigned short __init
+close_cplbtab(struct cplb_tab *table)
+{
+
+ while (table->pos < table->size) {
+
+ table->tab[table->pos++] = 0;
+ table->tab[table->pos++] = 0; /* !CPLB_VALID */
+ }
+ return 0;
+}
+
+static void __init generate_cpl_tables(void)
+{
+
+ u16 i, j, process;
+ u32 a_start, a_end, as, ae, as_1m;
+
+ struct cplb_tab *t_i = NULL;
+ struct cplb_tab *t_d = NULL;
+ struct s_cplb cplb;
+
+ cplb.init_i.size = MAX_CPLBS;
+ cplb.init_d.size = MAX_CPLBS;
+ cplb.switch_i.size = MAX_SWITCH_I_CPLBS;
+ cplb.switch_d.size = MAX_SWITCH_D_CPLBS;
+
+ cplb.init_i.pos = 0;
+ cplb.init_d.pos = 0;
+ cplb.switch_i.pos = 0;
+ cplb.switch_d.pos = 0;
+
+ cplb.init_i.tab = icplb_table;
+ cplb.init_d.tab = dcplb_table;
+ cplb.switch_i.tab = ipdt_table;
+ cplb.switch_d.tab = dpdt_table;
+
+ cplb_data[SDRAM_KERN].end = memory_end;
+
+#ifdef CONFIG_MTD_UCLINUX
+ cplb_data[SDRAM_RAM_MTD].start = memory_mtd_start;
+ cplb_data[SDRAM_RAM_MTD].end = memory_mtd_start + mtd_size;
+ cplb_data[SDRAM_RAM_MTD].valid = mtd_size > 0;
+# if defined(CONFIG_ROMFS_FS)
+ cplb_data[SDRAM_RAM_MTD].attr |= I_CPLB;
+
+ /*
+ * The ROMFS_FS size is often not multiple of 1MB.
+ * This can cause multiple CPLB sets covering the same memory area.
+ * This will then cause multiple CPLB hit exceptions.
+ * Workaround: We ensure a contiguous memory area by extending the kernel
+ * memory section over the mtd section.
+ * For ROMFS_FS memory must be covered with ICPLBs anyways.
+ * So there is no difference between kernel and mtd memory setup.
+ */
+
+ cplb_data[SDRAM_KERN].end = memory_mtd_start + mtd_size;;
+ cplb_data[SDRAM_RAM_MTD].valid = 0;
+
+# endif
+#else
+ cplb_data[SDRAM_RAM_MTD].valid = 0;
+#endif
+
+ cplb_data[SDRAM_DMAZ].start = _ramend - DMA_UNCACHED_REGION;
+ cplb_data[SDRAM_DMAZ].end = _ramend;
+
+ cplb_data[RES_MEM].start = _ramend;
+ cplb_data[RES_MEM].end = physical_mem_end;
+
+ if (reserved_mem_dcache_on)
+ cplb_data[RES_MEM].d_conf = SDRAM_DGENERIC;
+ else
+ cplb_data[RES_MEM].d_conf = SDRAM_DNON_CHBL;
+
+ if (reserved_mem_icache_on)
+ cplb_data[RES_MEM].i_conf = SDRAM_IGENERIC;
+ else
+ cplb_data[RES_MEM].i_conf = SDRAM_INON_CHBL;
+
+ for (i = ZERO_P; i <= L2_MEM; i++) {
+
+ if (cplb_data[i].valid) {
+
+ as_1m = cplb_data[i].start % SIZE_1M;
+
+ /* We need to make sure all sections are properly 1M aligned
+ * However between Kernel Memory and the Kernel mtd section, depending on the
+ * rootfs size, there can be overlapping memory areas.
+ */
+
+ if (as_1m && i!=L1I_MEM && i!=L1D_MEM) {
+#ifdef CONFIG_MTD_UCLINUX
+ if (i == SDRAM_RAM_MTD) {
+ if ((cplb_data[SDRAM_KERN].end + 1) > cplb_data[SDRAM_RAM_MTD].start)
+ cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M)) + SIZE_1M;
+ else
+ cplb_data[SDRAM_RAM_MTD].start = (cplb_data[i].start & (-2*SIZE_1M));
+ } else
+#endif
+ printk(KERN_WARNING "Unaligned Start of %s at 0x%X\n",
+ cplb_data[i].name, cplb_data[i].start);
+ }
+
+ as = cplb_data[i].start % SIZE_4M;
+ ae = cplb_data[i].end % SIZE_4M;
+
+ if (as)
+ a_start = cplb_data[i].start + (SIZE_4M - (as));
+ else
+ a_start = cplb_data[i].start;
+
+ a_end = cplb_data[i].end - ae;
+
+ for (j = INITIAL_T; j <= SWITCH_T; j++) {
+
+ switch (j) {
+ case INITIAL_T:
+ if (cplb_data[i].attr & INITIAL_T) {
+ t_i = &cplb.init_i;
+ t_d = &cplb.init_d;
+ process = 1;
+ } else
+ process = 0;
+ break;
+ case SWITCH_T:
+ if (cplb_data[i].attr & SWITCH_T) {
+ t_i = &cplb.switch_i;
+ t_d = &cplb.switch_d;
+ process = 1;
+ } else
+ process = 0;
+ break;
+ default:
+ process = 0;
+ break;
+ }
+
+ if (process) {
+ if (cplb_data[i].attr & I_CPLB) {
+
+ if (cplb_data[i].psize) {
+ fill_cplbtab(t_i,
+ cplb_data[i].start,
+ cplb_data[i].end,
+ cplb_data[i].psize,
+ cplb_data[i].i_conf);
+ } else {
+ /*icplb_table */
+#if (defined(CONFIG_BLKFIN_CACHE) && defined(ANOMALY_05000263))
+ if (i == SDRAM_KERN) {
+ fill_cplbtab(t_i,
+ cplb_data[i].start,
+ cplb_data[i].end,
+ SIZE_4M,
+ cplb_data[i].i_conf);
+ } else
+#endif
+ {
+ fill_cplbtab(t_i,
+ cplb_data[i].start,
+ a_start,
+ SIZE_1M,
+ cplb_data[i].i_conf);
+ fill_cplbtab(t_i,
+ a_start,
+ a_end,
+ SIZE_4M,
+ cplb_data[i].i_conf);
+ fill_cplbtab(t_i, a_end,
+ cplb_data[i].end,
+ SIZE_1M,
+ cplb_data[i].i_conf);
+ }
+ }
+
+ }
+ if (cplb_data[i].attr & D_CPLB) {
+
+ if (cplb_data[i].psize) {
+ fill_cplbtab(t_d,
+ cplb_data[i].start,
+ cplb_data[i].end,
+ cplb_data[i].psize,
+ cplb_data[i].d_conf);
+ } else {
+/*dcplb_table*/
+ fill_cplbtab(t_d,
+ cplb_data[i].start,
+ a_start, SIZE_1M,
+ cplb_data[i].d_conf);
+ fill_cplbtab(t_d, a_start,
+ a_end, SIZE_4M,
+ cplb_data[i].d_conf);
+ fill_cplbtab(t_d, a_end,
+ cplb_data[i].end,
+ SIZE_1M,
+ cplb_data[i].d_conf);
+
+ }
+
+ }
+ }
+ }
+
+ }
+ }
+
+/* close tables */
+
+ close_cplbtab(&cplb.init_i);
+ close_cplbtab(&cplb.init_d);
+
+ cplb.init_i.tab[cplb.init_i.pos] = -1;
+ cplb.init_d.tab[cplb.init_d.pos] = -1;
+ cplb.switch_i.tab[cplb.switch_i.pos] = -1;
+ cplb.switch_d.tab[cplb.switch_d.pos] = -1;
+
+}
+
+#endif
+
+static inline u_long get_vco(void)
+{
+ u_long msel;
+ u_long vco;
+
+ msel = (bfin_read_PLL_CTL() >> 9) & 0x3F;
+ if (0 == msel)
+ msel = 64;
+
+ vco = CONFIG_CLKIN_HZ;
+ vco >>= (1 & bfin_read_PLL_CTL()); /* DF bit */
+ vco = msel * vco;
+ return vco;
+}
+
+/*Get the Core clock*/
+u_long get_cclk(void)
+{
+ u_long csel, ssel;
+ if (bfin_read_PLL_STAT() & 0x1)
+ return CONFIG_CLKIN_HZ;
+
+ ssel = bfin_read_PLL_DIV();
+ csel = ((ssel >> 4) & 0x03);
+ ssel &= 0xf;
+ if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */
+ return get_vco() / ssel;
+ return get_vco() >> csel;
+}
+
+EXPORT_SYMBOL(get_cclk);
+
+/* Get the System clock */
+u_long get_sclk(void)
+{
+ u_long ssel;
+
+ if (bfin_read_PLL_STAT() & 0x1)
+ return CONFIG_CLKIN_HZ;
+
+ ssel = (bfin_read_PLL_DIV() & 0xf);
+ if (0 == ssel) {
+ printk(KERN_WARNING "Invalid System Clock\n");
+ ssel = 1;
+ }
+
+ return get_vco() / ssel;
+}
+
+EXPORT_SYMBOL(get_sclk);
+
+/*
+ * Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+ char *cpu, *mmu, *fpu, *name;
+ uint32_t revid;
+
+ u_long cclk = 0, sclk = 0;
+ u_int dcache_size = 0, dsup_banks = 0;
+
+ cpu = CPU;
+ mmu = "none";
+ fpu = "none";
+ revid = bfin_revid();
+ name = bfin_board_name;
+
+ cclk = get_cclk();
+ sclk = get_sclk();
+
+ seq_printf(m, "CPU:\t\tADSP-%s Rev. 0.%d\n"
+ "MMU:\t\t%s\n"
+ "FPU:\t\t%s\n"
+ "Core Clock:\t%9lu Hz\n"
+ "System Clock:\t%9lu Hz\n"
+ "BogoMips:\t%lu.%02lu\n"
+ "Calibration:\t%lu loops\n",
+ cpu, revid, mmu, fpu,
+ cclk,
+ sclk,
+ (loops_per_jiffy * HZ) / 500000,
+ ((loops_per_jiffy * HZ) / 5000) % 100,
+ (loops_per_jiffy * HZ));
+ seq_printf(m, "Board Name:\t%s\n", name);
+ seq_printf(m, "Board Memory:\t%ld MB\n", physical_mem_end >> 20);
+ seq_printf(m, "Kernel Memory:\t%ld MB\n", (unsigned long)_ramend >> 20);
+ if (bfin_read_IMEM_CONTROL() & (ENICPLB | IMC))
+ seq_printf(m, "I-CACHE:\tON\n");
+ else
+ seq_printf(m, "I-CACHE:\tOFF\n");
+ if ((bfin_read_DMEM_CONTROL()) & (ENDCPLB | DMC_ENABLE))
+ seq_printf(m, "D-CACHE:\tON"
+#if defined CONFIG_BLKFIN_WB
+ " (write-back)"
+#elif defined CONFIG_BLKFIN_WT
+ " (write-through)"
+#endif
+ "\n");
+ else
+ seq_printf(m, "D-CACHE:\tOFF\n");
+
+
+ switch(bfin_read_DMEM_CONTROL() & (1 << DMC0_P | 1 << DMC1_P)) {
+ case ACACHE_BSRAM:
+ seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tSRAM\n");
+ dcache_size = 16;
+ dsup_banks = 1;
+ break;
+ case ACACHE_BCACHE:
+ seq_printf(m, "DBANK-A:\tCACHE\n" "DBANK-B:\tCACHE\n");
+ dcache_size = 32;
+ dsup_banks = 2;
+ break;
+ case ASRAM_BSRAM:
+ seq_printf(m, "DBANK-A:\tSRAM\n" "DBANK-B:\tSRAM\n");
+ dcache_size = 0;
+ dsup_banks = 0;
+ break;
+ default:
+ break;
+ }
+
+
+ seq_printf(m, "I-CACHE Size:\t%dKB\n", BLKFIN_ICACHESIZE / 1024);
+ seq_printf(m, "D-CACHE Size:\t%dKB\n", dcache_size);
+ seq_printf(m, "I-CACHE Setup:\t%d Sub-banks/%d Ways, %d Lines/Way\n",
+ BLKFIN_ISUBBANKS, BLKFIN_IWAYS, BLKFIN_ILINES);
+ seq_printf(m,
+ "D-CACHE Setup:\t%d Super-banks/%d Sub-banks/%d Ways, %d Lines/Way\n",
+ dsup_banks, BLKFIN_DSUBBANKS, BLKFIN_DWAYS,
+ BLKFIN_DLINES);
+#ifdef CONFIG_BLKFIN_CACHE_LOCK
+ switch (read_iloc()) {
+ case WAY0_L:
+ seq_printf(m, "Way0 Locked-Down\n");
+ break;
+ case WAY1_L:
+ seq_printf(m, "Way1 Locked-Down\n");
+ break;
+ case WAY01_L:
+ seq_printf(m, "Way0,Way1 Locked-Down\n");
+ break;
+ case WAY2_L:
+ seq_printf(m, "Way2 Locked-Down\n");
+ break;
+ case WAY02_L:
+ seq_printf(m, "Way0,Way2 Locked-Down\n");
+ break;
+ case WAY12_L:
+ seq_printf(m, "Way1,Way2 Locked-Down\n");
+ break;
+ case WAY012_L:
+ seq_printf(m, "Way0,Way1 & Way2 Locked-Down\n");
+ break;
+ case WAY3_L:
+ seq_printf(m, "Way3 Locked-Down\n");
+ break;
+ case WAY03_L:
+ seq_printf(m, "Way0,Way3 Locked-Down\n");
+ break;
+ case WAY13_L:
+ seq_printf(m, "Way1,Way3 Locked-Down\n");
+ break;
+ case WAY013_L:
+ seq_printf(m, "Way 0,Way1,Way3 Locked-Down\n");
+ break;
+ case WAY32_L:
+ seq_printf(m, "Way3,Way2 Locked-Down\n");
+ break;
+ case WAY320_L:
+ seq_printf(m, "Way3,Way2,Way0 Locked-Down\n");
+ break;
+ case WAY321_L:
+ seq_printf(m, "Way3,Way2,Way1 Locked-Down\n");
+ break;
+ case WAYALL_L:
+ seq_printf(m, "All Ways are locked\n");
+ break;
+ default:
+ seq_printf(m, "No Ways are locked\n");
+ }
+#endif
+ return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+ return *pos < NR_CPUS ? ((void *)0x12345678) : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ ++*pos;
+ return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op = {
+ .start = c_start,
+ .next = c_next,
+ .stop = c_stop,
+ .show = show_cpuinfo,
+};
+
+void cmdline_init(unsigned long r0)
+{
+ if (r0)
+ strncpy(command_line, (char *)r0, COMMAND_LINE_SIZE);
+}
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/signal.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description:
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/ptrace.h>
+#include <linux/tty.h>
+#include <linux/personality.h>
+#include <linux/binfmts.h>
+#include <linux/freezer.h>
+
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+struct fdpic_func_descriptor {
+ unsigned long text;
+ unsigned long GOT;
+};
+
+struct rt_sigframe {
+ int sig;
+ struct siginfo *pinfo;
+ void *puc;
+ char retcode[8];
+ struct siginfo info;
+ struct ucontext uc;
+};
+
+asmlinkage int sys_sigaltstack(const stack_t * uss, stack_t * uoss)
+{
+ return do_sigaltstack(uss, uoss, rdusp());
+}
+
+static inline int
+rt_restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *pr0)
+{
+ unsigned long usp = 0;
+ int err = 0;
+
+#define RESTORE(x) err |= __get_user(regs->x, &sc->sc_##x)
+
+ /* restore passed registers */
+ RESTORE(r0); RESTORE(r1); RESTORE(r2); RESTORE(r3);
+ RESTORE(r4); RESTORE(r5); RESTORE(r6); RESTORE(r7);
+ RESTORE(p0); RESTORE(p1); RESTORE(p2); RESTORE(p3);
+ RESTORE(p4); RESTORE(p5);
+ err |= __get_user(usp, &sc->sc_usp);
+ wrusp(usp);
+ RESTORE(a0w); RESTORE(a1w);
+ RESTORE(a0x); RESTORE(a1x);
+ RESTORE(astat);
+ RESTORE(rets);
+ RESTORE(pc);
+ RESTORE(retx);
+ RESTORE(fp);
+ RESTORE(i0); RESTORE(i1); RESTORE(i2); RESTORE(i3);
+ RESTORE(m0); RESTORE(m1); RESTORE(m2); RESTORE(m3);
+ RESTORE(l0); RESTORE(l1); RESTORE(l2); RESTORE(l3);
+ RESTORE(b0); RESTORE(b1); RESTORE(b2); RESTORE(b3);
+ RESTORE(lc0); RESTORE(lc1);
+ RESTORE(lt0); RESTORE(lt1);
+ RESTORE(lb0); RESTORE(lb1);
+ RESTORE(seqstat);
+
+ regs->orig_p0 = -1; /* disable syscall checks */
+
+ *pr0 = regs->r0;
+ return err;
+}
+
+asmlinkage int do_rt_sigreturn(unsigned long __unused)
+{
+ struct pt_regs *regs = (struct pt_regs *)__unused;
+ unsigned long usp = rdusp();
+ struct rt_sigframe *frame = (struct rt_sigframe *)(usp);
+ sigset_t set;
+ int r0;
+
+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+ goto badframe;
+
+ if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->usp) == -EFAULT)
+ goto badframe;
+
+ return r0;
+
+ badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs)
+{
+ int err = 0;
+
+#define SETUP(x) err |= __put_user(regs->x, &sc->sc_##x)
+
+ SETUP(r0); SETUP(r1); SETUP(r2); SETUP(r3);
+ SETUP(r4); SETUP(r5); SETUP(r6); SETUP(r7);
+ SETUP(p0); SETUP(p1); SETUP(p2); SETUP(p3);
+ SETUP(p4); SETUP(p5);
+ err |= __put_user(rdusp(), &sc->sc_usp);
+ SETUP(a0w); SETUP(a1w);
+ SETUP(a0x); SETUP(a1x);
+ SETUP(astat);
+ SETUP(rets);
+ SETUP(pc);
+ SETUP(retx);
+ SETUP(fp);
+ SETUP(i0); SETUP(i1); SETUP(i2); SETUP(i3);
+ SETUP(m0); SETUP(m1); SETUP(m2); SETUP(m3);
+ SETUP(l0); SETUP(l1); SETUP(l2); SETUP(l3);
+ SETUP(b0); SETUP(b1); SETUP(b2); SETUP(b3);
+ SETUP(lc0); SETUP(lc1);
+ SETUP(lt0); SETUP(lt1);
+ SETUP(lb0); SETUP(lb1);
+ SETUP(seqstat);
+
+ return err;
+}
+
+static inline void push_cache(unsigned long vaddr, unsigned int len)
+{
+ flush_icache_range(vaddr, vaddr + len);
+}
+
+static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+ size_t frame_size)
+{
+ unsigned long usp;
+
+ /* Default to using normal stack. */
+ usp = rdusp();
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ if (!on_sig_stack(usp))
+ usp = current->sas_ss_sp + current->sas_ss_size;
+ }
+ return (void *)((usp - frame_size) & -8UL);
+}
+
+static int
+setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
+ sigset_t * set, struct pt_regs *regs)
+{
+ struct rt_sigframe *frame;
+ int err = 0;
+
+ frame = get_sigframe(ka, regs, sizeof(*frame));
+
+ err |= __put_user((current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->
+ signal_invmap[sig] : sig), &frame->sig);
+
+ err |= __put_user(&frame->info, &frame->pinfo);
+ err |= __put_user(&frame->uc, &frame->puc);
+ err |= copy_siginfo_to_user(&frame->info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |=
+ __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(rdusp()), &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs);
+ err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ /* Set up to return from userspace. */
+ err |= __put_user(0x28, &(frame->retcode[0]));
+ err |= __put_user(0xe1, &(frame->retcode[1]));
+ err |= __put_user(0xad, &(frame->retcode[2]));
+ err |= __put_user(0x00, &(frame->retcode[3]));
+ err |= __put_user(0xa0, &(frame->retcode[4]));
+ err |= __put_user(0x00, &(frame->retcode[5]));
+
+ if (err)
+ goto give_sigsegv;
+
+ push_cache((unsigned long)&frame->retcode, sizeof(frame->retcode));
+
+ /* Set up registers for signal handler */
+ wrusp((unsigned long)frame);
+ if (get_personality & FDPIC_FUNCPTRS) {
+ struct fdpic_func_descriptor __user *funcptr =
+ (struct fdpic_func_descriptor *) ka->sa.sa_handler;
+ __get_user(regs->pc, &funcptr->text);
+ __get_user(regs->p3, &funcptr->GOT);
+ } else
+ regs->pc = (unsigned long)ka->sa.sa_handler;
+ regs->rets = (unsigned long)(frame->retcode);
+
+ regs->r0 = frame->sig;
+ regs->r1 = (unsigned long)(&frame->info);
+ regs->r2 = (unsigned long)(&frame->uc);
+
+ return 0;
+
+ give_sigsegv:
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+ return -EFAULT;
+}
+
+static inline void
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
+{
+ switch (regs->r0) {
+ case -ERESTARTNOHAND:
+ if (!has_handler)
+ goto do_restart;
+ regs->r0 = -EINTR;
+ break;
+
+ case -ERESTARTSYS:
+ if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
+ regs->r0 = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+ do_restart:
+ regs->p0 = regs->orig_p0;
+ regs->r0 = regs->orig_r0;
+ regs->pc -= 2;
+ break;
+ }
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static int
+handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
+ sigset_t *oldset, struct pt_regs *regs)
+{
+ int ret;
+
+ /* are we from a system call? to see pt_regs->orig_p0 */
+ if (regs->orig_p0 >= 0)
+ /* If so, check system call restarting.. */
+ handle_restart(regs, ka, 1);
+
+ /* set up the stack frame */
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
+
+ if (ret == 0) {
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked, ¤t->blocked,
+ &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(¤t->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+ }
+ return ret;
+}
+
+/*
+ * 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.
+ *
+ * Note that we go through the signals twice: once to check the signals
+ * that the kernel can handle, and then we build all the user-level signal
+ * handling stack-frames in one go after that.
+ */
+asmlinkage void do_signal(struct pt_regs *regs)
+{
+ siginfo_t info;
+ int signr;
+ struct k_sigaction ka;
+ sigset_t *oldset;
+
+ current->thread.esp0 = (unsigned long)regs;
+
+ if (try_to_freeze())
+ goto no_signal;
+
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = ¤t->saved_sigmask;
+ else
+ oldset = ¤t->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ if (signr > 0) {
+ /* Whee! Actually deliver the signal. */
+ if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
+ /* a signal was successfully delivered; the saved
+ * sigmask will have been stored in the signal frame,
+ * and will be restored by sigreturn, so we can simply
+ * clear the TIF_RESTORE_SIGMASK flag */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }
+
+ return;
+ }
+
+no_signal:
+ /* Did we come from a system call? */
+ if (regs->orig_p0 >= 0)
+ /* Restart the system call - no handlers present */
+ handle_restart(regs, NULL, 0);
+
+ /* if there's no signal to deliver, we just put the saved sigmask
+ * back */
+ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+ clear_thread_flag(TIF_RESTORE_SIGMASK);
+ sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
+ }
+}
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/sys_bfin.c
+ * Based on:
+ * Author:
+ *
+ * Created:
+ * Description: This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/bfin
+ * platform.
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+
+#include <asm/cacheflush.h>
+#include <asm/uaccess.h>
+#include <asm/ipc.h>
+#include <asm/dma.h>
+#include <asm/unistd.h>
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix traditionally does this, though.
+ */
+asmlinkage int sys_pipe(unsigned long *fildes)
+{
+ int fd[2];
+ int error;
+
+ error = do_pipe(fd);
+ if (!error) {
+ if (copy_to_user(fildes, fd, 2 * sizeof(int)))
+ error = -EFAULT;
+ }
+ return error;
+}
+
+/* common code for old and new mmaps */
+static inline long
+do_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ int error = -EBADF;
+ struct file *file = NULL;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+
+ down_write(¤t->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(¤t->mm->mmap_sem);
+
+ if (file)
+ fput(file);
+ out:
+ return error;
+}
+
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+asmlinkage int sys_getpagesize(void)
+{
+ return PAGE_SIZE;
+}
+
+asmlinkage void *sys_sram_alloc(size_t size, unsigned long flags)
+{
+ return sram_alloc_with_lsl(size, flags);
+}
+
+asmlinkage int sys_sram_free(const void *addr)
+{
+ return sram_free_with_lsl(addr);
+}
+
+asmlinkage void *sys_dma_memcpy(void *dest, const void *src, size_t len)
+{
+ return safe_dma_memcpy(dest, src, len);
+}
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/time.c
+ * Based on: none - original work
+ * Author:
+ *
+ * Created:
+ * Description: This file contains the bfin-specific time handling details.
+ * Most of the stuff is located in the machine specific files.
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <linux/module.h>
+#include <linux/profile.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/irq.h>
+
+#include <asm/blackfin.h>
+
+/* This is an NTP setting */
+#define TICK_SIZE (tick_nsec / 1000)
+
+static void time_sched_init(irqreturn_t(*timer_routine)
+ (int, void *));
+static unsigned long gettimeoffset(void);
+static inline void do_leds(void);
+
+#if (defined(CONFIG_BFIN_ALIVE_LED) || defined(CONFIG_BFIN_IDLE_LED))
+void __init init_leds(void)
+{
+ unsigned int tmp = 0;
+
+#if defined(CONFIG_BFIN_ALIVE_LED)
+ /* config pins as output. */
+ tmp = bfin_read_CONFIG_BFIN_ALIVE_LED_DPORT();
+ SSYNC();
+ bfin_write_CONFIG_BFIN_ALIVE_LED_DPORT(tmp | CONFIG_BFIN_ALIVE_LED_PIN);
+ SSYNC();
+
+ /* First set led be off */
+ tmp = bfin_read_CONFIG_BFIN_ALIVE_LED_PORT();
+ SSYNC();
+ bfin_write_CONFIG_BFIN_ALIVE_LED_PORT(tmp | CONFIG_BFIN_ALIVE_LED_PIN); /* light off */
+ SSYNC();
+#endif
+
+#if defined(CONFIG_BFIN_IDLE_LED)
+ /* config pins as output. */
+ tmp = bfin_read_CONFIG_BFIN_IDLE_LED_DPORT();
+ SSYNC();
+ bfin_write_CONFIG_BFIN_IDLE_LED_DPORT(tmp | CONFIG_BFIN_IDLE_LED_PIN);
+ SSYNC();
+
+ /* First set led be off */
+ tmp = bfin_read_CONFIG_BFIN_IDLE_LED_PORT();
+ SSYNC();
+ bfin_write_CONFIG_BFIN_IDLE_LED_PORT(tmp | CONFIG_BFIN_IDLE_LED_PIN); /* light off */
+ SSYNC();
+#endif
+}
+#else
+void __init init_leds(void)
+{
+}
+#endif
+
+#if defined(CONFIG_BFIN_ALIVE_LED)
+static inline void do_leds(void)
+{
+ static unsigned int count = 50;
+ static int flag = 0;
+ unsigned short tmp = 0;
+
+ if (--count == 0) {
+ count = 50;
+ flag = ~flag;
+ }
+ tmp = bfin_read_CONFIG_BFIN_ALIVE_LED_PORT();
+ SSYNC();
+
+ if (flag)
+ tmp &= ~CONFIG_BFIN_ALIVE_LED_PIN; /* light on */
+ else
+ tmp |= CONFIG_BFIN_ALIVE_LED_PIN; /* light off */
+
+ bfin_write_CONFIG_BFIN_ALIVE_LED_PORT(tmp);
+ SSYNC();
+
+}
+#else
+static inline void do_leds(void)
+{
+}
+#endif
+
+static struct irqaction bfin_timer_irq = {
+ .name = "BFIN Timer Tick",
+ .flags = IRQF_DISABLED
+};
+
+/*
+ * The way that the Blackfin core timer works is:
+ * - CCLK is divided by a programmable 8-bit pre-scaler (TSCALE)
+ * - Every time TSCALE ticks, a 32bit is counted down (TCOUNT)
+ *
+ * If you take the fastest clock (1ns, or 1GHz to make the math work easier)
+ * 10ms is 10,000,000 clock ticks, which fits easy into a 32-bit counter
+ * (32 bit counter is 4,294,967,296ns or 4.2 seconds) so, we don't need
+ * to use TSCALE, and program it to zero (which is pass CCLK through).
+ * If you feel like using it, try to keep HZ * TIMESCALE to some
+ * value that divides easy (like power of 2).
+ */
+
+#define TIME_SCALE 1
+
+static void
+time_sched_init(irqreturn_t(*timer_routine) (int, void *))
+{
+ u32 tcount;
+
+ /* power up the timer, but don't enable it just yet */
+ bfin_write_TCNTL(1);
+ CSYNC();
+
+ /*
+ * the TSCALE prescaler counter.
+ */
+ bfin_write_TSCALE((TIME_SCALE - 1));
+
+ tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
+ bfin_write_TPERIOD(tcount);
+ bfin_write_TCOUNT(tcount);
+
+ /* now enable the timer */
+ CSYNC();
+
+ bfin_write_TCNTL(7);
+
+ bfin_timer_irq.handler = (irq_handler_t)timer_routine;
+ /* call setup_irq instead of request_irq because request_irq calls
+ * kmalloc which has not been initialized yet
+ */
+ setup_irq(IRQ_CORETMR, &bfin_timer_irq);
+}
+
+/*
+ * Should return useconds since last timer tick
+ */
+static unsigned long gettimeoffset(void)
+{
+ unsigned long offset;
+ unsigned long clocks_per_jiffy;
+
+ clocks_per_jiffy = bfin_read_TPERIOD();
+ offset =
+ (clocks_per_jiffy -
+ bfin_read_TCOUNT()) / (((clocks_per_jiffy + 1) * HZ) /
+ USEC_PER_SEC);
+
+ /* Check if we just wrapped the counters and maybe missed a tick */
+ if ((bfin_read_ILAT() & (1 << IRQ_CORETMR))
+ && (offset < (100000 / HZ / 2)))
+ offset += (USEC_PER_SEC / HZ);
+
+ return offset;
+}
+
+static inline int set_rtc_mmss(unsigned long nowtime)
+{
+ return 0;
+}
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+#ifdef CONFIG_CORE_TIMER_IRQ_L1
+irqreturn_t timer_interrupt(int irq, void *dummy)__attribute__((l1_text));
+#endif
+
+irqreturn_t timer_interrupt(int irq, void *dummy)
+{
+ /* last time the cmos clock got updated */
+ static long last_rtc_update = 0;
+
+ write_seqlock(&xtime_lock);
+
+ do_timer(1);
+ do_leds();
+
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(get_irq_regs()));
+#endif
+ profile_tick(CPU_PROFILING);
+
+ /*
+ * If we have an externally synchronized Linux clock, then update
+ * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+ * called as close as possible to 500 ms before the new second starts.
+ */
+
+ if (ntp_synced() &&
+ xtime.tv_sec > last_rtc_update + 660 &&
+ (xtime.tv_nsec / NSEC_PER_USEC) >=
+ 500000 - ((unsigned)TICK_SIZE) / 2
+ && (xtime.tv_nsec / NSEC_PER_USEC) <=
+ 500000 + ((unsigned)TICK_SIZE) / 2) {
+ if (set_rtc_mmss(xtime.tv_sec) == 0)
+ last_rtc_update = xtime.tv_sec;
+ else
+ /* Do it again in 60s. */
+ last_rtc_update = xtime.tv_sec - 600;
+ }
+ write_sequnlock(&xtime_lock);
+ return IRQ_HANDLED;
+}
+
+void __init time_init(void)
+{
+ time_t secs_since_1970 = (365 * 37 + 9) * 24 * 60 * 60; /* 1 Jan 2007 */
+
+#ifdef CONFIG_RTC_DRV_BFIN
+ /* [#2663] hack to filter junk RTC values that would cause
+ * userspace to have to deal with time values greater than
+ * 2^31 seconds (which uClibc cannot cope with yet)
+ */
+ if ((bfin_read_RTC_STAT() & 0xC0000000) == 0xC0000000) {
+ printk(KERN_NOTICE "bfin-rtc: invalid date; resetting\n");
+ bfin_write_RTC_STAT(0);
+ }
+#endif
+
+ /* Initialize xtime. From now on, xtime is updated with timer interrupts */
+ xtime.tv_sec = secs_since_1970;
+ xtime.tv_nsec = 0;
+
+ wall_to_monotonic.tv_sec = -xtime.tv_sec;
+
+ time_sched_init(timer_interrupt);
+}
+
+#ifndef CONFIG_GENERIC_TIME
+void do_gettimeofday(struct timeval *tv)
+{
+ unsigned long flags;
+ unsigned long seq;
+ unsigned long usec, sec;
+
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+ usec = gettimeoffset();
+ sec = xtime.tv_sec;
+ usec += (xtime.tv_nsec / NSEC_PER_USEC);
+ }
+ while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+
+ while (usec >= USEC_PER_SEC) {
+ usec -= USEC_PER_SEC;
+ sec++;
+ }
+
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
+}
+EXPORT_SYMBOL(do_gettimeofday);
+
+int do_settimeofday(struct timespec *tv)
+{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+
+ if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ return -EINVAL;
+
+ write_seqlock_irq(&xtime_lock);
+ /*
+ * This is revolting. We need to set the xtime.tv_usec
+ * correctly. However, the value in this location is
+ * is value at the last tick.
+ * Discover what correction gettimeofday
+ * would have done, and then undo it!
+ */
+ nsec -= (gettimeoffset() * NSEC_PER_USEC);
+
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+ ntp_clear();
+
+ write_sequnlock_irq(&xtime_lock);
+ clock_was_set();
+
+ return 0;
+}
+EXPORT_SYMBOL(do_settimeofday);
+#endif /* !CONFIG_GENERIC_TIME */
+
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+ return (unsigned long long)jiffies *(NSEC_PER_SEC / HZ);
+}
--- /dev/null
+/*
+ * File: arch/blackfin/kernel/traps.c
+ * Based on:
+ * Author: Hamish Macdonald
+ *
+ * Created:
+ * Description: uses S/W interrupt 15 for the system calls
+ *
+ * Modified:
+ * Copyright 2004-2006 Analog Devices Inc.
+ *
+ * Bugs: Enter bugs at http://blackfin.uclinux.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see the file COPYING, or write
+ * to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <asm/uaccess.h>
+#include <asm/traps.h>
+#include <asm/cacheflush.h>
+#include <asm/blackfin.h>
+#include <asm/uaccess.h>
+#include <asm/irq_handler.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+
+#ifdef CONFIG_KGDB
+# include <linux/debugger.h>
+# include <linux/kgdb.h>
+#endif
+
+/* Initiate the event table handler */
+void __init trap_init(void)
+{
+ CSYNC();
+ bfin_write_EVT3(trap);
+ CSYNC();
+}
+
+asmlinkage void trap_c(struct pt_regs *fp);
+
+int kstack_depth_to_print = 48;
+
+static int printk_address(unsigned long address)
+{
+ struct vm_list_struct *vml;
+ struct task_struct *p;
+ struct mm_struct *mm;
+
+#ifdef CONFIG_KALLSYMS
+ unsigned long offset = 0, symsize;
+ const char *symname;
+ char *modname;
+ char *delim = ":";
+ char namebuf[128];
+
+ /* look up the address and see if we are in kernel space */
+ symname = kallsyms_lookup(address, &symsize, &offset, &modname, namebuf);
+
+ if (symname) {
+ /* yeah! kernel space! */
+ if (!modname)
+ modname = delim = "";
+ return printk("<0x%p> { %s%s%s%s + 0x%lx }",
+ (void*)address, delim, modname, delim, symname,
+ (unsigned long)offset);
+
+ }
+#endif
+
+ /* looks like we're off in user-land, so let's walk all the
+ * mappings of all our processes and see if we can't be a whee
+ * bit more specific
+ */
+ write_lock_irq(&tasklist_lock);
+ for_each_process(p) {
+ mm = get_task_mm(p);
+ if (!mm)
+ continue;
+
+ vml = mm->context.vmlist;
+ while (vml) {
+ struct vm_area_struct *vma = vml->vma;
+
+ if (address >= vma->vm_start && address < vma->vm_end) {
+ char *name = p->comm;
+ struct file *file = vma->vm_file;
+ if (file) {
+ char _tmpbuf[256];
+ name = d_path(file->f_dentry,
+ file->f_vfsmnt,
+ _tmpbuf,
+ sizeof(_tmpbuf));
+ }
+
+ write_unlock_irq(&tasklist_lock);
+ return printk("<0x%p> [ %s + 0x%lx ]",
+ (void*)address, name,
+ (unsigned long)
+ ((address - vma->vm_start) +
+ (vma->vm_pgoff << PAGE_SHIFT)));
+ }
+
+ vml = vml->next;
+ }
+ }
+ write_unlock_irq(&tasklist_lock);
+
+ /* we were unable to find this address anywhere */
+ return printk("[<0x%p>]", (void*)address);
+}
+
+#define trace_buffer_save(x) \
+ do { \
+ (x) = bfin_read_TBUFCTL(); \
+ bfin_write_TBUFCTL((x) & ~TBUFEN); \
+ } while (0)
+#define trace_buffer_restore(x) \
+ do { \
+ bfin_write_TBUFCTL((x)); \
+ } while (0)
+
+asmlinkage void trap_c(struct pt_regs *fp)
+{
+ int j, sig = 0;
+ siginfo_t info;
+ unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE;
+
+#ifdef CONFIG_KGDB
+# define CHK_DEBUGGER_TRAP() do { CHK_DEBUGGER(trapnr, sig, info.si_code, fp,); } while (0)
+# define CHK_DEBUGGER_TRAP_MAYBE() do { if (kgdb_connected) CHK_DEBUGGER_TRAP(); } while (0)
+#else
+# define CHK_DEBUGGER_TRAP() do { } while (0)
+# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0)
+#endif
+
+ trace_buffer_save(j);
+
+ /* trap_c() will be called for exceptions. During exceptions
+ * processing, the pc value should be set with retx value.
+ * With this change we can cleanup some code in signal.c- TODO
+ */
+ fp->orig_pc = fp->retx;
+ /* printk("exception: 0x%x, ipend=%x, reti=%x, retx=%x\n",
+ trapnr, fp->ipend, fp->pc, fp->retx); */
+
+ /* send the appropriate signal to the user program */
+ switch (trapnr) {
+
+ /* This table works in conjuction with the one in ./mach-common/entry.S
+ * Some exceptions are handled there (in assembly, in exception space)
+ * Some are handled here, (in C, in interrupt space)
+ * Some, like CPLB, are handled in both, where the normal path is
+ * handled in assembly/exception space, and the error path is handled
+ * here
+ */
+
+ /* 0x00 - Linux Syscall, getting here is an error */
+ /* 0x01 - userspace gdb breakpoint, handled here */
+ case VEC_EXCPT01:
+ info.si_code = TRAP_ILLTRAP;
+ sig = SIGTRAP;
+ CHK_DEBUGGER_TRAP_MAYBE();
+ /* Check if this is a breakpoint in kernel space */
+ if (fp->ipend & 0xffc0)
+ return;
+ else
+ break;
+#ifdef CONFIG_KGDB
+ case VEC_EXCPT02 : /* gdb connection */
+ info.si_code = TRAP_ILLTRAP;
+ sig = SIGTRAP;
+ CHK_DEBUGGER_TRAP();
+ return;
+#else
+ /* 0x02 - User Defined, Caught by default */
+#endif
+ /* 0x03 - Atomic test and set */
+ case VEC_EXCPT03:
+ info.si_code = SEGV_STACKFLOW;
+ sig = SIGSEGV;
+ printk(KERN_EMERG EXC_0x03);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x04 - spinlock - handled by _ex_spinlock,
+ getting here is an error */
+ /* 0x05 - User Defined, Caught by default */
+ /* 0x06 - User Defined, Caught by default */
+ /* 0x07 - User Defined, Caught by default */
+ /* 0x08 - User Defined, Caught by default */
+ /* 0x09 - User Defined, Caught by default */
+ /* 0x0A - User Defined, Caught by default */
+ /* 0x0B - User Defined, Caught by default */
+ /* 0x0C - User Defined, Caught by default */
+ /* 0x0D - User Defined, Caught by default */
+ /* 0x0E - User Defined, Caught by default */
+ /* 0x0F - User Defined, Caught by default */
+ /* 0x10 HW Single step, handled here */
+ case VEC_STEP:
+ info.si_code = TRAP_STEP;
+ sig = SIGTRAP;
+ CHK_DEBUGGER_TRAP_MAYBE();
+ /* Check if this is a single step in kernel space */
+ if (fp->ipend & 0xffc0)
+ return;
+ else
+ break;
+ /* 0x11 - Trace Buffer Full, handled here */
+ case VEC_OVFLOW:
+ info.si_code = TRAP_TRACEFLOW;
+ sig = SIGTRAP;
+ printk(KERN_EMERG EXC_0x11);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x12 - Reserved, Caught by default */
+ /* 0x13 - Reserved, Caught by default */
+ /* 0x14 - Reserved, Caught by default */
+ /* 0x15 - Reserved, Caught by default */
+ /* 0x16 - Reserved, Caught by default */
+ /* 0x17 - Reserved, Caught by default */
+ /* 0x18 - Reserved, Caught by default */
+ /* 0x19 - Reserved, Caught by default */
+ /* 0x1A - Reserved, Caught by default */
+ /* 0x1B - Reserved, Caught by default */
+ /* 0x1C - Reserved, Caught by default */
+ /* 0x1D - Reserved, Caught by default */
+ /* 0x1E - Reserved, Caught by default */
+ /* 0x1F - Reserved, Caught by default */
+ /* 0x20 - Reserved, Caught by default */
+ /* 0x21 - Undefined Instruction, handled here */
+ case VEC_UNDEF_I:
+ info.si_code = ILL_ILLOPC;
+ sig = SIGILL;
+ printk(KERN_EMERG EXC_0x21);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x22 - Illegal Instruction Combination, handled here */
+ case VEC_ILGAL_I:
+ info.si_code = ILL_ILLPARAOP;
+ sig = SIGILL;
+ printk(KERN_EMERG EXC_0x22);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x23 - Data CPLB Protection Violation,
+ normal case is handled in _cplb_hdr */
+ case VEC_CPLB_VL:
+ info.si_code = ILL_CPLB_VI;
+ sig = SIGILL;
+ printk(KERN_EMERG EXC_0x23);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x24 - Data access misaligned, handled here */
+ case VEC_MISALI_D:
+ info.si_code = BUS_ADRALN;
+ sig = SIGBUS;
+ printk(KERN_EMERG EXC_0x24);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x25 - Unrecoverable Event, handled here */
+ case VEC_UNCOV:
+ info.si_code = ILL_ILLEXCPT;
+ sig = SIGILL;
+ printk(KERN_EMERG EXC_0x25);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr,
+ error case is handled here */
+ case VEC_CPLB_M:
+ info.si_code = BUS_ADRALN;
+ sig = SIGBUS;
+ printk(KERN_EMERG EXC_0x26);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */
+ case VEC_CPLB_MHIT:
+ info.si_code = ILL_CPLB_MULHIT;
+#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
+ sig = SIGSEGV;
+ printk(KERN_EMERG "\n\nNULL pointer access (probably)\n");
+#else
+ sig = SIGILL;
+ printk(KERN_EMERG EXC_0x27);
+#endif
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x28 - Emulation Watchpoint, handled here */
+ case VEC_WATCH:
+ info.si_code = TRAP_WATCHPT;
+ sig = SIGTRAP;
+ pr_debug(EXC_0x28);
+ CHK_DEBUGGER_TRAP_MAYBE();
+ /* Check if this is a watchpoint in kernel space */
+ if (fp->ipend & 0xffc0)
+ return;
+ else
+ break;
+#ifdef CONFIG_BF535
+ /* 0x29 - Instruction fetch access error (535 only) */
+ case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */
+ info.si_code = BUS_OPFETCH;
+ sig = SIGBUS;
+ printk(KERN_EMERG "BF535: VEC_ISTRU_VL\n");
+ CHK_DEBUGGER_TRAP();
+ break;
+#else
+ /* 0x29 - Reserved, Caught by default */
+#endif
+ /* 0x2A - Instruction fetch misaligned, handled here */
+ case VEC_MISALI_I:
+ info.si_code = BUS_ADRALN;
+ sig = SIGBUS;
+ printk(KERN_EMERG EXC_0x2A);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x2B - Instruction CPLB protection Violation,
+ handled in _cplb_hdr */
+ case VEC_CPLB_I_VL:
+ info.si_code = ILL_CPLB_VI;
+ sig = SIGILL;
+ printk(KERN_EMERG EXC_0x2B);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */
+ case VEC_CPLB_I_M:
+ info.si_code = ILL_CPLB_MISS;
+ sig = SIGBUS;
+ printk(KERN_EMERG EXC_0x2C);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x2D - Instruction CPLB Multiple Hits, handled here */
+ case VEC_CPLB_I_MHIT:
+ info.si_code = ILL_CPLB_MULHIT;
+#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO
+ sig = SIGSEGV;
+ printk(KERN_EMERG "\n\nJump to address 0 - 0x0fff\n");
+#else
+ sig = SIGILL;
+ printk(KERN_EMERG EXC_0x2D);
+#endif
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x2E - Illegal use of Supervisor Resource, handled here */
+ case VEC_ILL_RES:
+ info.si_code = ILL_PRVOPC;
+ sig = SIGILL;
+ printk(KERN_EMERG EXC_0x2E);
+ CHK_DEBUGGER_TRAP();
+ break;
+ /* 0x2F - Reserved, Caught by default */
+ /* 0x30 - Reserved, Caught by default */
+ /* 0x31 - Reserved, Caught by default */
+ /* 0x32 - Reserved, Caught by default */
+ /* 0x33 - Reserved, Caught by default */
+ /* 0x34 - Reserved, Caught by default */
+ /* 0x35 - Reserved, Caught by default */
+ /* 0x36 - Reserved, Caught by default */
+ /* 0x37 - Reserved, Caught by default */
+ /* 0x38 - Reserved, Caught by default */
+ /* 0x39 - Reserved, Caught by default */
+ /* 0x3A - Reserved, Caught by default */
+ /* 0x3B - Reserved, Caught by default */
+ /* 0x3C - Reserved, Caught by default */
+ /* 0x3D - Reserved, Caught by default */
+ /* 0x3E - Reserved, Caught by default */
+ /* 0x3F - Reserved, Caught by default */
+ default:
+ info.si_code = TRAP_ILLTRAP;
+ sig = SIGTRAP;
+ printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n",
+ (fp->seqstat & SEQSTAT_EXCAUSE));
+ CHK_DEBUGGER_TRAP();
+ break;
+ }
+
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_addr = (void *)fp->pc;
+ force_sig_info(sig, &info, current);
+ if (sig != 0 && sig != SIGTRAP) {
+ unsigned long stack;
+ dump_bfin_regs(fp, (void *)fp->retx);
+ dump_bfin_trace_buffer();
+ show_stack(current, &stack);
+ if (current->mm == NULL)
+ panic("Kernel exception");
+ }
+
+ /* if the address that we are about to return to is not valid, set it
+ * to a valid address, if we have a current application or panic
+ */
+ if (!(fp->pc <= physical_mem_end
+#if L1_CODE_LENGTH != 0
+ || (fp->pc >= L1_CODE_START &&
+ fp->pc <= (L1_CODE_START + L1_CODE_LENGTH))
+#endif
+ )) {
+ if (current->mm) {
+ fp->pc = current->mm->start_code;
+ } else {
+ printk(KERN_EMERG "I can't return to memory that doesn't exist - bad things happen\n");
+ panic("Help - I've fallen and can't get up\n");
+ }
+ }
+
+ trace_buffer_restore(j);
+ return;
+}
+
+/* Typical exception handling routines */
+
+void dump_bfin_trace_buffer(void)
+{
+ int tflags;
+ trace_buffer_save(tflags);
+
+ if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
+ int i;
+ printk(KERN_EMERG "Hardware Trace:\n");
+ for (i = 0; bfin_read_TBUFSTAT() & TBUFCNT; i++) {
+ printk(KERN_EMERG "%2i Target : ", i);
+ printk_address((unsigned long)bfin_read_TBUF());
+ printk("\n" KERN_EMERG " Source : ");
+ printk_address((unsigned long)bfin_read_TBUF());
+ printk("\n");
+ }
+ }
+
+ trace_buffer_restore(tflags);
+}
+EXPORT_SYMBOL(dump_bfin_trace_buffer);
+
+static void show_trace(struct task_struct *tsk, unsigned long *sp)
+{
+ unsigned long addr;
+
+ printk("\nCall Trace:");
+#ifdef CONFIG_KALLSYMS
+ printk("\n");
+#endif
+
+ while (!kstack_end(sp)) {
+ addr = *sp++;
+ /*
+ * If the address is either in the text segment of the
+ * kernel, or in the region which contains vmalloc'ed
+ * memory, it *may* be the address of a calling
+ * routine; if so, print it so that someone tracing
+ * down the cause of the crash will be able to figure
+ * out the call path that was taken.
+ */
+ if (kernel_text_address(addr))
+ print_ip_sym(addr);
+ }
+
+ printk("\n");
+}
+
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+ unsigned long *endstack, addr;
+ int i;
+
+ /* Cannot call dump_bfin_trace_buffer() here as show_stack() is
+ * called externally in some places in the kernel.
+ */
+
+ if (!stack) {
+ if (task)
+ stack = (unsigned long *)task->thread.ksp;
+ else
+ stack = (unsigned long *)&stack;
+ }
+
+ addr = (unsigned long)stack;
+ endstack = (unsigned long *)PAGE_ALIGN(addr);
+
+ printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
+ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (stack + 1 > endstack)
+ break;
+ if (i % 8 == 0)
+ printk("\n" KERN_EMERG " ");
+ printk(" %08lx", *stack++);
+ }
+
+ show_trace(task, stack);
+}
+
+void dump_stack(void)
+{
+ unsigned long stack;
+ int tflags;
+ trace_buffer_save(tflags);
+ dump_bfin_trace_buffer();
+ show_stack(current, &stack);
+ trace_buffer_restore(tflags);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+void dump_bfin_regs(struct pt_regs *fp, void *retaddr)
+{
+ if (current->pid) {
+ printk("\nCURRENT PROCESS:\n\n");
+ printk("COMM=%s PID=%d\n", current->comm, current->pid);
+ } else {
+ printk
+ ("\nNo Valid pid - Either things are really messed up, or you are in the kernel\n");
+ }
+
+ if (current->mm) {
+ printk("TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n"
+ "BSS = 0x%p-0x%p USER-STACK = 0x%p\n\n",
+ (void*)current->mm->start_code,
+ (void*)current->mm->end_code,
+ (void*)current->mm->start_data,
+ (void*)current->mm->end_data,
+ (void*)current->mm->end_data,
+ (void*)current->mm->brk,
+ (void*)current->mm->start_stack);
+ }
+
+ printk("return address: 0x%p; contents of [PC-16...PC+8]:\n", retaddr);
+ if (retaddr != 0 && retaddr <= (void*)physical_mem_end
+#if L1_CODE_LENGTH != 0
+ /* FIXME: Copy the code out of L1 Instruction SRAM through dma
+ memcpy. */
+ && !(retaddr >= (void*)L1_CODE_START
+ && retaddr < (void*)(L1_CODE_START + L1_CODE_LENGTH))
+#endif
+ ) {
+ int i = 0;
+ unsigned short x = 0;
+ for (i = -16; i < 8; i++) {
+ if (get_user(x, (unsigned short *)retaddr + i))
+ break;
+#ifndef CONFIG_DEBUG_HWERR
+ /* If one of the last few instructions was a STI
+ * it is likily that the error occured awhile ago
+ * and we just noticed
+ */
+ if (x >= 0x0040 && x <= 0x0047 && i <= 0)
+ panic("\n\nWARNING : You should reconfigure the kernel to turn on\n"
+ " 'Hardware error interrupt debugging'\n"
+ " The rest of this error is meanless\n");
+#endif
+
+ if (i == -8)
+ printk("\n");
+ if (i == 0)
+ printk("X\n");
+ printk("%04x ", x);
+ }
+ } else
+ printk("Cannot look at the [PC] for it is in unreadable L1 SRAM - sorry\n");
+