diff options
Diffstat (limited to 'recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff')
-rw-r--r-- | recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff | 43746 |
1 files changed, 43746 insertions, 0 deletions
diff --git a/recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff b/recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff new file mode 100644 index 0000000000..3dc6b004b8 --- /dev/null +++ b/recipes/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff @@ -0,0 +1,43746 @@ +diff --git a/Documentation/arm/ep93xx/config.txt b/Documentation/arm/ep93xx/config.txt +new file mode 100644 +index 0000000..9d13a15 +--- /dev/null ++++ b/Documentation/arm/ep93xx/config.txt +@@ -0,0 +1,207 @@ ++------------------------------------------------------------------------- ++config.txt ++ ++Information on configuration options in the Linux kernel for the Cirrus ++EP93xx. ++ ++Note to developers: Let's stick to the essentials on "how to turn things ++on in the Linux build." This information is presented from the standpoint ++of someone doing a build, looking at a make menuconfig screen. If what you ++are describing doesn't fit here, it should get its own document to go into ++the level of detail you feel is most practicle. ++------------------------------------------------------------------------- ++ ++All options configured as built-in drivers, not loadable modules. ++So on options that are selected by < >, select <*>, not <M>. To ++do this either hit 'y' or hit the space bar twice. ++ ++ ++---------------- ++Audio ++---------------- ++Needed by: ++Needs: DMA Support, dev fs. ++ ++Ac97 and I2S audio are currently mutually exclusive. ++ ++To enable Ac97 Audio: ++ Go into "Sound --->" ++ Enable "Sound Support" ++ Enable "OSS sound modules" ++ Select "Ac97" for "Cirrus EP93xx Sound Support" ++ ++To enable I2S Audio: ++ Go into "Sound --->" ++ Enable "Sound Support" ++ Enable "OSS sound modules" ++ Select "I2S" for "Cirrus EP93xx Sound Support" ++ If you have an EDB9312 board, select "CS4228A" for "Cirrus I2S Codec Support" ++ If you have an EDB9301 board, select "CS4271" for "Cirrus I2S Codec Support" ++ ++ ++---------------- ++Dev Fs ++---------------- ++ DEVFS support is no longer available. ++ Please consider using udev or create device nodes manually instead. ++ You might also need to adapt your startup scripts and userspace ++ apps. ++ ++---------------- ++DMA ++---------------- ++Needed by: Audio, IDE/DMA ++Needs: ++ ++To enable DMA: ++ Go into "System Type --->" ++ Go into "EP93XX Options --->" ++ Enable "EP93XX Internal DMA Support" ++ ++ ++---------------- ++IDE ++---------------- ++Needed by: ++Needs: ++ To Turn on IDE support for the platform, you need to enable ++General IDE support first - CONFIG_BLK_DEV_IDE, CONFIG_BLK_DEV_IDEDISK, ++CONFIG_BLK_DEV_IDECD. ++ ++ If multiword DMA and ultra DMA support is needed, general DMA support for ++the platform must be enabled first. See DMA section of this document for ++options to enable DMA for the platform. ++ ++ If CDROM support is enabled, ISO9660 file system support should be enabled. ++If a DVD support is needed, UDF file system support should be enabled. ++ ++To enable CONFIG_BLK_DEV_IDE: ++ Go into "ATA /ATAPI/MFM/RLL support --->" ++ Enable "ATA/ATAPI/MFM/RLL support" ++ Go into "IDE, ATA, and ATAPI Block devices --->" ++ Enable "Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support" ++ ++To enable CONFIG_BLK_DEV_IDEDISK: ++ Go into "ATA /ATAPI/MFM/RLL support --->" ++ Go into "IDE, ATA, and ATAPI Block devices --->" ++ Enable "Include IDE/ATA-2 DISK support" ++ ++To enable CONFIG_BLK_DEV_IDECD: ++ Go into "ATA /ATAPI/MFM/RLL support --->" ++ Go into "IDE, ATA, and ATAPI Block devices --->" ++ Enable "Include IDE/ATAPI CDROM support" ++ ++To enable EP93XX IDE (PIO mode only): ++ Go into "ATA /ATAPI/MFM/RLL support --->" ++ Go into "IDE, ATA, and ATAPI Block devices --->" ++ Enable "EP93XX IDE Support" ++ ++To enable EP93XX IDE DMA (mdma and udma modes): ++ Go into "ATA /ATAPI/MFM/RLL support --->" ++ Go into "IDE, ATA, and ATAPI Block devices --->" ++ Enable "EP93XX IDE DMA support" ++ ++To enabled ISO 9660 file system support: ++ Go into "File systems --->" ++ Enable "ISo 9660 CDROM file system support" ++ Enable "Microsoft Joliet CDROM extensions" ++ ++To enable UDF file system support: ++ Go into "File systems --->" ++ Enable "UDF file system support (read only)" ++ ++See also /Documentation/arm/ep93xx/ide-hard-drive-support.txt for information ++on configuring the hard drive. ++ ++---------------- ++IrDA ++---------------- ++Described in /Documentation/arm/ep93xx/irda.txt ++ ++ ++---------------- ++NFS ++---------------- ++Described in /Documentation/arm/ep93xx/nfs.txt ++ ++ ++---------------- ++Serial Terminal ++---------------- ++To enable serial terminal: ++ Go into "Character devices --->" ++ Turn off "Support for console on virtual terminal" ++ Turn off "Virtual terminal" ++ Go into "Serial drivers --->" ++ Turn on "Cirrus EP93xx ARM AMBA serial port support" ++ Turn on "Support for console on EP93xx serial port" ++ ++Serial terminal is the bottom jack of J7. ++Format is 57600,8N1, flow control: "none". ++ ++ ++---------------- ++Touchscreen ++---------------- ++To enable touchscreen driver: ++ Go into "Character devices --->" ++ Go into "Mice --->" ++ Enable "Mouse Support (not serial and bus mice)" ++ Disable "PS/2 Mouse (aka "auxiliary device") support ++ Enable "EP93xx touch screen support" ++ ++ ++---------------- ++USB ++---------------- ++The order of all of the following statements is critical as some options enable ++other options. ++ ++To enable basic USB support(required for all devices listed below): ++ Go into "USB support --->" ++ Enable "Support for USB" ++ Enable "Preliminary USB device filesystem" (optional) ++ Enable "EP93XX OHCI-compatible host interface support" ++ ++To enable support for USB mouse: ++ Go into "Input core support --->" ++ Enable "Input core support" ++ Enable "Mouse support" ++ ++ Go back to the top level of menuconfig ++ ++ Go into "USB support --->" ++ Enable "USB Human Interface Device (full HID) support" ++ Enable "HID input layer support" ++ ++To enable support for USB Keyboard: ++ Go into "Input core support --->" ++ Enable "Input core support" ++ Enable "Keyboard support" ++ ++ Go back to the top level of menuconfig ++ ++ Go into "USB support --->" ++ Enable "USB Human Interface Device (full HID) support" ++ Enable "HID input layer support" ++ ++ Go back to the top level of menuconfig ++ Go into "Character devices --->" ++ Set EP93xx Keyboard Support to "USB" ++ ++To enable USB Mass Storage support: ++ Go into "SCSI Support --->" ++ Enable "SCSI Support" ++ Enable "SCSI disk support" ++ ++ Go back to the top level of menuconfig ++ ++ Go into "USB support --->" ++ Enable "USB Mass Storage support" ++ ++ Go back to the top level of menuconfig ++ ++(optional - Do this if you want to mount a USB flash drive) ++ Go into "File systems --->" ++ Enable "DOS FAT fs support" ++ Enable "VFAT (Windows-95) fs support" +diff --git a/Documentation/arm/ep93xx/dma.txt b/Documentation/arm/ep93xx/dma.txt +new file mode 100644 +index 0000000..e7fc1bb +--- /dev/null ++++ b/Documentation/arm/ep93xx/dma.txt +@@ -0,0 +1,300 @@ ++Support Functions for the Cirrus Logic ep93xx Internal DMA controller. ++============================================================================== ++ ++State diagram ++ ++States: ++Uninitialized (!pause & !xfer_enable) ++Stopped (pause & !xfer_enable) ++Transferring (!pause & xfer_enable) ++Stopped by starvation (pause & xfer_enable) ++ ++ _______________ ++ request ----------> | | <------- free ----------- ++ | Uninitialized | /\ ++ |_______________| || ++ || ++ || || ++ init || ------------------------------>|| ++ || /\ || ++ \/ || || ++ _________ || ++ ||<-- start && new_buffers <= 1 -- | | <----- flush <--------- || ++ || | Stopped | /\ || ++ || ---------> pause------> |_________| -------------------->|| || ++ || /\ || ++ || || || || ++ || || || start && new_buffers > 1 || ++ || || || || ++ || || \/ || ++ || || ______________ || ++ || || | | ------------------------->|| ++ || ||<---------------- | Transferring | ------------------->|| || ++ || || |______________| || || ++ || || || || ++ || || || || || ++ || || || new_buffers = 0 || || ++ || || /\ || || || ++ || || || \/ || || ++ || || new_buffers > 1 || || || ++ || || || || || ++ || || _______________________ || || ++ || ||<-------------- | | || || ++ \/ | Stopped by starvation | ------------>|| || ++ ---------------------------> |_______________________| || || ++ || || ++ || /\ || || ++ || || || || ++ || ||<-------- flush <--------------- || ++ || || ++ ------------------------------------------->|| ++ ++ ++------------------------------------------------------------------------------ ++EP93XX DMA API Functions ++------------------------------------------------------------------------------ ++ ++ int ep93xx_dma_request(int * handle, const char * device_id, ++ ep93xx_dma_dev_t device) ++ ++This function will allocate a DMA channel for a particular hardware ++peripheral. Before initiating a transfer on the allocated channel, the ++channel has to be setup, and buffers have to be added to the channel. ++ ++Parameters: ++ int * handle A pointer which is filled in with a unique ++ integer value, or handle. The handle is used ++ to verify the validity of each call to ++ access the dma channel. ++ ++ const char * device_id string which is the name of the device ++ attached to the dma channel. ++ ++ ep93xx_dma_dev_t device hardware port to attach to the dma channel ++ ++------------------------------------------------------------------------------ ++ ++ int ep93xx_dma_free(int handle) ++ ++This function disables and powers down the dma channel, and releases it ++for future requests. Buffers queued up for the specified channel are ++released without transferring. ++ ++Parameters: ++ int handle A unique integer value, assigned ++ during open, used to verify the validity of ++ this call to access a DMA channel. ++ ++------------------------------------------------------------------------------ ++ ++ int ep93xx_dma_add_buffer(int handle, unsigned int source, ++ unsigned int dest, unsigned int size ++ unsigned int last, unsigned int buf_id) ++ ++This function adds a buffer entry to the DMA buffer queue. If the channel is ++in the active transfer state, the buffer is immediately transferred, ++otherwise the buffer is not transferred until a start or resume ++command is issued. A -1 is returned if an error occurs, otherwise ++a 0 is returned. ++ ++Parameter: ++ int handle A unique integer value, assigned ++ during open, used to verify the validity of ++ this call to access a dma channel. ++ ++ unsigned int source physical address for the start of this ++ buffer. ++ ++ unsigned int source physical address destination of the data. ++ ++ unsigned int size buffer size in bytes ++ ++ unsigned int last 1 if this is the last buffer in the transfer. ++ If 1, disable the NFBint so we aren't ++ interrupted for another buffer ++ when we know there won't be another. ++ ++ unsigned int buf_id Unique value used to identify this buffer. ++ ++------------------------------------------------------------------------------ ++ ++ int ep93xx_dma_remove_buffer(int handle, unsigned int * address, ++ unsigned int * size) ++ ++This function removes a buffer entry from the DMA buffer queue. If a buffer ++was removed successfully, a 0 is returned, otherwise -1 is returned. ++ ++Parameter: ++ int handle A unique integer value, assigned ++ during open, used to verify the validity of ++ this call to access a dma channel. ++ ++ unsigned int * buf_id Pointer to an integer which is filled in ++ with the buffer id.. ++ ++------------------------------------------------------------------------------ ++ ++ int ep93xx_dma_queue_full(int handle) ++ ++This function queries to determine if the buffer queue for the specified ++channel is full. A return value of 1 indicates the queue is not full, and a ++0 indicates the queue is full. ++ ++Parameters: ++ int handle A unique integer value, assigned ++ during open, used to verify the validity of ++ this call to access a dma channel. ++ ++------------------------------------------------------------------------------ ++ ++ int ep93xx_dma_get_position(int handle, unsigned int * buf_id, ++ unsigned int * total) ++ ++This function fills in the buffer ID of the current buffer and fills in the ++total bytes transferred on the channel. If no buffer is active on the channel, ++buf_id is filled in with a -1, otherwise it is the active buffer. ++ ++Parameter: ++ int handle A unique integer value, assigned ++ during open, used to verify the validity of ++ this call to access a dma channel. ++ ++ unsigned int * buf_id pointer to an integer which is filled in with ++ buffer ID of the buffer currently ++ transferring. ++ ++ unsigned int * total pointer to an integer which is filled in ++ with the total bytes transferred on the channel. ++ ++------------------------------------------------------------------------------ ++ ++ int ep93xx_dma_config(int handle, unsigned int flags_m2m, ++ unsigned int flags_m2p, dma_callback callback, ++ unsigned int user_data) ++ ++This function configures the DMA channel registers and installs a dma ++callback function into the DMA instance. The DMA callback function is ++defined by the driver which is using this DMA channel. It is called in ++response to DMA interrupts, at the end of the DMA channel's interrupt ++handler. A -1 is returned if an error occurs, otherwise a 0 is returned. ++ ++Parameter: ++ int handle A unique integer value, assigned ++ during open, used to verify the validity of ++ this call to access a dma channel. ++ ++ unsigned int flags_m2m Flags used for M2M channel configuration. ++ ++ unsigned int flags_m2p Flags used for M2P/P2M channel ++ configuration. ++ ++ dma_callback callback Pointer to the callback function which will ++ be called at the end of the dma interrupt ++ service routine. ++ ++ unsigned int user_data Data defined by the driver installing the ++ callback function. This piece of data will ++ be returned to the driver when the callback ++ function is called. ++ ++Callback function prototype: ++ ++ void (* dma_callback)(ep93xx_dma_int_t interrupt, ++ ep93xx_dma_dev_t device, unsigned int user_data) ++ ++ Parameters: ++ ep93xx_dma_int_t interrupt ++ used by the DMA driver to inform the DMA callback ++ function of the type of DMA interrupt that happened. ++ ++ ep93xx_dma_dev_t device ++ hardware port attached to the dma channel. ++ ++ unsigned int user_data ++ is a value defined and passed in by the driver which ++ registered the callback function. ++ ++------------------------------------------------------------------------------ ++ ++ int ep93xx_dma_start(int handle, unsigned int channels, ++ unsigned int * handles ++ ++This function enables the DMA channel, and initiates the transfer. If the ++peripheral interface calls for it, multiple DMA channels can be started ++with one call to this IOCTL. A -1 is returned if an error occurs, ++otherwise a 0 is returned. ++ ++Parameter: ++ int handle A unique integer value, assigned ++ during open, used to verify the validity of ++ this call to access a dma channel. For a start ++ multiple, this handle can be the handle ++ for any of the channels to be started. ++ ++ unsigned int channels Number of channels to start for this transfer. ++ Specifically this applies to an audio interface ++ where you can have up to 3 dma channels ++ servicing a 6 audio channel output, in which case ++ you need to initiate transfers on all 3 dma ++ channels as closely together as possible. For ++ the case of only one channel to be started, this ++ field should be a 1. ++ ++ unsigned int * handles Pointer to an array of handles, one for ++ each channel which is to be started. If only one ++ channel is to be started, this field should be ++ NULL. ++ ++------------------------------------------------------------------------------ ++ ++ int ep93xx_dma_pause(int handle, unsigned int channels, ++ unsigned int * handles) ++ ++This function disables the DMA channel, pausing the transfer. The ++position within the currently transferring buffer is saved, and restored upon ++restarting the transfer on this channel. If the peripheral interface calls ++for it, multiple DMA channels can be paused with one call to this IOCTL. ++A -1 is returned if an error occurs, otherwise a 0 is returned. ++ ++Parameter: ++ int handle A unique integer value, assigned ++ during open, used to verify the validity of ++ this call to access a dma channel. ++ ++ unsigned int channels Number of channels to pause for this ++ transfer. Specifically this applies to ++ an audio interface where you can have ++ up to 3 dma channels servicing a 6 ++ audio channel output, in which case you ++ need to pause transfers on all 3 dma ++ channels as closely together as possible. ++ ++ unsigned int * handles Pointer to an array of handles, one for ++ each channel which is to be paused. ++ ++NOTE: There is another way to pause the DMA channel - starve it. ++When the dma channel reaches the point where there are no buffers in ++the queue, but the interface has not been paused, then the dma instance ++will indicate that the channel is in the transfer state, but the ++channel itself is disabled until a new buffer is added to the queue ++If the channel is stopped via this method, a resume command is not ++required to restart a transfer. A transfer is started immediately ++after two new buffers are added to the queue. The reason for two is ++so that both channel buffer descriptors can be programmed with valid ++buffers ++ ++------------------------------------------------------------------------------ ++ ++ int ep93xx_dma_flush(int handle) ++ ++This function completely flushes all queued buffers and any on going ++DMA transfers on a given channel. If the dma channel is in the ++active transfer state, once two buffers are added to the queue, the ++channel will begin transferring data right away. If in the stop ++state, a start command must be issued before any new buffers are ++processed. A -1 is returned if an error occurs, otherwise a 0 is returned. ++ ++Parameters: ++ int handle A unique integer value, assigned ++ during open, used to verify the validity of ++ this call to access a dma channel. +diff --git a/Documentation/arm/ep93xx/status.txt b/Documentation/arm/ep93xx/status.txt +new file mode 100644 +index 0000000..082c2dd +--- /dev/null ++++ b/Documentation/arm/ep93xx/status.txt +@@ -0,0 +1,288 @@ ++# ++# EP93xx driver support status ++# ++ ++====================================================================== ++(I) Introduction ++====================================================================== ++ ++The EP93xx are embedded System On Chip (SOC) processors produced ++by Cirrus (www.cirrus.com). They provided support based on 2.4.21-rmk1 ++kernels, and they said that there might be 2.6.x support some day. ++Meanwhile they've released a 2.6.8.1 based kernel called "ursus". ++ ++Currently we still have got a communication problem with cirrus, ++for some reason it seems to be impossible to directly talk to their ++developers. Hope this will change some day, but we really cannot afford ++to just sit down and wait. ++ ++The purpose of this file is to document success and todo's. ++ ++ - Section II describes hardware support, organized according to the ++ EP9315 datasheet. Other device datasheets are ordered similarly, ++ though section numbers may vary. ++ ++ - Section III contains other miscellaneous information. ++ ++The latest version of this document may be found at: ++ ++ linux/Documentation/arm/ep93xx/status.txt ++ ++projects homepage can be found at: ++ ++ http://members.inode.at/m.burian/ep93xx/index.html ++ ++ ++====================================================================== ++(II) Hardware Support ++====================================================================== ++ ++These section numbers mirror the EP9315 datasheet. ++ ++1. Introduction ++--------------- ++N/A ++ ++2. ARM920T Core and Advanced High-Speed Bus (AHB) ++------------------------------------------------- ++We have standard Linux 2.6 support for ARM920T Core. Thumb support ++is pretty shaky, as most people do not seem to use Thumb in the ++kernel. Address translation uses 16K small pages exclusively (FIXME: ++is this true?) ++ ++3. MaverickCrunch Coprocessor ++----------------------------- ++People have started with forward porting. Note that there's more ++to it than just kernel support. You also need to have a toolchain ++supporting it. We're in need of a comprehensive HOWTO that explains kernel, ++toolchain and userspace aspects to a point where average developers can use it ++ ++ ++4. Boot ROM ++----------- ++Well, not really kernel related, most people start with redboot. Make ++sure to use a version that passes the correct machine type. Some ++people also started porting blob / uboot. ++ ++If any support is added for this device, it will likely be a simple ++char device that allows you to read the contents of the boot rom ++for interests sake. ++ ++5. System Controller ++-------------------- ++System Controllers registers are set by startup code and by individual ++drivers as needed, we try to keep the processor dependent stuff to ++a minimum. ++ ++Ray really wants to overhaul the system configuration stuff and move ++towards something like the SA1100 people are doing. It should make ++things a lot cleaner for drivers that share physical pins, or for ++multifunctional blocks that require several drivers (eg: UART2 with ++IrDA support) ++ ++There is currently no dynamic clock control support. We'll probably ++want to tie into the CPUfreq code at some point. ++ ++There is no support for querying the system boot configuration or ++last reset source. ++ ++There is no power management support. Individual drivers may power ++up silicon blocks as required. Some research is needed to map the ++EP93xx power states onto the ACPI or PCI states that everyone seems ++to use. ++ ++There is no support for the TICK and WATCHDOGEXPIRED interrupts ++generated by this block. ++ ++There is no support for the AHB bus arbiter priority settings. ++ ++6. Vectored Interrupt Controller ++-------------------------------- ++Since we can boot this can't be done dead wrong. Standard level-triggered ++interrupt support is present. ++ ++No FIQ interrupts are supported. ++ ++Support for demultiplexing GPIO IRQs is available. ++ ++ ++7. Raster Engine With Analog/LCD Integrated Timing and Interface ++---------------------------------------------------------------- ++ ++Michael has rewritten large parts of the framebuffer driver based on ++skeleton.c. You need to adapt this in case you can't live with ++the standard display(s) that are included. Framebuffer is fixed ++size, you can change some settings at compile time, though. ++TODO: clean ups, different resolutions, etc ++ ++ ++8. Graphics Accelerator ++----------------------- ++not available yet, will be done after the framebuffer code has been ++cleaned up. ++ ++ ++9. 1/10/100 Mbps Ethernet LAN Controller ++---------------------------------------- ++Supported. Driver has been reviewed and cleaned up. ++Uses generic mii routines now. It might be possible ++to use DMA - but in that case we'd need to find a ++workaround to get around the fact that it can only ++transfer 32bit aligned data, while we'd need to transfer ++data that's only 16 bit aligned. ++ ++NICE-TO-HAVE: Could be ported to use NAPI. ++ ++10. DMA Controller ++------------------ ++There is some code and documentation ported forward from the Cirrus ++2.4 port. ++ ++11. Universal Serial Bus Host Controller ++---------------------------------------- ++Ray has written some glue code to plug the OHCI host controller into ++the Linux 2.6 USB stack. This has been tested on an EDB9301 board with ++a single port populated. A serial dongle worked fine, and several ++different flash keys seem to work okay with the USB mass storage ++driver using SCSI disk emulation. This hasn't really been stress tested ++yet, but initial results look very encouraging. ++ ++12. Static Memory Controller ++---------------------------- ++Not sure how much kernel support is required here. Flash and memory ++timing needs to be setup by the bootloader, so there's not much ++that needs to be done here. ++ ++No support for PCMCIA at this time. ++ ++13. SDRAM, SyncROM, and SyncFLASH Controller ++-------------------------------------------- ++Again, this is probably the bootloaders problem. ++ ++There is an errata about system instability when suspending with ++an SDRAM bus speed over 50 MHz. May need to tweak this if we start ++doing power management modes. ++ ++14. UART1 With HDLC and Modem Control Signals ++--------------------------------------------- ++We've got a driver to use this one as UART. No DMA support. FIFO support ++works. No HDLC support. Needs some syscon support to cleanly handle ++HDLC and some modem signals. ++ ++15. UART2 ++--------- ++We've got a driver to use this one as UART. No DMA support. FIFO support ++works. No IrDA SIR support. Needs some syscon support to cleanly handle ++IrDA SIR. ++ ++16. UART3 With HDLC Encoder ++--------------------------- ++We've got a driver to use this one as UART. No DMA support. FIFO support ++works. No HDLC or RS-485 support. Needs some syscon support to cleanly ++handle HDLC and RS-485. ++ ++17. IRDA ++-------- ++There is some code and documentation ported forward from the Cirrus ++2.4 port. No idea how well this works, if at all. ++ ++18. TIMERS ++---------- ++Timer1 is used at 508 kHz with a reload value of 5080 to provide a 100 Hz ++tick signal to drive the kernel. ++ ++Timer 2 and 3 are not currently used, nor is the debug timer 4. ++ ++ ++19. WATCHDOG Timer ++------------------ ++Ray has some initial experimental code written (not pushed) to drive this. ++The onboard watchdog seems to have a 250 ms (!) timeout, while most PC ++dogs seem to have timeouts on the order of one minute or more. The standard ++approach of having a user level process open the watchdog device and ++kick it every so often seems like a bad idea here... a momentary system ++load spike could easily delay the monitor from being scheduled, and the ++system would reboot. ++ ++Test out a watchdog monitor running at a high scheduling priority, or else ++design a kernel watchdog that kicks the dog every timer tick and exports ++a more reasonable timeout value to userspace. ++ ++20. Real Time Clock With Software Trim ++-------------------------------------- ++We did not bother to write a driver yet, it would require a design ++that ensures CPU is always powered on, and always have at least ++a 32kHz clock running. Most people prefer to use and external RTC. ++We've got support for the DS1337 RTC that seems to be popular on ++ep93xx based boards. ++ ++21. I2S Controller ++------------------ ++No support yet. Klaus is working on it. ++ ++22. AC97 Controller ++------------------- ++Supported but could need some testing. ++ ++23. Synchronous Serial Port ++--------------------------- ++Two driver are available, a forward port from the cirrus driver and ++another driver from Ray. ++ ++24. Pulse Width Modulator ++------------------------- ++No support yet. ++ ++25. Analog Touch Screen Interface ++--------------------------------- ++People already played with this, AFAIK one would need a silicon ++revision > D1 (November 2004) for this to work properly. ++ ++26. Keypad Interface ++-------------------- ++We've got a driver for the 8x8 keypad. Chances are that you might ++want to create a custom keymap. There's also support for mobile ++phone like input (key 1 becomes -> A -> B -> C) if pressed repeatedly ++within half a second. ++ ++27. IDE interface ++----------------- ++We've got IDE working in polling only, no DMA support so far. ++It needs to be cleaned up, too. ++ ++28. GPIO ++-------- ++Standard LED support for red and green leds is present. ++ ++Michael has written an I2C bus driver using the new Linux device driver model. ++It supports an external DS1337 RTC device on the EECLK/EEDAT pins. ++ ++Need some syscon support to cleanly handle the multi-function GPIO pins. ++ ++Demultiplexing of GPIO interrupts is possible now. ++ ++29. Security ++------------ ++No information available on this, so support is unlikely in the near future. ++ ++30. Glossary ++------------ ++N/A ++ ++ ++====================================================================== ++(III) Stuff not found in the datasheet ++====================================================================== ++ ++1. printascii hack has been removed from our tree. ++ ++2. I2C driver ++We've got a bit banging I2C driver ++ ++3. External RTC (DS1337) ++Setting and getting the time works ++TODO: advanced features, such as alarm, timer for /dev/rtc ++ ++4. Controller Area Network (CAN) ++We have got a character device based driver for the OKI ML9620 CAN Controller. ++ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 4b15f5f..f23341e 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -103,6 +103,17 @@ config ARCH_EBSA110 + Ethernet interface, two PCMCIA sockets, two serial ports and a + parallel port. + ++config ARCH_EP93XX ++ bool "EP93xx" ++ select ARM_AMBA ++ help ++ Say Y here to enable support for the Cirrus EP93xx CPU family ++ and choose your specific CPU below. ++ ++ See the Cirrus web page for details. ++ ++ <http://www.cirrus.com/> ++ + config ARCH_CAMELOT + bool "Epxa10db" + help +@@ -219,6 +230,8 @@ endchoice + + source "arch/arm/mach-clps711x/Kconfig" + ++source "arch/arm/mach-ep93xx/Kconfig" ++ + source "arch/arm/mach-epxa10db/Kconfig" + + source "arch/arm/mach-footbridge/Kconfig" +@@ -403,7 +416,7 @@ config NO_IDLE_HZ + + config ARCH_DISCONTIGMEM_ENABLE + bool +- default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) ++ default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) || ARCH_EP93XX + help + Say Y to support efficient handling of discontiguous physical memory, + for architectures which are either NUMA (Non-Uniform Memory Access) +@@ -415,7 +428,7 @@ source "mm/Kconfig" + config LEDS + bool "Timer and CPU usage LEDs" + depends on ARCH_CDB89712 || ARCH_CO285 || ARCH_EBSA110 || \ +- ARCH_EBSA285 || ARCH_IMX || ARCH_INTEGRATOR || \ ++ ARCH_EBSA285 || ARCH_EP93XX || ARCH_IMX || ARCH_INTEGRATOR || \ + ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \ + ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \ + ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE +@@ -432,7 +445,7 @@ config LEDS + + config LEDS_TIMER + bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \ +- MACH_OMAP_H2 || MACH_OMAP_PERSEUS2 ++ MACH_OMAP_H2 || MACH_OMAP_PERSEUS2 + depends on LEDS + default y if ARCH_EBSA110 + help +@@ -702,9 +715,10 @@ source "drivers/block/Kconfig" + + source "drivers/acorn/block/Kconfig" + +-if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \ +- || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \ +- || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE ++if PCMCIA || ARCH_CLPS7500 || ARCH_EP9312 || ARCH_EP9315 \ ++ || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X \ ++ || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK \ ++ || FOOTBRIDGE + source "drivers/ide/Kconfig" + endif + +diff --git a/arch/arm/Makefile b/arch/arm/Makefile +index 81bd219..924d31f 100644 +--- a/arch/arm/Makefile ++++ b/arch/arm/Makefile +@@ -92,6 +92,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0x + machine-$(CONFIG_ARCH_IOP3XX) := iop3xx + machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx + machine-$(CONFIG_ARCH_IXP2000) := ixp2000 ++ machine-$(CONFIG_ARCH_EP93XX) := ep93xx + machine-$(CONFIG_ARCH_OMAP1) := omap1 + machine-$(CONFIG_ARCH_OMAP2) := omap2 + incdir-$(CONFIG_ARCH_OMAP) := omap +diff --git a/arch/arm/configs/adssphere_defconfig b/arch/arm/configs/adssphere_defconfig +new file mode 100644 +index 0000000..195d80e +--- /dev/null ++++ b/arch/arm/configs/adssphere_defconfig +@@ -0,0 +1,1240 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.12.2 ++# Wed Jul 6 13:49:08 2005 ++# ++CONFIG_ARM=y ++CONFIG_MMU=y ++CONFIG_UID16=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++CONFIG_GENERIC_IOMAP=y ++ ++# ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_CLEAN_COMPILE=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++ ++# ++# General setup ++# ++CONFIG_LOCALVERSION="" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++CONFIG_SYSCTL=y ++# CONFIG_AUDIT is not set ++CONFIG_HOTPLUG=y ++CONFIG_KOBJECT_UEVENT=y ++# CONFIG_IKCONFIG is not set ++# CONFIG_EMBEDDED is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SHMEM=y ++CONFIG_CC_ALIGN_FUNCTIONS=0 ++CONFIG_CC_ALIGN_LABELS=0 ++CONFIG_CC_ALIGN_LOOPS=0 ++CONFIG_CC_ALIGN_JUMPS=0 ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=0 ++ ++# ++# Loadable module support ++# ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++# CONFIG_MODULE_FORCE_UNLOAD is not set ++CONFIG_OBSOLETE_MODPARM=y ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++# CONFIG_KMOD is not set ++ ++# ++# System Type ++# ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++CONFIG_ARCH_EP93XX=y ++# CONFIG_ARCH_CAMELOT is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_IOP3XX is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_H720X is not set ++ ++# ++# EP93xx ++# ++# CONFIG_ARCH_EP9301 is not set ++# CONFIG_ARCH_EP9302 is not set ++# CONFIG_ARCH_EP9312 is not set ++CONFIG_ARCH_EP9315=y ++# CONFIG_MACH_EDB9315 is not set ++CONFIG_MACH_ADSSPHERE=y ++# CONFIG_MACH_ZEFEERDZQ is not set ++CONFIG_EP93XX_DMA=y ++# CONFIG_ARCH_EP93XX_IDE is not set ++# CONFIG_EP93XX_SSP is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM920T=y ++CONFIG_CPU_32v4=y ++CONFIG_CPU_ABRT_EV4T=y ++CONFIG_CPU_CACHE_V4WT=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_THUMB is not set ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++CONFIG_ISA_DMA_API=y ++ ++# ++# PCCARD (PCMCIA/CardBus) support ++# ++CONFIG_PCCARD=y ++# CONFIG_PCMCIA_DEBUG is not set ++CONFIG_PCMCIA=y ++ ++# ++# PC-card bridges ++# ++# CONFIG_TCIC is not set ++CONFIG_PCMCIA_EP93XX=y ++ ++# ++# Kernel Features ++# ++# CONFIG_SMP is not set ++# CONFIG_PREEMPT is not set ++CONFIG_DISCONTIGMEM=y ++CONFIG_LEDS=y ++CONFIG_LEDS_TIMER=y ++# CONFIG_LEDS_CPU is not set ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Boot options ++# ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="console=ttyAM0,38400 rw root=/dev/ram initrd=0x00600000,5m ramdisk_size=12288 rootfstype=ext2 mtdparts=flash:256k(boot),256k(bootvars),1536k(zImage),5m(ramdisk.gz),-(flashfs1) SERIALGETTY=ttyAM0 SERIALBAUD=38400" ++# CONFIG_XIP_KERNEL is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++# CONFIG_ARTHUR is not set ++ ++# ++# Power management options ++# ++# CONFIG_PM is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++CONFIG_FW_LOADER=y ++# CONFIG_DEBUG_DRIVER 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=y ++# CONFIG_MTD_AFS_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_GEN_PROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++CONFIG_MTD_CFI_GEOMETRY=y ++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=y ++# CONFIG_MTD_CFI_AMDSTD is not set ++# CONFIG_MTD_CFI_STAA is not set ++CONFIG_MTD_CFI_UTIL=y ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++# CONFIG_MTD_XIP is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_PHYSMAP is not set ++CONFIG_MTD_ADSFLASH=y ++# CONFIG_MTD_ARM_INTEGRATOR is not set ++# CONFIG_MTD_EDB7312 is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLKMTD 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 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=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=4096 ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++# CONFIG_CDROM_PKTCDVD is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_ATA_OVER_ETH is not set ++ ++# ++# ATA/ATAPI/MFM/RLL support ++# ++CONFIG_IDE=y ++CONFIG_BLK_DEV_IDE=y ++ ++# ++# Please see Documentation/ide.txt for help/info on IDE drives ++# ++# CONFIG_BLK_DEV_IDE_SATA is not set ++CONFIG_BLK_DEV_IDEDISK=y ++# CONFIG_IDEDISK_MULTI_MODE is not set ++CONFIG_BLK_DEV_IDECS=y ++# CONFIG_BLK_DEV_IDECD is not set ++# CONFIG_BLK_DEV_IDETAPE is not set ++# CONFIG_BLK_DEV_IDEFLOPPY is not set ++# CONFIG_BLK_DEV_IDESCSI is not set ++# CONFIG_IDE_TASK_IOCTL is not set ++ ++# ++# IDE chipset support/bugfixes ++# ++CONFIG_IDE_GENERIC=y ++CONFIG_BLK_DEV_EP93XX=y ++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set ++CONFIG_IDE_ARM=y ++# CONFIG_BLK_DEV_IDEDMA is not set ++# CONFIG_IDEDMA_AUTO is not set ++# CONFIG_BLK_DEV_HD is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI=y ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++CONFIG_CHR_DEV_SG=y ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++ ++# ++# SCSI Transport Attributes ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++ ++# ++# SCSI low-level drivers ++# ++# CONFIG_SCSI_SATA is not set ++# CONFIG_SCSI_DEBUG is not set ++ ++# ++# PCMCIA SCSI adapter support ++# ++# CONFIG_PCMCIA_AHA152X is not set ++# CONFIG_PCMCIA_FDOMAIN is not set ++# CONFIG_PCMCIA_NINJA_SCSI is not set ++# CONFIG_PCMCIA_QLOGIC is not set ++# CONFIG_PCMCIA_SYM53C500 is not set ++ ++# ++# Multi-device support (RAID and LVM) ++# ++# CONFIG_MD is not set ++ ++# ++# Fusion MPT device support ++# ++ ++# ++# IEEE 1394 (FireWire) support ++# ++ ++# ++# I2O device support ++# ++ ++# ++# Networking support ++# ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_PACKET_MMAP=y ++CONFIG_UNIX=y ++# CONFIG_NET_KEY is not set ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# CONFIG_IP_PNP_RARP is not set ++# CONFIG_NET_IPIP is not set ++# CONFIG_NET_IPGRE is not set ++CONFIG_IP_MROUTE=y ++# CONFIG_IP_PIMSM_V1 is not set ++# CONFIG_IP_PIMSM_V2 is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_TUNNEL is not set ++CONFIG_IP_TCPDIAG=y ++# CONFIG_IP_TCPDIAG_IPV6 is not set ++# CONFIG_IPV6 is not set ++# CONFIG_NETFILTER is not set ++ ++# ++# SCTP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_SCTP 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_NET_DIVERT 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 ++# CONFIG_NET_CLS_ROUTE is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_IRDA is not set ++CONFIG_BT=y ++CONFIG_BT_L2CAP=y ++# CONFIG_BT_SCO is not set ++# CONFIG_BT_RFCOMM is not set ++CONFIG_BT_BNEP=y ++# CONFIG_BT_BNEP_MC_FILTER is not set ++# CONFIG_BT_BNEP_PROTO_FILTER is not set ++# CONFIG_BT_HIDP is not set ++ ++# ++# Bluetooth device drivers ++# ++CONFIG_BT_HCIUSB=y ++# CONFIG_BT_HCIUSB_SCO is not set ++# CONFIG_BT_HCIUART is not set ++# CONFIG_BT_HCIBCM203X is not set ++# CONFIG_BT_HCIBPA10X is not set ++# CONFIG_BT_HCIBFUSB is not set ++# CONFIG_BT_HCIDTL1 is not set ++# CONFIG_BT_HCIBT3C is not set ++# CONFIG_BT_HCIBLUECARD is not set ++# CONFIG_BT_HCIBTUART is not set ++# CONFIG_BT_HCIVHCI is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_TUN is not set ++ ++# ++# Ethernet (10 or 100Mbit) ++# ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=y ++CONFIG_EP93XX_ETHERNET=y ++# CONFIG_SMC91X is not set ++ ++# ++# Ethernet (1000 Mbit) ++# ++ ++# ++# Ethernet (10000 Mbit) ++# ++ ++# ++# Token Ring devices ++# ++ ++# ++# Wireless LAN (non-hamradio) ++# ++CONFIG_NET_RADIO=y ++ ++# ++# Obsolete Wireless cards support (pre-802.11) ++# ++# CONFIG_STRIP is not set ++# CONFIG_PCMCIA_WAVELAN is not set ++# CONFIG_PCMCIA_NETWAVE is not set ++ ++# ++# Wireless 802.11 Frequency Hopping cards support ++# ++# CONFIG_PCMCIA_RAYCS is not set ++ ++# ++# Wireless 802.11b ISA/PCI cards support ++# ++CONFIG_HERMES=y ++CONFIG_ATMEL=y ++ ++# ++# Wireless 802.11b Pcmcia/Cardbus cards support ++# ++CONFIG_PCMCIA_HERMES=y ++CONFIG_AIRO_CS=y ++CONFIG_PCMCIA_ATMEL=y ++CONFIG_PCMCIA_WL3501=y ++CONFIG_NET_WIRELESS=y ++ ++# ++# PCMCIA network device support ++# ++CONFIG_NET_PCMCIA=y ++# CONFIG_PCMCIA_3C589 is not set ++# CONFIG_PCMCIA_3C574 is not set ++# CONFIG_PCMCIA_FMVJ18X is not set ++CONFIG_PCMCIA_PCNET=y ++# CONFIG_PCMCIA_NMCLAN is not set ++# CONFIG_PCMCIA_SMC91C92 is not set ++# CONFIG_PCMCIA_XIRC2PS is not set ++# CONFIG_PCMCIA_AXNET 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 ++ ++# ++# ISDN subsystem ++# ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 ++# CONFIG_INPUT_JOYDEV is not set ++CONFIG_INPUT_TSDEV=y ++CONFIG_INPUT_TSDEV_SCREEN_X=640 ++CONFIG_INPUT_TSDEV_SCREEN_Y=480 ++CONFIG_INPUT_EVDEV=y ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++# CONFIG_KEYBOARD_EP93XX is not set ++CONFIG_INPUT_MOUSE=y ++# CONFIG_MOUSE_PS2 is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_INPUT_JOYSTICK is not set ++CONFIG_INPUT_TOUCHSCREEN=y ++# CONFIG_TOUCHSCREEN_GUNZE is not set ++# CONFIG_TOUCHSCREEN_ELO is not set ++# CONFIG_TOUCHSCREEN_MTOUCH is not set ++# CONFIG_TOUCHSCREEN_MK712 is not set ++CONFIG_TOUCHSCREEN_EP93XX=y ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++# CONFIG_SERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++CONFIG_SERIAL_EP93XX=y ++CONFIG_SERIAL_EP93XX_CONSOLE=y ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++ ++# ++# IPMI ++# ++# CONFIG_IPMI_HANDLER is not set ++ ++# ++# Watchdog Cards ++# ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++CONFIG_EP93XX_WATCHDOG=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++# CONFIG_NVRAM is not set ++# CONFIG_RTC is not set ++# CONFIG_EP93XX_RTC is not set ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++ ++# ++# Ftape, the floppy tape device driver ++# ++# CONFIG_DRM is not set ++ ++# ++# PCMCIA character devices ++# ++# CONFIG_SYNCLINK_CS is not set ++# CONFIG_RAW_DRIVER is not set ++ ++# ++# TPM devices ++# ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++# ++# I2C Algorithms ++# ++CONFIG_I2C_ALGOBIT=y ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++CONFIG_I2C_EP93XX=y ++# CONFIG_I2C_ISA is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_STUB is not set ++# CONFIG_I2C_PCA_ISA is not set ++ ++# ++# Hardware Sensors Chip support ++# ++CONFIG_I2C_SENSOR=y ++# 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_ASB100 is not set ++# CONFIG_SENSORS_DS1621 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_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_SMSC47B397 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++ ++# ++# Other I2C Chip support ++# ++# CONFIG_SENSORS_DS1337 is not set ++CONFIG_SENSORS_DS1307=y ++CONFIG_SENSORS_EEPROM=y ++# CONFIG_SENSORS_PCF8574 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_RTC8564 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 ++ ++# ++# Misc devices ++# ++ ++# ++# Multimedia devices ++# ++CONFIG_VIDEO_DEV=y ++ ++# ++# Video For Linux ++# ++ ++# ++# Video Adapters ++# ++# CONFIG_VIDEO_CPIA is not set ++# CONFIG_VIDEO_SAA5246A is not set ++# CONFIG_VIDEO_SAA5249 is not set ++# CONFIG_TUNER_3036 is not set ++# CONFIG_VIDEO_OVCAMCHIP is not set ++ ++# ++# Radio Adapters ++# ++# CONFIG_RADIO_MAESTRO is not set ++ ++# ++# Digital Video Broadcasting Devices ++# ++# CONFIG_DVB is not set ++ ++# ++# Graphics support ++# ++CONFIG_FB=y ++CONFIG_FB_CFB_FILLRECT=y ++CONFIG_FB_CFB_COPYAREA=y ++CONFIG_FB_CFB_IMAGEBLIT=y ++CONFIG_FB_SOFT_CURSOR=y ++# CONFIG_FB_MACMODES is not set ++CONFIG_FB_MODE_HELPERS=y ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CX25871_I2C is not set ++CONFIG_FB_EP93XX=y ++# CONFIG_FB_CRT_EP93XX is not set ++# CONFIG_FB_LCD_EP93XX is not set ++# CONFIG_FB_LCD_EP93XX_SHARP is not set ++CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343=y ++# CONFIG_FB_CX25871 is not set ++# CONFIG_FB_EP93XX_8BPP is not set ++CONFIG_FB_EP93XX_16BPP_565=y ++# CONFIG_FB_EP93XX_24BPP is not set ++# CONFIG_FB_EP93XX_32BPP is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_FONTS=y ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++# CONFIG_FONT_6x11 is not set ++# CONFIG_FONT_PEARL_8x8 is not set ++# CONFIG_FONT_ACORN_8x8 is not set ++# CONFIG_FONT_MINI_4x6 is not set ++# CONFIG_FONT_SUN8x16 is not set ++# CONFIG_FONT_SUN12x22 is not set ++ ++# ++# Logo configuration ++# ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_LOGO_LINUX_CLUT224=y ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Sound ++# ++CONFIG_SOUND=y ++ ++# ++# Advanced Linux Sound Architecture ++# ++# CONFIG_SND is not set ++ ++# ++# Open Sound System ++# ++CONFIG_SOUND_PRIME=y ++# CONFIG_SOUND_BT878 is not set ++# CONFIG_SOUND_FUSION is not set ++# CONFIG_SOUND_CS4281 is not set ++# CONFIG_SOUND_SONICVIBES is not set ++# CONFIG_SOUND_TRIDENT is not set ++# CONFIG_SOUND_MSNDCLAS is not set ++# CONFIG_SOUND_MSNDPIN is not set ++CONFIG_SOUND_OSS=y ++# CONFIG_SOUND_TRACEINIT is not set ++# CONFIG_SOUND_DMAP is not set ++# CONFIG_SOUND_AD1816 is not set ++# CONFIG_SOUND_SGALAXY is not set ++# CONFIG_SOUND_ADLIB is not set ++# CONFIG_SOUND_ACI_MIXER is not set ++# CONFIG_SOUND_CS4232 is not set ++# CONFIG_SOUND_SSCAPE is not set ++# CONFIG_SOUND_GUS is not set ++# CONFIG_SOUND_VMIDI is not set ++# CONFIG_SOUND_TRIX is not set ++# CONFIG_SOUND_MSS is not set ++# CONFIG_SOUND_MPU401 is not set ++# CONFIG_SOUND_NM256 is not set ++# CONFIG_SOUND_MAD16 is not set ++# CONFIG_SOUND_PAS is not set ++# CONFIG_SOUND_PSS is not set ++# CONFIG_SOUND_SB is not set ++# CONFIG_SOUND_AWE32_SYNTH is not set ++# CONFIG_SOUND_WAVEFRONT is not set ++# CONFIG_SOUND_MAUI is not set ++# CONFIG_SOUND_YM3812 is not set ++# CONFIG_SOUND_OPL3SA1 is not set ++# CONFIG_SOUND_OPL3SA2 is not set ++# CONFIG_SOUND_UART6850 is not set ++# CONFIG_SOUND_AEDSP16 is not set ++CONFIG_SOUND_EP93XX_AC97=y ++# CONFIG_SOUND_TVMIXER is not set ++# CONFIG_SOUND_AD1980 is not set ++ ++# ++# USB support ++# ++CONFIG_USB_ARCH_HAS_HCD=y ++# CONFIG_USB_ARCH_HAS_OHCI is not set ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEVICEFS is not set ++# CONFIG_USB_BANDWIDTH is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_SL811_HCD is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_AUDIO is not set ++ ++# ++# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem ++# ++# CONFIG_USB_MIDI is not set ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++ ++# ++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++ ++# ++# USB Input Devices ++# ++CONFIG_USB_HID=y ++CONFIG_USB_HIDINPUT=y ++# CONFIG_HID_FF is not set ++# CONFIG_USB_HIDDEV is not set ++# CONFIG_USB_AIPTEK is not set ++# CONFIG_USB_WACOM is not set ++# CONFIG_USB_KBTAB is not set ++# CONFIG_USB_POWERMATE is not set ++# CONFIG_USB_MTOUCH is not set ++# CONFIG_USB_EGALAX is not set ++# CONFIG_USB_XPAD is not set ++# CONFIG_USB_ATI_REMOTE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB Multimedia devices ++# ++# CONFIG_USB_DABUSB is not set ++# CONFIG_USB_VICAM is not set ++# CONFIG_USB_DSBR is not set ++# CONFIG_USB_IBMCAM is not set ++# CONFIG_USB_KONICAWC is not set ++CONFIG_USB_OV511=y ++# CONFIG_USB_SE401 is not set ++# CONFIG_USB_SN9C102 is not set ++# CONFIG_USB_STV680 is not set ++# CONFIG_USB_PWC is not set ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++CONFIG_USB_PEGASUS=y ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_USB_ZD1201 is not set ++CONFIG_USB_MON=y ++ ++# ++# USB port drivers ++# ++ ++# ++# USB Serial Converter support ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_AUERSWALD is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGETKIT is not set ++# CONFIG_USB_PHIDGETSERVO is not set ++# CONFIG_USB_IDMOUSE is not set ++ ++# ++# USB ATM/DSL drivers ++# ++ ++# ++# USB Gadget Support ++# ++# CONFIG_USB_GADGET is not set ++ ++# ++# MMC/SD Card support ++# ++# CONFIG_MMC is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_XATTR=y ++# CONFIG_EXT3_FS_POSIX_ACL is not set ++# CONFIG_EXT3_FS_SECURITY is not set ++CONFIG_JBD=y ++# CONFIG_JBD_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++ ++# ++# XFS support ++# ++# CONFIG_XFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_QUOTA is not set ++CONFIG_DNOTIFY=y ++# CONFIG_AUTOFS_FS is not set ++# CONFIG_AUTOFS4_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_FAT_FS=y ++# CONFIG_MSDOS_FS is not set ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_SYSFS=y ++# CONFIG_DEVFS_FS is not set ++CONFIG_DEVPTS_FS_XATTR=y ++# CONFIG_DEVPTS_FS_SECURITY is not set ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_XATTR is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_RAMFS=y ++ ++# ++# 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_JFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++# CONFIG_JFFS2_FS_NAND is not set ++# CONFIG_JFFS2_FS_NOR_ECC 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=y ++# 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=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_DIRECTIO is not set ++# CONFIG_NFSD is not set ++CONFIG_ROOT_NFS=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS 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 ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++ ++# ++# Native Language Support ++# ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++CONFIG_NLS_CODEPAGE_850=y ++# 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=y ++# 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=y ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=y ++ ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_DEBUG_KERNEL=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_LOG_BUF_SHIFT=14 ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_DEBUG_FS is not set ++CONFIG_FRAME_POINTER=y ++CONFIG_DEBUG_USER=y ++# CONFIG_DEBUG_WAITQ is not set ++CONFIG_DEBUG_ERRORS=y ++# CONFIG_DEBUG_LL is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set ++ ++# ++# Cryptographic options ++# ++# CONFIG_CRYPTO is not set ++ ++# ++# Hardware crypto devices ++# ++ ++# ++# Library routines ++# ++# CONFIG_CRC_CCITT is not set ++CONFIG_CRC32=y ++# CONFIG_LIBCRC32C is not set ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y +diff --git a/arch/arm/configs/dma03_defconfig b/arch/arm/configs/dma03_defconfig +new file mode 100644 +index 0000000..59b677c +--- /dev/null ++++ b/arch/arm/configs/dma03_defconfig +@@ -0,0 +1,1281 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.15-rc4 ++# Fri Dec 9 21:21:27 2005 ++# ++CONFIG_ARM=y ++CONFIG_MMU=y ++CONFIG_UID16=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++ ++# ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++# CONFIG_CLEAN_COMPILE is not set ++CONFIG_BROKEN=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++ ++# ++# General setup ++# ++CONFIG_LOCALVERSION="" ++CONFIG_LOCALVERSION_AUTO=y ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++CONFIG_SYSCTL=y ++# CONFIG_AUDIT is not set ++CONFIG_HOTPLUG=y ++CONFIG_KOBJECT_UEVENT=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_INITRAMFS_SOURCE="" ++# CONFIG_EMBEDDED is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SHMEM=y ++CONFIG_CC_ALIGN_FUNCTIONS=0 ++CONFIG_CC_ALIGN_LABELS=0 ++CONFIG_CC_ALIGN_LOOPS=0 ++CONFIG_CC_ALIGN_JUMPS=0 ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=0 ++ ++# ++# Loadable module support ++# ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_OBSOLETE_MODPARM=y ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_KMOD=y ++ ++# ++# Block layer ++# ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++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" ++ ++# ++# System Type ++# ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++CONFIG_ARCH_EP93XX=y ++# CONFIG_ARCH_CAMELOT is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_IOP3XX is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_REALVIEW is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_AAEC2000 is not set ++ ++# ++# EP93xx ++# ++# CONFIG_ARCH_EP9301 is not set ++# CONFIG_ARCH_EP9302 is not set ++# CONFIG_ARCH_EP9312 is not set ++CONFIG_ARCH_EP9315=y ++# CONFIG_MACH_EDB9315 is not set ++# CONFIG_MACH_ADSSPHERE is not set ++# CONFIG_MACH_ZEFEERDZQ is not set ++CONFIG_MACH_DMA03=y ++CONFIG_ARCH_EP93XX_GPIO_IRQ=y ++CONFIG_EP93XX_DMA=y ++CONFIG_EP93XX_SSP=y ++CONFIG_EP93XX_SSP_CIRRUS=y ++# CONFIG_EP93XX_SSP_LINUX is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM920T=y ++CONFIG_CPU_32v4=y ++CONFIG_CPU_ABRT_EV4T=y ++CONFIG_CPU_CACHE_V4WT=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_THUMB is not set ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++CONFIG_ISA_DMA_API=y ++ ++# ++# PCCARD (PCMCIA/CardBus) support ++# ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++# CONFIG_PREEMPT is not set ++# CONFIG_NO_IDLE_HZ is not set ++CONFIG_ARCH_DISCONTIGMEM_ENABLE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++# CONFIG_FLATMEM_MANUAL is not set ++CONFIG_DISCONTIGMEM_MANUAL=y ++# CONFIG_SPARSEMEM_MANUAL is not set ++CONFIG_DISCONTIGMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_NEED_MULTIPLE_NODES=y ++# CONFIG_SPARSEMEM_STATIC is not set ++CONFIG_SPLIT_PTLOCK_CPUS=4096 ++CONFIG_LEDS=y ++CONFIG_LEDS_TIMER=y ++CONFIG_LEDS_CPU=y ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Boot options ++# ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="root=/dev/hda1 slram=sram,0x20000000,0x2010000 parport=0xD0000020,74 lp=parport0" ++# CONFIG_XIP_KERNEL is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_BINFMT_AOUT=y ++CONFIG_BINFMT_MISC=y ++# CONFIG_ARTHUR is not set ++ ++# ++# Power management options ++# ++# CONFIG_PM is not set ++ ++# ++# Networking ++# ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_PACKET_MMAP=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++CONFIG_NET_KEY=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_FIB_HASH=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++# 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_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_TUNNEL is not set ++CONFIG_INET_DIAG=y ++CONFIG_INET_TCP_DIAG=y ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_BIC=y ++# CONFIG_IPV6 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 ++# 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_NET_DIVERT 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 is not set ++# CONFIG_BT is not set ++# CONFIG_IEEE80211 is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_STANDALONE is not set ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++# CONFIG_FW_LOADER is not set ++# CONFIG_DEBUG_DRIVER 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=y ++CONFIG_MTD_PARTITIONS=y ++CONFIG_MTD_REDBOOT_PARTS=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=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 ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_GEN_PROBE=y ++# 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=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_AMDSTD_RETRY=0 ++CONFIG_MTD_CFI_STAA=y ++CONFIG_MTD_CFI_UTIL=y ++CONFIG_MTD_RAM=y ++CONFIG_MTD_ROM=y ++CONFIG_MTD_ABSENT=y ++# CONFIG_MTD_OBSOLETE_CHIPS is not set ++# CONFIG_MTD_XIP is not set ++ ++# ++# Mapping drivers for chip access ++# ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x60000000 ++CONFIG_MTD_PHYSMAP_LEN=0x02000000 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=4 ++# CONFIG_MTD_ARM_INTEGRATOR is not set ++# CONFIG_MTD_IMPA7 is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++CONFIG_MTD_SLRAM=y ++CONFIG_MTD_PHRAM=y ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLKMTD 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=y ++CONFIG_MTD_NAND_VERIFY_WRITE=y ++CONFIG_MTD_NAND_IDS=y ++# 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=y ++CONFIG_PARPORT_PC=y ++# CONFIG_PARPORT_PC_FIFO is not set ++# CONFIG_PARPORT_PC_SUPERIO is not set ++# CONFIG_PARPORT_ARC is not set ++# CONFIG_PARPORT_GSC is not set ++CONFIG_PARPORT_1284=y ++ ++# ++# Plug and Play support ++# ++ ++# ++# Block devices ++# ++# CONFIG_PARIDE is not set ++# CONFIG_BLK_DEV_COW_COMMON is not set ++CONFIG_BLK_DEV_LOOP=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=12288 ++CONFIG_BLK_DEV_INITRD=y ++# CONFIG_CDROM_PKTCDVD is not set ++# CONFIG_ATA_OVER_ETH is not set ++ ++# ++# ATA/ATAPI/MFM/RLL support ++# ++CONFIG_IDE=y ++CONFIG_BLK_DEV_IDE=y ++ ++# ++# Please see Documentation/ide.txt for help/info on IDE drives ++# ++# CONFIG_BLK_DEV_IDE_SATA is not set ++CONFIG_BLK_DEV_IDEDISK=y ++CONFIG_IDEDISK_MULTI_MODE=y ++CONFIG_BLK_DEV_IDECD=y ++# CONFIG_BLK_DEV_IDETAPE is not set ++# CONFIG_BLK_DEV_IDEFLOPPY is not set ++# CONFIG_BLK_DEV_IDESCSI is not set ++# CONFIG_IDE_TASK_IOCTL is not set ++ ++# ++# IDE chipset support/bugfixes ++# ++CONFIG_IDE_GENERIC=y ++CONFIG_BLK_DEV_EP93XX=y ++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set ++CONFIG_IDE_ARM=y ++# CONFIG_BLK_DEV_IDEDMA is not set ++# CONFIG_IDEDMA_AUTO is not set ++# CONFIG_BLK_DEV_HD is not set ++ ++# ++# SCSI device support ++# ++# CONFIG_RAID_ATTRS is not set ++CONFIG_SCSI=y ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++ ++# ++# SCSI Transport Attributes ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++# CONFIG_SCSI_SAS_ATTRS is not set ++ ++# ++# SCSI low-level drivers ++# ++# CONFIG_ISCSI_TCP is not set ++# CONFIG_SCSI_SATA is not set ++# CONFIG_SCSI_PPA is not set ++# CONFIG_SCSI_IMM is not set ++# CONFIG_SCSI_DEBUG 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 ++# ++# CONFIG_IEEE1394 is not set ++ ++# ++# 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_EP93XX_ETHERNET=y ++# CONFIG_SMC91X is not set ++# CONFIG_DM9000 is not set ++# CONFIG_NET_POCKET 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_PLIP is not set ++# CONFIG_PPP is not set ++# CONFIG_SLIP is not set ++# CONFIG_SHAPER is not set ++CONFIG_NETCONSOLE=y ++CONFIG_NETPOLL=y ++# CONFIG_NETPOLL_RX is not set ++# CONFIG_NETPOLL_TRAP is not set ++CONFIG_NET_POLL_CONTROLLER=y ++ ++# ++# ISDN subsystem ++# ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_TSDEV is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++CONFIG_KEYBOARD_EP93XX=y ++CONFIG_KEYBOARD_EP93XX_SPI=y ++CONFIG_KEYBOARD_EP93XX_8X8=y ++CONFIG_KEYBOARD_EP93XX_8X8_CYCLING=y ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_SERIAL=y ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_INPUT_JOYSTICK is not set ++CONFIG_INPUT_TOUCHSCREEN=y ++# CONFIG_TOUCHSCREEN_GUNZE is not set ++# CONFIG_TOUCHSCREEN_ELO is not set ++# CONFIG_TOUCHSCREEN_MTOUCH is not set ++# CONFIG_TOUCHSCREEN_MK712 is not set ++CONFIG_TOUCHSCREEN_EP93XX=y ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_PARKBD is not set ++# CONFIG_SERIO_AMBAKMI is not set ++CONFIG_SERIO_LIBPS2=y ++# CONFIG_SERIO_RAW is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++# ++# Serial drivers ++# ++CONFIG_SERIAL_8250=y ++CONFIG_SERIAL_8250_CONSOLE=y ++CONFIG_SERIAL_8250_NR_UARTS=4 ++# CONFIG_SERIAL_8250_EXTENDED is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++CONFIG_SERIAL_EP93XX=y ++CONFIG_SERIAL_EP93XX_CONSOLE=y ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++CONFIG_PRINTER=m ++# CONFIG_LP_CONSOLE is not set ++CONFIG_PPDEV=m ++# CONFIG_TIPAR is not set ++ ++# ++# IPMI ++# ++# CONFIG_IPMI_HANDLER is not set ++ ++# ++# Watchdog Cards ++# ++# CONFIG_WATCHDOG is not set ++# CONFIG_NVRAM is not set ++# CONFIG_RTC is not set ++# CONFIG_EP93XX_RTC is not set ++CONFIG_DS1337_RTC=y ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++ ++# ++# Ftape, the floppy tape device driver ++# ++ ++# ++# CAN bus devices ++# ++CONFIG_CAN_BUS=y ++CONFIG_OKI_CAN_ML9620=y ++# CONFIG_OKI_CAN_ML9620_MICRO9 is not set ++CONFIG_OKI_CAN_ML9620_GASSNER=y ++CONFIG_OKI_CAN_ML9620_2DEV=y ++# CONFIG_RAW_DRIVER is not set ++ ++# ++# TPM devices ++# ++# CONFIG_TCG_TPM is not set ++# CONFIG_TELCLOCK is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++# ++# I2C Algorithms ++# ++CONFIG_I2C_ALGOBIT=y ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++CONFIG_I2C_EP93XX=y ++# CONFIG_I2C_PARPORT 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=y ++# CONFIG_SENSORS_DS1374 is not set ++# CONFIG_SENSORS_DS1307 is not set ++# CONFIG_SENSORS_EEPROM is not set ++# CONFIG_SENSORS_PCF8574 is not set ++# CONFIG_SENSORS_PCA9539 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_RTC8564 is not set ++# CONFIG_SENSORS_MAX6875 is not set ++# CONFIG_RTC_X1205_I2C 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 ++ ++# ++# Hardware Monitoring support ++# ++CONFIG_HWMON=y ++# CONFIG_HWMON_VID 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_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_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_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83792D 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 ++ ++# ++# Misc devices ++# ++ ++# ++# Multimedia Capabilities Port drivers ++# ++ ++# ++# Multimedia devices ++# ++# CONFIG_VIDEO_DEV is not set ++ ++# ++# Digital Video Broadcasting Devices ++# ++# CONFIG_DVB is not set ++ ++# ++# Graphics support ++# ++CONFIG_FB=y ++CONFIG_FB_CFB_FILLRECT=y ++CONFIG_FB_CFB_COPYAREA=y ++CONFIG_FB_CFB_IMAGEBLIT=y ++# CONFIG_FB_MACMODES is not set ++CONFIG_FB_MODE_HELPERS=y ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CX25871_I2C is not set ++CONFIG_FB_EP93XX=y ++# CONFIG_FB_CRT_EP93XX is not set ++# CONFIG_FB_LCD_EP93XX is not set ++CONFIG_FB_LCD_EP93XX_SHARP=y ++# CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343 is not set ++# CONFIG_FB_CX25871 is not set ++# CONFIG_FB_LCD_TX09D50VM1CCA is not set ++# CONFIG_FB_EP93XX_8BPP is not set ++# CONFIG_FB_EP93XX_16BPP_565 is not set ++# CONFIG_FB_EP93XX_24BPP is not set ++CONFIG_FB_EP93XX_32BPP=y ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set ++CONFIG_FONTS=y ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++CONFIG_FONT_6x11=y ++CONFIG_FONT_7x14=y ++CONFIG_FONT_PEARL_8x8=y ++CONFIG_FONT_ACORN_8x8=y ++CONFIG_FONT_MINI_4x6=y ++CONFIG_FONT_SUN8x16=y ++CONFIG_FONT_SUN12x22=y ++CONFIG_FONT_10x18=y ++ ++# ++# Logo configuration ++# ++# CONFIG_LOGO is not set ++CONFIG_BACKLIGHT_LCD_SUPPORT=y ++CONFIG_BACKLIGHT_CLASS_DEVICE=y ++CONFIG_BACKLIGHT_DEVICE=y ++CONFIG_LCD_CLASS_DEVICE=y ++CONFIG_LCD_DEVICE=y ++ ++# ++# Sound ++# ++CONFIG_SOUND=m ++ ++# ++# Advanced Linux Sound Architecture ++# ++# CONFIG_SND is not set ++ ++# ++# Open Sound System ++# ++CONFIG_SOUND_PRIME=m ++# CONFIG_OBSOLETE_OSS_DRIVER is not set ++# CONFIG_SOUND_MSNDCLAS is not set ++# CONFIG_SOUND_MSNDPIN is not set ++CONFIG_SOUND_OSS=m ++# CONFIG_SOUND_TRACEINIT is not set ++# CONFIG_SOUND_DMAP is not set ++# CONFIG_SOUND_AD1816 is not set ++# CONFIG_SOUND_ADLIB is not set ++# CONFIG_SOUND_ACI_MIXER is not set ++# CONFIG_SOUND_VMIDI is not set ++# CONFIG_SOUND_TRIX is not set ++# CONFIG_SOUND_MSS is not set ++# CONFIG_SOUND_MPU401 is not set ++# CONFIG_SOUND_PAS is not set ++# CONFIG_SOUND_PSS is not set ++# CONFIG_SOUND_SB is not set ++# CONFIG_SOUND_OPL3SA2 is not set ++# CONFIG_SOUND_UART6850 is not set ++# CONFIG_SOUND_AEDSP16 is not set ++CONFIG_SOUND_EP93XX_AC97=m ++CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297=y ++# CONFIG_SOUND_EP93XX_AUDIO_PIO is not set ++# CONFIG_SOUND_TVMIXER is not set ++ ++# ++# USB support ++# ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++# CONFIG_USB_BANDWIDTH is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_ISP116X_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++# CONFIG_USB_OHCI_BIG_ENDIAN is not set ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++# CONFIG_USB_SL811_HCD is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set ++# CONFIG_USB_ACM is not set ++CONFIG_USB_PRINTER=y ++ ++# ++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' ++# ++ ++# ++# may also be needed; see USB_STORAGE Help for more information ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++CONFIG_USB_STORAGE_DATAFAB=y ++CONFIG_USB_STORAGE_FREECOM=y ++CONFIG_USB_STORAGE_ISD200=y ++CONFIG_USB_STORAGE_DPCM=y ++CONFIG_USB_STORAGE_USBAT=y ++CONFIG_USB_STORAGE_SDDR09=y ++CONFIG_USB_STORAGE_SDDR55=y ++CONFIG_USB_STORAGE_JUMPSHOT=y ++ ++# ++# USB Input Devices ++# ++CONFIG_USB_HID=y ++CONFIG_USB_HIDINPUT=y ++# CONFIG_HID_FF is not set ++# CONFIG_USB_HIDDEV is not set ++# CONFIG_USB_AIPTEK is not set ++# CONFIG_USB_WACOM is not set ++# CONFIG_USB_ACECAD is not set ++# CONFIG_USB_KBTAB is not set ++# CONFIG_USB_POWERMATE is not set ++# CONFIG_USB_MTOUCH is not set ++# CONFIG_USB_ITMTOUCH is not set ++# CONFIG_USB_EGALAX is not set ++# CONFIG_USB_YEALINK is not set ++# CONFIG_USB_XPAD is not set ++# CONFIG_USB_ATI_REMOTE is not set ++# CONFIG_USB_KEYSPAN_REMOTE is not set ++# CONFIG_USB_APPLETOUCH is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB Multimedia devices ++# ++# CONFIG_USB_DABUSB is not set ++ ++# ++# Video4Linux support is needed for USB Multimedia device support ++# ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++CONFIG_USB_MON=y ++ ++# ++# USB port drivers ++# ++# CONFIG_USB_USS720 is not set ++ ++# ++# USB Serial Converter support ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_AUERSWALD is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGETKIT is not set ++# CONFIG_USB_PHIDGETSERVO is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TEST is not set ++ ++# ++# USB DSL modem support ++# ++ ++# ++# USB Gadget Support ++# ++# CONFIG_USB_GADGET is not set ++ ++# ++# MMC/SD Card support ++# ++# CONFIG_MMC is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_XATTR=y ++# CONFIG_EXT3_FS_POSIX_ACL is not set ++# CONFIG_EXT3_FS_SECURITY is not set ++CONFIG_JBD=y ++# CONFIG_JBD_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=y ++# CONFIG_REISERFS_CHECK is not set ++# CONFIG_REISERFS_PROC_INFO is not set ++# CONFIG_REISERFS_FS_XATTR is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_FS_POSIX_ACL is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_MINIX_FS is not set ++CONFIG_ROMFS_FS=y ++CONFIG_INOTIFY=y ++# CONFIG_QUOTA is not set ++CONFIG_DNOTIFY=y ++CONFIG_AUTOFS_FS=y ++# CONFIG_AUTOFS4_FS is not set ++CONFIG_FUSE_FS=y ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_ZISOFS_FS=y ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=850 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++CONFIG_NTFS_FS=y ++# CONFIG_NTFS_DEBUG is not set ++# CONFIG_NTFS_RW is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_SYSFS=y ++CONFIG_TMPFS=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_RAMFS=y ++CONFIG_RELAYFS_FS=y ++ ++# ++# 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_JFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# CONFIG_JFFS2_SUMMARY is not set ++CONFIG_JFFS2_COMPRESSION_OPTIONS=y ++CONFIG_JFFS2_ZLIB=y ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_JFFS2_CMODE_NONE is not set ++CONFIG_JFFS2_CMODE_PRIORITY=y ++# CONFIG_JFFS2_CMODE_SIZE 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=y ++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_ROOT_NFS=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS 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=y ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++ ++# ++# Native Language Support ++# ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++CONFIG_NLS_CODEPAGE_850=y ++# 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=y ++CONFIG_NLS_ISO8859_1=y ++# 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=y ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=y ++ ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_DEBUG_KERNEL=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_LOG_BUF_SHIFT=17 ++# CONFIG_DETECT_SOFTLOCKUP is not set ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_DEBUG_FS is not set ++# CONFIG_DEBUG_VM is not set ++CONFIG_FRAME_POINTER=y ++# CONFIG_RCU_TORTURE_TEST is not set ++CONFIG_DEBUG_USER=y ++# CONFIG_DEBUG_WAITQ is not set ++CONFIG_DEBUG_ERRORS=y ++CONFIG_DEBUG_LL=y ++# CONFIG_DEBUG_ICEDCC is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set ++ ++# ++# Cryptographic options ++# ++CONFIG_CRYPTO=y ++CONFIG_CRYPTO_HMAC=y ++CONFIG_CRYPTO_NULL=y ++CONFIG_CRYPTO_MD4=y ++CONFIG_CRYPTO_MD5=y ++CONFIG_CRYPTO_SHA1=y ++CONFIG_CRYPTO_SHA256=y ++CONFIG_CRYPTO_SHA512=y ++CONFIG_CRYPTO_WP512=y ++CONFIG_CRYPTO_TGR192=y ++CONFIG_CRYPTO_DES=y ++CONFIG_CRYPTO_BLOWFISH=y ++CONFIG_CRYPTO_TWOFISH=y ++CONFIG_CRYPTO_SERPENT=y ++CONFIG_CRYPTO_AES=y ++CONFIG_CRYPTO_CAST5=y ++CONFIG_CRYPTO_CAST6=y ++CONFIG_CRYPTO_TEA=y ++CONFIG_CRYPTO_ARC4=y ++CONFIG_CRYPTO_KHAZAD=y ++CONFIG_CRYPTO_ANUBIS=y ++CONFIG_CRYPTO_DEFLATE=y ++CONFIG_CRYPTO_MICHAEL_MIC=y ++CONFIG_CRYPTO_CRC32C=y ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Hardware crypto devices ++# ++ ++# ++# Library routines ++# ++CONFIG_CRC_CCITT=y ++CONFIG_CRC16=y ++CONFIG_CRC32=y ++CONFIG_LIBCRC32C=y ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y +diff --git a/arch/arm/configs/edb9301_defconfig b/arch/arm/configs/edb9301_defconfig +new file mode 100644 +index 0000000..e105976 +--- /dev/null ++++ b/arch/arm/configs/edb9301_defconfig +@@ -0,0 +1,965 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.9-rc2-ep93xx ++# Mon Nov 8 16:32:53 2004 ++# ++CONFIG_ARM=y ++CONFIG_MMU=y ++CONFIG_UID16=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_IOMAP=y ++ ++# ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_CLEAN_COMPILE=y ++CONFIG_BROKEN_ON_SMP=y ++ ++# ++# General setup ++# ++CONFIG_LOCALVERSION="" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++CONFIG_SYSCTL=y ++# CONFIG_AUDIT is not set ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_HOTPLUG=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_EMBEDDED=y ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_IOSCHED_NOOP=y ++# CONFIG_IOSCHED_AS is not set ++CONFIG_IOSCHED_DEADLINE=y ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SHMEM=y ++# CONFIG_TINY_SHMEM is not set ++ ++# ++# Loadable module support ++# ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_OBSOLETE_MODPARM=y ++# CONFIG_MODVERSIONS is not set ++CONFIG_KMOD=y ++ ++# ++# System Type ++# ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++CONFIG_ARCH_EP93XX=y ++# CONFIG_ARCH_CAMELOT is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_IOP3XX is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_VERSATILE_PB is not set ++# CONFIG_ARCH_IMX is not set ++ ++# ++# EP93xx ++# ++CONFIG_ARCH_EP9301=y ++# CONFIG_ARCH_EP9302 is not set ++# CONFIG_ARCH_EP9312 is not set ++# CONFIG_ARCH_EP9315 is not set ++CONFIG_MACH_EDB9301=y ++# CONFIG_MACH_TTML is not set ++CONFIG_EP93XX_DMA=y ++CONFIG_EP93XX_SSP=y ++CONFIG_EP93XX_SSP_CIRRUS=y ++# CONFIG_EP93XX_SSP_LINUX is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM920T=y ++CONFIG_CPU_32v4=y ++CONFIG_CPU_ABRT_EV4T=y ++CONFIG_CPU_CACHE_V4WT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++ ++# ++# General setup ++# ++CONFIG_DISCONTIGMEM=y ++CONFIG_ARM_AMBA=y ++# CONFIG_ZBOOT_ROM is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++ ++# ++# PCMCIA/CardBus support ++# ++# CONFIG_PCMCIA is not set ++ ++# ++# At least one math emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++CONFIG_FPE_NWFPE_XP=y ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_BINFMT_ELF=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Generic Driver Options ++# ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++# CONFIG_FW_LOADER is not set ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_PM is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_ARTHUR is not set ++CONFIG_CMDLINE="root=/dev/nfs ip=dhcp" ++CONFIG_LEDS=y ++CONFIG_LEDS_TIMER=y ++CONFIG_LEDS_CPU=y ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Parallel port support ++# ++# CONFIG_PARPORT is not set ++ ++# ++# Memory Technology Devices (MTD) ++# ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++CONFIG_MTD_PARTITIONS=y ++# CONFIG_MTD_CONCAT is not set ++CONFIG_MTD_REDBOOT_PARTS=y ++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++# CONFIG_MTD_CMDLINE_PARTS is not set ++# CONFIG_MTD_AFS_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_GEN_PROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++CONFIG_MTD_CFI_GEOMETRY=y ++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set ++# 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 is not set ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++CONFIG_MTD_CFI_INTELEXT=y ++# CONFIG_MTD_CFI_AMDSTD is not set ++# CONFIG_MTD_CFI_STAA is not set ++CONFIG_MTD_CFI_UTIL=y ++# CONFIG_MTD_RAM is not set ++CONFIG_MTD_ROM=y ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x60000000 ++CONFIG_MTD_PHYSMAP_LEN=0x01000000 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=2 ++# CONFIG_MTD_ARM_INTEGRATOR is not set ++# CONFIG_MTD_EDB7312 is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLKMTD 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 is not set ++ ++# ++# Plug and Play support ++# ++ ++# ++# Block devices ++# ++# CONFIG_BLK_DEV_FD is not set ++# CONFIG_BLK_DEV_LOOP is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_UB is not set ++# CONFIG_BLK_DEV_RAM is not set ++ ++# ++# Multi-device support (RAID and LVM) ++# ++# CONFIG_MD is not set ++ ++# ++# Networking support ++# ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_PACKET_MMAP=y ++# CONFIG_NETLINK_DEV is not set ++CONFIG_UNIX=y ++CONFIG_NET_KEY=y ++CONFIG_INET=y ++# CONFIG_IP_MULTICAST is not set ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# 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_TUNNEL is not set ++# CONFIG_IPV6 is not set ++# CONFIG_NETFILTER is not set ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++ ++# ++# SCTP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_SCTP 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_NET_DIVERT is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_NET_HW_FLOWCONTROL is not set ++ ++# ++# QoS and/or fair queueing ++# ++# CONFIG_NET_SCHED is not set ++# CONFIG_NET_CLS_ROUTE is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_TUN is not set ++ ++# ++# Ethernet (10 or 100Mbit) ++# ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=y ++CONFIG_EP93XX_ETHERNET=y ++# CONFIG_SMC91X 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 ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++ ++# ++# SCSI Transport Attributes ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++ ++# ++# SCSI low-level drivers ++# ++# CONFIG_SCSI_SATA is not set ++# CONFIG_SCSI_DEBUG is not set ++ ++# ++# Fusion MPT device support ++# ++ ++# ++# IEEE 1394 (FireWire) support ++# ++ ++# ++# I2O device support ++# ++ ++# ++# ISDN subsystem ++# ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++ ++# ++# Userland interfaces ++# ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_TSDEV is not set ++CONFIG_INPUT_EVDEV=y ++CONFIG_INPUT_EVBUG=y ++ ++# ++# Input I/O drivers ++# ++# CONFIG_GAMEPORT is not set ++CONFIG_SOUND_GAMEPORT=y ++# CONFIG_SERIO 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=y ++ ++# ++# Character devices ++# ++# 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_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++CONFIG_SERIAL_EP93XX=y ++CONFIG_SERIAL_EP93XX_CONSOLE=y ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++# CONFIG_LEGACY_PTYS is not set ++ ++# ++# IPMI ++# ++# CONFIG_IPMI_HANDLER is not set ++ ++# ++# Watchdog Cards ++# ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++CONFIG_EP93XX_WATCHDOG=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++# CONFIG_NVRAM is not set ++# CONFIG_RTC is not set ++CONFIG_EP93XX_RTC=y ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++ ++# ++# Ftape, the floppy tape device driver ++# ++# CONFIG_DRM is not set ++# CONFIG_RAW_DRIVER is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++# ++# I2C Algorithms ++# ++CONFIG_I2C_ALGOBIT=y ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++# CONFIG_I2C_EP93XX is not set ++# CONFIG_I2C_ISA is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_SCx200_ACB is not set ++# CONFIG_I2C_PCA_ISA is not set ++ ++# ++# Hardware Sensors Chip support ++# ++# CONFIG_I2C_SENSOR is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_FSCHER is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_IT87 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_LM90 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++ ++# ++# Other I2C Chip support ++# ++# CONFIG_SENSORS_DS1337 is not set ++# CONFIG_SENSORS_EEPROM is not set ++# CONFIG_SENSORS_PCF8574 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_RTC8564 is not set ++CONFIG_I2C_DEBUG_CORE=y ++CONFIG_I2C_DEBUG_ALGO=y ++CONFIG_I2C_DEBUG_BUS=y ++CONFIG_I2C_DEBUG_CHIP=y ++ ++# ++# Multimedia devices ++# ++# CONFIG_VIDEO_DEV is not set ++ ++# ++# Digital Video Broadcasting Devices ++# ++# CONFIG_DVB is not set ++ ++# ++# File systems ++# ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_JBD is not set ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_QUOTA is not set ++# CONFIG_AUTOFS_FS is not set ++# CONFIG_AUTOFS4_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_FAT_FS=y ++# CONFIG_MSDOS_FS is not set ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_SYSFS=y ++# CONFIG_DEVFS_FS is not set ++CONFIG_DEVPTS_FS_XATTR=y ++CONFIG_DEVPTS_FS_SECURITY=y ++CONFIG_TMPFS=y ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_RAMFS=y ++ ++# ++# 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_JFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++# CONFIG_JFFS2_FS_NAND is not set ++CONFIG_JFFS2_COMPRESSION_OPTIONS=y ++CONFIG_JFFS2_ZLIB=y ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_JFFS2_CMODE_NONE is not set ++CONFIG_JFFS2_CMODE_PRIORITY=y ++# CONFIG_JFFS2_CMODE_SIZE 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=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_DIRECTIO is not set ++# CONFIG_NFSD is not set ++CONFIG_ROOT_NFS=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++# CONFIG_EXPORTFS is not set ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS 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 ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++ ++# ++# Native Language Support ++# ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# 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=y ++# 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 ++ ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set ++ ++# ++# Graphics support ++# ++# CONFIG_FB is not set ++# CONFIG_FB_CX25871_I2C is not set ++ ++# ++# Sound ++# ++CONFIG_SOUND=y ++ ++# ++# Advanced Linux Sound Architecture ++# ++CONFIG_SND=y ++CONFIG_SND_TIMER=y ++CONFIG_SND_PCM=y ++# CONFIG_SND_SEQUENCER is not set ++CONFIG_SND_OSSEMUL=y ++CONFIG_SND_MIXER_OSS=y ++CONFIG_SND_PCM_OSS=y ++CONFIG_SND_VERBOSE_PRINTK=y ++CONFIG_SND_DEBUG=y ++CONFIG_SND_DEBUG_MEMORY=y ++CONFIG_SND_DEBUG_DETECT=y ++ ++# ++# Generic devices ++# ++CONFIG_SND_DUMMY=y ++# CONFIG_SND_MTPAV is not set ++# CONFIG_SND_SERIAL_U16550 is not set ++# CONFIG_SND_MPU401 is not set ++ ++# ++# ALSA ARM devices ++# ++ ++# ++# ALSA USB devices ++# ++# CONFIG_SND_USB_AUDIO is not set ++# CONFIG_SND_USB_USX2Y is not set ++ ++# ++# Open Sound System ++# ++# CONFIG_SOUND_PRIME is not set ++ ++# ++# Misc devices ++# ++ ++# ++# USB support ++# ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++# CONFIG_USB_BANDWIDTH is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_EHCI_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++# CONFIG_USB_UHCI_HCD is not set ++# CONFIG_USB_SL811HS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_AUDIO is not set ++# CONFIG_USB_BLUETOOTH_TTY is not set ++# CONFIG_USB_MIDI is not set ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++CONFIG_USB_STORAGE_RW_DETECT=y ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_HP8200e is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++ ++# ++# USB Human Interface Devices (HID) ++# ++# CONFIG_USB_HID is not set ++ ++# ++# USB HID Boot Protocol drivers ++# ++# CONFIG_USB_KBD is not set ++# CONFIG_USB_MOUSE is not set ++# CONFIG_USB_AIPTEK is not set ++# CONFIG_USB_WACOM is not set ++# CONFIG_USB_KBTAB is not set ++# CONFIG_USB_POWERMATE is not set ++# CONFIG_USB_MTOUCH is not set ++# CONFIG_USB_EGALAX is not set ++# CONFIG_USB_XPAD is not set ++# CONFIG_USB_ATI_REMOTE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USB_HPUSBSCSI is not set ++ ++# ++# USB Multimedia devices ++# ++# CONFIG_USB_DABUSB is not set ++ ++# ++# Video4Linux support is needed for USB Multimedia device support ++# ++ ++# ++# USB Network adaptors ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++ ++# ++# USB port drivers ++# ++ ++# ++# USB Serial Converter support ++# ++CONFIG_USB_SERIAL=y ++# CONFIG_USB_SERIAL_CONSOLE is not set ++# CONFIG_USB_SERIAL_GENERIC is not set ++# CONFIG_USB_SERIAL_BELKIN is not set ++# CONFIG_USB_SERIAL_WHITEHEAT is not set ++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set ++# CONFIG_USB_SERIAL_EMPEG is not set ++# CONFIG_USB_SERIAL_FTDI_SIO is not set ++# CONFIG_USB_SERIAL_VISOR is not set ++# CONFIG_USB_SERIAL_IPAQ is not set ++# CONFIG_USB_SERIAL_IR is not set ++# CONFIG_USB_SERIAL_EDGEPORT is not set ++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set ++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set ++# CONFIG_USB_SERIAL_KEYSPAN is not set ++# CONFIG_USB_SERIAL_KLSI is not set ++# CONFIG_USB_SERIAL_KOBIL_SCT is not set ++# CONFIG_USB_SERIAL_MCT_U232 is not set ++CONFIG_USB_SERIAL_PL2303=y ++# CONFIG_USB_SERIAL_SAFE is not set ++# CONFIG_USB_SERIAL_CYBERJACK is not set ++# CONFIG_USB_SERIAL_XIRCOM is not set ++# CONFIG_USB_SERIAL_OMNINET is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_TIGL is not set ++# CONFIG_USB_AUERSWALD is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGETSERVO is not set ++# CONFIG_USB_TEST is not set ++ ++# ++# USB Gadget Support ++# ++# CONFIG_USB_GADGET is not set ++ ++# ++# MMC/SD Card support ++# ++# CONFIG_MMC is not set ++ ++# ++# Kernel hacking ++# ++CONFIG_DEBUG_KERNEL=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_DEBUG_SLAB=y ++CONFIG_DEBUG_SPINLOCK=y ++CONFIG_DEBUG_BUGVERBOSE=y ++# CONFIG_DEBUG_INFO is not set ++CONFIG_FRAME_POINTER=y ++CONFIG_DEBUG_USER=y ++CONFIG_DEBUG_WAITQ=y ++CONFIG_DEBUG_ERRORS=y ++CONFIG_DEBUG_LL=y ++# CONFIG_DEBUG_LL_PRINTK_HACK is not set ++# CONFIG_DEBUG_ICEDCC is not set ++ ++# ++# Security options ++# ++# CONFIG_SECURITY is not set ++ ++# ++# Cryptographic options ++# ++# CONFIG_CRYPTO is not set ++ ++# ++# Library routines ++# ++# CONFIG_CRC_CCITT is not set ++CONFIG_CRC32=y ++CONFIG_LIBCRC32C=y ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y +diff --git a/arch/arm/configs/edb9312_defconfig b/arch/arm/configs/edb9312_defconfig +new file mode 100644 +index 0000000..1a0aa51 +--- /dev/null ++++ b/arch/arm/configs/edb9312_defconfig +@@ -0,0 +1,920 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.9-rc2-ep93xx ++# Mon Nov 8 16:40:30 2004 ++# ++CONFIG_ARM=y ++CONFIG_MMU=y ++CONFIG_UID16=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_IOMAP=y ++ ++# ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++# CONFIG_CLEAN_COMPILE is not set ++CONFIG_BROKEN=y ++CONFIG_BROKEN_ON_SMP=y ++ ++# ++# General setup ++# ++CONFIG_LOCALVERSION="" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++CONFIG_SYSCTL=y ++# CONFIG_AUDIT is not set ++CONFIG_LOG_BUF_SHIFT=14 ++# CONFIG_HOTPLUG is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++# CONFIG_EMBEDDED is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SHMEM=y ++# CONFIG_TINY_SHMEM is not set ++ ++# ++# Loadable module support ++# ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_OBSOLETE_MODPARM=y ++# CONFIG_MODVERSIONS is not set ++CONFIG_KMOD=y ++ ++# ++# System Type ++# ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++CONFIG_ARCH_EP93XX=y ++# CONFIG_ARCH_CAMELOT is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_IOP3XX is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_VERSATILE_PB is not set ++# CONFIG_ARCH_IMX is not set ++ ++# ++# EP93xx ++# ++# CONFIG_ARCH_EP9301 is not set ++# CONFIG_ARCH_EP9302 is not set ++CONFIG_ARCH_EP9312=y ++# CONFIG_ARCH_EP9315 is not set ++CONFIG_MACH_EDB9312=y ++# CONFIG_MACH_ACC is not set ++CONFIG_EP93XX_DMA=y ++CONFIG_ARCH_EP93XX_IDE=y ++CONFIG_EP93XX_SSP=y ++CONFIG_EP93XX_SSP_CIRRUS=y ++# CONFIG_EP93XX_SSP_LINUX is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM920T=y ++CONFIG_CPU_32v4=y ++CONFIG_CPU_ABRT_EV4T=y ++CONFIG_CPU_CACHE_V4WT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_THUMB is not set ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++ ++# ++# General setup ++# ++CONFIG_DISCONTIGMEM=y ++CONFIG_ARM_AMBA=y ++# CONFIG_ZBOOT_ROM is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++ ++# ++# At least one math emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_BINFMT_ELF=y ++CONFIG_BINFMT_AOUT=y ++CONFIG_BINFMT_MISC=y ++ ++# ++# Generic Driver Options ++# ++# CONFIG_STANDALONE is not set ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_PM is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_ARTHUR is not set ++CONFIG_CMDLINE="root=/dev/hda1" ++CONFIG_LEDS=y ++CONFIG_LEDS_TIMER=y ++CONFIG_LEDS_CPU=y ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Parallel port support ++# ++# CONFIG_PARPORT is not set ++ ++# ++# Memory Technology Devices (MTD) ++# ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++CONFIG_MTD_PARTITIONS=y ++CONFIG_MTD_CONCAT=y ++CONFIG_MTD_REDBOOT_PARTS=y ++CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++CONFIG_MTD_CMDLINE_PARTS=y ++# CONFIG_MTD_AFS_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++CONFIG_FTL=y ++CONFIG_NFTL=y ++CONFIG_NFTL_RW=y ++CONFIG_INFTL=y ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++CONFIG_MTD_JEDECPROBE=y ++CONFIG_MTD_GEN_PROBE=y ++# 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=y ++CONFIG_MTD_CFI_AMDSTD=y ++CONFIG_MTD_CFI_AMDSTD_RETRY=0 ++CONFIG_MTD_CFI_STAA=y ++CONFIG_MTD_CFI_UTIL=y ++CONFIG_MTD_RAM=y ++CONFIG_MTD_ROM=y ++CONFIG_MTD_ABSENT=y ++# CONFIG_MTD_OBSOLETE_CHIPS is not set ++ ++# ++# Mapping drivers for chip access ++# ++CONFIG_MTD_COMPLEX_MAPPINGS=y ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x60000000 ++CONFIG_MTD_PHYSMAP_LEN=0x02000000 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=4 ++# CONFIG_MTD_ARM_INTEGRATOR is not set ++# CONFIG_MTD_EDB7312 is not set ++# CONFIG_MTD_IMPA7 is not set ++ ++# ++# Self-contained MTD device drivers ++# ++CONFIG_MTD_SLRAM=y ++CONFIG_MTD_PHRAM=y ++CONFIG_MTD_MTDRAM=y ++CONFIG_MTDRAM_TOTAL_SIZE=512 ++CONFIG_MTDRAM_ERASE_SIZE=1 ++CONFIG_MTDRAM_ABS_POS=0x20000000 ++# CONFIG_MTD_BLKMTD 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=y ++CONFIG_MTD_NAND_VERIFY_WRITE=y ++CONFIG_MTD_NAND_IDS=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++ ++# ++# Plug and Play support ++# ++ ++# ++# Block devices ++# ++# CONFIG_BLK_DEV_FD is not set ++CONFIG_BLK_DEV_LOOP=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_NBD is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_SIZE=12288 ++CONFIG_BLK_DEV_INITRD=y ++ ++# ++# Multi-device support (RAID and LVM) ++# ++# CONFIG_MD is not set ++ ++# ++# Networking support ++# ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_PACKET_MMAP=y ++# CONFIG_NETLINK_DEV is not set ++CONFIG_UNIX=y ++CONFIG_NET_KEY=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++# 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_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_TUNNEL is not set ++# CONFIG_IPV6 is not set ++# CONFIG_NETFILTER is not set ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++ ++# ++# SCTP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_SCTP 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_NET_DIVERT is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_NET_HW_FLOWCONTROL is not set ++ ++# ++# QoS and/or fair queueing ++# ++# CONFIG_NET_SCHED is not set ++# CONFIG_NET_CLS_ROUTE is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++CONFIG_NETPOLL=y ++# CONFIG_NETPOLL_RX is not set ++# CONFIG_NETPOLL_TRAP is not set ++CONFIG_NET_POLL_CONTROLLER=y ++# CONFIG_HAMRADIO is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_TUN is not set ++ ++# ++# Ethernet (10 or 100Mbit) ++# ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=y ++CONFIG_EP93XX_ETHERNET=y ++# CONFIG_SMC91X 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=y ++ ++# ++# ATA/ATAPI/MFM/RLL support ++# ++CONFIG_IDE=y ++CONFIG_BLK_DEV_IDE=y ++ ++# ++# Please see Documentation/ide.txt for help/info on IDE drives ++# ++# CONFIG_BLK_DEV_IDE_SATA is not set ++CONFIG_BLK_DEV_IDEDISK=y ++CONFIG_IDEDISK_MULTI_MODE=y ++CONFIG_BLK_DEV_IDECD=y ++# CONFIG_BLK_DEV_IDETAPE is not set ++# CONFIG_BLK_DEV_IDEFLOPPY is not set ++# CONFIG_BLK_DEV_IDESCSI is not set ++# CONFIG_IDE_TASK_IOCTL is not set ++# CONFIG_IDE_TASKFILE_IO is not set ++ ++# ++# IDE chipset support/bugfixes ++# ++CONFIG_IDE_GENERIC=y ++CONFIG_BLK_DEV_EP93XX=y ++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set ++CONFIG_IDE_ARM=y ++# CONFIG_BLK_DEV_IDEDMA is not set ++# CONFIG_IDEDMA_AUTO is not set ++# CONFIG_BLK_DEV_HD is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI=y ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++# CONFIG_BLK_DEV_SD is not set ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++ ++# ++# SCSI Transport Attributes ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++ ++# ++# SCSI low-level drivers ++# ++# CONFIG_SCSI_SATA is not set ++# CONFIG_SCSI_DEBUG is not set ++ ++# ++# Fusion MPT device support ++# ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_IEEE1394 is not set ++ ++# ++# I2O device support ++# ++ ++# ++# ISDN subsystem ++# ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_TSDEV is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input I/O drivers ++# ++# CONFIG_GAMEPORT is not set ++CONFIG_SOUND_GAMEPORT=y ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_CT82C710 is not set ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_RAW is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++CONFIG_KEYBOARD_EP93XX=y ++CONFIG_KEYBOARD_EP93XX_SPI=y ++CONFIG_KEYBOARD_EP93XX_8X8=y ++CONFIG_INPUT_MOUSE=y ++CONFIG_MOUSE_PS2=y ++CONFIG_MOUSE_SERIAL=y ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_INPUT_JOYSTICK is not set ++CONFIG_INPUT_TOUCHSCREEN=y ++# CONFIG_TOUCHSCREEN_GUNZE is not set ++CONFIG_TOUCHSCREEN_EP93XX=y ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++CONFIG_SERIAL_EP93XX=y ++CONFIG_SERIAL_EP93XX_CONSOLE=y ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++ ++# ++# IPMI ++# ++# CONFIG_IPMI_HANDLER is not set ++ ++# ++# Watchdog Cards ++# ++# CONFIG_WATCHDOG is not set ++# CONFIG_NVRAM is not set ++# CONFIG_RTC is not set ++# CONFIG_EP93XX_RTC is not set ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++ ++# ++# Ftape, the floppy tape device driver ++# ++# CONFIG_DRM is not set ++# CONFIG_RAW_DRIVER is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++# ++# I2C Algorithms ++# ++CONFIG_I2C_ALGOBIT=y ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++CONFIG_I2C_EP93XX=y ++# CONFIG_I2C_ISA is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_SCx200_ACB is not set ++# CONFIG_I2C_PCA_ISA is not set ++ ++# ++# Hardware Sensors Chip support ++# ++CONFIG_I2C_SENSOR=y ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_FSCHER is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_IT87 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_LM90 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++ ++# ++# Other I2C Chip support ++# ++CONFIG_SENSORS_DS1337=y ++CONFIG_SENSORS_EEPROM=y ++# CONFIG_SENSORS_PCF8574 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_RTC8564 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 ++ ++# ++# Multimedia devices ++# ++# CONFIG_VIDEO_DEV is not set ++ ++# ++# Digital Video Broadcasting Devices ++# ++# CONFIG_DVB is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_XATTR=y ++# CONFIG_EXT3_FS_POSIX_ACL is not set ++# CONFIG_EXT3_FS_SECURITY is not set ++CONFIG_JBD=y ++# CONFIG_JBD_DEBUG is not set ++CONFIG_FS_MBCACHE=y ++CONFIG_REISERFS_FS=y ++# CONFIG_REISERFS_CHECK is not set ++# CONFIG_REISERFS_PROC_INFO is not set ++# CONFIG_REISERFS_FS_XATTR is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_MINIX_FS is not set ++CONFIG_ROMFS_FS=y ++# CONFIG_QUOTA is not set ++CONFIG_AUTOFS_FS=y ++# CONFIG_AUTOFS4_FS is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_ZISOFS_FS=y ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_SYSFS=y ++# CONFIG_DEVFS_FS is not set ++# CONFIG_DEVFS_MOUNT is not set ++# CONFIG_DEVFS_DEBUG is not set ++# CONFIG_DEVPTS_FS_XATTR is not set ++CONFIG_TMPFS=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_RAMFS=y ++ ++# ++# 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_JFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++# CONFIG_JFFS2_FS_NAND is not set ++CONFIG_JFFS2_COMPRESSION_OPTIONS=y ++CONFIG_JFFS2_ZLIB=y ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_JFFS2_CMODE_NONE is not set ++CONFIG_JFFS2_CMODE_PRIORITY=y ++# CONFIG_JFFS2_CMODE_SIZE 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=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_DIRECTIO is not set ++# CONFIG_NFSD is not set ++CONFIG_ROOT_NFS=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++# CONFIG_EXPORTFS is not set ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS 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 ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++ ++# ++# Native Language Support ++# ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# 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=y ++CONFIG_NLS_ISO8859_1=y ++# 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=y ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=y ++ ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set ++ ++# ++# Graphics support ++# ++CONFIG_FB=y ++CONFIG_FB_MODE_HELPERS=y ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CX25871_I2C is not set ++CONFIG_FB_EP93XX=y ++# CONFIG_FB_CRT_EP93XX is not set ++CONFIG_FB_LCD_EP93XX=y ++# CONFIG_FB_LCD_EP93XX_SHARP is not set ++# CONFIG_FB_CX25871 is not set ++# CONFIG_FB_EP93XX_8BPP is not set ++# CONFIG_FB_EP93XX_16BPP_565 is not set ++# CONFIG_FB_EP93XX_24BPP is not set ++CONFIG_FB_EP93XX_32BPP=y ++# CONFIG_FB_VIRTUAL is not set ++ ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_FONTS=y ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++CONFIG_FONT_6x11=y ++CONFIG_FONT_PEARL_8x8=y ++CONFIG_FONT_ACORN_8x8=y ++# CONFIG_FONT_MINI_4x6 is not set ++CONFIG_FONT_SUN8x16=y ++CONFIG_FONT_SUN12x22=y ++ ++# ++# Logo configuration ++# ++CONFIG_LOGO=y ++CONFIG_LOGO_LINUX_MONO=y ++CONFIG_LOGO_LINUX_VGA16=y ++CONFIG_LOGO_LINUX_CLUT224=y ++ ++# ++# Sound ++# ++CONFIG_SOUND=y ++ ++# ++# Advanced Linux Sound Architecture ++# ++# CONFIG_SND is not set ++ ++# ++# Open Sound System ++# ++CONFIG_SOUND_PRIME=y ++# CONFIG_SOUND_BT878 is not set ++# CONFIG_SOUND_FUSION is not set ++# CONFIG_SOUND_CS4281 is not set ++# CONFIG_SOUND_SONICVIBES is not set ++# CONFIG_SOUND_TRIDENT is not set ++# CONFIG_SOUND_MSNDCLAS is not set ++# CONFIG_SOUND_MSNDPIN is not set ++# CONFIG_SOUND_OSS is not set ++# CONFIG_SOUND_TVMIXER is not set ++# CONFIG_SOUND_AD1980 is not set ++ ++# ++# Misc devices ++# ++ ++# ++# USB support ++# ++# CONFIG_USB is not set ++ ++# ++# USB Gadget Support ++# ++# CONFIG_USB_GADGET is not set ++ ++# ++# MMC/SD Card support ++# ++# CONFIG_MMC is not set ++ ++# ++# Kernel hacking ++# ++CONFIG_DEBUG_KERNEL=y ++CONFIG_MAGIC_SYSRQ=y ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_INFO=y ++CONFIG_FRAME_POINTER=y ++CONFIG_DEBUG_USER=y ++# CONFIG_DEBUG_WAITQ is not set ++CONFIG_DEBUG_ERRORS=y ++CONFIG_DEBUG_LL=y ++CONFIG_DEBUG_LL_PRINTK_HACK=y ++# CONFIG_DEBUG_ICEDCC is not set ++ ++# ++# Security options ++# ++# CONFIG_SECURITY is not set ++ ++# ++# Cryptographic options ++# ++# CONFIG_CRYPTO is not set ++ ++# ++# Library routines ++# ++CONFIG_CRC_CCITT=y ++CONFIG_CRC32=y ++CONFIG_LIBCRC32C=y ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y +diff --git a/arch/arm/configs/edb9315_defconfig b/arch/arm/configs/edb9315_defconfig +new file mode 100644 +index 0000000..3e6033b +--- /dev/null ++++ b/arch/arm/configs/edb9315_defconfig +@@ -0,0 +1,954 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.9-rc2-ep93xx ++# Mon Nov 8 17:01:50 2004 ++# ++CONFIG_ARM=y ++CONFIG_MMU=y ++CONFIG_UID16=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_IOMAP=y ++ ++# ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++# CONFIG_CLEAN_COMPILE is not set ++CONFIG_BROKEN=y ++CONFIG_BROKEN_ON_SMP=y ++ ++# ++# General setup ++# ++CONFIG_LOCALVERSION="" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++CONFIG_POSIX_MQUEUE=y ++CONFIG_BSD_PROCESS_ACCT=y ++# CONFIG_BSD_PROCESS_ACCT_V3 is not set ++CONFIG_SYSCTL=y ++# CONFIG_AUDIT is not set ++CONFIG_LOG_BUF_SHIFT=14 ++# CONFIG_HOTPLUG is not set ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_EMBEDDED=y ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SHMEM=y ++# CONFIG_TINY_SHMEM is not set ++ ++# ++# Loadable module support ++# ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_OBSOLETE_MODPARM=y ++# CONFIG_MODVERSIONS is not set ++CONFIG_KMOD=y ++ ++# ++# System Type ++# ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++CONFIG_ARCH_EP93XX=y ++# CONFIG_ARCH_CAMELOT is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_IOP3XX is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_VERSATILE_PB is not set ++# CONFIG_ARCH_IMX is not set ++ ++# ++# EP93xx ++# ++# CONFIG_ARCH_EP9301 is not set ++# CONFIG_ARCH_EP9302 is not set ++# CONFIG_ARCH_EP9312 is not set ++CONFIG_ARCH_EP9315=y ++CONFIG_MACH_EDB9315=y ++CONFIG_EP93XX_DMA=y ++# CONFIG_ARCH_EP93XX_IDE is not set ++CONFIG_EP93XX_SSP=y ++CONFIG_EP93XX_SSP_CIRRUS=y ++# CONFIG_EP93XX_SSP_LINUX is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM920T=y ++CONFIG_CPU_32v4=y ++CONFIG_CPU_ABRT_EV4T=y ++CONFIG_CPU_CACHE_V4WT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++ ++# ++# General setup ++# ++CONFIG_DISCONTIGMEM=y ++CONFIG_ARM_AMBA=y ++# CONFIG_ZBOOT_ROM is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++ ++# ++# At least one math emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_BINFMT_ELF=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Generic Driver Options ++# ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_PM is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_ARTHUR is not set ++CONFIG_CMDLINE="console=ttyCL0 map=mtd6,0x30000000,+0x200000 root=/dev/nfs nfsroot=192.168.1.224:/nfsarm_grma video=ep93xxfb ip=192.168.1.220:192.168.1.224:192.168.1.2:255.255.255.0::eth0:" ++CONFIG_LEDS=y ++CONFIG_LEDS_TIMER=y ++CONFIG_LEDS_CPU=y ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Parallel port support ++# ++# CONFIG_PARPORT is not set ++ ++# ++# Memory Technology Devices (MTD) ++# ++CONFIG_MTD=y ++CONFIG_MTD_DEBUG=y ++CONFIG_MTD_DEBUG_VERBOSE=3 ++CONFIG_MTD_PARTITIONS=y ++# CONFIG_MTD_CONCAT is not set ++CONFIG_MTD_REDBOOT_PARTS=y ++CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y ++CONFIG_MTD_REDBOOT_PARTS_READONLY=y ++# CONFIG_MTD_CMDLINE_PARTS is not set ++# CONFIG_MTD_AFS_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_GEN_PROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++CONFIG_MTD_CFI_GEOMETRY=y ++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set ++# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set ++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 is not set ++CONFIG_MTD_CFI_I2=y ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++CONFIG_MTD_CFI_INTELEXT=y ++# CONFIG_MTD_CFI_AMDSTD is not set ++# CONFIG_MTD_CFI_STAA is not set ++CONFIG_MTD_CFI_UTIL=y ++CONFIG_MTD_RAM=y ++CONFIG_MTD_ROM=y ++# CONFIG_MTD_ABSENT is not set ++# CONFIG_MTD_OBSOLETE_CHIPS is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x60000000 ++CONFIG_MTD_PHYSMAP_LEN=0x2000000 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=4 ++# CONFIG_MTD_ARM_INTEGRATOR is not set ++# CONFIG_MTD_EDB7312 is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++CONFIG_MTD_MTDRAM=y ++CONFIG_MTDRAM_TOTAL_SIZE=512 ++CONFIG_MTDRAM_ERASE_SIZE=128 ++CONFIG_MTDRAM_ABS_POS=0x20000000 ++# CONFIG_MTD_BLKMTD 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 is not set ++ ++# ++# Plug and Play support ++# ++ ++# ++# Block devices ++# ++# CONFIG_BLK_DEV_FD is not set ++CONFIG_BLK_DEV_LOOP=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_UB is not set ++# CONFIG_BLK_DEV_RAM is not set ++ ++# ++# Multi-device support (RAID and LVM) ++# ++# CONFIG_MD is not set ++ ++# ++# Networking support ++# ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_PACKET_MMAP=y ++# CONFIG_NETLINK_DEV is not set ++CONFIG_UNIX=y ++CONFIG_NET_KEY=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++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_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_TUNNEL is not set ++# CONFIG_IPV6 is not set ++# CONFIG_NETFILTER is not set ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++ ++# ++# SCTP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_SCTP 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_NET_DIVERT is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_NET_HW_FLOWCONTROL is not set ++ ++# ++# QoS and/or fair queueing ++# ++# CONFIG_NET_SCHED is not set ++# CONFIG_NET_CLS_ROUTE is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_TUN is not set ++ ++# ++# Ethernet (10 or 100Mbit) ++# ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=y ++CONFIG_EP93XX_ETHERNET=y ++# CONFIG_SMC91X 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 ++ ++# ++# ATA/ATAPI/MFM/RLL support ++# ++# CONFIG_IDE is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI=y ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++CONFIG_CHR_DEV_SG=y ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++ ++# ++# SCSI Transport Attributes ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++ ++# ++# SCSI low-level drivers ++# ++# CONFIG_SCSI_SATA is not set ++# CONFIG_SCSI_DEBUG is not set ++ ++# ++# Fusion MPT device support ++# ++ ++# ++# IEEE 1394 (FireWire) support ++# ++# CONFIG_IEEE1394 is not set ++ ++# ++# I2O device support ++# ++ ++# ++# ISDN subsystem ++# ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_TSDEV is not set ++# CONFIG_INPUT_EVDEV is not set ++# CONFIG_INPUT_EVBUG is not set ++ ++# ++# Input I/O drivers ++# ++# CONFIG_GAMEPORT is not set ++CONFIG_SOUND_GAMEPORT=y ++CONFIG_SERIO=y ++# CONFIG_SERIO_SERPORT is not set ++# CONFIG_SERIO_CT82C710 is not set ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_RAW is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++CONFIG_KEYBOARD_EP93XX=y ++# CONFIG_KEYBOARD_EP93XX_SPI is not set ++# CONFIG_KEYBOARD_EP93XX_8X8 is not set ++CONFIG_INPUT_MOUSE=y ++# CONFIG_MOUSE_PS2 is not set ++# CONFIG_MOUSE_SERIAL is not set ++# CONFIG_MOUSE_VSXXXAA is not set ++# CONFIG_INPUT_JOYSTICK is not set ++CONFIG_INPUT_TOUCHSCREEN=y ++# CONFIG_TOUCHSCREEN_GUNZE is not set ++CONFIG_TOUCHSCREEN_EP93XX=y ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++CONFIG_SERIAL_EP93XX=y ++CONFIG_SERIAL_EP93XX_CONSOLE=y ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++ ++# ++# IPMI ++# ++# CONFIG_IPMI_HANDLER is not set ++ ++# ++# Watchdog Cards ++# ++# CONFIG_WATCHDOG is not set ++# CONFIG_NVRAM is not set ++# CONFIG_RTC is not set ++# CONFIG_EP93XX_RTC is not set ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++ ++# ++# Ftape, the floppy tape device driver ++# ++# CONFIG_DRM is not set ++# CONFIG_RAW_DRIVER is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++# ++# I2C Algorithms ++# ++CONFIG_I2C_ALGOBIT=y ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++CONFIG_I2C_EP93XX=y ++# CONFIG_I2C_ISA is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_SCx200_ACB is not set ++# CONFIG_I2C_PCA_ISA is not set ++ ++# ++# Hardware Sensors Chip support ++# ++# CONFIG_I2C_SENSOR is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_FSCHER is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_IT87 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_LM90 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++ ++# ++# Other I2C Chip support ++# ++CONFIG_SENSORS_DS1337=y ++# CONFIG_SENSORS_EEPROM is not set ++# CONFIG_SENSORS_PCF8574 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_RTC8564 is not set ++CONFIG_I2C_DEBUG_CORE=y ++CONFIG_I2C_DEBUG_ALGO=y ++CONFIG_I2C_DEBUG_BUS=y ++CONFIG_I2C_DEBUG_CHIP=y ++ ++# ++# Multimedia devices ++# ++# CONFIG_VIDEO_DEV is not set ++ ++# ++# Digital Video Broadcasting Devices ++# ++# CONFIG_DVB is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_JBD is not set ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_XFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_QUOTA is not set ++CONFIG_AUTOFS_FS=y ++# CONFIG_AUTOFS4_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_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_SYSFS=y ++# CONFIG_DEVFS_FS is not set ++CONFIG_DEVPTS_FS_XATTR=y ++# CONFIG_DEVPTS_FS_SECURITY is not set ++CONFIG_TMPFS=y ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_RAMFS=y ++ ++# ++# 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_JFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=2 ++# CONFIG_JFFS2_FS_NAND 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=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_DIRECTIO is not set ++# CONFIG_NFSD is not set ++CONFIG_ROOT_NFS=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++# CONFIG_EXPORTFS is not set ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS 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 ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++CONFIG_LDM_PARTITION=y ++# CONFIG_LDM_DEBUG is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++ ++# ++# Native Language Support ++# ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# CONFIG_NLS_CODEPAGE_737 is not set ++# CONFIG_NLS_CODEPAGE_775 is not set ++CONFIG_NLS_CODEPAGE_850=y ++# 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=y ++# 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=y ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=y ++ ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set ++ ++# ++# Graphics support ++# ++CONFIG_FB=y ++CONFIG_FB_MODE_HELPERS=y ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CX25871_I2C is not set ++CONFIG_FB_EP93XX=y ++# CONFIG_FB_CRT_EP93XX is not set ++CONFIG_FB_LCD_EP93XX=y ++# CONFIG_FB_LCD_EP93XX_SHARP is not set ++# CONFIG_FB_CX25871 is not set ++# CONFIG_FB_EP93XX_8BPP is not set ++CONFIG_FB_EP93XX_16BPP_565=y ++# CONFIG_FB_EP93XX_24BPP is not set ++# CONFIG_FB_EP93XX_32BPP is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_FONTS=y ++CONFIG_FONT_8x8=y ++CONFIG_FONT_8x16=y ++# CONFIG_FONT_6x11 is not set ++# CONFIG_FONT_PEARL_8x8 is not set ++# CONFIG_FONT_ACORN_8x8 is not set ++# CONFIG_FONT_MINI_4x6 is not set ++# CONFIG_FONT_SUN8x16 is not set ++# CONFIG_FONT_SUN12x22 is not set ++ ++# ++# Logo configuration ++# ++CONFIG_LOGO=y ++# CONFIG_LOGO_LINUX_MONO is not set ++# CONFIG_LOGO_LINUX_VGA16 is not set ++CONFIG_LOGO_LINUX_CLUT224=y ++ ++# ++# Sound ++# ++# CONFIG_SOUND is not set ++ ++# ++# Misc devices ++# ++ ++# ++# USB support ++# ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++ ++# ++# Miscellaneous USB options ++# ++# CONFIG_USB_DEVICEFS is not set ++# CONFIG_USB_BANDWIDTH is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_EHCI_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++# CONFIG_USB_UHCI_HCD is not set ++# CONFIG_USB_SL811HS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_BLUETOOTH_TTY is not set ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_RW_DETECT is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_HP8200e is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++ ++# ++# USB Human Interface Devices (HID) ++# ++CONFIG_USB_HID=y ++CONFIG_USB_HIDINPUT=y ++# CONFIG_HID_FF is not set ++CONFIG_USB_HIDDEV=y ++# CONFIG_USB_AIPTEK is not set ++# CONFIG_USB_WACOM is not set ++# CONFIG_USB_KBTAB is not set ++# CONFIG_USB_POWERMATE is not set ++# CONFIG_USB_MTOUCH is not set ++# CONFIG_USB_EGALAX is not set ++# CONFIG_USB_XPAD is not set ++# CONFIG_USB_ATI_REMOTE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USB_HPUSBSCSI is not set ++ ++# ++# USB Multimedia devices ++# ++# CONFIG_USB_DABUSB is not set ++ ++# ++# Video4Linux support is needed for USB Multimedia device support ++# ++ ++# ++# USB Network adaptors ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++ ++# ++# USB port drivers ++# ++ ++# ++# USB Serial Converter support ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_TIGL is not set ++# CONFIG_USB_AUERSWALD is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGETSERVO is not set ++ ++# ++# USB Gadget Support ++# ++# CONFIG_USB_GADGET is not set ++ ++# ++# MMC/SD Card support ++# ++# CONFIG_MMC is not set ++ ++# ++# Kernel hacking ++# ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_MAGIC_SYSRQ is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_INFO=y ++CONFIG_FRAME_POINTER=y ++CONFIG_DEBUG_USER=y ++# CONFIG_DEBUG_WAITQ is not set ++CONFIG_DEBUG_ERRORS=y ++CONFIG_DEBUG_LL=y ++# CONFIG_DEBUG_LL_PRINTK_HACK is not set ++# CONFIG_DEBUG_ICEDCC is not set ++ ++# ++# Security options ++# ++# CONFIG_SECURITY is not set ++ ++# ++# Cryptographic options ++# ++# CONFIG_CRYPTO is not set ++ ++# ++# Library routines ++# ++# CONFIG_CRC_CCITT is not set ++CONFIG_CRC32=y ++CONFIG_LIBCRC32C=y ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y +diff --git a/arch/arm/configs/ttml_defconfig b/arch/arm/configs/ttml_defconfig +new file mode 100644 +index 0000000..e0b96ae +--- /dev/null ++++ b/arch/arm/configs/ttml_defconfig +@@ -0,0 +1,1052 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.13 ++# Thu Sep 8 16:54:14 2005 ++# ++CONFIG_ARM=y ++CONFIG_MMU=y ++CONFIG_UID16=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++ ++# ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_CLEAN_COMPILE=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++ ++# ++# General setup ++# ++CONFIG_LOCALVERSION="" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++CONFIG_SYSCTL=y ++# CONFIG_AUDIT is not set ++CONFIG_HOTPLUG=y ++CONFIG_KOBJECT_UEVENT=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_EMBEDDED=y ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SHMEM=y ++CONFIG_CC_ALIGN_FUNCTIONS=0 ++CONFIG_CC_ALIGN_LABELS=0 ++CONFIG_CC_ALIGN_LOOPS=0 ++CONFIG_CC_ALIGN_JUMPS=0 ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=0 ++ ++# ++# Loadable module support ++# ++CONFIG_MODULES=y ++# CONFIG_MODULE_UNLOAD is not set ++CONFIG_OBSOLETE_MODPARM=y ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_KMOD=y ++ ++# ++# System Type ++# ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++CONFIG_ARCH_EP93XX=y ++# CONFIG_ARCH_CAMELOT is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_IOP3XX is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_AAEC2000 is not set ++ ++# ++# EP93xx ++# ++CONFIG_ARCH_EP9301=y ++# CONFIG_ARCH_EP9302 is not set ++# CONFIG_ARCH_EP9312 is not set ++# CONFIG_ARCH_EP9315 is not set ++# CONFIG_MACH_EDB9301 is not set ++CONFIG_MACH_TTML=y ++# CONFIG_ARCH_EP93XX_GPIO_IRQ is not set ++CONFIG_EP93XX_DMA=y ++CONFIG_EP93XX_SSP=y ++# CONFIG_EP93XX_SSP_CIRRUS is not set ++CONFIG_EP93XX_SSP_LINUX=y ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM920T=y ++CONFIG_CPU_32v4=y ++CONFIG_CPU_ABRT_EV4T=y ++CONFIG_CPU_CACHE_V4WT=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++CONFIG_ISA_DMA_API=y ++ ++# ++# PCCARD (PCMCIA/CardBus) support ++# ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++# CONFIG_PREEMPT is not set ++# CONFIG_NO_IDLE_HZ is not set ++CONFIG_ARCH_DISCONTIGMEM_ENABLE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++# CONFIG_FLATMEM_MANUAL is not set ++CONFIG_DISCONTIGMEM_MANUAL=y ++# CONFIG_SPARSEMEM_MANUAL is not set ++CONFIG_DISCONTIGMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_NEED_MULTIPLE_NODES=y ++# CONFIG_LEDS is not set ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Boot options ++# ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="ip=off root=1f02 rootfstype=jffs2" ++# CONFIG_XIP_KERNEL is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++CONFIG_FPE_NWFPE_XP=y ++# CONFIG_FPE_FASTFPE is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++# CONFIG_ARTHUR is not set ++ ++# ++# Power management options ++# ++# CONFIG_PM is not set ++ ++# ++# Networking ++# ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_PACKET_MMAP=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++CONFIG_NET_KEY=y ++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=y ++CONFIG_IP_PNP_BOOTP=y ++# 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_TUNNEL is not set ++CONFIG_IP_TCPDIAG=y ++# CONFIG_IP_TCPDIAG_IPV6 is not set ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_BIC=y ++# CONFIG_IPV6 is not set ++# CONFIG_NETFILTER is not set ++ ++# ++# SCTP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_SCTP 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_NET_DIVERT is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_NET_CLS_ROUTE is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++# CONFIG_FW_LOADER is not set ++# CONFIG_DEBUG_DRIVER 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=y ++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1 ++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++# CONFIG_MTD_CMDLINE_PARTS is not set ++# CONFIG_MTD_AFS_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_GEN_PROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++CONFIG_MTD_CFI_GEOMETRY=y ++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set ++# 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 is not set ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_OTP is not set ++CONFIG_MTD_CFI_INTELEXT=y ++# CONFIG_MTD_CFI_AMDSTD is not set ++# CONFIG_MTD_CFI_STAA is not set ++CONFIG_MTD_CFI_UTIL=y ++# CONFIG_MTD_RAM is not set ++CONFIG_MTD_ROM=y ++# CONFIG_MTD_ABSENT is not set ++# CONFIG_MTD_XIP is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++CONFIG_MTD_PHYSMAP=y ++CONFIG_MTD_PHYSMAP_START=0x60000000 ++CONFIG_MTD_PHYSMAP_LEN=0x01000000 ++CONFIG_MTD_PHYSMAP_BANKWIDTH=2 ++# CONFIG_MTD_ARM_INTEGRATOR is not set ++# CONFIG_MTD_EDB7312 is not set ++# CONFIG_MTD_PLATRAM is not set ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLKMTD 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 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_UB is not set ++# CONFIG_BLK_DEV_RAM is not set ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_INITRAMFS_SOURCE="" ++# CONFIG_CDROM_PKTCDVD is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++# CONFIG_IOSCHED_AS is not set ++# CONFIG_IOSCHED_DEADLINE is not set ++# CONFIG_IOSCHED_CFQ is not set ++# CONFIG_ATA_OVER_ETH is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++# CONFIG_CHR_DEV_SCH is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++ ++# ++# SCSI Transport Attributes ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++ ++# ++# SCSI low-level drivers ++# ++# CONFIG_SCSI_SATA is not set ++# CONFIG_SCSI_DEBUG 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 ++ ++# ++# Ethernet (10 or 100Mbit) ++# ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=y ++CONFIG_EP93XX_ETHERNET=y ++# CONFIG_SMC91X is not set ++# CONFIG_DM9000 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 ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++ ++# ++# Userland interfaces ++# ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_TSDEV is not set ++CONFIG_INPUT_EVDEV=y ++CONFIG_INPUT_EVBUG=y ++ ++# ++# 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=y ++ ++# ++# Hardware I/O ports ++# ++# CONFIG_SERIO is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_TTML_DEVICES=y ++# 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_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++CONFIG_SERIAL_EP93XX=y ++CONFIG_SERIAL_EP93XX_CONSOLE=y ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++# CONFIG_LEGACY_PTYS is not set ++ ++# ++# IPMI ++# ++# CONFIG_IPMI_HANDLER is not set ++ ++# ++# Watchdog Cards ++# ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++CONFIG_EP93XX_WATCHDOG=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++# CONFIG_NVRAM is not set ++# CONFIG_RTC is not set ++CONFIG_EP93XX_RTC=y ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++ ++# ++# Ftape, the floppy tape device driver ++# ++ ++# ++# CAN bus devices ++# ++# CONFIG_CAN_BUS is not set ++# CONFIG_RAW_DRIVER is not set ++ ++# ++# TPM devices ++# ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++# ++# I2C Algorithms ++# ++CONFIG_I2C_ALGOBIT=y ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++# CONFIG_I2C_EP93XX is not set ++# CONFIG_I2C_ISA is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_STUB is not set ++# CONFIG_I2C_PCA_ISA is not set ++# CONFIG_I2C_SENSOR is not set ++ ++# ++# Miscellaneous I2C Chip support ++# ++# CONFIG_SENSORS_DS1337 is not set ++# CONFIG_SENSORS_DS1374 is not set ++# CONFIG_SENSORS_DS1307 is not set ++# CONFIG_SENSORS_EEPROM is not set ++# CONFIG_SENSORS_PCF8574 is not set ++# CONFIG_SENSORS_PCA9539 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_RTC8564 is not set ++# CONFIG_SENSORS_MAX6875 is not set ++CONFIG_I2C_DEBUG_CORE=y ++CONFIG_I2C_DEBUG_ALGO=y ++CONFIG_I2C_DEBUG_BUS=y ++CONFIG_I2C_DEBUG_CHIP=y ++ ++# ++# Hardware Monitoring support ++# ++CONFIG_HWMON=y ++# 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_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_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_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_W83781D 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 ++ ++# ++# Misc devices ++# ++ ++# ++# Multimedia devices ++# ++# CONFIG_VIDEO_DEV is not set ++ ++# ++# Digital Video Broadcasting Devices ++# ++# CONFIG_DVB is not set ++ ++# ++# Graphics support ++# ++# CONFIG_FB is not set ++# CONFIG_FB_CX25871_I2C is not set ++ ++# ++# Sound ++# ++# CONFIG_SOUND is not set ++ ++# ++# USB support ++# ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++# CONFIG_USB_BANDWIDTH is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_ISP116X_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++# CONFIG_USB_OHCI_BIG_ENDIAN is not set ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++# CONFIG_USB_SL811_HCD is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_BLUETOOTH_TTY is not set ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++ ++# ++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++ ++# ++# USB Input Devices ++# ++# CONFIG_USB_HID is not set ++ ++# ++# USB HID Boot Protocol drivers ++# ++# CONFIG_USB_KBD is not set ++# CONFIG_USB_MOUSE is not set ++# CONFIG_USB_AIPTEK is not set ++# CONFIG_USB_WACOM is not set ++# CONFIG_USB_ACECAD is not set ++# CONFIG_USB_KBTAB is not set ++# CONFIG_USB_POWERMATE is not set ++# CONFIG_USB_MTOUCH is not set ++# CONFIG_USB_ITMTOUCH is not set ++# CONFIG_USB_EGALAX is not set ++# CONFIG_USB_XPAD is not set ++# CONFIG_USB_ATI_REMOTE is not set ++# CONFIG_USB_KEYSPAN_REMOTE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB Multimedia devices ++# ++# CONFIG_USB_DABUSB is not set ++ ++# ++# Video4Linux support is needed for USB Multimedia device support ++# ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++CONFIG_USB_MON=y ++ ++# ++# USB port drivers ++# ++ ++# ++# USB Serial Converter support ++# ++CONFIG_USB_SERIAL=y ++# CONFIG_USB_SERIAL_CONSOLE is not set ++# CONFIG_USB_SERIAL_GENERIC is not set ++# CONFIG_USB_SERIAL_AIRPRIME is not set ++# CONFIG_USB_SERIAL_BELKIN is not set ++# CONFIG_USB_SERIAL_WHITEHEAT is not set ++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set ++# CONFIG_USB_SERIAL_CP2101 is not set ++# CONFIG_USB_SERIAL_CYPRESS_M8 is not set ++# CONFIG_USB_SERIAL_EMPEG is not set ++# CONFIG_USB_SERIAL_FTDI_SIO is not set ++# CONFIG_USB_SERIAL_VISOR is not set ++# CONFIG_USB_SERIAL_IPAQ is not set ++# CONFIG_USB_SERIAL_IR is not set ++# CONFIG_USB_SERIAL_EDGEPORT is not set ++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set ++# CONFIG_USB_SERIAL_GARMIN is not set ++# CONFIG_USB_SERIAL_IPW is not set ++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set ++# CONFIG_USB_SERIAL_KEYSPAN is not set ++# CONFIG_USB_SERIAL_KLSI is not set ++# CONFIG_USB_SERIAL_KOBIL_SCT is not set ++# CONFIG_USB_SERIAL_MCT_U232 is not set ++CONFIG_USB_SERIAL_PL2303=y ++# CONFIG_USB_SERIAL_HP4X is not set ++# CONFIG_USB_SERIAL_SAFE is not set ++# CONFIG_USB_SERIAL_TI is not set ++# CONFIG_USB_SERIAL_CYBERJACK is not set ++# CONFIG_USB_SERIAL_XIRCOM is not set ++# CONFIG_USB_SERIAL_OMNINET is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_AUERSWALD is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGETKIT is not set ++# CONFIG_USB_PHIDGETSERVO is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TEST is not set ++ ++# ++# USB DSL modem support ++# ++ ++# ++# USB Gadget Support ++# ++# CONFIG_USB_GADGET is not set ++ ++# ++# MMC/SD Card support ++# ++# CONFIG_MMC is not set ++ ++# ++# File systems ++# ++# CONFIG_EXT2_FS is not set ++# CONFIG_EXT3_FS is not set ++# CONFIG_JBD is not set ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++# CONFIG_FS_POSIX_ACL is not set ++ ++# ++# XFS support ++# ++# CONFIG_XFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_ROMFS_FS is not set ++CONFIG_INOTIFY=y ++# CONFIG_QUOTA is not set ++CONFIG_DNOTIFY=y ++# CONFIG_AUTOFS_FS is not set ++# CONFIG_AUTOFS4_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_FAT_FS=y ++# CONFIG_MSDOS_FS is not set ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_SYSFS=y ++CONFIG_DEVPTS_FS_XATTR=y ++CONFIG_DEVPTS_FS_SECURITY=y ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_XATTR is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_RAMFS=y ++ ++# ++# 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_JFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++CONFIG_JFFS2_COMPRESSION_OPTIONS=y ++CONFIG_JFFS2_ZLIB=y ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_JFFS2_CMODE_NONE is not set ++CONFIG_JFFS2_CMODE_PRIORITY=y ++# CONFIG_JFFS2_CMODE_SIZE 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=y ++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_ROOT_NFS=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS 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 ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++ ++# ++# Native Language Support ++# ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# 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=y ++# 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 ++ ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_DEBUG_KERNEL=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_LOG_BUF_SHIFT=14 ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set ++# CONFIG_DEBUG_KOBJECT is not set ++# CONFIG_DEBUG_BUGVERBOSE is not set ++# CONFIG_DEBUG_INFO is not set ++# CONFIG_DEBUG_FS is not set ++CONFIG_FRAME_POINTER=y ++# CONFIG_DEBUG_USER is not set ++# CONFIG_DEBUG_WAITQ is not set ++CONFIG_DEBUG_ERRORS=y ++CONFIG_DEBUG_LL=y ++# CONFIG_DEBUG_ICEDCC is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set ++ ++# ++# Cryptographic options ++# ++# CONFIG_CRYPTO is not set ++ ++# ++# Hardware crypto devices ++# ++ ++# ++# Library routines ++# ++# CONFIG_CRC_CCITT is not set ++CONFIG_CRC32=y ++CONFIG_LIBCRC32C=y ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y +diff --git a/arch/arm/configs/zefeerdzb_defconfig b/arch/arm/configs/zefeerdzb_defconfig +new file mode 100644 +index 0000000..39aefdd +--- /dev/null ++++ b/arch/arm/configs/zefeerdzb_defconfig +@@ -0,0 +1,961 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.9-rc2-ep93xx ++# Fri Jan 7 11:19:19 2005 ++# ++CONFIG_ARM=y ++CONFIG_MMU=y ++CONFIG_UID16=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_IOMAP=y ++ ++# ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++CONFIG_CLEAN_COMPILE=y ++CONFIG_BROKEN_ON_SMP=y ++ ++# ++# General setup ++# ++CONFIG_LOCALVERSION="" ++# CONFIG_SWAP is not set ++CONFIG_SYSVIPC=y ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++CONFIG_SYSCTL=y ++# CONFIG_AUDIT is not set ++CONFIG_LOG_BUF_SHIFT=14 ++CONFIG_HOTPLUG=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++CONFIG_EMBEDDED=y ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_IOSCHED_NOOP=y ++# CONFIG_IOSCHED_AS is not set ++CONFIG_IOSCHED_DEADLINE=y ++# CONFIG_IOSCHED_CFQ is not set ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SHMEM=y ++# CONFIG_TINY_SHMEM is not set ++ ++# ++# Loadable module support ++# ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_OBSOLETE_MODPARM=y ++# CONFIG_MODVERSIONS is not set ++CONFIG_KMOD=y ++ ++# ++# System Type ++# ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++CONFIG_ARCH_EP93XX=y ++# CONFIG_ARCH_CAMELOT is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_IOP3XX is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_VERSATILE_PB is not set ++# CONFIG_ARCH_IMX is not set ++ ++# ++# EP93xx ++# ++# CONFIG_ARCH_EP9301 is not set ++CONFIG_ARCH_EP9302=y ++# CONFIG_ARCH_EP9312 is not set ++# CONFIG_ARCH_EP9315 is not set ++# CONFIG_MACH_EDB9302 is not set ++CONFIG_MACH_ZEFEERDZB=y ++CONFIG_ARCH_EP93XX_GPIO_IRQ=y ++CONFIG_EP93XX_DMA=y ++# CONFIG_EP93XX_SSP is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM920T=y ++CONFIG_CPU_32v4=y ++CONFIG_CPU_ABRT_EV4T=y ++CONFIG_CPU_CACHE_V4WT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++ ++# ++# Processor Features ++# ++CONFIG_ARM_THUMB=y ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++ ++# ++# General setup ++# ++CONFIG_DISCONTIGMEM=y ++CONFIG_ARM_AMBA=y ++# CONFIG_ZBOOT_ROM is not set ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++ ++# ++# PCMCIA/CardBus support ++# ++# CONFIG_PCMCIA is not set ++ ++# ++# At least one math emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++CONFIG_FPE_NWFPE_XP=y ++# CONFIG_FPE_FASTFPE is not set ++CONFIG_BINFMT_ELF=y ++# CONFIG_BINFMT_AOUT is not set ++# CONFIG_BINFMT_MISC is not set ++ ++# ++# Generic Driver Options ++# ++CONFIG_STANDALONE=y ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++# CONFIG_FW_LOADER is not set ++# CONFIG_DEBUG_DRIVER is not set ++# CONFIG_PM is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_ARTHUR is not set ++CONFIG_CMDLINE="root=/dev/nfs ip=dhcp" ++# CONFIG_LEDS is not set ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Parallel port support ++# ++# CONFIG_PARPORT is not set ++ ++# ++# Memory Technology Devices (MTD) ++# ++CONFIG_MTD=y ++# CONFIG_MTD_DEBUG is not set ++CONFIG_MTD_PARTITIONS=y ++# CONFIG_MTD_CONCAT is not set ++CONFIG_MTD_REDBOOT_PARTS=y ++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set ++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set ++# CONFIG_MTD_CMDLINE_PARTS is not set ++# CONFIG_MTD_AFS_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_GEN_PROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++CONFIG_MTD_CFI_GEOMETRY=y ++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set ++# 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 is not set ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++CONFIG_MTD_CFI_INTELEXT=y ++# CONFIG_MTD_CFI_AMDSTD is not set ++# CONFIG_MTD_CFI_STAA is not set ++CONFIG_MTD_CFI_UTIL=y ++# CONFIG_MTD_RAM is not set ++CONFIG_MTD_ROM=y ++# CONFIG_MTD_ABSENT is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_PHYSMAP is not set ++# CONFIG_MTD_ARM_INTEGRATOR is not set ++# CONFIG_MTD_EDB7312 is not set ++CONFIG_MTD_ZEFEERDZB=y ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLKMTD 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=y ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++CONFIG_MTD_NAND_IDS=y ++CONFIG_MTD_NAND_ZEFEEREVB=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++ ++# ++# Plug and Play support ++# ++ ++# ++# Block devices ++# ++# CONFIG_BLK_DEV_FD is not set ++CONFIG_BLK_DEV_LOOP=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_SIZE=6144 ++CONFIG_BLK_DEV_INITRD=y ++ ++# ++# Multi-device support (RAID and LVM) ++# ++# CONFIG_MD is not set ++ ++# ++# Networking support ++# ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_PACKET_MMAP=y ++# CONFIG_NETLINK_DEV is not set ++CONFIG_UNIX=y ++CONFIG_NET_KEY=y ++CONFIG_INET=y ++# CONFIG_IP_MULTICAST is not set ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++CONFIG_IP_PNP_BOOTP=y ++# 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_TUNNEL is not set ++# CONFIG_IPV6 is not set ++# CONFIG_NETFILTER is not set ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++ ++# ++# SCTP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_SCTP 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_NET_DIVERT is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_NET_HW_FLOWCONTROL is not set ++ ++# ++# QoS and/or fair queueing ++# ++# CONFIG_NET_SCHED is not set ++# CONFIG_NET_CLS_ROUTE is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_NETPOLL is not set ++# CONFIG_NET_POLL_CONTROLLER is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++CONFIG_NETDEVICES=y ++# CONFIG_DUMMY is not set ++# CONFIG_BONDING is not set ++# CONFIG_EQUALIZER is not set ++# CONFIG_TUN is not set ++ ++# ++# Ethernet (10 or 100Mbit) ++# ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=y ++CONFIG_EP93XX_ETHERNET=y ++# CONFIG_SMC91X 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 ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI=y ++# CONFIG_SCSI_PROC_FS is not set ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++# CONFIG_CHR_DEV_SG is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++ ++# ++# SCSI Transport Attributes ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++ ++# ++# SCSI low-level drivers ++# ++# CONFIG_SCSI_SATA is not set ++# CONFIG_SCSI_DEBUG is not set ++ ++# ++# Fusion MPT device support ++# ++ ++# ++# IEEE 1394 (FireWire) support ++# ++ ++# ++# I2O device support ++# ++ ++# ++# ISDN subsystem ++# ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++ ++# ++# Userland interfaces ++# ++# CONFIG_INPUT_MOUSEDEV is not set ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_TSDEV is not set ++CONFIG_INPUT_EVDEV=y ++CONFIG_INPUT_EVBUG=y ++ ++# ++# Input I/O drivers ++# ++# CONFIG_GAMEPORT is not set ++CONFIG_SOUND_GAMEPORT=y ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_CT82C710 is not set ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_RAW is not set ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++CONFIG_KEYBOARD_ATKBD=y ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++CONFIG_KEYBOARD_EP93XX=y ++# CONFIG_KEYBOARD_EP93XX_SPI is not set ++# CONFIG_KEYBOARD_EP93XX_8X8 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=y ++ ++# ++# Character devices ++# ++# 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_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++CONFIG_SERIAL_EP93XX=y ++CONFIG_SERIAL_EP93XX_CONSOLE=y ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++# CONFIG_LEGACY_PTYS is not set ++ ++# ++# IPMI ++# ++# CONFIG_IPMI_HANDLER is not set ++ ++# ++# Watchdog Cards ++# ++CONFIG_WATCHDOG=y ++# CONFIG_WATCHDOG_NOWAYOUT is not set ++ ++# ++# Watchdog Device Drivers ++# ++# CONFIG_SOFT_WATCHDOG is not set ++CONFIG_EP93XX_WATCHDOG=y ++ ++# ++# USB-based Watchdog Cards ++# ++# CONFIG_USBPCWATCHDOG is not set ++# CONFIG_NVRAM is not set ++# CONFIG_RTC is not set ++CONFIG_EP93XX_RTC=y ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++ ++# ++# Ftape, the floppy tape device driver ++# ++# CONFIG_DRM is not set ++# CONFIG_RAW_DRIVER is not set ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++# ++# I2C Algorithms ++# ++CONFIG_I2C_ALGOBIT=y ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++# CONFIG_I2C_AMD756 is not set ++# CONFIG_I2C_AMD8111 is not set ++CONFIG_I2C_EP93XX=y ++# CONFIG_I2C_ISA is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_SCx200_ACB is not set ++# CONFIG_I2C_PCA_ISA is not set ++ ++# ++# Hardware Sensors Chip support ++# ++# CONFIG_I2C_SENSOR is not set ++# CONFIG_SENSORS_ADM1021 is not set ++# CONFIG_SENSORS_ADM1025 is not set ++# CONFIG_SENSORS_ADM1031 is not set ++# CONFIG_SENSORS_ASB100 is not set ++# CONFIG_SENSORS_DS1621 is not set ++# CONFIG_SENSORS_FSCHER is not set ++# CONFIG_SENSORS_GL518SM is not set ++# CONFIG_SENSORS_IT87 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_LM90 is not set ++# CONFIG_SENSORS_MAX1619 is not set ++# CONFIG_SENSORS_SMSC47M1 is not set ++# CONFIG_SENSORS_W83781D is not set ++# CONFIG_SENSORS_W83L785TS is not set ++# CONFIG_SENSORS_W83627HF is not set ++ ++# ++# Other I2C Chip support ++# ++# CONFIG_SENSORS_DS1337 is not set ++# CONFIG_SENSORS_EEPROM is not set ++# CONFIG_SENSORS_PCF8574 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_RTC8564 is not set ++# CONFIG_SENSORS_M41T00 is not set ++CONFIG_I2C_DEBUG_CORE=y ++CONFIG_I2C_DEBUG_ALGO=y ++CONFIG_I2C_DEBUG_BUS=y ++CONFIG_I2C_DEBUG_CHIP=y ++ ++# ++# Multimedia devices ++# ++# CONFIG_VIDEO_DEV is not set ++ ++# ++# Digital Video Broadcasting Devices ++# ++# CONFIG_DVB is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++CONFIG_EXT2_FS_XATTR=y ++CONFIG_EXT2_FS_POSIX_ACL=y ++CONFIG_EXT2_FS_SECURITY=y ++# CONFIG_EXT3_FS is not set ++# CONFIG_JBD is not set ++CONFIG_FS_MBCACHE=y ++# CONFIG_REISERFS_FS is not set ++# CONFIG_JFS_FS is not set ++CONFIG_FS_POSIX_ACL=y ++# CONFIG_XFS_FS is not set ++# CONFIG_MINIX_FS is not set ++# CONFIG_ROMFS_FS is not set ++# CONFIG_QUOTA is not set ++# CONFIG_AUTOFS_FS is not set ++# CONFIG_AUTOFS4_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_FAT_FS=y ++# CONFIG_MSDOS_FS is not set ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++# CONFIG_NTFS_FS is not set ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_SYSFS=y ++# CONFIG_DEVFS_FS is not set ++CONFIG_DEVPTS_FS_XATTR=y ++CONFIG_DEVPTS_FS_SECURITY=y ++CONFIG_TMPFS=y ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_RAMFS=y ++ ++# ++# 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_JFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_NAND=y ++CONFIG_JFFS2_COMPRESSION_OPTIONS=y ++CONFIG_JFFS2_ZLIB=y ++CONFIG_JFFS2_RTIME=y ++# CONFIG_JFFS2_RUBIN is not set ++# CONFIG_JFFS2_CMODE_NONE is not set ++CONFIG_JFFS2_CMODE_PRIORITY=y ++# CONFIG_JFFS2_CMODE_SIZE 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=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V4 is not set ++# CONFIG_NFS_DIRECTIO is not set ++# CONFIG_NFSD is not set ++CONFIG_ROOT_NFS=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++# CONFIG_EXPORTFS is not set ++CONFIG_SUNRPC=y ++# CONFIG_RPCSEC_GSS_KRB5 is not set ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS 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 ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++ ++# ++# Native Language Support ++# ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# 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=y ++# 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 ++ ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set ++ ++# ++# Graphics support ++# ++# CONFIG_FB is not set ++# CONFIG_FB_CX25871_I2C is not set ++ ++# ++# Sound ++# ++CONFIG_SOUND=y ++ ++# ++# Advanced Linux Sound Architecture ++# ++CONFIG_SND=y ++CONFIG_SND_TIMER=y ++CONFIG_SND_PCM=y ++# CONFIG_SND_SEQUENCER is not set ++CONFIG_SND_OSSEMUL=y ++CONFIG_SND_MIXER_OSS=y ++CONFIG_SND_PCM_OSS=y ++CONFIG_SND_VERBOSE_PRINTK=y ++CONFIG_SND_DEBUG=y ++CONFIG_SND_DEBUG_MEMORY=y ++CONFIG_SND_DEBUG_DETECT=y ++ ++# ++# Generic devices ++# ++CONFIG_SND_DUMMY=y ++# CONFIG_SND_MTPAV is not set ++# CONFIG_SND_SERIAL_U16550 is not set ++# CONFIG_SND_MPU401 is not set ++ ++# ++# ALSA ARM devices ++# ++ ++# ++# ALSA USB devices ++# ++# CONFIG_SND_USB_AUDIO is not set ++# CONFIG_SND_USB_USX2Y is not set ++ ++# ++# Open Sound System ++# ++# CONFIG_SOUND_PRIME is not set ++ ++# ++# Misc devices ++# ++ ++# ++# USB support ++# ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++# CONFIG_USB_BANDWIDTH is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_EHCI_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++# CONFIG_USB_UHCI_HCD is not set ++# CONFIG_USB_SL811HS is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_AUDIO is not set ++# CONFIG_USB_BLUETOOTH_TTY is not set ++# CONFIG_USB_MIDI is not set ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++CONFIG_USB_STORAGE_RW_DETECT=y ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_HP8200e is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++ ++# ++# USB Human Interface Devices (HID) ++# ++CONFIG_USB_HID=y ++CONFIG_USB_HIDINPUT=y ++# CONFIG_HID_FF is not set ++# CONFIG_USB_HIDDEV is not set ++# CONFIG_USB_AIPTEK is not set ++# CONFIG_USB_WACOM is not set ++# CONFIG_USB_KBTAB is not set ++# CONFIG_USB_POWERMATE is not set ++# CONFIG_USB_MTOUCH is not set ++# CONFIG_USB_EGALAX is not set ++# CONFIG_USB_XPAD is not set ++# CONFIG_USB_ATI_REMOTE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++# CONFIG_USB_HPUSBSCSI is not set ++ ++# ++# USB Multimedia devices ++# ++# CONFIG_USB_DABUSB is not set ++ ++# ++# Video4Linux support is needed for USB Multimedia device support ++# ++ ++# ++# USB Network adaptors ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++ ++# ++# USB port drivers ++# ++ ++# ++# USB Serial Converter support ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_TIGL is not set ++# CONFIG_USB_AUERSWALD is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGETSERVO is not set ++# CONFIG_USB_TEST is not set ++ ++# ++# USB Gadget Support ++# ++# CONFIG_USB_GADGET is not set ++ ++# ++# MMC/SD Card support ++# ++# CONFIG_MMC is not set ++ ++# ++# Kernel hacking ++# ++CONFIG_DEBUG_KERNEL=y ++CONFIG_MAGIC_SYSRQ=y ++CONFIG_DEBUG_SLAB=y ++CONFIG_DEBUG_SPINLOCK=y ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_INFO=y ++CONFIG_FRAME_POINTER=y ++CONFIG_DEBUG_USER=y ++CONFIG_DEBUG_WAITQ=y ++CONFIG_DEBUG_ERRORS=y ++# CONFIG_DEBUG_DONT_REORDER_CODE is not set ++CONFIG_DEBUG_LL=y ++# CONFIG_DEBUG_LL_PRINTK_HACK is not set ++# CONFIG_DEBUG_ICEDCC is not set ++ ++# ++# Security options ++# ++# CONFIG_SECURITY is not set ++ ++# ++# Cryptographic options ++# ++# CONFIG_CRYPTO is not set ++ ++# ++# Library routines ++# ++# CONFIG_CRC_CCITT is not set ++CONFIG_CRC32=y ++CONFIG_LIBCRC32C=y ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y +diff --git a/arch/arm/configs/zefeerdzq_defconfig b/arch/arm/configs/zefeerdzq_defconfig +new file mode 100644 +index 0000000..8314eee +--- /dev/null ++++ b/arch/arm/configs/zefeerdzq_defconfig +@@ -0,0 +1,1174 @@ ++# ++# Automatically generated make config: don't edit ++# Linux kernel version: 2.6.13 ++# Tue Oct 4 10:04:06 2005 ++# ++CONFIG_ARM=y ++CONFIG_MMU=y ++CONFIG_UID16=y ++CONFIG_RWSEM_GENERIC_SPINLOCK=y ++CONFIG_GENERIC_CALIBRATE_DELAY=y ++ ++# ++# Code maturity level options ++# ++CONFIG_EXPERIMENTAL=y ++# CONFIG_CLEAN_COMPILE is not set ++CONFIG_BROKEN=y ++CONFIG_BROKEN_ON_SMP=y ++CONFIG_INIT_ENV_ARG_LIMIT=32 ++ ++# ++# General setup ++# ++CONFIG_LOCALVERSION="" ++CONFIG_SWAP=y ++CONFIG_SYSVIPC=y ++# CONFIG_POSIX_MQUEUE is not set ++# CONFIG_BSD_PROCESS_ACCT is not set ++CONFIG_SYSCTL=y ++# CONFIG_AUDIT is not set ++# CONFIG_HOTPLUG is not set ++CONFIG_KOBJECT_UEVENT=y ++CONFIG_IKCONFIG=y ++CONFIG_IKCONFIG_PROC=y ++# CONFIG_EMBEDDED is not set ++CONFIG_KALLSYMS=y ++# CONFIG_KALLSYMS_ALL is not set ++# CONFIG_KALLSYMS_EXTRA_PASS is not set ++CONFIG_PRINTK=y ++CONFIG_BUG=y ++CONFIG_BASE_FULL=y ++CONFIG_FUTEX=y ++CONFIG_EPOLL=y ++CONFIG_CC_OPTIMIZE_FOR_SIZE=y ++CONFIG_SHMEM=y ++CONFIG_CC_ALIGN_FUNCTIONS=0 ++CONFIG_CC_ALIGN_LABELS=0 ++CONFIG_CC_ALIGN_LOOPS=0 ++CONFIG_CC_ALIGN_JUMPS=0 ++# CONFIG_TINY_SHMEM is not set ++CONFIG_BASE_SMALL=0 ++ ++# ++# Loadable module support ++# ++CONFIG_MODULES=y ++CONFIG_MODULE_UNLOAD=y ++CONFIG_MODULE_FORCE_UNLOAD=y ++CONFIG_OBSOLETE_MODPARM=y ++# CONFIG_MODVERSIONS is not set ++# CONFIG_MODULE_SRCVERSION_ALL is not set ++CONFIG_KMOD=y ++ ++# ++# System Type ++# ++# CONFIG_ARCH_CLPS7500 is not set ++# CONFIG_ARCH_CLPS711X is not set ++# CONFIG_ARCH_CO285 is not set ++# CONFIG_ARCH_EBSA110 is not set ++CONFIG_ARCH_EP93XX=y ++# CONFIG_ARCH_CAMELOT is not set ++# CONFIG_ARCH_FOOTBRIDGE is not set ++# CONFIG_ARCH_INTEGRATOR is not set ++# CONFIG_ARCH_IOP3XX is not set ++# CONFIG_ARCH_IXP4XX is not set ++# CONFIG_ARCH_IXP2000 is not set ++# CONFIG_ARCH_L7200 is not set ++# CONFIG_ARCH_PXA is not set ++# CONFIG_ARCH_RPC is not set ++# CONFIG_ARCH_SA1100 is not set ++# CONFIG_ARCH_S3C2410 is not set ++# CONFIG_ARCH_SHARK is not set ++# CONFIG_ARCH_LH7A40X is not set ++# CONFIG_ARCH_OMAP is not set ++# CONFIG_ARCH_VERSATILE is not set ++# CONFIG_ARCH_IMX is not set ++# CONFIG_ARCH_H720X is not set ++# CONFIG_ARCH_AAEC2000 is not set ++ ++# ++# EP93xx ++# ++# CONFIG_ARCH_EP9301 is not set ++# CONFIG_ARCH_EP9302 is not set ++# CONFIG_ARCH_EP9312 is not set ++CONFIG_ARCH_EP9315=y ++# CONFIG_MACH_EDB9315 is not set ++# CONFIG_MACH_ADSSPHERE is not set ++CONFIG_MACH_ZEFEERDZQ=y ++# CONFIG_MACH_DMA03 is not set ++# CONFIG_ARCH_EP93XX_GPIO_IRQ is not set ++CONFIG_EP93XX_DMA=y ++# CONFIG_ARCH_EP93XX_IDE is not set ++# CONFIG_EP93XX_SSP is not set ++ ++# ++# Processor Type ++# ++CONFIG_CPU_32=y ++CONFIG_CPU_ARM920T=y ++CONFIG_CPU_32v4=y ++CONFIG_CPU_ABRT_EV4T=y ++CONFIG_CPU_CACHE_V4WT=y ++CONFIG_CPU_CACHE_VIVT=y ++CONFIG_CPU_COPY_V4WB=y ++CONFIG_CPU_TLB_V4WBI=y ++ ++# ++# Processor Features ++# ++# CONFIG_ARM_THUMB is not set ++# CONFIG_CPU_ICACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_DISABLE is not set ++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set ++ ++# ++# Bus support ++# ++CONFIG_ARM_AMBA=y ++CONFIG_ISA_DMA_API=y ++ ++# ++# PCCARD (PCMCIA/CardBus) support ++# ++# CONFIG_PCCARD is not set ++ ++# ++# Kernel Features ++# ++# CONFIG_SMP is not set ++# CONFIG_PREEMPT is not set ++# CONFIG_NO_IDLE_HZ is not set ++CONFIG_ARCH_DISCONTIGMEM_ENABLE=y ++CONFIG_SELECT_MEMORY_MODEL=y ++# CONFIG_FLATMEM_MANUAL is not set ++CONFIG_DISCONTIGMEM_MANUAL=y ++# CONFIG_SPARSEMEM_MANUAL is not set ++CONFIG_DISCONTIGMEM=y ++CONFIG_FLAT_NODE_MEM_MAP=y ++CONFIG_NEED_MULTIPLE_NODES=y ++# CONFIG_LEDS is not set ++CONFIG_ALIGNMENT_TRAP=y ++ ++# ++# Boot options ++# ++CONFIG_ZBOOT_ROM_TEXT=0x0 ++CONFIG_ZBOOT_ROM_BSS=0x0 ++CONFIG_CMDLINE="root=/dev/ram" ++# CONFIG_XIP_KERNEL is not set ++ ++# ++# Floating point emulation ++# ++ ++# ++# At least one emulation must be selected ++# ++CONFIG_FPE_NWFPE=y ++# CONFIG_FPE_NWFPE_XP is not set ++# CONFIG_FPE_FASTFPE is not set ++ ++# ++# Userspace binary formats ++# ++CONFIG_BINFMT_ELF=y ++CONFIG_BINFMT_AOUT=y ++CONFIG_BINFMT_MISC=y ++# CONFIG_ARTHUR is not set ++ ++# ++# Power management options ++# ++# CONFIG_PM is not set ++ ++# ++# Networking ++# ++CONFIG_NET=y ++ ++# ++# Networking options ++# ++CONFIG_PACKET=y ++CONFIG_PACKET_MMAP=y ++CONFIG_UNIX=y ++CONFIG_XFRM=y ++# CONFIG_XFRM_USER is not set ++CONFIG_NET_KEY=y ++CONFIG_INET=y ++CONFIG_IP_MULTICAST=y ++# CONFIG_IP_ADVANCED_ROUTER is not set ++CONFIG_IP_FIB_HASH=y ++CONFIG_IP_PNP=y ++CONFIG_IP_PNP_DHCP=y ++# 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_IP_MROUTE is not set ++# CONFIG_ARPD is not set ++# CONFIG_SYN_COOKIES is not set ++# CONFIG_INET_AH is not set ++# CONFIG_INET_ESP is not set ++# CONFIG_INET_IPCOMP is not set ++# CONFIG_INET_TUNNEL is not set ++CONFIG_IP_TCPDIAG=y ++# CONFIG_IP_TCPDIAG_IPV6 is not set ++# CONFIG_TCP_CONG_ADVANCED is not set ++CONFIG_TCP_CONG_BIC=y ++# CONFIG_IPV6 is not set ++# CONFIG_NETFILTER is not set ++ ++# ++# SCTP Configuration (EXPERIMENTAL) ++# ++# CONFIG_IP_SCTP 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_NET_DIVERT is not set ++# CONFIG_ECONET is not set ++# CONFIG_WAN_ROUTER is not set ++# CONFIG_NET_SCHED is not set ++# CONFIG_NET_CLS_ROUTE is not set ++ ++# ++# Network testing ++# ++# CONFIG_NET_PKTGEN is not set ++# CONFIG_HAMRADIO is not set ++# CONFIG_IRDA is not set ++# CONFIG_BT is not set ++ ++# ++# Device Drivers ++# ++ ++# ++# Generic Driver Options ++# ++# CONFIG_STANDALONE is not set ++CONFIG_PREVENT_FIRMWARE_BUILD=y ++# CONFIG_FW_LOADER is not set ++# CONFIG_DEBUG_DRIVER 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 ++# CONFIG_MTD_AFS_PARTS is not set ++ ++# ++# User Modules And Translation Layers ++# ++CONFIG_MTD_CHAR=y ++CONFIG_MTD_BLOCK=y ++# CONFIG_FTL is not set ++# CONFIG_NFTL is not set ++# CONFIG_INFTL is not set ++ ++# ++# RAM/ROM/Flash chip drivers ++# ++CONFIG_MTD_CFI=y ++# CONFIG_MTD_JEDECPROBE is not set ++CONFIG_MTD_GEN_PROBE=y ++CONFIG_MTD_CFI_ADV_OPTIONS=y ++CONFIG_MTD_CFI_NOSWAP=y ++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set ++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set ++CONFIG_MTD_CFI_GEOMETRY=y ++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set ++CONFIG_MTD_MAP_BANK_WIDTH_2=y ++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set ++# 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 is not set ++# CONFIG_MTD_CFI_I4 is not set ++# CONFIG_MTD_CFI_I8 is not set ++# CONFIG_MTD_OTP is not set ++CONFIG_MTD_CFI_INTELEXT=y ++# CONFIG_MTD_CFI_AMDSTD is not set ++# CONFIG_MTD_CFI_STAA is not set ++CONFIG_MTD_CFI_UTIL=y ++# CONFIG_MTD_RAM is not set ++# CONFIG_MTD_ROM is not set ++# CONFIG_MTD_ABSENT is not set ++# CONFIG_MTD_OBSOLETE_CHIPS is not set ++# CONFIG_MTD_XIP is not set ++ ++# ++# Mapping drivers for chip access ++# ++# CONFIG_MTD_COMPLEX_MAPPINGS is not set ++# CONFIG_MTD_PHYSMAP is not set ++# CONFIG_MTD_ARM_INTEGRATOR is not set ++# CONFIG_MTD_EDB7312 is not set ++# CONFIG_MTD_PLATRAM is not set ++CONFIG_MTD_ZEFEERDZQ=y ++ ++# ++# Self-contained MTD device drivers ++# ++# CONFIG_MTD_SLRAM is not set ++# CONFIG_MTD_PHRAM is not set ++# CONFIG_MTD_MTDRAM is not set ++# CONFIG_MTD_BLKMTD 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=y ++# CONFIG_MTD_NAND_VERIFY_WRITE is not set ++CONFIG_MTD_NAND_IDS=y ++CONFIG_MTD_NAND_ZEFEEREVB=y ++# CONFIG_MTD_NAND_DISKONCHIP is not set ++# CONFIG_MTD_NAND_NANDSIM 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=y ++# CONFIG_BLK_DEV_CRYPTOLOOP is not set ++# CONFIG_BLK_DEV_NBD is not set ++# CONFIG_BLK_DEV_UB is not set ++CONFIG_BLK_DEV_RAM=y ++CONFIG_BLK_DEV_RAM_COUNT=16 ++CONFIG_BLK_DEV_RAM_SIZE=12288 ++CONFIG_BLK_DEV_INITRD=y ++CONFIG_INITRAMFS_SOURCE="" ++# CONFIG_CDROM_PKTCDVD is not set ++ ++# ++# IO Schedulers ++# ++CONFIG_IOSCHED_NOOP=y ++CONFIG_IOSCHED_AS=y ++CONFIG_IOSCHED_DEADLINE=y ++CONFIG_IOSCHED_CFQ=y ++# CONFIG_ATA_OVER_ETH is not set ++ ++# ++# ATA/ATAPI/MFM/RLL support ++# ++CONFIG_IDE=y ++CONFIG_BLK_DEV_IDE=y ++ ++# ++# Please see Documentation/ide.txt for help/info on IDE drives ++# ++# CONFIG_BLK_DEV_IDE_SATA is not set ++CONFIG_BLK_DEV_IDEDISK=y ++# CONFIG_IDEDISK_MULTI_MODE is not set ++CONFIG_BLK_DEV_IDECD=y ++# CONFIG_BLK_DEV_IDETAPE is not set ++# CONFIG_BLK_DEV_IDEFLOPPY is not set ++# CONFIG_BLK_DEV_IDESCSI is not set ++# CONFIG_IDE_TASK_IOCTL is not set ++ ++# ++# IDE chipset support/bugfixes ++# ++CONFIG_IDE_GENERIC=y ++CONFIG_BLK_DEV_EP93XX=y ++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set ++CONFIG_IDE_ARM=y ++# CONFIG_BLK_DEV_IDEDMA is not set ++# CONFIG_IDEDMA_AUTO is not set ++# CONFIG_BLK_DEV_HD is not set ++ ++# ++# SCSI device support ++# ++CONFIG_SCSI=y ++CONFIG_SCSI_PROC_FS=y ++ ++# ++# SCSI support type (disk, tape, CD-ROM) ++# ++CONFIG_BLK_DEV_SD=y ++# CONFIG_CHR_DEV_ST is not set ++# CONFIG_CHR_DEV_OSST is not set ++# CONFIG_BLK_DEV_SR is not set ++CONFIG_CHR_DEV_SG=y ++# CONFIG_CHR_DEV_SCH is not set ++ ++# ++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs ++# ++# CONFIG_SCSI_MULTI_LUN is not set ++# CONFIG_SCSI_CONSTANTS is not set ++# CONFIG_SCSI_LOGGING is not set ++ ++# ++# SCSI Transport Attributes ++# ++# CONFIG_SCSI_SPI_ATTRS is not set ++# CONFIG_SCSI_FC_ATTRS is not set ++# CONFIG_SCSI_ISCSI_ATTRS is not set ++ ++# ++# SCSI low-level drivers ++# ++# CONFIG_SCSI_SATA is not set ++# CONFIG_SCSI_DEBUG 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 ++# ++# CONFIG_IEEE1394 is not set ++ ++# ++# 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 ++ ++# ++# Ethernet (10 or 100Mbit) ++# ++CONFIG_NET_ETHERNET=y ++CONFIG_MII=y ++CONFIG_EP93XX_ETHERNET=y ++# CONFIG_SMC91X is not set ++# CONFIG_DM9000 is not set ++ ++# ++# Ethernet (1000 Mbit) ++# ++ ++# ++# Ethernet (10000 Mbit) ++# ++ ++# ++# Token Ring devices ++# ++ ++# ++# Wireless LAN (non-hamradio) ++# ++CONFIG_NET_RADIO=y ++ ++# ++# Obsolete Wireless cards support (pre-802.11) ++# ++# CONFIG_STRIP is not set ++# CONFIG_ATMEL 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=y ++CONFIG_NETPOLL=y ++# CONFIG_NETPOLL_RX is not set ++# CONFIG_NETPOLL_TRAP is not set ++CONFIG_NET_POLL_CONTROLLER=y ++ ++# ++# ISDN subsystem ++# ++# CONFIG_ISDN is not set ++ ++# ++# Input device support ++# ++CONFIG_INPUT=y ++ ++# ++# Userland interfaces ++# ++CONFIG_INPUT_MOUSEDEV=y ++CONFIG_INPUT_MOUSEDEV_PSAUX=y ++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640 ++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480 ++# CONFIG_INPUT_JOYDEV is not set ++# CONFIG_INPUT_TSDEV is not set ++CONFIG_INPUT_EVDEV=y ++CONFIG_INPUT_EVBUG=y ++ ++# ++# Input Device Drivers ++# ++CONFIG_INPUT_KEYBOARD=y ++# CONFIG_KEYBOARD_ATKBD is not set ++# CONFIG_KEYBOARD_SUNKBD is not set ++# CONFIG_KEYBOARD_LKKBD is not set ++# CONFIG_KEYBOARD_XTKBD is not set ++# CONFIG_KEYBOARD_NEWTON is not set ++CONFIG_KEYBOARD_EP93XX=y ++# CONFIG_KEYBOARD_EP93XX_SPI is not set ++# CONFIG_KEYBOARD_EP93XX_8X8 is not set ++# CONFIG_INPUT_MOUSE is not set ++# CONFIG_INPUT_JOYSTICK is not set ++# CONFIG_INPUT_TOUCHSCREEN is not set ++# CONFIG_INPUT_MISC is not set ++ ++# ++# Hardware I/O ports ++# ++CONFIG_SERIO=y ++CONFIG_SERIO_SERPORT=y ++# CONFIG_SERIO_AMBAKMI is not set ++# CONFIG_SERIO_RAW is not set ++# CONFIG_GAMEPORT is not set ++ ++# ++# Character devices ++# ++CONFIG_VT=y ++CONFIG_VT_CONSOLE=y ++CONFIG_HW_CONSOLE=y ++# CONFIG_SERIAL_NONSTANDARD is not set ++ ++# ++# Serial drivers ++# ++# CONFIG_SERIAL_8250 is not set ++ ++# ++# Non-8250 serial port support ++# ++# CONFIG_SERIAL_AMBA_PL010 is not set ++# CONFIG_SERIAL_AMBA_PL011 is not set ++CONFIG_SERIAL_EP93XX=y ++CONFIG_SERIAL_EP93XX_CONSOLE=y ++CONFIG_SERIAL_CORE=y ++CONFIG_SERIAL_CORE_CONSOLE=y ++CONFIG_UNIX98_PTYS=y ++CONFIG_LEGACY_PTYS=y ++CONFIG_LEGACY_PTY_COUNT=256 ++ ++# ++# IPMI ++# ++# CONFIG_IPMI_HANDLER is not set ++ ++# ++# Watchdog Cards ++# ++# CONFIG_WATCHDOG is not set ++# CONFIG_NVRAM is not set ++# CONFIG_RTC is not set ++# CONFIG_EP93XX_RTC is not set ++# CONFIG_DS1337_RTC is not set ++# CONFIG_DTLK is not set ++# CONFIG_R3964 is not set ++ ++# ++# Ftape, the floppy tape device driver ++# ++ ++# ++# CAN bus devices ++# ++# CONFIG_CAN_BUS is not set ++# CONFIG_RAW_DRIVER is not set ++ ++# ++# TPM devices ++# ++ ++# ++# I2C support ++# ++CONFIG_I2C=y ++CONFIG_I2C_CHARDEV=y ++ ++# ++# I2C Algorithms ++# ++CONFIG_I2C_ALGOBIT=y ++# CONFIG_I2C_ALGOPCF is not set ++# CONFIG_I2C_ALGOPCA is not set ++ ++# ++# I2C Hardware Bus support ++# ++CONFIG_I2C_EP93XX=y ++# CONFIG_I2C_ISA is not set ++# CONFIG_I2C_PARPORT_LIGHT is not set ++# CONFIG_I2C_STUB is not set ++# CONFIG_I2C_PCA_ISA is not set ++# CONFIG_I2C_SENSOR is not set ++ ++# ++# Miscellaneous I2C Chip support ++# ++# CONFIG_SENSORS_DS1337 is not set ++# CONFIG_SENSORS_DS1374 is not set ++# CONFIG_SENSORS_DS1307 is not set ++# CONFIG_SENSORS_EEPROM is not set ++# CONFIG_SENSORS_PCF8574 is not set ++# CONFIG_SENSORS_PCA9539 is not set ++# CONFIG_SENSORS_PCF8591 is not set ++# CONFIG_SENSORS_RTC8564 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 ++ ++# ++# Hardware Monitoring support ++# ++CONFIG_HWMON=y ++# 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_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_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_SMSC47M1 is not set ++# CONFIG_SENSORS_SMSC47B397 is not set ++# CONFIG_SENSORS_W83781D 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 ++ ++# ++# Misc devices ++# ++ ++# ++# Multimedia devices ++# ++# CONFIG_VIDEO_DEV is not set ++ ++# ++# Digital Video Broadcasting Devices ++# ++# CONFIG_DVB is not set ++ ++# ++# Graphics support ++# ++CONFIG_FB=y ++CONFIG_FB_CFB_FILLRECT=y ++CONFIG_FB_CFB_COPYAREA=y ++CONFIG_FB_CFB_IMAGEBLIT=y ++CONFIG_FB_SOFT_CURSOR=y ++# CONFIG_FB_MACMODES is not set ++CONFIG_FB_MODE_HELPERS=y ++# CONFIG_FB_TILEBLITTING is not set ++# CONFIG_FB_ARMCLCD is not set ++# CONFIG_FB_CX25871_I2C is not set ++CONFIG_FB_EP93XX=y ++# CONFIG_FB_CRT_EP93XX is not set ++# CONFIG_FB_LCD_EP93XX is not set ++# CONFIG_FB_LCD_EP93XX_SHARP is not set ++# CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343 is not set ++# CONFIG_FB_CX25871 is not set ++CONFIG_FB_LCD_TX09D50VM1CCA=y ++# CONFIG_FB_EP93XX_8BPP is not set ++# CONFIG_FB_EP93XX_16BPP_565 is not set ++CONFIG_FB_EP93XX_24BPP=y ++# CONFIG_FB_EP93XX_32BPP is not set ++# CONFIG_FB_S1D13XXX is not set ++# CONFIG_FB_VIRTUAL is not set ++ ++# ++# Console display driver support ++# ++# CONFIG_VGA_CONSOLE is not set ++CONFIG_DUMMY_CONSOLE=y ++CONFIG_FRAMEBUFFER_CONSOLE=y ++CONFIG_FONTS=y ++# CONFIG_FONT_8x8 is not set ++CONFIG_FONT_8x16=y ++# CONFIG_FONT_6x11 is not set ++# CONFIG_FONT_7x14 is not set ++# CONFIG_FONT_PEARL_8x8 is not set ++# CONFIG_FONT_ACORN_8x8 is not set ++# CONFIG_FONT_MINI_4x6 is not set ++CONFIG_FONT_SUN8x16=y ++# CONFIG_FONT_SUN12x22 is not set ++# CONFIG_FONT_10x18 is not set ++ ++# ++# Logo configuration ++# ++CONFIG_LOGO=y ++CONFIG_LOGO_LINUX_MONO=y ++CONFIG_LOGO_LINUX_VGA16=y ++CONFIG_LOGO_LINUX_CLUT224=y ++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set ++ ++# ++# Sound ++# ++CONFIG_SOUND=y ++ ++# ++# Advanced Linux Sound Architecture ++# ++# CONFIG_SND is not set ++ ++# ++# Open Sound System ++# ++CONFIG_SOUND_PRIME=y ++# CONFIG_SOUND_MSNDCLAS is not set ++# CONFIG_SOUND_MSNDPIN is not set ++# CONFIG_SOUND_OSS is not set ++# CONFIG_SOUND_TVMIXER is not set ++# CONFIG_SOUND_AD1980 is not set ++ ++# ++# USB support ++# ++CONFIG_USB_ARCH_HAS_HCD=y ++CONFIG_USB_ARCH_HAS_OHCI=y ++CONFIG_USB=y ++# CONFIG_USB_DEBUG is not set ++ ++# ++# Miscellaneous USB options ++# ++CONFIG_USB_DEVICEFS=y ++# CONFIG_USB_BANDWIDTH is not set ++# CONFIG_USB_DYNAMIC_MINORS is not set ++# CONFIG_USB_OTG is not set ++ ++# ++# USB Host Controller Drivers ++# ++# CONFIG_USB_ISP116X_HCD is not set ++CONFIG_USB_OHCI_HCD=y ++# CONFIG_USB_OHCI_BIG_ENDIAN is not set ++CONFIG_USB_OHCI_LITTLE_ENDIAN=y ++# CONFIG_USB_SL811_HCD is not set ++ ++# ++# USB Device Class drivers ++# ++# CONFIG_USB_AUDIO is not set ++# CONFIG_USB_BLUETOOTH_TTY is not set ++# CONFIG_USB_MIDI is not set ++# CONFIG_USB_ACM is not set ++# CONFIG_USB_PRINTER is not set ++ ++# ++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information ++# ++CONFIG_USB_STORAGE=y ++# CONFIG_USB_STORAGE_DEBUG is not set ++# CONFIG_USB_STORAGE_DATAFAB is not set ++# CONFIG_USB_STORAGE_FREECOM is not set ++# CONFIG_USB_STORAGE_ISD200 is not set ++# CONFIG_USB_STORAGE_DPCM is not set ++# CONFIG_USB_STORAGE_USBAT is not set ++# CONFIG_USB_STORAGE_SDDR09 is not set ++# CONFIG_USB_STORAGE_SDDR55 is not set ++# CONFIG_USB_STORAGE_JUMPSHOT is not set ++ ++# ++# USB Input Devices ++# ++CONFIG_USB_HID=y ++CONFIG_USB_HIDINPUT=y ++# CONFIG_HID_FF is not set ++# CONFIG_USB_HIDDEV is not set ++# CONFIG_USB_AIPTEK is not set ++# CONFIG_USB_WACOM is not set ++# CONFIG_USB_ACECAD is not set ++# CONFIG_USB_KBTAB is not set ++# CONFIG_USB_POWERMATE is not set ++# CONFIG_USB_MTOUCH is not set ++# CONFIG_USB_ITMTOUCH is not set ++# CONFIG_USB_EGALAX is not set ++# CONFIG_USB_XPAD is not set ++# CONFIG_USB_ATI_REMOTE is not set ++# CONFIG_USB_KEYSPAN_REMOTE is not set ++ ++# ++# USB Imaging devices ++# ++# CONFIG_USB_MDC800 is not set ++# CONFIG_USB_MICROTEK is not set ++ ++# ++# USB Multimedia devices ++# ++# CONFIG_USB_DABUSB is not set ++ ++# ++# Video4Linux support is needed for USB Multimedia device support ++# ++ ++# ++# USB Network Adapters ++# ++# CONFIG_USB_CATC is not set ++# CONFIG_USB_KAWETH is not set ++# CONFIG_USB_PEGASUS is not set ++# CONFIG_USB_RTL8150 is not set ++# CONFIG_USB_USBNET is not set ++# CONFIG_USB_ZD1201 is not set ++CONFIG_USB_MON=y ++ ++# ++# USB port drivers ++# ++ ++# ++# USB Serial Converter support ++# ++# CONFIG_USB_SERIAL is not set ++ ++# ++# USB Miscellaneous drivers ++# ++# CONFIG_USB_EMI62 is not set ++# CONFIG_USB_EMI26 is not set ++# CONFIG_USB_AUERSWALD is not set ++# CONFIG_USB_RIO500 is not set ++# CONFIG_USB_LEGOTOWER is not set ++# CONFIG_USB_LCD is not set ++# CONFIG_USB_LED is not set ++# CONFIG_USB_CYTHERM is not set ++# CONFIG_USB_PHIDGETKIT is not set ++# CONFIG_USB_PHIDGETSERVO is not set ++# CONFIG_USB_IDMOUSE is not set ++# CONFIG_USB_LD is not set ++# CONFIG_USB_TEST is not set ++ ++# ++# USB DSL modem support ++# ++ ++# ++# USB Gadget Support ++# ++# CONFIG_USB_GADGET is not set ++ ++# ++# MMC/SD Card support ++# ++# CONFIG_MMC is not set ++ ++# ++# File systems ++# ++CONFIG_EXT2_FS=y ++# CONFIG_EXT2_FS_XATTR is not set ++# CONFIG_EXT2_FS_XIP is not set ++CONFIG_EXT3_FS=y ++CONFIG_EXT3_FS_XATTR=y ++# CONFIG_EXT3_FS_POSIX_ACL is not set ++# CONFIG_EXT3_FS_SECURITY is not set ++CONFIG_JBD=y ++# CONFIG_JBD_DEBUG 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 ++ ++# ++# XFS support ++# ++# CONFIG_XFS_FS is not set ++# CONFIG_MINIX_FS is not set ++CONFIG_ROMFS_FS=y ++CONFIG_INOTIFY=y ++# CONFIG_QUOTA is not set ++CONFIG_DNOTIFY=y ++CONFIG_AUTOFS_FS=y ++# CONFIG_AUTOFS4_FS is not set ++ ++# ++# CD-ROM/DVD Filesystems ++# ++CONFIG_ISO9660_FS=y ++CONFIG_JOLIET=y ++CONFIG_ZISOFS=y ++CONFIG_ZISOFS_FS=y ++CONFIG_UDF_FS=y ++CONFIG_UDF_NLS=y ++ ++# ++# DOS/FAT/NT Filesystems ++# ++CONFIG_FAT_FS=y ++CONFIG_MSDOS_FS=y ++CONFIG_VFAT_FS=y ++CONFIG_FAT_DEFAULT_CODEPAGE=437 ++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" ++CONFIG_NTFS_FS=y ++# CONFIG_NTFS_DEBUG is not set ++CONFIG_NTFS_RW=y ++ ++# ++# Pseudo filesystems ++# ++CONFIG_PROC_FS=y ++CONFIG_SYSFS=y ++# CONFIG_DEVPTS_FS_XATTR is not set ++CONFIG_TMPFS=y ++# CONFIG_TMPFS_XATTR is not set ++# CONFIG_HUGETLBFS is not set ++# CONFIG_HUGETLB_PAGE is not set ++CONFIG_RAMFS=y ++ ++# ++# 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_JFFS_FS is not set ++CONFIG_JFFS2_FS=y ++CONFIG_JFFS2_FS_DEBUG=0 ++CONFIG_JFFS2_FS_WRITEBUFFER=y ++# 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=y ++CONFIG_NFS_V3=y ++# CONFIG_NFS_V3_ACL is not set ++CONFIG_NFS_V4=y ++# CONFIG_NFS_DIRECTIO is not set ++# CONFIG_NFSD is not set ++CONFIG_ROOT_NFS=y ++CONFIG_LOCKD=y ++CONFIG_LOCKD_V4=y ++CONFIG_NFS_COMMON=y ++CONFIG_SUNRPC=y ++CONFIG_SUNRPC_GSS=y ++CONFIG_RPCSEC_GSS_KRB5=y ++# CONFIG_RPCSEC_GSS_SPKM3 is not set ++# CONFIG_SMB_FS 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 ++ ++# ++# Partition Types ++# ++CONFIG_PARTITION_ADVANCED=y ++# CONFIG_ACORN_PARTITION is not set ++# CONFIG_OSF_PARTITION is not set ++# CONFIG_AMIGA_PARTITION is not set ++# CONFIG_ATARI_PARTITION is not set ++# CONFIG_MAC_PARTITION is not set ++CONFIG_MSDOS_PARTITION=y ++# CONFIG_BSD_DISKLABEL is not set ++# CONFIG_MINIX_SUBPARTITION is not set ++# CONFIG_SOLARIS_X86_PARTITION is not set ++# CONFIG_UNIXWARE_DISKLABEL is not set ++# CONFIG_LDM_PARTITION is not set ++# CONFIG_SGI_PARTITION is not set ++# CONFIG_ULTRIX_PARTITION is not set ++# CONFIG_SUN_PARTITION is not set ++# CONFIG_EFI_PARTITION is not set ++ ++# ++# Native Language Support ++# ++CONFIG_NLS=y ++CONFIG_NLS_DEFAULT="iso8859-1" ++CONFIG_NLS_CODEPAGE_437=y ++# 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=y ++# 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=y ++# CONFIG_NLS_KOI8_R is not set ++# CONFIG_NLS_KOI8_U is not set ++CONFIG_NLS_UTF8=y ++ ++# ++# Profiling support ++# ++# CONFIG_PROFILING is not set ++ ++# ++# Kernel hacking ++# ++# CONFIG_PRINTK_TIME is not set ++CONFIG_DEBUG_KERNEL=y ++# CONFIG_MAGIC_SYSRQ is not set ++CONFIG_LOG_BUF_SHIFT=14 ++# CONFIG_SCHEDSTATS is not set ++# CONFIG_DEBUG_SLAB is not set ++# CONFIG_DEBUG_SPINLOCK is not set ++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set ++# CONFIG_DEBUG_KOBJECT is not set ++CONFIG_DEBUG_BUGVERBOSE=y ++CONFIG_DEBUG_INFO=y ++# CONFIG_DEBUG_FS is not set ++CONFIG_FRAME_POINTER=y ++CONFIG_DEBUG_USER=y ++# CONFIG_DEBUG_WAITQ is not set ++CONFIG_DEBUG_ERRORS=y ++CONFIG_DEBUG_DONT_REORDER_CODE=y ++CONFIG_DEBUG_LL=y ++# CONFIG_DEBUG_ICEDCC is not set ++ ++# ++# Security options ++# ++# CONFIG_KEYS is not set ++# CONFIG_SECURITY is not set ++ ++# ++# Cryptographic options ++# ++CONFIG_CRYPTO=y ++# CONFIG_CRYPTO_HMAC is not set ++# CONFIG_CRYPTO_NULL is not set ++# CONFIG_CRYPTO_MD4 is not set ++CONFIG_CRYPTO_MD5=y ++# CONFIG_CRYPTO_SHA1 is not set ++# CONFIG_CRYPTO_SHA256 is not set ++# CONFIG_CRYPTO_SHA512 is not set ++# CONFIG_CRYPTO_WP512 is not set ++# CONFIG_CRYPTO_TGR192 is not set ++CONFIG_CRYPTO_DES=y ++# CONFIG_CRYPTO_BLOWFISH is not set ++# CONFIG_CRYPTO_TWOFISH is not set ++# CONFIG_CRYPTO_SERPENT is not set ++# CONFIG_CRYPTO_AES is not set ++# CONFIG_CRYPTO_CAST5 is not set ++# CONFIG_CRYPTO_CAST6 is not set ++# CONFIG_CRYPTO_TEA is not set ++# CONFIG_CRYPTO_ARC4 is not set ++# CONFIG_CRYPTO_KHAZAD is not set ++# CONFIG_CRYPTO_ANUBIS is not set ++# CONFIG_CRYPTO_DEFLATE is not set ++# CONFIG_CRYPTO_MICHAEL_MIC is not set ++# CONFIG_CRYPTO_CRC32C is not set ++# CONFIG_CRYPTO_TEST is not set ++ ++# ++# Hardware crypto devices ++# ++ ++# ++# Library routines ++# ++# CONFIG_CRC_CCITT is not set ++CONFIG_CRC32=y ++CONFIG_LIBCRC32C=y ++CONFIG_ZLIB_INFLATE=y ++CONFIG_ZLIB_DEFLATE=y +diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig +new file mode 100644 +index 0000000..2b5c2d6 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/Kconfig +@@ -0,0 +1,193 @@ ++ ++menu "EP93xx" ++ depends on ARCH_EP93XX ++ ++choice ++ prompt "EP93xx CPU Type" ++ default EP9312 ++ help ++ There are several types of EP93xx CPUs available. ++ Choosing the right one here enables you to select ++ model specific drivers later. ++ ++config ARCH_EP9301 ++ bool "EP9301" ++ help ++ Say Y here if you have intend to run this kernel on a EP9301 CPU. ++ ++config ARCH_EP9302 ++ bool "EP9302" ++ help ++ Say Y here if you have intend to run this kernel on a EP9302 CPU. ++ ++config ARCH_EP9312 ++ bool "EP9312" ++ help ++ Say Y here if you intend to run this kernel on a EP9312 CPU. ++ ++ ++config ARCH_EP9315 ++ bool "EP9315" ++ help ++ Say Y here if you intend to run this kernel on a EP9315 CPU. ++endchoice ++ ++choice ++ prompt "EP9301 Boards" ++ depends on ARCH_EP9301 ++ default EDB9301 ++ help ++ There are several EP9301-based boards available. ++ Choosing the right one here enables various board- ++ specific options. ++ ++config MACH_EDB9301 ++ bool "Cirrus Logic EDB9301" ++ select MTD ++ select MTD_PHYSMAP ++ help ++ Say Y here if you intend to run this kernel on an EDB9301. ++ ++config MACH_TTML ++ bool "TTML TripDawg" ++ help ++ Say Y here if you intend to run this kernel on an TTML TripDawg. ++ ++endchoice ++ ++choice ++ prompt "EP9302 Boards" ++ depends on ARCH_EP9302 ++ default EDB9302 ++ help ++ There are several EP9302-based boards available. ++ Choosing the right one here enables various board- ++ specific options. ++ ++config MACH_EDB9302 ++ bool "Cirrus Logic EDB9302" ++ select MTD ++ select MTD_PHYSMAP ++ help ++ Say Y here if you intend to run this kernel on an EDB9302. ++ ++config MACH_ZEFEERDZB ++ bool "Dave Zefeer DZB on ZefeerEVB-L" ++ select MTD ++ help ++ Say Y here if you intend to run this kernel on an Zefeer DZB. ++ pluggend onto ZefeerEVB-L board. ++ ++config MACH_ZEFEER_EVBL_107 ++ bool " Dave ZefeerEVB-L - version 1.0.7 (PCB CS044404)" ++ depends on MACH_ZEFEERDZB ++ default n ++ help ++ Say Y here if you intend to run this kernel on an ZefeerEVB-L ++ version 1.0.7. ++ ++endchoice ++ ++choice ++ prompt "EP9312 Boards" ++ depends on ARCH_EP9312 ++ default EDB9312 ++ help ++ There are several EP9312-based boards available. ++ Choosing the right one here enables various board- ++ specific options. ++ ++config MACH_EDB9312 ++ bool "Cirrus Logic EDB9312" ++ select MTD ++ select MTD_PHYSMAP ++ help ++ Say Y here if you intend to run this kernel on an EDB9312. ++ ++ ++config MACH_ACC ++ bool "HiFish ACC" ++ help ++ Say Y here if you are using the HiFish Audio Control Center" ++ ++endchoice ++ ++choice ++ prompt "EP9315 Boards" ++ depends on ARCH_EP9315 ++ default EDB9315 ++ help ++ There are several EP9315-based boards available. ++ Choosing the right one here enables various board- ++ specific options. ++ ++config MACH_EDB9315 ++ bool "Cirrus Logic EDB9315" ++ select MTD ++ select MTD_PHYSMAP ++ help ++ Say Y here if you intend to run this kernel on an EDB9315. ++ ++config MACH_ADSSPHERE ++ bool "Applied Data Systems Sphere" ++ select MTD ++ help ++ Say Y here if you intend to run this kernel on an ADSSPHERE. ++ ++config MACH_ZEFEERDZQ ++ bool "Dave Zefeer DZQ on ZefeerEVB (L or H)" ++ select MTD ++ help ++ Say Y here if you intend to run this kernel on an Zefeer DZQ. ++ Both evaluation board are supported (ZefeerEVB-L/ZefeerEVB-H). ++ ++config MACH_DMA03 ++ bool "Gassner DMA03" ++ select MTD ++ select MTD_PHYSMAP ++ help ++ Say Y here if you intend to run this kernel on an DMA03. ++ ++endchoice ++ ++config ARCH_EP93XX_GPIO_IRQ ++ bool " EP93xx GPIO IRQ demux" ++ depends on ARCH_EP93XX ++ help ++ Say Y here if you want to expand the IRQ number to GPIO IRQ. ++ ++config EP93XX_DMA ++ bool " EP93xx Internal DMA Support" ++ default y ++ help ++ Say Y here if you want to enable DMA Support for EP93XX family ++ CPUs. ++ ++config EP93XX_SSP ++ bool "SSP support" ++ help ++ If you require SSP support, there are two SSP drivers ++ available to choose from. ++ ++choice ++ prompt "SSP driver" ++ depends on EP93XX_SSP ++ default EP93XX_SSP_LINUX ++ ++config EP93XX_SSP_CIRRUS ++ tristate "Cirrus Logic SSP driver" ++ depends on EP93XX_SSP ++ help ++ Say Y here for the Cirrus-supplied SSP driver. It is ++ quite specific to the EDB93xx evaluation boards. ++ ++config EP93XX_SSP_LINUX ++ tristate "Linux SSP driver" ++ depends on EP93XX_SSP ++ help ++ Say Y here for an SSP driver which is heavily based on the ++ SA-1100 and PXA2xx SSP drivers. ++ ++endchoice ++ ++endmenu +diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile +new file mode 100644 +index 0000000..19c56b3 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/Makefile +@@ -0,0 +1,17 @@ ++obj-y += ep93xx.o irq.o time.o ++ ++obj-$(CONFIG_MACH_ACC) += mach-acc.o ++obj-$(CONFIG_MACH_EDB9301) += mach-edb9301.o ++obj-$(CONFIG_MACH_EDB9302) += mach-edb9302.o ++obj-$(CONFIG_MACH_EDB9312) += mach-edb9312.o ++obj-$(CONFIG_MACH_EDB9315) += mach-edb9315.o ++obj-$(CONFIG_MACH_ADSSPHERE) += mach-adssphere.o ++obj-$(CONFIG_MACH_TTML) += mach-ttml.o ++obj-$(CONFIG_MACH_ZEFEERDZB) += mach-zefeerdzb.o ++obj-$(CONFIG_MACH_ZEFEERDZQ) += mach-zefeerdzq.o ++obj-$(CONFIG_MACH_DMA03) += mach-dma03.o ++ ++obj-$(CONFIG_EP93XX_DMA) += dma_ep93xx.o ++ ++obj-$(CONFIG_EP93XX_SSP_LINUX) += ssp.o ssp2.o ++obj-$(CONFIG_EP93XX_SSP_CIRRUS) += ssp-cirrus.o +diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot +new file mode 100644 +index 0000000..c87653e +--- /dev/null ++++ b/arch/arm/mach-ep93xx/Makefile.boot +@@ -0,0 +1,6 @@ ++ zreladdr-y := 0x00008000 ++params_phys-y := 0x00000100 ++ zreladdr-$(CONFIG_MACH_ZEFEERDZB) := 0xD0008000 ++params_phys-$(CONFIG_MACH_ZEFEERDZB) := 0xD0000100 ++ zreladdr-$(CONFIG_MACH_ZEFEERDZQ) := 0xD0008000 ++params_phys-$(CONFIG_MACH_ZEFEERDZQ) := 0xD0000100 +diff --git a/arch/arm/mach-ep93xx/dma_ep93xx.c b/arch/arm/mach-ep93xx/dma_ep93xx.c +new file mode 100644 +index 0000000..817de48 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/dma_ep93xx.c +@@ -0,0 +1,3346 @@ ++/****************************************************************************** ++ * arch/arm/mach-ep9312/dma_ep93xx.c ++ * ++ * Support functions for the ep93xx internal DMA channels. ++ * (see also Documentation/arm/ep93xx/dma.txt) ++ * ++ * Copyright (C) 2003 Cirrus Logic ++ * ++ * A large portion of this file is based on the dma api implemented by ++ * Nicolas Pitre, dma-sa1100.c, copyrighted 2000. ++ * ++ * ++ * 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/init.h> ++#include <linux/sched.h> ++#include <linux/spinlock.h> ++#include <linux/slab.h> ++#include <linux/errno.h> ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++ ++#include <asm/system.h> ++#include <asm/irq.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/dma.h> ++#include <asm/mach/dma.h> ++#include "dma_ep93xx.h" ++ ++/***************************************************************************** ++ * ++ * Debugging macros ++ * ++ ****************************************************************************/ ++#undef DEBUG ++/*#define DEBUG 1 */ ++#ifdef DEBUG ++#define DPRINTK( x... ) printk( ##x ) ++#else ++#define DPRINTK( x... ) ++#endif ++ ++/***************************************************************************** ++ * ++ * static global variables ++ * ++ ****************************************************************************/ ++ep93xx_dma_t dma_chan[MAX_EP93XX_DMA_CHANNELS]; ++ ++/* ++ * Maximum physical DMA buffer size ++ */ ++#define MAX_DMA_SIZE 0xffff ++#define MAX_DMA_ORDER 12 ++ ++/* ++ * lock used to protect the list of dma channels while searching for a free ++ * channel during dma_request. ++ */ ++static spinlock_t dma_list_lock = SPIN_LOCK_UNLOCKED; ++ ++/***************************************************************************** ++ * ++ * Internal DMA processing functions. ++ * ++ ****************************************************************************/ ++/***************************************************************************** ++ * ++ * get_dma_channel_from_handle() ++ * ++ * If Handle is valid, returns the DMA channel # (0 to 9 for channels 1-10) ++ * If Handle is not valid, returns -1. ++ * ++ ****************************************************************************/ ++static int dma_get_channel_from_handle(int handle) ++{ ++ int channel; ++ ++ /* ++ * Get the DMA channel # from the handle. ++ */ ++ channel = ((int)handle & DMA_HANDLE_SPECIFIER_MASK) >> 28; ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (dma_chan[channel].last_valid_handle != (int)handle) { ++ DPRINTK("DMA ERROR - invalid handle 0x%x \n", handle); ++ /* ++ * Fail, invalid handle ++ */ ++ return (-1); ++ } ++ ++ /* ++ * See if this instance is still open ++ */ ++ if (!dma_chan[channel].ref_count) { ++ /* ++ * Fail, instance closed ++ */ ++ return (-1); ++ } ++ ++ return (channel); ++} ++ ++/***************************************************************************** ++ * ++ * dma_m2m_irq_handler ++ * ++ * TODO: need to add support for M2M interrupt handling!!! ++ * ++ ****************************************************************************/ ++static irqreturn_t ++dma_m2m_irq_handler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ ep93xx_dma_t *dma = (ep93xx_dma_t *) dev_id; ++ unsigned int M2M_reg_base = dma->reg_base; ++ ep93xx_dma_dev_t dma_int = UNDEF_INT; ++ unsigned int read_back, loop, uiCONTROL, uiINTERRUPT; ++ ++ loop = readl(M2M_reg_base + M2M_OFFSET_INTERRUPT); ++ ++ /* ++ * Determine what kind of dma interrupt this is. ++ */ ++ if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) & ++ INTERRUPT_M2M_STALLINT) ++ dma_int = STALL; ++ else if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) & ++ INTERRUPT_M2M_NFBINT) ++ dma_int = NFB; ++ else if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) & ++ INTERRUPT_M2M_DONEINT) ++ dma_int = DONE; ++ ++ DPRINTK("IRQ: b=%#x st=%#x\n", (int)dma->current_buffer->source, ++ dma_int); ++ ++ /* ++ * Stall Interrupt: The Channel is stalled, meaning nothing is ++ * programmed to transfer right now. So, we're back to the ++ * beginnning. If there's a buffer to transfer, program it into ++ * max and base 0 registers. ++ */ ++ if (dma_int == STALL) { ++ DPRINTK("1 "); ++ ++ if (dma->total_buffers) { ++ ++ if (readl(M2M_reg_base + M2M_OFFSET_BCR0) != ++ 0) { ++ writel(0x0, M2M_reg_base + M2M_OFFSET_INTERRUPT); ++ return IRQ_HANDLED; ++ ++ } ++ ++ /* ++ * The current_buffer has already been tranfered, so add the ++ * byte count to the total_bytes field. ++ */ ++ dma->total_bytes = dma->total_bytes + ++ dma->buffer_queue[dma->current_buffer].size; ++ ++ /* ++ * Mark the current_buffer as used. ++ */ ++ dma->buffer_queue[dma->current_buffer].used = TRUE; ++ ++ /* ++ * Increment the used buffer counter ++ */ ++ dma->used_buffers++; ++ ++ DPRINTK("#%d", dma->current_buffer); ++ ++ /* ++ * Increment the current_buffer ++ */ ++ dma->current_buffer = (dma->current_buffer + 1) % ++ MAX_EP93XX_DMA_BUFFERS; ++ ++ /* ++ * check if there's a new buffer to transfer. ++ */ ++ if (dma->new_buffers && dma->xfer_enable) { ++ /* ++ * We have a new buffer to transfer so program in the buffer ++ * values. Since a STALL interrupt was triggered, we ++ * program the buffer descriptor 0 ++ * ++ * Set the SAR_BASE/DAR_BASE/BCR registers with values from the ++ * next buffer in the queue. ++ */ ++ writel(dma->buffer_queue[dma->current_buffer]. ++ source, ++ M2M_reg_base + M2M_OFFSET_SAR_BASE0); ++ writel(dma->buffer_queue[dma->current_buffer]. ++ dest, ++ M2M_reg_base + M2M_OFFSET_DAR_BASE0); ++ writel(dma->buffer_queue[dma->current_buffer]. ++ size, ++ M2M_reg_base + M2M_OFFSET_BCR0); ++ ++ /* ++ * Decrement the new buffer counter ++ */ ++ dma->new_buffers--; ++ ++ /* ++ * If there's a second new buffer, we program the second ++ * buffer descriptor. ++ */ ++#if 0 ++ if (dma->new_buffers) { ++ DPRINTK("A "); ++ ++ /* ++ * Set the SAR_BASE/DAR_BASE/BCR registers with values from the ++ * next buffer in the queue. ++ */ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ source, ++ M2M_reg_base + M2M_OFFSET_SAR_BASE1); ++ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ dest, ++ M2M_reg_base + M2M_OFFSET_DAR_BASE0); ++ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ size, ++ M2M_reg_base + M2M_OFFSET_BCR0); ++ ++ /* ++ * Decrement the new buffer counter ++ */ ++ dma->new_buffers--; ++ ++ /* ++ * Enable the NFB Interrupt. ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL |= CONTROL_M2M_NFBINTEN; ++ writel(uiCONTROL, ++ M2M_reg_base + M2M_OFFSET_CONTROL); ++ } ++#endif ++ } ++ /* ++ * Read my lips. No new buffers. ++ */ ++ else { ++ DPRINTK("2 \n"); ++ /* ++ * There's a chance we setup both buffer descriptors, but ++ * didn't service the NFB quickly enough, causing the channel ++ * to transfer both buffers, then enter the stall state. ++ * So, we need to be able to process the second buffer. ++ */ ++ if ((dma->used_buffers + dma->new_buffers) < ++ dma->total_buffers) { ++ DPRINTK("3 "); ++ ++ /* ++ * The current_buffer has already been tranfered, so add the ++ * byte count to the total_bytes field. ++ */ ++ dma->total_bytes = dma->total_bytes + ++ dma->buffer_queue[dma-> ++ current_buffer]. ++ size; ++ ++ /* ++ * Mark the current_buffer as used. ++ */ ++ dma->buffer_queue[dma->current_buffer]. ++ used = TRUE; ++ ++ /* ++ * Increment the used buffer counter ++ */ ++ dma->used_buffers++; ++ ++ DPRINTK("#%d", dma->current_buffer); ++ ++ /* ++ * Increment the current buffer pointer. ++ */ ++ dma->current_buffer = ++ (dma->current_buffer + ++ 1) % MAX_EP93XX_DMA_BUFFERS; ++ ++ } ++ ++ /* ++ * No new buffers to transfer, so disable the channel. ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2M_ENABLE; ++ writel(uiCONTROL, ++ M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * Indicate that this channel is in the pause by starvation ++ * state by setting the pause bit to true. ++ */ ++ dma->pause = TRUE; ++ ++ DPRINTK("End of stall handling. \n"); ++ DPRINTK("STATUS - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_STATUS)); ++ DPRINTK("CONTROL - 0x%x \n", ++ readl(M2M_reg_base + M2M_CONTROL.Value)); ++ DPRINTK("REMAIN - 0x%x \n", ++ readl(M2M_reg_base + M2M_REMAIN.Value)); ++ DPRINTK("PPALLOC - 0x%x \n", ++ readl(M2M_reg_base + M2M_PPALLOC.Value)); ++ DPRINTK("BASE0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_BASE0.Value)); ++ DPRINTK("MAXCNT0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_MAXCNT0.Value)); ++ DPRINTK("CURRENT0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_CURRENT0.Value)); ++ DPRINTK("BASE1 - 0x%x \n", ++ readl(M2M_reg_base + M2M_BASE1.Value)); ++ DPRINTK("MAXCNT1 - 0x%x \n", ++ readl(M2M_reg_base + M2M_MAXCNT1.Value)); ++ DPRINTK("CURRENT1 - 0x%x \n", ++ readl(M2M_reg_base + M2M_CURRENT1.Value)); ++ ++ DPRINTK ++ ("Buffer buf_id source size last used \n"); ++ for (loop = 0; loop < 32; loop++) { ++ DPRINTK ++ ("%d 0x%x 0x%x 0x%x %d %d \n", ++ loop, ++ dma->buffer_queue[loop].buf_id, ++ dma->buffer_queue[loop].source, ++ dma->buffer_queue[loop].size, ++ dma->buffer_queue[loop].last, ++ dma->buffer_queue[loop].used); ++ } ++ DPRINTK("Pause - %d \n", dma->pause); ++ DPRINTK("xfer_enable - %d \n", ++ dma->xfer_enable); ++ DPRINTK("total bytes - 0x%x \n", ++ dma->total_bytes); ++ DPRINTK("total buffer - %d \n", ++ dma->total_buffers); ++ DPRINTK("new buffers - %d \n", ++ dma->new_buffers); ++ DPRINTK("current buffer - %d \n", ++ dma->current_buffer); ++ DPRINTK("last buffer - %d \n", ++ dma->last_buffer); ++ DPRINTK("used buffers - %d \n", ++ dma->used_buffers); ++ DPRINTK("callback addr - 0x%x \n", ++ dma->callback); ++ } ++ } ++ /* ++ * Total number of buffers in the queue is 0. ++ */ ++ else { ++ /* ++ * No buffers to transfer, or old buffers to mark as used, ++ * so Disable the channel ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2M_ENABLE; ++ writel(uiCONTROL, ++ M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * Must read the control register back after a write. ++ */ ++ read_back = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * Indicate that this channel is in the pause by ++ * starvation state by setting the pause bit to true. ++ */ ++ dma->pause = TRUE; ++ } ++ } ++ /* ++ * Next Frame Buffer Interrupt. If there's a new buffer program it ++ * Check if this is the last buffer in the transfer, ++ * and if it is, disable the NFB int to prevent being ++ * interrupted for another buffer when we know there won't be ++ * another. ++ */ ++ if (dma_int == NFB) { ++ DPRINTK("5 "); ++ ++ if (dma->total_buffers) { ++ DPRINTK("6 "); ++ /* ++ * The iCurrentBuffer has already been transfered. so add the ++ * byte count from the current buffer to the total byte count. ++ */ ++ dma->total_bytes = dma->total_bytes + ++ dma->buffer_queue[dma->current_buffer].size; ++ ++ /* ++ * Mark the Current Buffer as used. ++ */ ++ dma->buffer_queue[dma->current_buffer].used = TRUE; ++ ++ /* ++ * Increment the used buffer counter ++ */ ++ dma->used_buffers++; ++ ++ DPRINTK("#%d", dma->current_buffer); ++ ++ if ((dma->buffer_queue[(dma->current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS].last) ++ || (dma->new_buffers == 0) ++ || (dma->xfer_enable == FALSE)) { ++ DPRINTK("7 "); ++ ++ /* ++ * This is the last Buffer in this transaction, so disable ++ * the NFB interrupt. We shouldn't get an NFB int when the ++ * FSM moves to the ON state where it would typically get the ++ * NFB int indicating a new buffer can be programmed. ++ * Instead, once in the ON state, the DMA will just proceed ++ * to complet the transfer of the current buffer, move the ++ * FSB directly to the STALL state where a STALL interrupt ++ * will be generated. ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2M_NFBINTEN; ++ writel(uiCONTROL, ++ M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * The current buffer has been transferred, so increment ++ * the current buffer counter to reflect this. ++ */ ++ dma->current_buffer = ++ (dma->current_buffer + ++ 1) % MAX_EP93XX_DMA_BUFFERS; ++ ++ DPRINTK("End of NFB handling. \n"); ++ DPRINTK("STATUS - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_STATUS)); ++ DPRINTK("CONTROL - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL)); ++ DPRINTK("REMAIN - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_REMAIN)); ++ DPRINTK("PPALLOC - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_PPALLOC)); ++ DPRINTK("BASE0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_BASE0)); ++ DPRINTK("MAXCNT0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_MAXCNT0)); ++ DPRINTK("CURRENT0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_CURRENT0)); ++ DPRINTK("BASE1 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_BASE1)); ++ DPRINTK("MAXCNT1 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_MAXCNT1)); ++ DPRINTK("CURRENT1 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_CURRENT1)); ++ ++ DPRINTK ++ ("Buffer buf_id source size last used \n"); ++ for (loop = 0; loop < 32; loop++) { ++ DPRINTK ++ ("%d 0x%x 0x%x 0x%x %d %d \n", ++ loop, ++ dma->buffer_queue[loop].buf_id, ++ dma->buffer_queue[loop].source, ++ dma->buffer_queue[loop].size, ++ dma->buffer_queue[loop].last, ++ dma->buffer_queue[loop].used); ++ } ++ DPRINTK ++ ("pause 0x%x 0x%x 0x%x %d %d \n", ++ dma->pause_buf.buf_id, ++ dma->pause_buf.source, dma->pause_buf.size, ++ dma->pause_buf.last, dma->pause_buf.used); ++ ++ DPRINTK("Pause - %d \n", dma->pause); ++ DPRINTK("xfer_enable - %d \n", ++ dma->xfer_enable); ++ DPRINTK("total bytes - 0x%x \n", ++ dma->total_bytes); ++ DPRINTK("total buffer - %d \n", ++ dma->total_buffers); ++ DPRINTK("new buffers - %d \n", ++ dma->new_buffers); ++ DPRINTK("current buffer - %d \n", ++ dma->current_buffer); ++ DPRINTK("last buffer - %d \n", ++ dma->last_buffer); ++ DPRINTK("used buffers - %d \n", ++ dma->used_buffers); ++ DPRINTK("callback addr - 0x%x \n", ++ dma->callback); ++ ++ } else if (dma->new_buffers) { ++ DPRINTK("8 "); ++ /* ++ * we have a new buffer, so increment the current buffer to ++ * point to the next buffer, which is already programmed into ++ * the DMA. Next time around, it'll be pointing to the ++ * current buffer. ++ */ ++ dma->current_buffer = ++ (dma->current_buffer + ++ 1) % MAX_EP93XX_DMA_BUFFERS; ++ ++ /* ++ * we know we have a new buffer to program as the next ++ * buffer, so check which set of SAR_BASE/DAR_BASE/BCR registers ++ * to program. ++ */ ++ if (readl(M2M_reg_base + M2M_OFFSET_STATUS) & STATUS_M2M_NB) { ++ /* ++ * Set the SAR_BASE1/DAR_BASE1/BCR1 registers with values from the ++ * next buffer in the queue. ++ */ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ source, ++ M2M_reg_base + M2M_OFFSET_SAR_BASE1); ++ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ dest, ++ M2M_reg_base + M2M_OFFSET_DAR_BASE1); ++ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ size, ++ M2M_reg_base + M2M_OFFSET_BCR1); ++ } else { ++ /* ++ * Set the SAR_BASE0/DAR_BASE0/BCR0 registers with values from the ++ * next buffer in the queue. ++ */ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ source, ++ M2M_reg_base + M2M_OFFSET_SAR_BASE0); ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ dest, ++ M2M_reg_base + M2M_OFFSET_DAR_BASE0); ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ size, ++ M2M_reg_base + M2M_OFFSET_BCR0); ++ } ++ ++ /* ++ * Decrement the new buffers counter ++ */ ++ dma->new_buffers--; ++ } ++ } ++ /* ++ * Total number of buffers is 0 - really we should never get here, ++ * but just in case. ++ */ ++ else { ++ DPRINTK("9 \n"); ++ ++ /* ++ * No new buffers to transfer, so Disable the channel ++ */ ++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2M_ENABLE; ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * Indicate that the channel is paused by starvation. ++ */ ++ dma->pause = 1; ++ } ++ } ++ ++ /* ++ * Done interrupt generated, indicating that the transfer is complete. ++ */ ++ if (dma_int == DONE) { ++#if 0 ++ /* The current_buffer has already been tranfered, so add the ++ * byte count to the total_bytes field. ++ */ ++ dma->total_bytes = dma->total_bytes + ++ dma->buffer_queue[dma->current_buffer].size; ++ ++ /* ++ * Mark the current_buffer as used. ++ */ ++ dma->buffer_queue[dma->current_buffer].used = TRUE; ++ ++ /* ++ * Increment the used buffer counter ++ */ ++ dma->used_buffers++; ++ ++ /* ++ * Increment the current_buffer ++ */ ++ dma->current_buffer = (dma->current_buffer + 1) % ++ MAX_EP93XX_DMA_BUFFERS; ++#endif ++ /* ++ * Clear the interrupt. ++ */ ++ uiINTERRUPT = ++ readl(M2M_reg_base + M2M_OFFSET_INTERRUPT); ++ uiINTERRUPT &= ~INTERRUPT_M2M_DONEINT; ++ writel(uiINTERRUPT, ++ M2M_reg_base + M2M_OFFSET_INTERRUPT); ++ ++ DPRINTK("STATUS - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_STATUS)); ++ DPRINTK("CONTROL - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL)); ++ DPRINTK("SAR_BASE0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_SAR_BASE0)); ++ DPRINTK("DAR_BASE0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_DAR_BASE0)); ++ DPRINTK("SAR_CURRENT0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_SAR_CURRENT0)); ++ DPRINTK("DAR_CURRENT0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_DAR_CURRENT0)); ++ DPRINTK("BCR0 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_BCR0)); ++ DPRINTK("SAR_BASE1 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_SAR_BASE1)); ++ DPRINTK("DAR_BASE1 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_DAR_BASE1)); ++ DPRINTK("BCR1 - 0x%x \n", ++ readl(M2M_reg_base + M2M_OFFSET_BCR1)); ++ ++ /* ++ * Disable the channel. ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2M_ENABLE; ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * Indicate that we're in the stopped mode. ++ */ ++ dma->pause = 1; ++ dma->xfer_enable = 0; ++ } ++ ++ /* ++ * Make sure the interrupt was valid, and if it was, then check ++ * if a callback function was installed for this DMA channel. If a ++ * callback was installed call it. ++ */ ++ if ((dma_int != UNDEF_INT) && dma->callback) { ++ dma->callback(dma_int, dma->device, dma->user_data); ++ } ++ return IRQ_HANDLED; ++} ++ ++/***************************************************************************** ++ * ++ * dma_m2p_irq_handler ++ * ++ * ++ * ++ ****************************************************************************/ ++static irqreturn_t ++dma_m2p_irq_handler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ ep93xx_dma_t *dma = (ep93xx_dma_t *) dev_id; ++ unsigned int M2P_reg_base = dma->reg_base; ++ unsigned int read_back; ++ ep93xx_dma_dev_t dma_int = UNDEF_INT; ++ unsigned int loop, uiCONTROL, uiINTERRUPT; ++ ++ /* ++ * Determine what kind of dma interrupt this is. ++ */ ++ if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) & ++ INTERRUPT_M2P_STALLINT) ++ dma_int = STALL; ++ else if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) & ++ INTERRUPT_M2P_NFBINT) ++ dma_int = NFB; ++ else if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) & ++ INTERRUPT_M2P_CHERRORINT) ++ dma_int = CHERROR; ++ ++ /* ++ * Stall Interrupt: The Channel is stalled, meaning nothing is ++ * programmed to transfer right now. So, we're back to the ++ * beginnning. If there's a buffer to transfer, program it into ++ * max and base 0 registers. ++ */ ++ if (dma_int == STALL) { ++ DPRINTK("1 "); ++ ++ if (dma->total_buffers) { ++ /* ++ * The current_buffer has already been tranfered, so add the ++ * byte count to the total_bytes field. ++ */ ++ dma->total_bytes = dma->total_bytes + ++ dma->buffer_queue[dma->current_buffer].size; ++ ++ /* ++ * Mark the current_buffer as used. ++ */ ++ dma->buffer_queue[dma->current_buffer].used = TRUE; ++ ++ /* ++ * Increment the used buffer counter ++ */ ++ dma->used_buffers++; ++ ++ DPRINTK("#%d", dma->current_buffer); ++ ++ /* ++ * Increment the current_buffer ++ */ ++ dma->current_buffer = (dma->current_buffer + 1) % ++ MAX_EP93XX_DMA_BUFFERS; ++ ++ /* ++ * check if there's a new buffer to transfer. ++ */ ++ if (dma->new_buffers && dma->xfer_enable) { ++ /* ++ * We have a new buffer to transfer so program in the buffer ++ * values. Since a STALL interrupt was triggered, we ++ * program the base0 and maxcnt0 ++ * ++ * Set the MAXCNT0 register with the buffer size ++ */ ++ writel(dma->buffer_queue[dma->current_buffer].size, ++ M2P_reg_base + M2P_OFFSET_MAXCNT0); ++ ++ /* ++ * Set the BASE0 register with the buffer base address ++ */ ++ writel(dma->buffer_queue[dma->current_buffer].source, ++ M2P_reg_base + M2P_OFFSET_BASE0); ++ ++ /* ++ * Decrement the new buffer counter ++ */ ++ dma->new_buffers--; ++ ++ if (dma->new_buffers) { ++ DPRINTK("A "); ++ /* ++ * Set the MAXCNT1 register with the buffer size ++ */ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ size, ++ M2P_reg_base + M2P_OFFSET_MAXCNT1); ++ ++ /* ++ * Set the BASE1 register with the buffer base address ++ */ ++ writel(dma-> ++ buffer_queue[dma-> ++ current_buffer + ++ 1 % ++ MAX_EP93XX_DMA_BUFFERS]. ++ source, ++ M2P_reg_base + M2P_OFFSET_BASE1); ++ ++ /* ++ * Decrement the new buffer counter ++ */ ++ dma->new_buffers--; ++ ++ /* ++ * Enable the NFB Interrupt. ++ */ ++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ uiCONTROL |= CONTROL_M2P_NFBINTEN; ++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL); ++ } ++ } ++ /* ++ * No new buffers. ++ */ ++ else { ++ DPRINTK("2 \n"); ++ /* ++ * There's a chance we setup both buffer descriptors, but ++ * didn't service the NFB quickly enough, causing the channel ++ * to transfer both buffers, then enter the stall state. ++ * So, we need to be able to process the second buffer. ++ */ ++ if ((dma->used_buffers + dma->new_buffers) < ++ dma->total_buffers) { ++ DPRINTK("3 "); ++ ++ /* ++ * The current_buffer has already been tranfered, so add the ++ * byte count to the total_bytes field. ++ */ ++ dma->total_bytes = dma->total_bytes + ++ dma->buffer_queue[dma-> ++ current_buffer]. ++ size; ++ ++ /* ++ * Mark the current_buffer as used. ++ */ ++ dma->buffer_queue[dma->current_buffer]. ++ used = TRUE; ++ ++ /* ++ * Increment the used buffer counter ++ */ ++ dma->used_buffers++; ++ ++ DPRINTK("#%d", dma->current_buffer); ++ ++ /* ++ * Increment the current buffer pointer. ++ */ ++ dma->current_buffer = ++ (dma->current_buffer + ++ 1) % MAX_EP93XX_DMA_BUFFERS; ++ ++ } ++ ++ /* ++ * No new buffers to transfer, so disable the channel. ++ */ ++ /* go dma_regs->CONTROL.Field.ENABLE = 0; */ ++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2P_ENABLE; ++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL); ++ ++ /* ++ * Indicate that this channel is in the pause by starvation ++ * state by setting the pause bit to true. ++ */ ++ dma->pause = TRUE; ++ ++ DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS)); ++ DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL)); ++ DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN)); ++ DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC)); ++ DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0)); ++ DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0)); ++ DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0)); ++ DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1)); ++ DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1)); ++ DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1)); ++ ++ DPRINTK ++ ("Buffer buf_id source size last used \n"); ++ for (loop = 0; loop < 32; loop++) { ++ DPRINTK ++ ("%d 0x%x 0x%x 0x%x %d %d \n", ++ loop, ++ dma->buffer_queue[loop].buf_id, ++ dma->buffer_queue[loop].source, ++ dma->buffer_queue[loop].size, ++ dma->buffer_queue[loop].last, ++ dma->buffer_queue[loop].used); ++ } ++ DPRINTK ++ ("pause 0x%x 0x%x 0x%x %d %d \n", ++ dma->pause_buf.buf_id, ++ dma->pause_buf.source, dma->pause_buf.size, ++ dma->pause_buf.last, dma->pause_buf.used); ++ ++ DPRINTK("Pause - %d \n", dma->pause); ++ DPRINTK("xfer_enable - %d \n", ++ dma->xfer_enable); ++ DPRINTK("total bytes - 0x%x \n", ++ dma->total_bytes); ++ DPRINTK("total buffer - %d \n", ++ dma->total_buffers); ++ DPRINTK("new buffers - %d \n", ++ dma->new_buffers); ++ DPRINTK("current buffer - %d \n", ++ dma->current_buffer); ++ DPRINTK("last buffer - %d \n", ++ dma->last_buffer); ++ DPRINTK("used buffers - %d \n", ++ dma->used_buffers); ++ DPRINTK("callback addr - 0x%x \n", ++ dma->callback); ++ } ++ } ++ /* ++ * Total number of buffers in the queue is 0. ++ */ ++ else { ++ /* ++ * No buffers to transfer, or old buffers to mark as used, ++ * so Disable the channel ++ */ ++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2P_ENABLE; ++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL); ++ ++ /* ++ * Must read the control register back after a write. ++ */ ++ read_back = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ ++ /* ++ * Indicate that this channel is in the pause by ++ * starvation state by setting the pause bit to true. ++ */ ++ dma->pause = TRUE; ++ } ++ } ++ /* ++ * Next Frame Buffer Interrupt. If there's a new buffer program it ++ * Check if this is the last buffer in the transfer, ++ * and if it is, disable the NFB int to prevent being ++ * interrupted for another buffer when we know there won't be ++ * another. ++ */ ++ if (dma_int == NFB) { ++ DPRINTK("5 "); ++ ++ if (dma->total_buffers) { ++ DPRINTK("6 "); ++ /* ++ * The iCurrentBuffer has already been transfered. so add the ++ * byte count from the current buffer to the total byte count. ++ */ ++ dma->total_bytes = dma->total_bytes + ++ dma->buffer_queue[dma->current_buffer].size; ++ ++ /* ++ * Mark the Current Buffer as used. ++ */ ++ dma->buffer_queue[dma->current_buffer].used = TRUE; ++ ++ /* ++ * Increment the used buffer counter ++ */ ++ dma->used_buffers++; ++ ++ DPRINTK("#%d", dma->current_buffer); ++ ++ if ((dma->buffer_queue[(dma->current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS].last) ++ || (dma->new_buffers == 0) ++ || (dma->xfer_enable == FALSE)) { ++ DPRINTK("7 "); ++ ++ /* ++ * This is the last Buffer in this transaction, so disable ++ * the NFB interrupt. We shouldn't get an NFB int when the ++ * FSM moves to the ON state where it would typically get the ++ * NFB int indicating a new buffer can be programmed. ++ * Instead, once in the ON state, the DMA will just proceed ++ * to complet the transfer of the current buffer, move the ++ * FSB directly to the STALL state where a STALL interrupt ++ * will be generated. ++ */ ++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2P_NFBINTEN; ++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL); ++ ++ /* ++ * The current buffer has been transferred, so increment ++ * the current buffer counter to reflect this. ++ */ ++ dma->current_buffer = ++ (dma->current_buffer + ++ 1) % MAX_EP93XX_DMA_BUFFERS; ++ ++ DPRINTK("End of NFB handling. \n"); ++ DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS)); ++ DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL)); ++ DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN)); ++ DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC)); ++ DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0)); ++ DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0)); ++ DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0)); ++ DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1)); ++ DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1)); ++ DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1)); ++ ++ DPRINTK ++ ("Buffer buf_id source size last used \n"); ++ for (loop = 0; loop < 32; loop++) { ++ DPRINTK ++ ("%d 0x%x 0x%x 0x%x %d %d \n", ++ loop, ++ dma->buffer_queue[loop].buf_id, ++ dma->buffer_queue[loop].source, ++ dma->buffer_queue[loop].size, ++ dma->buffer_queue[loop].last, ++ dma->buffer_queue[loop].used); ++ } ++ DPRINTK ++ ("pause 0x%x 0x%x 0x%x %d %d \n", ++ dma->pause_buf.buf_id, ++ dma->pause_buf.source, dma->pause_buf.size, ++ dma->pause_buf.last, dma->pause_buf.used); ++ ++ DPRINTK("Pause - %d \n", dma->pause); ++ DPRINTK("xfer_enable - %d \n", ++ dma->xfer_enable); ++ DPRINTK("total bytes - 0x%x \n", ++ dma->total_bytes); ++ DPRINTK("total buffer - %d \n", ++ dma->total_buffers); ++ DPRINTK("new buffers - %d \n", ++ dma->new_buffers); ++ DPRINTK("current buffer - %d \n", ++ dma->current_buffer); ++ DPRINTK("last buffer - %d \n", ++ dma->last_buffer); ++ DPRINTK("used buffers - %d \n", ++ dma->used_buffers); ++ DPRINTK("callback addr - 0x%x \n", ++ dma->callback); ++ ++ } else if (dma->new_buffers) { ++ DPRINTK("8 "); ++ /* ++ * we have a new buffer, so increment the current buffer to ++ * point to the next buffer, which is already programmed into ++ * the DMA. Next time around, it'll be pointing to the ++ * current buffer. ++ */ ++ dma->current_buffer = ++ (dma->current_buffer + ++ 1) % MAX_EP93XX_DMA_BUFFERS; ++ ++ /* ++ * we know we have a new buffer to program as the next ++ * buffer, so check which set of MAXCNT and BASE registers ++ * to program. ++ */ ++ if (readl(M2P_reg_base + M2P_OFFSET_STATUS) & ++ STATUS_M2P_NEXTBUFFER) { ++ /* ++ * Set the MAXCNT1 register with the buffer size ++ */ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ size, ++ M2P_reg_base + M2P_OFFSET_MAXCNT1); ++ ++ /* ++ * Set the BASE1 register with the buffer base address ++ */ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ source, ++ M2P_reg_base + M2P_OFFSET_BASE1); ++ } else { ++ /* ++ * Set the MAXCNT0 register with the buffer size ++ */ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ size, ++ M2P_reg_base + M2P_OFFSET_MAXCNT0); ++ ++ /* ++ * Set the BASE0 register with the buffer base address ++ */ ++ writel(dma-> ++ buffer_queue[(dma-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS]. ++ source, ++ M2P_reg_base + M2P_OFFSET_BASE0); ++ } ++ ++ /* ++ * Decrement the new buffers counter ++ */ ++ dma->new_buffers--; ++ } ++ } ++ /* ++ * Total number of buffers is 0 - really we should never get here, ++ * but just in case. ++ */ ++ else { ++ DPRINTK("9 \n"); ++ ++ /* ++ * No new buffers to transfer, so Disable the channel ++ */ ++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2P_ENABLE; ++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL); ++ } ++ } ++ /* ++ * Channel Error Interrupt, or perhipheral interrupt, specific to the ++ * memory to/from peripheral channels. ++ */ ++ if (dma_int == CHERROR) { ++ /* ++ * just clear the interrupt, it's really up to the peripheral ++ * driver to determine if any further action is necessary. ++ */ ++ uiINTERRUPT = ++ readl(M2P_reg_base + M2P_OFFSET_INTERRUPT); ++ uiINTERRUPT &= ~INTERRUPT_M2P_CHERRORINT; ++ writel(uiINTERRUPT, M2P_reg_base + M2P_OFFSET_INTERRUPT); ++ } ++ ++ /* ++ * Make sure the interrupt was valid, and if it was, then check ++ * if a callback function was installed for this DMA channel. If a ++ * callback was installed call it. ++ */ ++ if ((dma_int != UNDEF_INT) && dma->callback) { ++ dma->callback(dma_int, dma->device, dma->user_data); ++ } ++ return IRQ_HANDLED; ++} ++ ++/***************************************************************************** ++ * ++ * ep9312_dma_open_m2p(int device) ++ * ++ * Description: This function will attempt to open a M2P/P2M DMA channel. ++ * If the open is successful, the channel number is returned, ++ * otherwise a negative number is returned. ++ * ++ * Parameters: ++ * device: device for which the dma channel is requested. ++ * ++ ****************************************************************************/ ++static int dma_open_m2p(int device) ++{ ++ int channel = -1; ++ unsigned int loop; ++ unsigned int M2P_reg_base; ++ unsigned int uiPWRCNT; ++ ++ DPRINTK("DMA Open M2P with hw dev %d\n", device); ++ ++ /* ++ * Lock the dma channel list. ++ */ ++ spin_lock(&dma_list_lock); ++ DPRINTK("1\n"); ++ /* ++ * Verify that the device requesting DMA isn't already using a DMA channel ++ */ ++ if (device >= 10) { ++ loop = 1; /* Rx transfer requested */ ++ } else { ++ loop = 0; /* Tx transfer requested */ ++ } ++ ++ for (; loop < 10; loop = loop + 2) { ++ /* ++ * Before checking for a matching device, check that the ++ * channel is in use, otherwise the device field is ++ * invalid. ++ */ ++ if (dma_chan[loop].ref_count) { ++ if (device == dma_chan[loop].device) { ++ DPRINTK("DMA Open M2P - Error\n"); ++ /* ++ * Fail. ++ */ ++ return (-1); ++ } ++ } ++ } ++ ++ /* ++ * Get a DMA channel instance for the given hardware device. ++ * If this is a TX look for even numbered channels, else look for ++ * odd numbered channels ++ */ ++ if (device >= 10) { ++ loop = 1; /* Rx transfer requested */ ++ } else { ++ loop = 0; /* Tx transfer requested */ ++ } ++ ++ for (; loop < 10; loop = loop + 2) { ++ if (!dma_chan[loop].ref_count) { ++ /* ++ * Capture the channel and increment the reference count. ++ */ ++ channel = loop; ++ dma_chan[channel].ref_count++; ++ break; ++ } ++ } ++ ++ /* ++ * Unlock the dma channel list. ++ */ ++ spin_unlock(&dma_list_lock); ++ ++ /* ++ * See if we got a valid channel. ++ */ ++ if (channel < 0) { ++ /* ++ * Fail. ++ */ ++ return (-1); ++ } ++ ++ /* ++ * Point regs to the correct dma channel register base. ++ */ ++ M2P_reg_base = dma_chan[channel].reg_base; ++ ++ /* ++ * Turn on the clock for the specified DMA channel ++ * TODO: need to use the correct register name for the ++ * power control register. ++ */ ++ uiPWRCNT = readl(SYSCON_PWRCNT); ++ switch (channel) { ++ case 0: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH0; ++ break; ++ } ++ ++ case 1: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH1; ++ break; ++ } ++ ++ case 2: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH2; ++ break; ++ } ++ ++ case 3: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH3; ++ break; ++ } ++ ++ case 4: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH4; ++ break; ++ } ++ ++ case 5: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH5; ++ break; ++ } ++ ++ case 6: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH6; ++ break; ++ } ++ ++ case 7: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH7; ++ break; ++ } ++ case 8: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH8; ++ break; ++ } ++ case 9: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH9; ++ break; ++ } ++ ++ default: ++ { ++ return (-1); ++ } ++ } ++ writel(uiPWRCNT, SYSCON_PWRCNT); ++ ++ /* ++ * Clear out the control register before any further setup. ++ */ ++ writel(0, M2P_reg_base + M2P_OFFSET_CONTROL); ++ ++ /* ++ * Setup the peripheral port value in the DMA channel registers. ++ */ ++ if (device < 10) { ++ writel((unsigned int)device, ++ M2P_reg_base + M2P_OFFSET_PPALLOC); ++ } else { ++ writel((unsigned int)(device - 10), ++ M2P_reg_base + M2P_OFFSET_PPALLOC); ++ } ++ ++ /* ++ * Let's hold on to the value of the Hw device for comparison later. ++ */ ++ dma_chan[channel].device = device; ++ ++ /* ++ * Success. ++ */ ++ return (channel); ++} ++ ++/***************************************************************************** ++ * ++ * dma_open_m2m(int device) ++ * ++ * Description: This function will attempt to open a M2M DMA channel. ++ * If the open is successful, the channel number is returned, ++ * otherwise a negative number is returned. ++ * ++ * Parameters: ++ * device: device for which the dma channel is requested. ++ * ++ ****************************************************************************/ ++static int dma_open_m2m(int device) ++{ ++ int channel = -1; ++ unsigned int loop; ++ unsigned int M2M_reg_base; ++ unsigned int uiPWRCNT, uiCONTROL; ++ ++ DPRINTK("DMA Open M2M with hw dev %d\n", device); ++ ++ /* ++ * Lock the dma channel list. ++ */ ++ spin_lock(&dma_list_lock); ++ DPRINTK("1\n"); ++ ++ /* ++ * Check if this device is already allocated a channel. ++ * TODO: can one M2M device be allocated multiple channels? ++ */ ++ for (loop = DMA_MEMORY; loop < UNDEF; loop++) { ++ /* ++ * Before checking for a matching device, check that the ++ * channel is in use, otherwise the device field is ++ * invalid. ++ */ ++ if (dma_chan[loop].ref_count) { ++ if (device == dma_chan[loop].device) { ++ DPRINTK ++ ("Error - dma_open_m2m - already allocated channel\n"); ++ ++ /* ++ * Unlock the dma channel list. ++ */ ++ spin_unlock(&dma_list_lock); ++ ++ /* ++ * Fail. ++ */ ++ return (-1); ++ } ++ } ++ } ++ ++ /* ++ * Get a DMA channel instance for the given hardware device. ++ */ ++ for (loop = 10; loop < 12; loop++) { ++ if (!dma_chan[loop].ref_count) { ++ /* ++ * Capture the channel and increment the reference count. ++ */ ++ channel = loop; ++ dma_chan[channel].ref_count++; ++ break; ++ } ++ } ++ ++ /* ++ * Unlock the dma channel list. ++ */ ++ spin_unlock(&dma_list_lock); ++ ++ /* ++ * See if we got a valid channel. ++ */ ++ if (channel < 0) { ++ /* ++ * Fail. ++ */ ++ return (-1); ++ } ++ ++ /* ++ * Point regs to the correct dma channel register base. ++ */ ++ M2M_reg_base = dma_chan[channel].reg_base; ++ ++ /* ++ * Turn on the clock for the specified DMA channel ++ * TODO: need to use the correct register name for the ++ * power control register. ++ */ ++ uiPWRCNT = readl(SYSCON_PWRCNT); ++ switch (channel) { ++ case 10: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH0; ++ break; ++ } ++ ++ case 11: ++ { ++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH1; ++ break; ++ } ++ ++ default: ++ { ++ return (-1); ++ } ++ } ++ writel(uiPWRCNT, SYSCON_PWRCNT); ++ ++ DPRINTK("DMA Open - power control: 0x%x \n", ++ readl(SYSCON_PWRCNT)); ++ ++ /* ++ * Clear out the control register before any further setup. ++ */ ++ writel(0, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * Setup the transfer mode and the request source selection within ++ * the DMA M2M channel registers. ++ */ ++ switch (device) { ++ case DMA_MEMORY: ++ { ++ /* ++ * Clear TM field, set RSS field to 0 ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ++ ~(CONTROL_M2M_TM_MASK | CONTROL_M2M_RSS_MASK); ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ break; ++ } ++ ++ case DMA_IDE: ++ { ++ /* ++ * Set RSS field to 3, Set NO_HDSK, Set PW field to 1 ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ++ ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_PW_MASK); ++ uiCONTROL |= ++ (3 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK | ++ (2 << CONTROL_M2M_PW_SHIFT); ++ ++ uiCONTROL &= ~(CONTROL_M2M_ETDP_MASK); ++ uiCONTROL &= ~(CONTROL_M2M_DACKP); ++ uiCONTROL &= ~(CONTROL_M2M_DREQP_MASK); ++ ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ break; ++ } ++ ++ case DMARx_SSP: ++ { ++ /* ++ * Set RSS field to 1, Set NO_HDSK, Set TM field to 2 ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ++ ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK); ++ uiCONTROL |= ++ (1 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK | ++ (2 << CONTROL_M2M_TM_SHIFT); ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ break; ++ } ++ ++ case DMATx_SSP: ++ { ++ /* ++ * Set RSS field to 2, Set NO_HDSK, Set TM field to 1 ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ++ ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK); ++ uiCONTROL |= ++ (2 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK | ++ (1 << CONTROL_M2M_TM_SHIFT); ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ break; ++ } ++ ++ case DMATx_EXT_DREQ: ++ { ++ /* ++ * Set TM field to 2, set RSS field to 0 ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ++ ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK); ++ uiCONTROL |= 1 << CONTROL_M2M_TM_SHIFT; ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ break; ++ } ++ ++ case DMARx_EXT_DREQ: ++ { ++ ++ /* ++ * Set TM field to 2, set RSS field to 0 ++ */ ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ++ ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK); ++ uiCONTROL |= 2 << CONTROL_M2M_TM_SHIFT; ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ break; ++ } ++ ++ default: ++ { ++ return -1; ++ } ++ } ++ ++ /* ++ * Let's hold on to the value of the Hw device for comparison later. ++ */ ++ dma_chan[channel].device = device; ++ ++ /* ++ * Success. ++ */ ++ return (channel); ++} ++ ++/***************************************************************************** ++ * ++ * int dma_config_m2m(ep93xx_dma_t * dma, unsigned int flags_m2m, ++ * dma_callback callback, unsigned int user_data) ++ * ++ * Description: Configure the DMA channel and install a callback function. ++ * This function will have to be called for every transfer ++ * ++ * dma: Pointer to the dma instance data for the M2M channel to ++ * configure. ++ * flags_m2m Flags used to configure an M2M dma channel and determine ++ * if a callback function and user_data information are included ++ * in this call. ++ * callback function pointer which is called near the end of the ++ * dma channel's irq handler. ++ * user_data defined by the calling driver. ++ * ++ ****************************************************************************/ ++static int ++dma_config_m2m(ep93xx_dma_t * dma, unsigned int flags_m2m, ++ dma_callback callback, unsigned int user_data) ++{ ++ unsigned long flags; ++ unsigned int M2M_reg_base, uiCONTROL; ++ ++ /* ++ * Make sure the channel is disabled before configuring the channel. ++ * ++ * TODO: Is this correct?? Making a big change here... ++ */ ++ /* if(!dma->pause || (!dma->pause && dma->xfer_enable)) */ ++ if (dma->xfer_enable) { ++ /* ++ * DMA channel is not paused, so we can't configure it. ++ */ ++ DPRINTK("DMA channel not paused, so can't configure! \n"); ++ return (-1); ++ } ++ ++ /* ++ * Mask interrupts. ++ */ ++ local_irq_save(flags); ++ ++ /* ++ * Setup a pointer into the dma channel's register set. ++ */ ++ M2M_reg_base = dma->reg_base; ++ ++ /* ++ * By default we enable the stall interrupt. ++ */ ++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL |= CONTROL_M2M_STALLINTEN; ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * By default we enable the done interrupt. ++ */ ++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2M_DONEINTEN; ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * Set up the transfer control fields based on values passed in ++ * the flags_m2m field. ++ */ ++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ if (flags_m2m & DESTINATION_HOLD) { ++ uiCONTROL |= CONTROL_M2M_DAH; ++ } else { ++ uiCONTROL &= ~CONTROL_M2M_DAH; ++ } ++ ++ if (flags_m2m & SOURCE_HOLD) { ++ uiCONTROL |= CONTROL_M2M_SAH; ++ } else { ++ uiCONTROL &= ~CONTROL_M2M_SAH; ++ } ++ ++ uiCONTROL &= ~CONTROL_M2M_TM_MASK; ++ uiCONTROL |= ++ (((flags_m2m & TRANSFER_MODE_MASK) >> TRANSFER_MODE_SHIFT) << ++ CONTROL_M2M_TM_SHIFT) & CONTROL_M2M_TM_MASK; ++ ++ uiCONTROL &= ~CONTROL_M2M_PWSC_MASK; ++ uiCONTROL |= (((flags_m2m & WAIT_STATES_MASK) >> WAIT_STATES_SHIFT) << ++ CONTROL_M2M_PWSC_SHIFT) & CONTROL_M2M_PWSC_MASK; ++ ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * Save the callback function in the dma instance for this channel. ++ */ ++ dma->callback = callback; ++ ++ /* ++ * Save the user data in the the dma instance for this channel. ++ */ ++ dma->user_data = user_data; ++ ++ /* ++ * Put the dma instance into the pause state by setting the ++ * pause bit to true. ++ */ ++ dma->pause = TRUE; ++ ++ local_irq_restore(flags); ++ ++ /* ++ * Success. ++ */ ++ return (0); ++} ++ ++/***************************************************************************** ++ * ++ * int dma_start(int handle, unsigned int channels, unsigned int * handles) ++ * ++ * Description: Initiate a transfer on up to 3 channels. ++ * ++ * handle: handle for the channel to initiate transfer on. ++ * channels: number of channels to initiate transfers on. ++ * handles: pointer to an array of handles, one for each channel which ++ * is to be started. ++ * ++ ****************************************************************************/ ++static int dma_start_m2m(int channel, ep93xx_dma_t * dma) ++{ ++ unsigned long flags; ++ unsigned int M2M_reg_base = dma->reg_base; ++ unsigned int uiCONTROL; ++ ++ /* ++ * Mask interrupts while we get this started. ++ */ ++ local_irq_save(flags); ++ ++ /* ++ * Make sure the channel has at least one buffer in the queue. ++ */ ++ if (dma->new_buffers < 1) { ++ /* ++ * Unmask irqs ++ */ ++ local_irq_restore(flags); ++ ++ DPRINTK("DMA Start: Channel starved.\n"); ++ ++ /* ++ * This channel does not have enough buffers queued up, ++ * so enter the pause by starvation state. ++ */ ++ dma->xfer_enable = TRUE; ++ dma->pause = TRUE; ++ ++ /* ++ * Success. ++ */ ++ return (0); ++ } ++ ++ /* ++ * Clear any pending interrupts. ++ */ ++ writel(0x0, M2M_reg_base + M2M_OFFSET_INTERRUPT); ++ ++ /* ++ * Set up one or both buffer descriptors with values from the next one or ++ * two buffers in the queue. By default enable the next frame buffer ++ * interrupt on the channel. ++ */ ++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2M_NFBINTEN; ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * enable the stall interrupt. ++ */ ++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL |= CONTROL_M2M_STALLINTEN; ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * Update the dma channel instance transfer state. ++ */ ++ dma->xfer_enable = TRUE; ++ dma->pause = FALSE; ++ ++ /* ++ * Decrement the new buffers counter. ++ */ ++ dma->new_buffers--; ++ ++ /* ++ * Program up the first buffer descriptor with a source and destination ++ * and a byte count. ++ */ ++ writel(dma->buffer_queue[dma->current_buffer].source, ++ M2M_reg_base + M2M_OFFSET_SAR_BASE0); ++ ++ writel(dma->buffer_queue[dma->current_buffer].dest, ++ M2M_reg_base + M2M_OFFSET_DAR_BASE0); ++ ++ writel(dma->buffer_queue[dma->current_buffer].size, ++ M2M_reg_base + M2M_OFFSET_BCR0); ++ ++ /* ++ * Now we enable the channel. This initiates the transfer. ++ */ ++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL |= CONTROL_M2M_ENABLE; ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ ++ /* ++ * Before restoring irqs set up the second buffer descriptor ++ * with a second buffer if we have a second buffer. ++ */ ++ /* if(dma->new_buffers) ++ { ++ outl( dma->buffer_queue[(dma->current_buffer + 1) % ++ MAX_EP93XX_DMA_BUFFERS].source, ++ M2M_reg_base+M2M_OFFSET_SAR_BASE1 ); ++ ++ outl( dma->buffer_queue[(dma->current_buffer + 1) % ++ MAX_EP93XX_DMA_BUFFERS].dest, ++ M2M_reg_base+M2M_OFFSET_DAR_BASE1 ); ++ ++ outl( dma->buffer_queue[(dma->current_buffer + 1) % ++ MAX_EP93XX_DMA_BUFFERS].size, ++ M2M_reg_base+M2M_OFFSET_BCR1 ); ++ } */ ++ ++ /* ++ * If this is a memory to memory transfer, we need to s/w trigger the ++ * transfer by setting the start bit within the control register. ++ */ ++ if (dma->device == DMA_MEMORY) { ++ uiCONTROL = ++ readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL |= CONTROL_M2M_START; ++ writel(uiCONTROL, ++ M2M_reg_base + M2M_OFFSET_CONTROL); ++ } ++ ++ DPRINTK("DMA - It's been started!!"); ++ DPRINTK("STATUS - 0x%x \n", readl(M2M_reg_base + M2M_OFFSET_STATUS)); ++ DPRINTK("CONTROL - 0x%x \n", readl(M2M_reg_base + M2M_CONTROL.Value)); ++ DPRINTK("REMAIN - 0x%x \n", readl(M2M_reg_base + M2M_REMAIN.Value)); ++ DPRINTK("PPALLOC - 0x%x \n", readl(M2M_reg_base + M2M_PPALLOC.Value)); ++ DPRINTK("BASE0 - 0x%x \n", readl(M2M_reg_base + M2M_BASE0.Value)); ++ DPRINTK("MAXCNT0 - 0x%x \n", readl(M2M_reg_base + M2M_MAXCNT0.Value)); ++ DPRINTK("CURRENT0 - 0x%x \n", readl(M2M_reg_base + M2M_CURRENT0.Value)); ++ DPRINTK("BASE1 - 0x%x \n", readl(M2M_reg_base + M2M_BASE1.Value)); ++ DPRINTK("MAXCNT1 - 0x%x \n", readl(M2M_reg_base + M2M_MAXCNT1.Value)); ++ DPRINTK("CURRENT1 - 0x%x \n", readl(M2M_reg_base + M2M_CURRENT1.Value)); ++ ++ DPRINTK("Pause - %d \n", dma_pointers[0]->pause); ++ DPRINTK("xfer_enable - %d \n", dma_pointers[0]->xfer_enable); ++ DPRINTK("total bytes - 0x%x \n", dma_pointers[0]->total_bytes); ++ DPRINTK("total buffer - %d \n", dma_pointers[0]->total_buffers); ++ DPRINTK("new buffers - %d \n", dma_pointers[0]->new_buffers); ++ DPRINTK("current buffer - %d \n", dma_pointers[0]->current_buffer); ++ DPRINTK("last buffer - %d \n", dma_pointers[0]->last_buffer); ++ DPRINTK("used buffers - %d \n", dma_pointers[0]->used_buffers); ++ ++ /* ++ * Unmask irqs ++ */ ++ local_irq_restore(flags); ++ ++ /* ++ * Success. ++ */ ++ return (0); ++} ++ ++/***************************************************************************** ++ * ++ * DMA interface functions ++ * ++ ****************************************************************************/ ++ ++/***************************************************************************** ++ * ++ * int dma_init(int handle, unsigned int flags_m2p, unsigned int flags_m2m, ++ * dma_callback callback, unsigned int user_data) ++ * ++ * Description: Configure the DMA channel and install a callback function. ++ * ++ * handle: Handle unique the each instance of the dma interface, used ++ * to verify this call. ++ * flags_m2p Flags used to configure an M2P/P2M dma channel and determine ++ * if a callback function and user_data information are included ++ * in this call. This field should be NULL if handle represents ++ * an M2M channel. ++ * flags_m2m Flags used to configure an M2M dma channel and determine ++ * if a callback function and user_data information are included ++ * in this call. This field should be NULL if handle represents ++ * an M2P/P2M channel. ++ * callback function pointer which is called near the end of the ++ * dma channel's irq handler. ++ * user_data defined by the calling driver. ++ * ++ ****************************************************************************/ ++int ++ep93xx_dma_config(int handle, unsigned int flags_m2p, unsigned int flags_m2m, ++ dma_callback callback, unsigned int user_data) ++{ ++ int channel; ++ ep93xx_dma_t *dma; ++ unsigned long flags; ++ unsigned int M2P_reg_base, uiCONTROL; ++ ++ /* ++ * Get the DMA hw channel # from the handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (channel < 0) { ++ printk(KERN_ERR "DMA Config: Invalid dma handle.\n"); ++ ++ /* ++ * Fail. ++ */ ++ return (-EINVAL); ++ } ++ ++ DPRINTK("DMA Config \n"); ++ ++ dma = &dma_chan[channel]; ++ ++ local_irq_save(flags); ++ ++ /* ++ * Check if the channel is currently transferring. ++ */ ++ if (dma->xfer_enable) { ++ local_irq_restore(flags); ++ ++ /* ++ * Already transferring, invalid command. ++ */ ++ return (-EINVAL); ++ } ++ ++ /* ++ * Check if this is an m2m function. ++ */ ++ if (channel >= 10) { ++ local_irq_restore(flags); ++ ++ /* ++ * Call another function to handle m2m config. ++ */ ++ return (dma_config_m2m(dma, flags_m2m, callback, user_data)); ++ } ++ ++ /* ++ * Setup a pointer into the dma channel's register set. ++ */ ++ M2P_reg_base = dma->reg_base; ++ ++ /* ++ * By default we enable the stall interrupt. ++ */ ++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ uiCONTROL |= CONTROL_M2P_STALLINTEN; ++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL); ++ ++ /* ++ * Configure the channel for an error from the peripheral. ++ */ ++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ if (flags_m2p && CHANNEL_ERROR_INT_ENABLE) ++ uiCONTROL |= CONTROL_M2P_CHERRORINTEN; ++ else ++ uiCONTROL &= ~CONTROL_M2P_CHERRORINTEN; ++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL); ++ ++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ if (flags_m2p && EP93XX_DMA_ABORT) ++ uiCONTROL |= CONTROL_M2P_ABRT; ++ else ++ uiCONTROL &= ~CONTROL_M2P_ABRT; ++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL); ++ ++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ if (flags_m2p && IGNORE_CHANNEL_ERROR) ++ uiCONTROL |= CONTROL_M2P_ICE; ++ else ++ uiCONTROL &= ~CONTROL_M2P_ICE; ++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL); ++ ++ /* ++ * Save the callback function in the dma instance for this channel. ++ */ ++ dma->callback = callback; ++ ++ /* ++ * Save the user data in the the dma instance for this channel. ++ */ ++ dma->user_data = user_data; ++ ++ /* ++ * Put the dma instance into the pause state by setting the ++ * pause bit to true. ++ */ ++ dma->pause = TRUE; ++ ++ local_irq_restore(flags); ++ ++ /* ++ * Success. ++ */ ++ return (0); ++} ++ ++/***************************************************************************** ++ * ++ * int dma_start(int handle, unsigned int channels, unsigned int * handles) ++ * ++ * Description: Initiate a transfer on up to 3 channels. ++ * ++ * handle: handle for the channel to initiate transfer on. ++ * channels: number of channels to initiate transfers on. ++ * handles: pointer to an array of handles, one for each channel which ++ * is to be started. ++ * ++ ****************************************************************************/ ++int ep93xx_dma_start(int handle, unsigned int channels, unsigned int *handles) ++{ ++ ep93xx_dma_t *dma_pointers[3]; ++ unsigned int M2P_reg_bases[3]; ++ unsigned int loop, uiCONTROL; ++ unsigned long flags; ++ int channel; ++ ++ /* ++ * Get the DMA hw channel # from the handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (channel < 0) { ++ printk(KERN_ERR "DMA Start: Invalid dma handle.\n"); ++ ++ /* ++ * Fail. ++ */ ++ return (-EINVAL); ++ } ++ ++ if (channels < 1) { ++ printk(KERN_ERR "DMA Start: Invalid parameter.\n"); ++ ++ return (-EINVAL); ++ } ++ ++ DPRINTK("DMA Start \n"); ++ ++ /* ++ * Mask off registers. ++ */ ++ local_irq_save(flags); ++ ++ /* ++ * Check if this is a start multiple. ++ */ ++ if (channels > 1) { ++ DPRINTK ++ ("DMA ERROR: Start, multiple start not supported yet \n"); ++ return (-1); ++ } ++ /* ++ * Only one channel ++ */ ++ else { ++ /* ++ * Check if this channel is already transferring. ++ */ ++ if (dma_chan[channel].xfer_enable && !dma_chan[channel].pause) { ++ printk(KERN_ERR ++ "DMA Start: Invalid command for channel %d.\n", ++ channel); ++ DPRINTK("DMA Start: Invalid command for channel %d.\n", ++ channel); ++ ++ /* ++ * Unmask irqs ++ */ ++ local_irq_restore(flags); ++ ++ /* ++ * This channel is already transferring, so return an error. ++ */ ++ return (-EINVAL); ++ } ++ ++ /* ++ * If this is an M2M channel, call a different function. ++ */ ++ if (channel >= 10) { ++ /* ++ * Unmask irqs ++ */ ++ local_irq_restore(flags); ++ ++ /* ++ * Call the m2m start function. Only start one channel. ++ */ ++ return (dma_start_m2m(channel, &dma_chan[channel])); ++ } ++ ++ /* ++ * Make sure the channel has at least one buffer in the queue. ++ */ ++ if (dma_chan[channel].new_buffers < 1) { ++ DPRINTK("DMA Start: Channel starved.\n"); ++ ++ /* ++ * This channel does not have enough buffers queued up, ++ * so enter the pause by starvation state. ++ */ ++ dma_chan[channel].xfer_enable = TRUE; ++ dma_chan[channel].pause = TRUE; ++ ++ /* ++ * Unmask irqs ++ */ ++ local_irq_restore(flags); ++ ++ /* ++ * Success. ++ */ ++ return (0); ++ } ++ ++ /* ++ * Set up a dma instance pointer for this dma channel. ++ */ ++ dma_pointers[0] = &dma_chan[channel]; ++ ++ /* ++ * Set up a pointer to the register set for this channel. ++ */ ++ M2P_reg_bases[0] = dma_pointers[0]->reg_base; ++ } ++ ++ /* ++ * Setup both MAXCNT registers with values from the next two buffers ++ * in the queue, and enable the next frame buffer interrupt on the channel. ++ */ ++ for (loop = 0; loop < channels; loop++) { ++ /* ++ * By default we enable the next frame buffer interrupt. ++ */ ++ uiCONTROL = readl(M2P_reg_bases[loop] + M2P_OFFSET_CONTROL); ++ uiCONTROL |= CONTROL_M2P_NFBINTEN; ++ writel(uiCONTROL, M2P_reg_bases[loop] + M2P_OFFSET_CONTROL); ++ ++ /* ++ * Check if we need to restore a paused transfer. ++ */ ++ if (dma_pointers[loop]->pause_buf.buf_id != -1) { ++ writel(dma_pointers[loop]->pause_buf.size, ++ M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT0); ++ } else { ++ writel(dma_pointers[loop]-> ++ buffer_queue[dma_pointers[loop]->current_buffer]. ++ size, ++ M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT0); ++ } ++ } ++ ++ for (loop = 0; loop < channels; loop++) { ++ /* ++ * Enable the specified dma channels. ++ */ ++ uiCONTROL = ++ readl(M2P_reg_bases[loop] + M2P_OFFSET_CONTROL); ++ uiCONTROL |= CONTROL_M2P_ENABLE; ++ writel(uiCONTROL, ++ M2P_reg_bases[loop] + M2P_OFFSET_CONTROL); ++ ++ /* ++ * Update the dma channel instance transfer state. ++ */ ++ dma_pointers[loop]->xfer_enable = TRUE; ++ dma_pointers[loop]->pause = FALSE; ++ ++ if (dma_pointers[loop]->pause_buf.buf_id == -1) { ++ dma_pointers[loop]->new_buffers--; ++ } ++ } ++ ++ /* ++ * Program up the BASE0 registers for all specified channels, this ++ * will initiate transfers on all specified channels. ++ */ ++ for (loop = 0; loop < channels; loop++) { ++ /* ++ * Check if we need to restore a paused transfer. ++ */ ++ if (dma_pointers[loop]->pause_buf.buf_id != -1) { ++ writel(dma_pointers[loop]->pause_buf.source, ++ M2P_reg_bases[loop] + M2P_OFFSET_BASE0); ++ ++ /* ++ * Set the pause buffer to NULL ++ */ ++ dma_pointers[loop]->pause_buf.buf_id = -1; ++ dma_pointers[loop]->pause_buf.size = 0; ++ } else { ++ writel(dma_pointers[loop]-> ++ buffer_queue[dma_pointers[loop]->current_buffer]. ++ source, ++ M2P_reg_bases[loop] + M2P_OFFSET_BASE0); ++ } ++ } ++ ++ /* ++ * Before restoring irqs setup the second MAXCNT/BASE ++ * register with a second buffer. ++ */ ++ for (loop = 0; loop < channels; loop++) { ++ if (dma_pointers[loop]->new_buffers) { ++ writel(dma_pointers[loop]-> ++ buffer_queue[(dma_pointers[loop]-> ++ current_buffer + ++ 1) % MAX_EP93XX_DMA_BUFFERS].size, ++ M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT1); ++ writel(dma_pointers[loop]-> ++ buffer_queue[(dma_pointers[loop]-> ++ current_buffer + ++ 1) % ++ MAX_EP93XX_DMA_BUFFERS].source, ++ M2P_reg_bases[loop] + M2P_OFFSET_BASE1); ++ } ++ } ++ ++/* ++ DPRINTK("DMA - It's been started!!"); ++ DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_STATUS))); ++ DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_CONTROL))); ++ DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_REMAIN))); ++ DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_PPALLOC))); ++ DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_BASE0))); ++ DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_MAXCNT0))); ++ DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_CURRENT0))); ++ DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_BASE1))); ++ DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_MAXCNT1))); ++ DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_CURRENT1))); ++ ++ DPRINTK("Pause - %d \n", dma_pointers[0]->pause); ++ DPRINTK("xfer_enable - %d \n", dma_pointers[0]->xfer_enable); ++ DPRINTK("total bytes - 0x%x \n", dma_pointers[0]->total_bytes); ++ DPRINTK("total buffer - %d \n", dma_pointers[0]->total_buffers); ++ DPRINTK("new buffers - %d \n", dma_pointers[0]->new_buffers); ++ DPRINTK("current buffer - %d \n", dma_pointers[0]->current_buffer); ++ DPRINTK("last buffer - %d \n", dma_pointers[0]->last_buffer); ++ DPRINTK("used buffers - %d \n", dma_pointers[0]->used_buffers); ++*/ ++ /* ++ * Unmask irqs ++ */ ++ local_irq_restore(flags); ++ ++ /* ++ * Success. ++ */ ++ return (0); ++} ++ ++/***************************************************************************** ++ * ++ * int ep93xx_dma_add_buffer(int handle, unsigned int * address, ++ * unsigned int size, unsigned int last) ++ * ++ * Description: Add a buffer entry to the DMA buffer queue. ++ * ++ * handle: handle for the channel to add this buffer to. ++ * address: Pointer to an integer which is the start address of the ++ * buffer which is to be added to the queue. ++ * size: size of the buffer in bytes. ++ * last: 1 if this is the last buffer in this stream, 0 otherwise. ++ * ++ ****************************************************************************/ ++int ++ep93xx_dma_add_buffer(int handle, unsigned int source, unsigned int dest, ++ unsigned int size, unsigned int last, unsigned int buf_id) ++{ ++ unsigned long flags; ++ ep93xx_dma_t *dma; ++ int channel; ++ ++ /* ++ * Get the DMA hw channel # from the handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (channel < 0) { ++ printk(KERN_ERR "DMA Add Buffer: Invalid dma handle.\n"); ++ ++ /* ++ * Fail. ++ */ ++ return (-EINVAL); ++ } ++ ++ /* ++ * Get a pointer to the dma instance. ++ */ ++ dma = &dma_chan[channel]; ++ ++ /* ++ * Mask interrupts and hold on to the original state. ++ */ ++ local_irq_save(flags); ++ ++ /* ++ * If the buffer queue is full, last_buffer is the same as current_buffer and ++ * we're not tranfering, or last_buffer is pointing to a used buffer, then exit. ++ * TODO: do I need to do any more checks? ++ */ ++ if (dma->total_buffers >= MAX_EP93XX_DMA_BUFFERS) { ++ /* ++ * Restore the state of the irqs ++ */ ++ local_irq_restore(flags); ++ ++ /* ++ * Fail. ++ */ ++ return (-1); ++ } ++ ++ /* ++ * Add this buffer to the queue ++ */ ++ dma->buffer_queue[dma->last_buffer].source = source; ++ dma->buffer_queue[dma->last_buffer].dest = dest; ++ dma->buffer_queue[dma->last_buffer].size = size; ++ dma->buffer_queue[dma->last_buffer].last = last; ++ dma->buffer_queue[dma->last_buffer].buf_id = buf_id; ++ ++ /* ++ * Reset the used field of the buffer structure. ++ */ ++ dma->buffer_queue[dma->last_buffer].used = FALSE; ++ ++ /* ++ * Increment the End Item Pointer. ++ */ ++ dma->last_buffer = (dma->last_buffer + 1) % MAX_EP93XX_DMA_BUFFERS; ++ ++ /* ++ * Increment the new buffers counter and the total buffers counter ++ */ ++ dma->new_buffers++; ++ dma->total_buffers++; ++ ++ /* ++ * restore the interrupt state. ++ */ ++ local_irq_restore(flags); ++ ++ /* ++ * Check if the channel was starved into a stopped state. ++ */ ++ if (dma->pause && dma->xfer_enable) { ++ if (dma->new_buffers >= 1) { ++ DPRINTK ++ ("DMA - calling start from add after starve. \n"); ++ ++ /* ++ * The channel was starved into a stopped state, and we've got ++ * 2 new buffers, so start tranferring again. ++ */ ++ ep93xx_dma_start(handle, 1, NULL); ++ } ++ } ++ ++ /* ++ * Success. ++ */ ++ return (0); ++} ++ ++/***************************************************************************** ++ * ++ * int ep93xx_dma_remove_buffer(int handle, unsigned int * address, ++ * unsigned int * size) ++ * ++ * Description: Remove a buffer entry from the DMA buffer queue. If ++ * buffer was removed successfully, return 0, otherwise ++ * return -1. ++ * ++ * handle: handle for the channel to remove a buffer from. ++ * address: Pointer to an integer which is filled in with the start ++ * address of the removed buffer. ++ * size: Pointer to an integer which is filled in with the size in ++ * bytes of the removed buffer. ++ * ++ ****************************************************************************/ ++int ep93xx_dma_remove_buffer(int handle, unsigned int *buf_id) ++{ ++ unsigned int test; ++ unsigned int loop; ++ int return_val = -1; ++ unsigned long flags; ++ ep93xx_dma_t *dma; ++ int channel; ++ ++ /* ++ * Get the DMA hw channel # from the handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (channel < 0) { ++ printk(KERN_ERR "DMA Remove Buffer: Invalid dma handle.\n"); ++ ++ /* ++ * Fail. ++ */ ++ return (-EINVAL); ++ } ++ ++ dma = &dma_chan[channel]; ++ ++ /* ++ * Mask interrupts and hold on to the original state. ++ */ ++ local_irq_save(flags); ++ ++ /* ++ * Make sure there are used buffers to be returned. ++ */ ++ if (dma->used_buffers) { ++ test = dma->last_buffer; ++ ++ for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) { ++ if (dma->buffer_queue[test].used ++ && (dma->buffer_queue[test].buf_id != -1)) { ++ /*DPRINTK("buffer %d used \n", test); */ ++ ++ /* ++ * This is a used buffer, fill in the buf_id pointer ++ * with the buf_id for this buffer. ++ */ ++ *buf_id = dma->buffer_queue[test].buf_id; ++ ++ /* ++ * Reset this buffer structure ++ */ ++ dma->buffer_queue[test].buf_id = -1; ++ ++ /* ++ * Decrement the used buffer counter, and the total buffer counter. ++ */ ++ dma->used_buffers--; ++ dma->total_buffers--; ++ ++ /* ++ * Successful removal of a buffer, so set the return ++ * value to 0, then exit this loop. ++ */ ++ return_val = 0; ++ break; ++ } ++ ++ /* ++ * This buffer isn't used, let's see if the next one is. ++ */ ++ test = (test + 1) % MAX_EP93XX_DMA_BUFFERS; ++ } ++ } ++ ++ /* ++ * Restore interrupts. ++ */ ++ local_irq_restore(flags); ++ ++ /* ++ * Success. ++ */ ++ return (return_val); ++} ++ ++/***************************************************************************** ++ * ++ * int ep93xx_dma_pause(int handle, unsigned int channels, ++ * unsigned int * handles) ++ * ++ * Description: Disable any ongoing transfer for the given channel, retaining ++ * the state of the current buffer transaction so that upon ++ * resume, the dma will continue where it left off. ++ * ++ * handle: Handle for the channel to be paused. If this is a pause for ++ * for multiple channels, handle is a valid handle for one of ++ * the channels to be paused. ++ * channels: number of channel to pause transfers on. ++ * handles: Pointer to an array of handles, one for each channel which ++ * to be paused. If this pause is intended only for one ++ * channel, this field should be set to NULL. ++ * ++ ****************************************************************************/ ++int ep93xx_dma_pause(int handle, unsigned int channels, unsigned int *handles) ++{ ++ unsigned long flags; ++ ep93xx_dma_t *dma; ++ int channel; ++ unsigned int M2M_reg_base, M2P_reg_base; ++ ++ DPRINTK("ep93xx_dma_pause \n"); ++ ++ /* ++ * Mask interrupts and hold on to the original state. ++ */ ++ local_irq_save(flags); ++ ++ /* ++ * Get the DMA hw channel # from the handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (channel < 0) { ++ /* ++ * restore interrupts. ++ */ ++ local_irq_restore(flags); ++ ++ printk(KERN_ERR "DMA Pause: Invalid dma handle.\n"); ++ ++ /* ++ * Fail. ++ */ ++ return (-EINVAL); ++ } ++ ++ DPRINTK("DMA %d: pause \n", channel); ++ ++ /* ++ * Set up a pointer to the dma instance data. ++ */ ++ dma = &dma_chan[channel]; ++ ++ /* ++ * Set a pointer to the dma channel registers. ++ */ ++ if (channel < 10) { ++ M2P_reg_base = dma->reg_base; ++ } else { ++ M2M_reg_base = dma->reg_base; ++ } ++ ++ /* ++ * Check if we're already paused. ++ */ ++ if (dma->pause) { ++ /* ++ * We're paused, but are we stopped? ++ */ ++ if (dma->xfer_enable) { ++ /* ++ * Put the channel in the stopped state. ++ */ ++ dma->xfer_enable = FALSE; ++ } ++ ++ DPRINTK("DMA Pause - already paused."); ++ } else { ++ /* ++ * Put the channel into the stopped state. ++ */ ++ dma->xfer_enable = FALSE; ++ dma->pause = TRUE; ++ } ++ ++ /* ++ * restore interrupts. ++ */ ++ local_irq_restore(flags); ++ ++ /* ++ * Already paused, so exit. ++ */ ++ return (0); ++} ++ ++/***************************************************************************** ++ * ++ * void ep93xx_dma_flush(int handle) ++ * ++ * Description: Flushes all queued buffers and transfers in progress ++ * for the given channel. Return the buffer entries ++ * to the calling function. ++ * ++ * handle: handle for the channel for which the flush is intended. ++ * ++ ****************************************************************************/ ++int ep93xx_dma_flush(int handle) ++{ ++ unsigned int loop; ++ unsigned long flags; ++ ep93xx_dma_t *dma; ++ int channel; ++ unsigned int M2P_reg_base; ++ ++ /* ++ * Get the DMA hw channel # from the handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (channel < 0) { ++ printk(KERN_ERR "DMA Flush: Invalid dma handle.\n"); ++ ++ /* ++ * Fail. ++ */ ++ return (-EINVAL); ++ } ++ ++ DPRINTK("DMA %d: flush \n", channel); ++ ++ /* ++ * Set up a pointer to the dma instance data for this channel ++ */ ++ dma = &dma_chan[channel]; ++ ++ /* ++ * Mask interrupts and hold on to the original state. ++ */ ++ local_irq_save(flags); ++ ++ for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) { ++ dma->buffer_queue[loop].buf_id = -1; ++ } ++ ++ /* ++ * Set the Current and Last item to zero. ++ */ ++ dma->current_buffer = 0; ++ dma->last_buffer = 0; ++ ++ /* ++ * Reset the Buffer counters ++ */ ++ dma->used_buffers = 0; ++ dma->new_buffers = 0; ++ dma->total_buffers = 0; ++ ++ /* ++ * reset the Total bytes counter. ++ */ ++ dma->total_bytes = 0; ++ ++ M2P_reg_base = dma_chan[channel].reg_base; ++ ++ /* ++ * restore interrupts. ++ */ ++ local_irq_restore(flags); ++ ++ /* ++ * Success. ++ */ ++ return (0); ++} ++ ++/***************************************************************************** ++ * ++ * int ep93xx_dma_queue_full(int handle) ++ * ++ * Description: Query to determine if the DMA queue of buffers for ++ * a given channel is full. ++ * 0 = queue is full ++ * 1 = queue is not full ++ * ++ * handle: handle for the channel to query. ++ * ++ ****************************************************************************/ ++int ep93xx_dma_queue_full(int handle) ++{ ++ int list_full = 0; ++ unsigned long flags; ++ int channel; ++ ++ /* ++ * Get the DMA hw channel # from the handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (channel < 0) { ++ printk(KERN_ERR "DMA Queue Full: Invalid dma handle.\n"); ++ ++ /* ++ * Fail. ++ */ ++ return (-EINVAL); ++ } ++ ++ DPRINTK("DMA %d: queue full \n", channel); ++ ++ /* ++ * Mask interrupts and hold on to the original state. ++ */ ++ local_irq_save(flags); ++ ++ /* ++ * If the last item is equal to the used item then ++ * the queue is full. ++ */ ++ if (dma_chan[channel].total_buffers < MAX_EP93XX_DMA_BUFFERS) { ++ list_full = FALSE; ++ } else { ++ list_full = TRUE; ++ } ++ ++ /* ++ * restore interrupts. ++ */ ++ local_irq_restore(flags); ++ ++ return (list_full); ++} ++ ++ ++/***************************************************************************** ++ * ++ * int ep93xx_dma_get_position() ++ * ++ * Description: Takes two integer pointers and fills them with the start ++ * and current address of the buffer currently transferring ++ * on the specified DMA channel. ++ * ++ * handle handle for the channel to query. ++ * *buf_id buffer id for the current buffer transferring on the ++ * dma channel. ++ * *total total bytes transferred on the channel. Only counts ++ * whole buffers transferred. ++ * *current_frac number of bytes transferred so far in the current buffer. ++ ****************************************************************************/ ++int ++ep93xx_dma_get_position(int handle, unsigned int * buf_id, ++ unsigned int * total, unsigned int * current_frac ) ++{ ++ int channel; ++ ep93xx_dma_t * dma; ++ unsigned int buf_id1, total1, current_frac1, buf_id2, total2; ++ unsigned int Status, NextBuffer, StateIsBufNext, M2P_reg_base=0; ++ unsigned int pause1, pause2; ++ ++ /* ++ * Get the DMA hw channel # from the handle. See if this is a ++ * valid handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ if (channel < 0) { ++ printk(KERN_ERR "DMA Get Position: Invalid dma handle.\n"); ++ return(-EINVAL); ++ } ++ ++ dma = &dma_chan[channel]; ++ ++ /* ++ * If DMA moves to a new buffer in the middle of us grabbing the ++ * buffer info, then do it over again. ++ */ ++ do{ ++ buf_id1 = dma->buffer_queue[dma->current_buffer].buf_id; ++ total1 = dma->total_bytes; ++ pause1 = dma->pause; ++ ++ if (channel < 10) { ++ /* M2P */ ++ M2P_reg_base = dma->reg_base; ++ ++ Status = inl(M2P_reg_base+M2P_OFFSET_STATUS); ++ ++ NextBuffer = ((Status & STATUS_M2P_NEXTBUFFER) != 0); ++ ++ StateIsBufNext = ((Status & STATUS_M2P_CURRENT_MASK) == ++ STATUS_M2P_DMA_BUF_NEXT); ++ ++ if( NextBuffer ^ StateIsBufNext ) ++ current_frac1 = inl(M2P_reg_base+M2P_OFFSET_CURRENT1) - ++ inl(M2P_reg_base+M2P_OFFSET_BASE1); ++ else ++ current_frac1 = inl(M2P_reg_base+M2P_OFFSET_CURRENT0) - ++ inl(M2P_reg_base+M2P_OFFSET_BASE0); ++ ++ } else { ++ /* M2M - TODO implement this for M2M */ ++ current_frac1 = 0; ++ } ++ ++ buf_id2 = dma->buffer_queue[dma->current_buffer].buf_id; ++ total2 = dma->total_bytes; ++ pause2 = dma->pause; ++ ++ } while ( (buf_id1 != buf_id2) || (total1 != total2) || (pause1 != pause2) ); ++ ++ if (pause1) ++ current_frac1 = 0; ++ ++ if (buf_id) ++ *buf_id = buf_id1; ++ ++ if (total) ++ *total = total1; ++ ++ if (current_frac) ++ *current_frac = current_frac1; ++ ++ /* ++ * Success. ++ */ ++ return(0); ++} ++ ++/* changed for AC97 port from Virgo 1-4-3 */ ++#if 0 ++/***************************************************************************** ++ * ++ * int ep93xx_dma_get_position(int handle, unsigned int * buf_id, ++ unsigned int * total) ++ * ++ * Description: Takes two integer pointers and fills them with the start ++ * and current address of the buffer currently transferring ++ * on the specified DMA channel. ++ * ++ * handle: handle for the channel to query. ++ * buf_id: pointer which is filled in with the buffer id for the ++ * current buffer transferring on the dma channel. ++ * buffer being transferred. ++ * total : pointer which is filled in with the total bytes ++ * transferred on the channel. ++ ****************************************************************************/ ++int ++ep93xx_dma_get_position(int handle, unsigned int *buf_id, unsigned int *total) ++{ ++ int channel; ++ ep93xx_dma_t *dma; ++ ++ /* ++ * Get the DMA hw channel # from the handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (channel < 0) { ++ printk(KERN_ERR "DMA Get Position: Invalid dma handle.\n"); ++ ++ /* ++ * Fail. ++ */ ++ return (-EINVAL); ++ } ++ ++ dma = &dma_chan[channel]; ++ ++ /* ++ * TODO: should irqs be disabled here? ++ */ ++ ++ *buf_id = dma->buffer_queue[dma->current_buffer].buf_id; ++ ++ *total = dma->total_bytes; ++ ++ DPRINTK("DMA buf_id %d, total %d\n", *buf_id, *total); ++ ++ /* ++ * Success. ++ */ ++ return (0); ++} ++#endif ++ ++ ++ ++/***************************************************************************** ++ * ++ * int ep93xx_dma_get_total(int handle) ++ * ++ * Description: Returns the total number of bytes transferred on the ++ * specified channel since the channel was requested. ++ * ++ * handle: handle for the channel to query. ++ * ++ ****************************************************************************/ ++int ep93xx_dma_get_total(int handle) ++{ ++ int channel; ++ ++ /* ++ * Get the DMA hw channel # from the handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (channel < 0) { ++ printk(KERN_ERR "DMA Get Total: Invalid dma handle.\n"); ++ ++ /* ++ * Fail. ++ */ ++ return (-EINVAL); ++ } ++ ++ DPRINTK("DMA %d: total: %d \n", channel, dma_chan[channel].total_bytes); ++ ++ /* ++ * Return the total number of bytes transferred on this channel since ++ * it was requested. ++ */ ++ return (dma_chan[channel].total_bytes); ++} ++ ++/***************************************************************************** ++ * ep93xx_dma_request ++ * ++ * Description: This function will allocate a DMA channel for a particular ++ * hardware peripheral. Before initiating a transfer on the allocated ++ * channel, the channel must be set up and buffers have to queued up. ++ * ++ * handle: pointer to an integer which is filled in with a unique ++ * handle for this instance of the dma interface. ++ * device_id string with the device name, primarily used by /proc. ++ * device hardware device ID for which the requested dma channel will ++ * transfer data. ++ * ++ ****************************************************************************/ ++int ++ep93xx_dma_request(int *handle, const char *device_id, ep93xx_dma_dev_t device) ++{ ++ ep93xx_dma_t *dma = NULL; ++ int channel; ++ unsigned int error = 0; ++ unsigned int loop; ++ unsigned int M2P_reg_base; ++ ++ /* ++ * Check if the device requesting a DMA channel is a valid device. ++ */ ++ if ((device >= UNDEF) || (device < 0)) { ++ /* ++ * Invalid device, so return an error. ++ */ ++ return (-ENODEV); ++ } ++ ++ /* ++ * We've got a valid hardware device requesting a DMA channel. ++ * Now check if the device should open an M2P or M2M channel ++ */ ++ if (device < 20) { ++ channel = dma_open_m2p(device); ++ } else { ++ channel = dma_open_m2m(device); ++ } ++ ++ /* ++ * Check if we successfully opened a DMA channel ++ */ ++ if (channel < 0) { ++ printk(KERN_ERR ++ "%s: Could not open dma channel for this device.\n", ++ device_id); ++ ++ /* ++ * Fail. ++ */ ++ return (-EBUSY); ++ } ++ ++ dma = &dma_chan[channel]; ++ ++ /* ++ * Request the appropriate IRQ for the specified channel ++ */ ++ if (channel < 10) { ++ error = request_irq(dma->irq, dma_m2p_irq_handler, SA_INTERRUPT, ++ device_id, (void *)dma); ++ } else { ++ error = ++ request_irq(dma->irq, &dma_m2m_irq_handler, SA_INTERRUPT, ++ device_id, (void *)dma); ++ } ++ ++ /* ++ * Check for any errors during the irq request ++ */ ++ if (error) { ++ printk(KERN_ERR ++ "%s: unable to request IRQ %d for DMA channel\n", ++ device_id, dma->irq); ++ /* ++ * Fail. ++ */ ++ return (error); ++ } ++ ++ /* ++ * Generate a valid handle and exit. ++ * ++ * Increment the last valid handle. ++ * Check for wraparound (unlikely, but we like to be complete). ++ */ ++ dma->last_valid_handle++; ++ ++ if ((dma->last_valid_handle & DMA_HANDLE_SPECIFIER_MASK) != ++ (channel << 28)) { ++ /* ++ * If we wrapped around start over. ++ */ ++ dma->last_valid_handle = (channel << 28) + 1; ++ } ++ ++ /* ++ * Fill in the handle pointer with a valid handle for ++ * this dma channel instance. ++ */ ++ *handle = dma->last_valid_handle; ++ ++ DPRINTK("Handle for channel %d: 0x%x\n", channel, *handle); ++ ++ /* ++ * Save the device ID and device name. ++ */ ++ dma->device = device; ++ dma->device_id = device_id; ++ ++ /* ++ * Init all fields within the dma instance. ++ */ ++ for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) { ++ dma->buffer_queue[loop].buf_id = -1; ++ } ++ ++ /* ++ * Initialize all buffer queue variables. ++ */ ++ dma->current_buffer = 0; ++ dma->last_buffer = 0; ++ ++ dma->new_buffers = 0; ++ dma->used_buffers = 0; ++ dma->total_buffers = 0; ++ ++ /* ++ * Initialize the total bytes variable ++ */ ++ dma->total_bytes = 0; ++ ++ /* ++ * Initialize the transfer and pause state variables to 0. ++ */ ++ dma->xfer_enable = 0; ++ ++ dma->pause = 0; ++ ++ /* ++ * Initialize the pause buffer structure. ++ */ ++ dma->pause_buf.buf_id = -1; ++ ++ /* ++ * Initialize the callback function and user data fields. ++ */ ++ dma->callback = NULL; ++ ++ /* ++ * User data used as a parameter for the Callback function. The user ++ * sets up the data and sends it with the callback function. ++ */ ++ dma->user_data = 0; ++ ++ M2P_reg_base = dma_chan[channel].reg_base; ++ ++ /* ++ * Debugging message. ++ */ ++ DPRINTK("Successfully requested dma channel %d\n", channel); ++ DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS)); ++ DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL)); ++ DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN)); ++ DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC)); ++ DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0)); ++ DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0)); ++ DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0)); ++ DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1)); ++ DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1)); ++ DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1)); ++ ++ DPRINTK("Buffer source size last used \n"); ++ for (loop = 0; loop < 5; loop++) { ++ DPRINTK("%d 0x%x 0x%x %d %d \n", ++ loop, dma->buffer_queue[loop].source, ++ dma->buffer_queue[loop].size, ++ dma->buffer_queue[loop].last, ++ dma->buffer_queue[loop].used); ++ } ++ DPRINTK("pause 0x%x 0x%x %d %d \n", ++ dma->pause_buf.source, dma->pause_buf.size, ++ dma->pause_buf.last, dma->pause_buf.used); ++ ++ DPRINTK("Pause - %d \n", dma->pause); ++ DPRINTK("xfer_enable - %d \n", dma->xfer_enable); ++ DPRINTK("total bytes - 0x%x \n", dma->total_bytes); ++ DPRINTK("total buffer - %d \n", dma->total_buffers); ++ DPRINTK("new buffers - %d \n", dma->new_buffers); ++ DPRINTK("current buffer - %d \n", dma->current_buffer); ++ DPRINTK("last buffer - %d \n", dma->last_buffer); ++ DPRINTK("used buffers - %d \n", dma->used_buffers); ++ ++ DPRINTK("CURRENT1 - 0x%x \n", ++ readl(M2P_reg_base + M2P_OFFSET_CURRENT1)); ++ DPRINTK("VIC0IRQSTATUS - 0x%x, VIC0INTENABLE - 0x%x \n", ++ *(unsigned int *)(VIC0IRQSTATUS), ++ *(unsigned int *)(VIC0INTENABLE)); ++ ++ /* ++ * Success. ++ */ ++ return (0); ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_dma_free ++ * ++ * Description: This function will free the dma channel for future requests. ++ * ++ * handle: handle for the channel to be freed. ++ * ++ ****************************************************************************/ ++int ep93xx_dma_free(int handle) ++{ ++ ep93xx_dma_t *dma; ++ unsigned int M2M_reg_base, M2P_reg_base, uiCONTROL; ++ int channel; ++ ++ /* ++ * Get the DMA hw channel # from the handle. ++ */ ++ channel = dma_get_channel_from_handle(handle); ++ ++ /* ++ * See if this is a valid handle. ++ */ ++ if (channel < 0) { ++ printk(KERN_ERR "DMA Free: Invalid dma handle.\n"); ++ ++ /* ++ * Fail. ++ */ ++ return (-EINVAL); ++ } ++ ++ /* ++ * Get a pointer to the dma instance. ++ */ ++ dma = &dma_chan[channel]; ++ ++ /* ++ * Disable the dma channel ++ */ ++ if (channel < 10) { ++ /* ++ * M2P channel ++ */ ++ M2P_reg_base = dma->reg_base; ++ ++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2P_ENABLE; ++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL); ++ } else { ++ /* ++ * M2M channel ++ */ ++ M2M_reg_base = dma->reg_base; ++ ++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL); ++ uiCONTROL &= ~CONTROL_M2M_ENABLE; ++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL); ++ } ++ ++ /* ++ * Free the interrupt servicing this dma channel ++ */ ++ free_irq(dma->irq, (void *)dma); ++ ++ /* ++ * Decrement the reference count for this instance of the dma interface ++ */ ++ dma->ref_count--; ++ ++ /* ++ * Set the transfer and pause state variables to 0 ++ * (unititialized state). ++ */ ++ dma->xfer_enable = 0; ++ dma->pause = 0; ++ ++ /* ++ * Debugging message. ++ */ ++ DPRINTK("Successfully freed dma channel %d\n", channel); ++ ++ /* ++ * Success. ++ */ ++ return (0); ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_dma_init(void) ++ * ++ * Description: This function is called during system initialization to ++ * setup the interrupt number and register set base address for each DMA ++ * channel. ++ * ++ ****************************************************************************/ ++static int __init ep93xx_dma_init(void) ++{ ++ int channel; ++ ++ /* ++ * Init some values in each dma instance. ++ */ ++ for (channel = 0; channel < MAX_EP93XX_DMA_CHANNELS; channel++) { ++ /* ++ * IRQ for the specified dma channel. ++ */ ++ dma_chan[channel].irq = IRQ_DMAM2P0 + channel; ++ ++ /* ++ * Initial value of the dma channel handle. ++ */ ++ dma_chan[channel].last_valid_handle = channel << 28; ++ ++ /* ++ * Give the instance a pointer to the dma channel register ++ * base. ++ */ ++ if (channel < 10) { ++ dma_chan[channel].reg_base = DMAM2PChannelBase[channel]; ++ } else { ++ dma_chan[channel].reg_base = ++ DMAM2MChannelBase[channel - 10]; ++ } ++ ++ /* ++ * Initialize the reference count for this channel. ++ */ ++ dma_chan[channel].ref_count = 0; ++ } ++ ++ DPRINTK("DMA Interface intitialization complete\n"); ++ ++ /* ++ * Success ++ */ ++ return 0; ++} ++ ++__initcall(ep93xx_dma_init); ++ ++EXPORT_SYMBOL(ep93xx_dma_add_buffer); ++EXPORT_SYMBOL(ep93xx_dma_config); ++EXPORT_SYMBOL(ep93xx_dma_flush); ++EXPORT_SYMBOL(ep93xx_dma_free); ++EXPORT_SYMBOL(ep93xx_dma_get_position); ++EXPORT_SYMBOL(ep93xx_dma_get_total); ++EXPORT_SYMBOL(ep93xx_dma_init); ++EXPORT_SYMBOL(ep93xx_dma_pause); ++EXPORT_SYMBOL(ep93xx_dma_queue_full); ++EXPORT_SYMBOL(ep93xx_dma_remove_buffer); ++EXPORT_SYMBOL(ep93xx_dma_request); ++EXPORT_SYMBOL(ep93xx_dma_start); ++ +diff --git a/arch/arm/mach-ep93xx/dma_ep93xx.h b/arch/arm/mach-ep93xx/dma_ep93xx.h +new file mode 100644 +index 0000000..3ec0b0d +--- /dev/null ++++ b/arch/arm/mach-ep93xx/dma_ep93xx.h +@@ -0,0 +1,194 @@ ++/***************************************************************************** ++ * ++ * arch/arm/mach-ep93xx/dma_ep93xx.h ++ * ++ * DESCRIPTION: 93XX DMA controller API private defintions. ++ * ++ * Copyright Cirrus Logic Corporation, 2003. All rights reserved ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ ****************************************************************************/ ++#ifndef _EP93XX_DMA_H_ ++#define _EP93XX_DMA_H_ ++ ++#define MAX_EP93XX_DMA_BUFFERS 32 ++ ++#ifndef TRUE ++#define TRUE 1 ++#endif ++ ++#ifndef FALSE ++#define FALSE 0 ++#endif ++ ++#ifndef NULL ++#define NULL 0 ++#endif ++ ++/***************************************************************************** ++ * ++ * DMA buffer structure type. ++ * ++ ****************************************************************************/ ++typedef struct ep93xx_dma_buffer_s { ++ unsigned int source; /* buffer physical source address. */ ++ unsigned int dest; /* buffer physical destination address, */ ++ /* only used with the 2 M2M channels. */ ++ unsigned int size; /* buffer size in bytes */ ++ unsigned int last; /* 1 if this is the last buffer */ ++ /* in this transaction. If 1, */ ++ /* disable the NFBint so we aren't */ ++ /* interrupted for another buffer */ ++ /* when we know there won't be another. */ ++ unsigned int used; /* This field is set to 1 by the DMA */ ++ /* interface after the buffer is transferred */ ++ int buf_id; /* unique identifyer specified by the */ ++ /* the driver which requested the dma */ ++} ep93xx_dma_buffer_t; ++ ++typedef ep93xx_dma_buffer_t *ep93xx_dma_buffer_p; ++ ++/***************************************************************************** ++ * ++ * Instance definition for the DMA interface. ++ * ++ ****************************************************************************/ ++typedef struct ep7312_dma_s { ++ /* ++ * This 1 when the instance is in use, and 0 when it's not. ++ */ ++ unsigned int ref_count; ++ ++ /* ++ * This is the last valid handle for this instance. When giving out a ++ * new handle this will be incremented and given out. ++ */ ++ int last_valid_handle; ++ ++ /* ++ * device specifies one of the 20 DMA hardware ports this ++ * DMA channel will service. ++ */ ++ ep93xx_dma_dev_t device; ++ ++ /* ++ * DMABufferQueue is the queue of buffer structure pointers which the ++ * dma channel will use to setup transfers. ++ */ ++ ep93xx_dma_buffer_t buffer_queue[MAX_EP93XX_DMA_BUFFERS]; ++ ++ /* ++ * currnt_buffer : This is the buffer currently being transfered on ++ * this channel. ++ * last_buffer : This is the last buffer for this transfer. ++ * Note: current_buffer + 1 is already programmed into the dma ++ * channel as the next buffer to transfer. Don't write ++ * over either entry. ++ */ ++ int current_buffer; ++ int last_buffer; ++ ++ /* ++ * The following 3 fields are buffer counters. ++ * ++ * iNewBuffers: Buffers in the queue which have not been transfered. ++ * iUsedBuffers: Buffers in the queue which have have been tranferred, ++ * and are waiting to be returned. ++ * iTotalBuffers: Total number of buffers in the queue. ++ */ ++ int new_buffers; ++ int used_buffers; ++ int total_buffers; ++ ++ /* ++ * uiTotalBytes has the total bytes transfered on the channel since the ++ * last flush. This value does not include the bytes tranfered in the ++ * current buffer. A byte count is only added after a complete buffer ++ * is tranfered. ++ */ ++ unsigned int total_bytes; ++ ++ /* ++ * Interrupt number for this channel ++ */ ++ unsigned int irq; ++ ++ /* ++ * Indicates whether or not the channel is currently enabled to transfer ++ * data. ++ */ ++ unsigned int xfer_enable; ++ ++ /* ++ * pause indicates if the dma channel was paused by calling the pause ++ * ioctl. ++ */ ++ unsigned int pause; ++ ++ /* ++ * buffer structure used during a pause to capture the current ++ * address and remaining bytes for the buffer actively being transferred ++ * on the channel. This buffer will be used to reprogram the dma ++ * channel upon a resume. ++ */ ++ ep93xx_dma_buffer_t pause_buf; ++ ++ /* ++ * DMACallback is a function pointer which the calling application can ++ * use install a function to. this fuction can be used to notify the ++ * calling application of an interrupt. ++ */ ++ dma_callback callback; ++ ++ /* ++ * User data used as a parameter for the Callback function. The user ++ * sets up the data and sends it with the callback function. ++ */ ++ unsigned int user_data; ++ ++ /* ++ * A string representation of the device attached to the channel. ++ */ ++ const char *device_id; ++ ++ /* ++ * The register base address for this dma channel. ++ */ ++ unsigned int reg_base; ++ ++} ep93xx_dma_t; ++ ++/***************************************************************************** ++ * ++ * DMA macros ++ * ++ ****************************************************************************/ ++#define DMA_HANDLE_SPECIFIER_MASK 0xF0000000 ++#define DMA_CH0_HANDLE_SPECIFIER 0x00000000 ++#define DMA_CH1_HANDLE_SPECIFIER 0x10000000 ++#define DMA_CH2_HANDLE_SPECIFIER 0x20000000 ++#define DMA_CH3_HANDLE_SPECIFIER 0x30000000 ++#define DMA_CH4_HANDLE_SPECIFIER 0x40000000 ++#define DMA_CH5_HANDLE_SPECIFIER 0x50000000 ++#define DMA_CH6_HANDLE_SPECIFIER 0x60000000 ++#define DMA_CH7_HANDLE_SPECIFIER 0x70000000 ++#define DMA_CH8_HANDLE_SPECIFIER 0x80000000 ++#define DMA_CH9_HANDLE_SPECIFIER 0x90000000 ++#define DMA_CH10_HANDLE_SPECIFIER 0xA0000000 ++#define DMA_CH11_HANDLE_SPECIFIER 0xB0000000 ++ ++#endif ++ +diff --git a/arch/arm/mach-ep93xx/ep93xx.c b/arch/arm/mach-ep93xx/ep93xx.c +new file mode 100644 +index 0000000..a565f14 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/ep93xx.c +@@ -0,0 +1,571 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/ep93xx.c ++ * ++ * Copyright (C) 2000-2003 Deep Blue Solutions Ltd ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * Copyright (C) 2005 Michael Burian ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2, as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/device.h> ++#include <linux/interrupt.h> ++ ++#include <asm/irq.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++#include <asm/hardware/amba.h> ++#include <asm/mach/time.h> ++#include <asm/arch/platform.h> ++#include <asm/arch/regmap.h> ++ ++static __init void check_model(void) ++{ ++ unsigned long x; ++ char *model; ++ char *rev; ++ ++ printk(KERN_INFO "CPU model: "); ++ ++ x = readl(USRFLG); ++ switch (x) { ++ case 0: ++ model = "15"; ++ break; ++ case 2: ++ model = "12"; ++ break; ++ case 4: ++ model = "01"; ++ break; ++ default: ++ printk("(unknown model %ld) ", x); ++ model = "xx"; ++ break; ++ } ++ ++ x = readl(SYSCON_SYSCFG) >> 28; ++ switch (x) { ++ case 0: ++ rev = "A"; ++ break; ++ case 1: ++ rev = "B"; ++ break; ++ case 2: ++ rev = "C"; ++ break; ++ case 3: ++ rev = "D0"; ++ break; ++ case 4: ++ rev = "D1"; ++ break; ++ case 5: ++ rev = "E"; ++ break; ++ default: ++ printk("(unknown revision %ld) ", x); ++ rev = "unknown"; ++ break; ++ } ++ ++ printk("Cirrus Logic EP93%s, silicon rev %s\n", model, rev); ++} ++ ++static struct amba_device dma_device = { ++ .dev = { ++ .bus_id = "0x80000000:dma", ++ }, ++ .res = { ++ .start = DMA_BASE, ++ .end = DMA_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80000000, ++}; ++ ++static struct amba_device mac_device = { ++ .dev = { ++ .bus_id = "0x80010000:mac", ++ }, ++ .res = { ++ .start = MAC_BASE, ++ .end = MAC_BASE + SZ_64K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80010000, ++}; ++ ++static struct amba_device usb_device = { ++ .dev = { ++ .bus_id = "0x80020000:usb", ++ .coherent_dma_mask = 0xffffffff, ++ }, ++ .res = { ++ .start = USB_BASE, ++ .end = USB_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {IRQ_USH, NO_IRQ}, ++ .periphid = 0x80020000, ++}; ++ ++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315) ++static struct amba_device raster_device = { ++ .dev = { ++ .bus_id = "0x80030000:raster", ++ }, ++ .res = { ++ .start = RASTER_BASE, ++ .end = RASTER_BASE + SZ_8K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80030000, ++}; ++#endif ++ ++static struct amba_device sdram_device = { ++ .dev = { ++ .bus_id = "0x80060000:sdram", ++ }, ++ .res = { ++ .start = SDRAM_BASE, ++ .end = SDRAM_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80060000, ++}; ++ ++static struct amba_device smc_device = { ++ .dev = { ++ .bus_id = "0x80080000:smc", ++ }, ++ .res = { ++ .start = SMC_BASE, ++ .end = SMC_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80080000, ++}; ++ ++static struct amba_device boot_device = { ++ .dev = { ++ .bus_id = "0x80090000:boot", ++ }, ++ .res = { ++ .start = BOOT_BASE, ++ .end = BOOT_BASE + SZ_16K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80090000, ++}; ++ ++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315) ++static struct amba_device ide_device = { ++ .dev = { ++ .bus_id = "0x800a0000:ide", ++ }, ++ .res = { ++ .start = IDE_BASE, ++ .end = IDE_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x800a0000, ++}; ++#endif ++ ++static struct amba_device vic1_device = { ++ .dev = { ++ .bus_id = "0x800b0000:vic1", ++ }, ++ .res = { ++ .start = VIC0_BASE, ++ .end = VIC0_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x800b0000, ++}; ++ ++static struct amba_device vic2_device = { ++ .dev = { ++ .bus_id = "0x800c0000:vic2", ++ }, ++ .res = { ++ .start = VIC1_BASE, ++ .end = VIC1_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x800c0000, ++}; ++ ++static struct amba_device timer_device = { ++ .dev = { ++ .bus_id = "0x80810000:timer", ++ }, ++ .res = { ++ .start = TIMERS_BASE, ++ .end = TIMERS_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80810000, ++}; ++ ++static struct amba_device i2s_device = { ++ .dev = { ++ .bus_id = "0x80820000:i2s", ++ }, ++ .res = { ++ .start = I2S_BASE, ++ .end = I2S_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80820000, ++}; ++ ++static struct amba_device security_device = { ++ .dev = { ++ .bus_id = "0x80830000:security", ++ }, ++ .res = { ++ .start = SECURITY_BASE, ++ .end = SECURITY_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80830000, ++}; ++ ++static struct amba_device gpio_device = { ++ .dev = { ++ .bus_id = "0x80840000:gpio", ++ }, ++ .res = { ++ .start = GPIO_BASE, ++ .end = GPIO_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80840000, ++}; ++ ++static struct amba_device ac97_device = { ++ .dev = { ++ .bus_id = "0x80880000:ac97", ++ }, ++ .res = { ++ .start = AC97_BASE, ++ .end = AC97_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80880000, ++}; ++ ++static struct amba_device ssp_device = { ++ .dev = { ++ .bus_id = "0x808a0000:ssp", ++ }, ++ .res = { ++ .start = SSP_BASE, ++ .end = SSP_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x808a0000, ++}; ++ ++static struct amba_device irda_device = { ++ .dev = { ++ .bus_id = "0x808b0000:irda", ++ }, ++ .res = { ++ .start = IRDA_BASE, ++ .end = IRDA_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x808b0000, ++}; ++ ++static struct amba_device uart1_device = { ++ .dev = { ++ .bus_id = "0x808c0000:uart1", ++ }, ++ .res = { ++ .start = UART1_BASE, ++ .end = UART1_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {IRQ_UART1, NO_IRQ}, ++ .periphid = 0x808c0000, ++}; ++ ++static struct amba_device uart2_device = { ++ .dev = { ++ .bus_id = "0x808d0000:uart2", ++ }, ++ .res = { ++ .start = UART2_BASE, ++ .end = UART2_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {IRQ_UART2, NO_IRQ}, ++ .periphid = 0x808d0000, ++}; ++ ++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315) ++static struct amba_device uart3_device = { ++ .dev = { ++ .bus_id = "0x808e0000:uart3", ++ }, ++ .res = { ++ .start = UART3_BASE, ++ .end = UART3_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {IRQ_UART3, NO_IRQ}, ++ .periphid = 0x808e0000, ++}; ++ ++static struct amba_device key_device = { ++ .dev = { ++ .bus_id = "0x808f0000:key", ++ }, ++ .res = { ++ .start = KEY_BASE, ++ .end = KEY_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x808f0000, ++}; ++ ++static struct amba_device touch_device = { ++ .dev = { ++ .bus_id = "0x80900000:touch", ++ }, ++ .res = { ++ .start = TOUCH_BASE, ++ .end = TOUCH_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80900000, ++}; ++ ++static struct amba_device pwm_device = { ++ .dev = { ++ .bus_id = "0x80910000:pwm", ++ }, ++ .res = { ++ .start = PWM_BASE, ++ .end = PWM_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80910000, ++}; ++#endif ++ ++static struct amba_device rtc_device = { ++ .dev = { ++ .bus_id = "0x80920000:rtc", ++ }, ++ .res = { ++ .start = RTC_BASE, ++ .end = RTC_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {IRQ_RTC, NO_IRQ}, ++ .periphid = 0x80920000, ++}; ++ ++static struct amba_device syscon_device = { ++ .dev = { ++ .bus_id = "0x80930000:syscon", ++ }, ++ .res = { ++ .start = SYSCON_BASE, ++ .end = SYSCON_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80930000, ++}; ++ ++static struct amba_device watchdog_device = { ++ .dev = { ++ .bus_id = "0x80940000:watchdog", ++ }, ++ .res = { ++ .start = WATCHDOG_BASE, ++ .end = WATCHDOG_BASE + SZ_4K - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ .irq = {NO_IRQ, NO_IRQ}, ++ .periphid = 0x80940000, ++}; ++ ++static struct amba_device *amba_devs[] __initdata = { ++ /* AHB devices */ ++ &dma_device, ++ &mac_device, ++ &usb_device, ++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315) ++ &raster_device, ++#endif ++ &sdram_device, ++ &smc_device, ++ &boot_device, ++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315) ++ &ide_device, ++#endif ++ &vic1_device, ++ &vic2_device, ++ ++ /* APB devices */ ++ &timer_device, ++ &i2s_device, ++ &security_device, ++ &gpio_device, ++ &ac97_device, ++ &ssp_device, ++ &irda_device, ++ &uart1_device, ++ &uart2_device, ++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315) ++ &uart3_device, ++ &key_device, ++ &touch_device, ++ &pwm_device, ++#endif ++ &rtc_device, ++ &syscon_device, ++ &watchdog_device, ++}; ++ ++static int __init ep93xx_init(void) ++{ ++ int i; ++ ++ check_model(); ++ ++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { ++ struct amba_device *d = amba_devs[i]; ++ amba_device_register(d, &iomem_resource); ++ } ++ ++ return 0; ++} ++ ++arch_initcall(ep93xx_init); ++ ++#define TIMER_INTERVAL (508 * mSEC_10 / 1000) ++#define TICKS2USECS(x) ((x) * 1000 / 508) ++ ++static unsigned long timer_reload; ++ ++/* ++ * Returns number of ms since last clock interrupt. Note that interrupts ++ * will have been disabled by do_gettimeoffset() ++ */ ++static unsigned long ep93xx_gettimeoffset(void) ++{ ++ unsigned long ticks1, ticks2, status; ++ ++ /* ++ * Get the current number of ticks. Note that there is a race ++ * condition between us reading the timer and checking for ++ * an interrupt. We get around this by ensuring that the ++ * counter has not reloaded between our two reads. ++ */ ++ ticks2 = readl(TIMER1VALUE) & 0xffff; ++ do { ++ ticks1 = ticks2; ++ status = readl(VIC0RAWINTR); ++ ticks2 = readl(TIMER1VALUE) & 0xffff; ++ } while (ticks2 > ticks1); ++ ++ /* ++ * Number of ticks since last interrupt. ++ */ ++ ticks1 = timer_reload - ticks2; ++ ++ /* ++ * Interrupt pending? If so, we've reloaded once already. ++ */ ++ if (status & (1 << IRQ_TIMER1)) ++ ticks1 += timer_reload; ++ ++ return TICKS2USECS(ticks1); ++} ++ ++/* ++ * IRQ handler for the timer ++ */ ++static irqreturn_t ++ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ /* ...clear the interrupt */ ++ writel(1, TIMER1CLEAR); ++ ++ timer_tick(regs); ++ ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction ep93xx_timer_irq = { ++ .name = "timer", ++ .flags = SA_INTERRUPT, ++ .handler = ep93xx_timer_interrupt ++}; ++ ++/* ++ * Set up timer interrupt ++ */ ++static void __init __ep93xx_init_timer(unsigned long reload, unsigned int ctrl) ++{ ++ unsigned int timer_ctrl = 0x80 | 0x40 | 0x08; /* periodic at 508 kHz */ ++ ++ timer_reload = reload; ++ timer_ctrl |= ctrl; ++ ++ /* ++ * Initialise to a known state (all timers off) ++ */ ++ ++ writel(0, TIMER1CONTROL); ++ writel(0, TIMER2CONTROL); ++ writel(0, TIMER3CONTROL); ++ ++ writel(timer_reload, TIMER1LOAD); ++ writel(timer_reload, TIMER1VALUE); ++ writel(timer_ctrl, TIMER1CONTROL); ++ ++ setup_irq(IRQ_TIMER1, &ep93xx_timer_irq); ++} ++ ++static void __init ep93xx_init_timer(void) ++{ ++ /* 10 ms interval on a 508 kHz clock */ ++ __ep93xx_init_timer(5080, 0); ++} ++ ++struct sys_timer ep93xx_timer = { ++ .init = ep93xx_init_timer, ++ .offset = ep93xx_gettimeoffset, ++}; +diff --git a/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h b/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h +new file mode 100644 +index 0000000..d396e96 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h +@@ -0,0 +1,41 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h ++ * ++ * Copyright (C) 2004 Contec Steuerungstechnik & Automation GmbH ++ * Manfred Gruber <manfred.gruber@contec.at> ++ * ++ * 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 ++ */ ++ ++/* ++ * configuration struct for GPIO IRQs ++ * ++ * enable = 1 --> this EGIO is a irq ++ * enable = 0 --> this EGIO is a GPIO ++ * flags can be IRQT_RISING ++ * IRQT_FALLING ++ * IRQT_LOW ++ * IRQT_HIGH ++ * IRQT_PROBE ++ * ++ * On IRQT_PROBE nothing is done in setup irq code ++ */ ++ ++struct ep93xx_egpio_irq ++{ ++ unsigned int enable; ++ unsigned int flags; ++}; ++ +diff --git a/arch/arm/mach-ep93xx/irq.c b/arch/arm/mach-ep93xx/irq.c +new file mode 100644 +index 0000000..578c783 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/irq.c +@@ -0,0 +1,601 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/irq.c ++ * ++ * Copyright (C) 1999 ARM Limited ++ * ++ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA. All rights reserved. ++ * ++ * Copyright (C) 2002-2003 Cirrus Logic, Inc. ++ * ++ * Demux IRQ 59 by ++ * Copyright (C) 2004 Contec Steuerungstechnik & Automation GmbH ++ * Manfred Gruber <manfred.gruber@contec.at> ++ * ++ * 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 ++ * ++ * ++ * Modified by Stefano Lena <stefano.lena@dave-tech.it>, DAVE s.r.l. ++ * for Cirrus Logic EP93xx series ++ * ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/timer.h> ++#include <linux/init.h> ++ ++#include <asm/irq.h> ++ ++#include <asm/arch/irqs.h> ++ ++#include <asm/mach/irq.h> ++#include <asm/io.h> ++#include <asm/arch/hardware.h> ++ ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++#include <asm/arch/regmap.h> ++#include <linux/errno.h> ++#include "ep93xx_gpio_irq.h" ++extern struct ep93xx_egpio_irq egpio_irqs[]; ++ ++/* GPIO Port A/B debug messages */ ++/* #define DEBUG_GPIO */ ++#ifdef DEBUG_GPIO ++#define IRQDBG(args...) printk(args) ++#else ++#define IRQDBG(args...) do {} while(0) ++#endif ++#endif ++/******************************************************************** ++ * Interrupt functions are defined as machine specific here. ++ * ++ * Note: ++ * 1. Only normal interrupts are defined here. ++ * FIQs are a separate class of interrupts and would ++ * be slowed down if handled like normal interrupts. ++ * ++ * 2. TBD Invalid interrupt numbers are not checked. ++ * Some interrupt inputs are tied to GND, which means ++ * they will immediately activate when unmasked. ++ * Which may be useful for some devices. ++ * ++ * 3. TBD Edge triggered interrupts are not specially ++ * handled. The architecture should provide a way to ++ * set up the edge trigger features and then a way to ++ * control the acknowledge to the interrupt. ++ * ++ ************************************************************************/ ++ ++ /******************************************************************** ++ * demux interrupt handler for GPIO Port A and B on ep93xx ++ * ++ * Note: ++ That IRQs from 64 to 79 defined as GPIO_IRQ0 - GPIO_IRQ15 ++ * GPIO IRQs on port F are as the are defined as IRQ_GPIOX ++ * which are NOT handled in demux interrupt handler !!!!! ++ * ++ * Default in mach-xy file a struct ep93xx_egpio_irq ++ * can be set up, there you can configure which gpio ++ * of Port A/B should be used as interrupt on startup. ++ * Setting up this IRQs in your driver direct not on startup ++ * you have to do a set_irq_type(GPIO_IRQX, flags) before ++ * calling request irq. Possible Flags are: ++ * IRQT_RISING, IRQT_FALLING, IRQT_LOW, IRQT_HIGH, IRQT_PROBE, IRQ_DB, IRQ_NOTDB ++ * On IRQT_PROBE nothing is done. ++ ************************************************************************/ ++ ++ /******************************************************************** ++ * TODO: ++ * ++ * Configure ack, mask, unsmask to use the right ++ * Port F GPIO registers. ++ * ++************************************************************************/ ++ ++static void ep93xx_vic1_mask(unsigned int irq) ++{ ++ writel((1 << irq), VIC0INTENCLEAR); ++} ++ ++static void ep93xx_vic1_unmask(unsigned int irq) ++{ ++ writel((1 << irq), VIC0INTENABLE); ++} ++ ++static struct irqchip vic1_chip = { ++ .ack = ep93xx_vic1_mask, ++ .mask = ep93xx_vic1_mask, ++ .unmask = ep93xx_vic1_unmask, ++}; ++ ++static void ep93xx_vic2_mask(unsigned int irq) ++{ ++ writel((1 << (irq - 32)), VIC1INTENCLEAR); ++} ++ ++static void ep93xx_vic2_unmask(unsigned int irq) ++{ ++ writel((1 << (irq - 32)), VIC1INTENABLE); ++} ++ ++static struct irqchip vic2_chip = { ++ .ack = ep93xx_vic2_mask, ++ .mask = ep93xx_vic2_mask, ++ .unmask = ep93xx_vic2_unmask, ++}; ++ ++static void ep93xx_rtc_ack(unsigned int irq) ++{ ++} ++ ++static struct irqchip rtc_chip = { ++ .ack = ep93xx_rtc_ack, ++ .mask = ep93xx_vic2_mask, ++ .unmask = ep93xx_vic2_unmask, ++}; ++ ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++/* ++ * ack EGPIO irq's ++ * Ack only for edge triggered int's valid ++ */ ++static void inline ep93xx_ack_gpio_irq(u32 irq) ++{ ++ u32 irq_status; ++ u32 bit = IRQ_TO_BIT(irq); ++ ++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit); ++ ++ /* Port A */ ++ if(bit & 0xFF) { ++ irq_status = readl(GPIO_INTSTATUSA); ++ if(irq_status & bit) ++ writel(bit, GPIO_AEOI); ++ } ++ ++ /* Port B */ ++ if(bit & 0xFF00) { ++ irq_status = readl(GPIO_INTSTATUSB); ++ if(irq_status & (bit >> 8)) ++ writel((bit >> 8), GPIO_BEOI); ++ ++ } ++} ++ ++/* ++ * unmask EGPIO irq's (enable) ++ */ ++static void inline ep93xx_unmask_gpio_irq(u32 irq) ++{ ++ u32 irq_status; ++ u32 bit = IRQ_TO_BIT(irq); ++ ++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit); ++ ++ /* Port A */ ++ if(bit & 0xFF) { ++ irq_status = readl(GPIO_AINTEN); ++ irq_status |= bit; ++ writel(irq_status, GPIO_AINTEN); ++ } ++ ++ /* Port B */ ++ if(bit & 0xFF00) { ++ irq_status = readl(GPIO_BINTEN); ++ irq_status |= (bit >> 8); ++ writel(irq_status, GPIO_BINTEN); ++ } ++} ++ ++/* ++ * Enable debounce on EGPIO IRQ ++ */ ++ ++static void ep93xx_debounce_enable(u32 irq) ++{ ++ u32 db_status; ++ u32 bit = IRQ_TO_BIT(irq); ++ ++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit); ++ ++ /* Port A */ ++ if (bit & 0xFF) { ++ db_status = readl(GPIO_ADB); ++ db_status |= bit ; ++ writel(db_status, GPIO_ADB); ++ } ++ ++ /* Port B */ ++ if (bit & 0xFF00 ) { ++ db_status = readl(GPIO_BDB); ++ db_status |= (bit >> 8) ; ++ writel(db_status, GPIO_BDB); ++ } ++ ++} ++ ++/* ++ * Disable debounce on EGPIO IRQ ++ */ ++static void ep93xx_debounce_disable(u32 irq) ++{ ++ u32 db_status; ++ u32 bit = IRQ_TO_BIT(irq); ++ ++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit); ++ ++ /* Port A */ ++ if (bit & 0xFF) { ++ db_status = readl(GPIO_ADB); ++ db_status &= ~bit ; ++ writel(db_status, GPIO_ADB); ++ } ++ ++ /* Port B */ ++ if (bit & 0xFF00 ) { ++ db_status = readl(GPIO_BDB); ++ db_status &= ~(bit >> 8) ; ++ writel(db_status, GPIO_BDB); ++ } ++ ++} ++ ++/* ++ * mask EGPIO irq's (disable) ++ */ ++static void inline ep93xx_mask_gpio_irq(u32 irq) ++{ ++ u32 irq_status; ++ u32 bit = IRQ_TO_BIT(irq); ++ ++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit); ++ ++ /* Port A */ ++ if(bit & 0xFF) { ++ irq_status = readl(GPIO_AINTEN); ++ irq_status &= ~bit; ++ writel(irq_status, GPIO_AINTEN); ++ } ++ ++ /* Port B */ ++ if(bit & 0xFF00) { ++ irq_status = readl(GPIO_BINTEN); ++ irq_status &= ~(bit >> 8); ++ writel(irq_status, GPIO_BINTEN); ++ } ++} ++ ++ ++ ++/* ++ * make a EGPIO to a irq input ++ */ ++static int ep93xx_make_egio_to_irq(u32 bit,u32 irq) ++{ ++ u32 irq_value; ++ int ret; ++ ++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit); ++ ++ if(bit & 0xFF) { ++ /* Set direction to input for EGPIOA */ ++ irq_value = readl(GPIO_PADDR); ++ irq_value &= ~bit; ++ if((ret = writel(irq_value, GPIO_PADDR)) != irq_value) { ++ printk("%s irq: %d cannot set direction register(GPIO_PADDR) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret); ++ return -EFAULT; ++ } ++ } ++ /* Port B */ ++ if(bit & 0xFF00) { ++ /* Set direction to input for EGPIOB */ ++ irq_value = readl(GPIO_PBDDR); ++ irq_value &= ~(bit >> 8); ++ if((ret = writel(irq_value, GPIO_PBDDR)) != irq_value) { ++ printk("%s irq: %d cannot set direction register(GPIO_PBDDR) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret); ++ return -EFAULT; ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * make a EGPIO edge/level sensitive ++ */ ++static int ep93xx_make_egio_sensitive(u32 bit, unsigned int flags,u32 irq) ++{ ++ u32 irq_value; ++ int ret; ++ ++ /* PORT A */ ++ if(bit & 0xFF) { ++ /* Enable edge/level sensitive IRQ on EGPIO PORT A */ ++ irq_value = readl(GPIO_AINTTYPE1); ++ if(flags && 1) ++ irq_value |= bit; ++ else ++ irq_value &= ~bit; ++ if((ret = writel(irq_value, GPIO_AINTTYPE1)) != irq_value) { ++ printk("%s irq: %d cannot set IRQ parameter(GPIO_AINTYPE1) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret); ++ return -EFAULT; ++ } ++ } ++ ++ /* Port B */ ++ if(bit & 0xFF00) { ++ /* Enable edge/level sensitive IRQ on EGPIO PORT B */ ++ irq_value = readl(GPIO_BINTTYPE1); ++ if(flags && 1) ++ irq_value |= (bit >> 8); ++ else ++ irq_value &= ~(bit >> 8); ++ if((ret = writel(irq_value, GPIO_BINTTYPE1)) != irq_value) { ++ /* printk("%s irq: %d cannot set IRQ parameter(GPIO_BINTYPE1) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret); */ ++ return -EFAULT; ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * make a EGPIO high/low sensitive ++ */ ++static int ep93xx_make_egio_high_low_sensitive(u32 bit, unsigned int flags,u32 irq) ++{ ++ u32 irq_value; ++ int ret; ++ ++ /* PORT A */ ++ if(bit & 0xFF) { ++ /* Enable high/low sensitive IRQ on EGPIO PORT A */ ++ irq_value = readl(GPIO_AINTTYPE2); ++ if(flags && 1) ++ irq_value |= bit; ++ else ++ irq_value &= ~bit; ++ if((ret = writel(irq_value, GPIO_AINTTYPE2)) != irq_value) { ++ printk("%s irq: %d cannot set IRQ parameter(GPIO_AINTTYPE2) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret); ++ return -EFAULT; ++ } ++ } ++ ++ /* Port B */ ++ if(bit & 0xFF00) { ++ /* Enable high/low sensitive IRQ on EGPIO PORT B */ ++ irq_value = readl(GPIO_BINTTYPE2); ++ if(flags && 1) ++ irq_value |= (bit >> 8); ++ else ++ irq_value &= ~(bit >> 8); ++ if((ret = writel(irq_value, GPIO_BINTTYPE2)) != irq_value) ++ { ++ printk("%s irq: %d cannot set IRQ parameter(GPIO_BINTYPE2) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret); ++ return -EFAULT; ++ } ++ } ++ ++ return 0; ++} ++ ++ ++ ++ ++/* ++ * type of GPIO irq's ++ */ ++static int ep93xx_gpio_demux_handler_type(unsigned int irq, unsigned int flags) ++{ ++ u32 bit = IRQ_TO_BIT(irq); ++ unsigned int debounce = 0; ++ ++ IRQDBG("%s irq: %d\n",__FUNCTION__,irq); ++ ++ /*if (flags == IRQT_PROBE) ++ return 0;*/ ++ ++ if ((flags & __IRQT_RISEDGE) | (flags & __IRQT_FALEDGE) | (flags & __IRQT_LOWLVL) | (flags & __IRQT_HIGHLVL) | (flags & IRQT_DB) | (flags & IRQT_NOTDB)) { ++ if(0 != ep93xx_make_egio_to_irq(bit,irq)) { ++ printk("%s irq: %d cannot set direction register GPIO_PXDDR\n",__FUNCTION__,irq); ++ return -EINVAL; ++ } else { ++ if ((flags & IRQT_DB) | (flags & IRQT_NOTDB)) { /* To use switch structure extract debounce ++ flags from flags variable */ ++ debounce = (flags & IRQT_DB) | (flags & IRQT_NOTDB); ++ flags &= ~debounce; ++ } ++ if((flags & __IRQT_RISEDGE) | (flags & __IRQT_FALEDGE)) { ++ /* Configure for edge IRQ */ ++ if(0 == ep93xx_make_egio_sensitive(bit, 1,irq)) { ++ switch(flags) { ++ case __IRQT_RISEDGE: ++ if(0 != ep93xx_make_egio_high_low_sensitive(bit, 1,irq)) { ++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq); ++ return -EINVAL; ++ } ++ break; ++ case __IRQT_FALEDGE: ++ if(0 != ep93xx_make_egio_high_low_sensitive(bit, 0,irq)) { ++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq); ++ return -EINVAL; ++ } ++ break; ++ } ++ ++ /* Now we set IRQ handler for edge */ ++ /* set_irq_handler(irq, do_edge_IRQ); */ ++ } else { ++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE1\n",__FUNCTION__,irq); ++ return -EINVAL; ++ } ++ ++ } else { ++ if((flags & __IRQT_LOWLVL) | (flags & __IRQT_HIGHLVL)) { ++ /* Configure for level IRQ */ ++ if(0 == ep93xx_make_egio_sensitive(bit, 0,irq)) { ++ switch(flags) ++ { ++ case __IRQT_HIGHLVL: ++ if(0 != ep93xx_make_egio_high_low_sensitive(bit, 1,irq)) ++ { ++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq); ++ return -EINVAL; ++ } ++ break; ++ case __IRQT_LOWLVL: ++ if(0 != ep93xx_make_egio_high_low_sensitive(bit, 0,irq)) ++ { ++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq); ++ return -EINVAL; ++ } ++ break; ++ } ++ ++ /* Now we set IRQ handler level sensitive */ ++ /* set_irq_handler(irq, do_level_IRQ); */ ++ } else { ++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE1\n",__FUNCTION__,irq); ++ return -EINVAL; ++ } ++ ++ } ++ } ++ } ++ /* For debounce flags handling */ ++ if ((debounce & IRQT_DB) | (debounce & IRQT_NOTDB)) { ++ switch(debounce) ++ { ++ case IRQT_DB: ++ ep93xx_debounce_enable(irq); ++ break; ++ case IRQT_NOTDB: ++ ep93xx_debounce_disable(irq); ++ break; ++ } ++ } ++ } else { ++ printk("ep93xx_type_gpio_irq: IRQ:%d no flags defined\n",irq); ++ return -EINVAL; ++ } ++return 0; ++} ++ ++/* ++ * GPIO call handler ++ */ ++static void ep93xx_gpio_handler(unsigned int mask, unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) ++{ ++ IRQDBG("%s irq: %d\n",__FUNCTION__,irq); ++ ++ desc = irq_desc + irq; ++ ++ while (mask) { ++ if (mask & 1) { ++ IRQDBG("handling irq %d\n", irq); ++ desc->handle(irq, desc, regs); ++ } ++ irq++; ++ desc++; ++ mask >>= 1; ++ } ++ ++} ++ ++/* ++ * GPIO dmux handler ++ */ ++static void ep93xx_gpio_demux_handler(unsigned int irq_gpio, struct irqdesc *desc, struct pt_regs *regs) ++{ ++ unsigned int mask; ++ unsigned int irq = IRQ_CHAINED_GPIO(0); ++ ++ /* ++ * Mask the parent IRQ. ++ */ ++ ep93xx_vic2_mask(irq_gpio); ++ ++ mask = readl(GPIO_INTSTATUSA) | (readl(GPIO_INTSTATUSB) << 8); ++ ++ irq = IRQ_CHAINED_GPIO(0); ++ IRQDBG("%s mask: 0x%x irq: %d\n",__FUNCTION__,mask,irq); ++ ep93xx_gpio_handler(mask, irq, desc, regs); ++ ++ /* ++ * Unmask the parent IRQ ++ */ ++ ep93xx_vic2_unmask(irq_gpio); ++} ++ ++ ++static struct irqchip ep93xx_gpio_irq = { ++ .ack = ep93xx_ack_gpio_irq, ++ .mask = ep93xx_mask_gpio_irq, ++ .unmask = ep93xx_unmask_gpio_irq, ++ .set_type = ep93xx_gpio_demux_handler_type, ++}; ++ ++#endif ++ ++ ++void __init ep93xx_init_irq(void) ++{ ++ unsigned int i; ++ ++ /* Interrupt bits 0 and 1 are unused */ ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++ for (i = 2; i < NR_GLBL_IRQS; i++) { ++#else ++ for (i = 2; i < NR_IRQS; i++) { ++#endif ++ if(i < 32){ ++ /* Interrupts below 32 belong to VIC1 */ ++ set_irq_handler(i, do_level_IRQ); ++ set_irq_chip(i, &vic1_chip); ++ set_irq_flags(i, IRQF_VALID); ++ ++ } else { ++ if (i == IRQ_1HZ) { ++ /* 1 Hz int is edge trigered, and not ackable */ ++ set_irq_handler(i, do_edge_IRQ); ++ set_irq_chip(i, &rtc_chip); ++ set_irq_flags(i, IRQF_VALID | IRQF_NOAUTOEN); ++ } else { ++ /* Interrupt 32 and above belong to VIC2 */ ++ set_irq_handler(i, do_level_IRQ); ++ set_irq_chip(i, &vic2_chip); ++ set_irq_flags(i, IRQF_VALID); ++ } ++ } ++ } ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++ for (i = IRQ_CHAINED_GPIO(0) ; i <= IRQ_CHAINED_GPIO(15); i++) { ++ ++ IRQDBG("%s irq: %d init \n",__FUNCTION__, i); ++ ++ /* GPIO Interrupt is demux to 16 IRQs */ ++ set_irq_chip(i, &ep93xx_gpio_irq); ++ set_irq_flags(i, IRQF_VALID); ++ ++ if(egpio_irqs[i - NR_GLBL_IRQS].enable == 1) { ++ set_irq_handler(i, do_level_IRQ); ++ set_irq_type(i, egpio_irqs[i - NR_GLBL_IRQS].flags); ++ } else { ++ set_irq_handler(i, do_edge_IRQ); ++ } ++ } ++ set_irq_chained_handler(IRQ_GPIO, ep93xx_gpio_demux_handler); ++#endif ++} +diff --git a/arch/arm/mach-ep93xx/mach-acc.c b/arch/arm/mach-ep93xx/mach-acc.c +new file mode 100644 +index 0000000..aa002ac +--- /dev/null ++++ b/arch/arm/mach-ep93xx/mach-acc.c +@@ -0,0 +1,67 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/acc.c ++ * ++ * Copyright (C) 2000 Deep Blue Solutions Ltd ++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * Copyright (C) 2004 Klaus Fetscher ++ * ++ * 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/kernel.h> ++#include <linux/init.h> ++ ++#include <asm/mach-types.h> ++#include <asm/memory.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++ ++#include <asm/arch/platform.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/map.h> ++ ++extern void ep93xx_init_irq(void); ++ ++/* break this up into individual register blocks and map them in ++ the associated device drivers */ ++ ++static struct map_desc acc_io_desc[] __initdata = { ++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE }, ++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE }, ++}; ++ ++static void __init acc_map_io(void) ++{ ++ iotable_init(acc_io_desc, ARRAY_SIZE(acc_io_desc)); ++} ++ ++static void __init acc_init(void) ++{ ++} ++ ++MACHINE_START(ACC, "acc") ++ /* Maintainer HiFish */ ++ .phys_ram = SDRAM_START, ++ .phys_io = 0x80000000, ++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, ++ .boot_params = (SDRAM_START + 0x00000100), ++ ++ .map_io = acc_map_io, ++ .init_irq = ep93xx_init_irq, ++ .init_machine = acc_init, ++ .timer = &ep93xx_timer, ++MACHINE_END +diff --git a/arch/arm/mach-ep93xx/mach-adssphere.c b/arch/arm/mach-ep93xx/mach-adssphere.c +new file mode 100644 +index 0000000..2cbf5ca +--- /dev/null ++++ b/arch/arm/mach-ep93xx/mach-adssphere.c +@@ -0,0 +1,281 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/adssphere.c ++ * ++ * Copyright (C) 2000 Deep Blue Solutions Ltd ++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * Copyright (C) 2005 Robert Whaley, ADS ++ * ++ * 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/config.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/platform_device.h> ++#include <linux/fb.h> ++ ++#include <asm/mach-types.h> ++#include <asm/memory.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++#include <asm/leds.h> ++#include <asm/system.h> ++ ++#include <asm/arch/platform.h> ++#include <asm/arch/regmap.h> ++ ++#include <asm/arch/adssphere.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++#include <asm/mach/map.h> ++ ++extern void ep93xx_init_irq(void); ++ ++/* break this up into individual register blocks and map them in ++ the associated device drivers */ ++ ++static struct map_desc adssphere_io_desc[] __initdata = ++{ ++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE }, ++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE }, ++ { ADSSPHERE_BASE_VIRT, ADSSPHERE_BASE_PHYS, SZ_1M, MT_DEVICE }, ++}; ++ ++static void __init adssphere_map_io(void) ++{ ++ iotable_init(adssphere_io_desc, ARRAY_SIZE(adssphere_io_desc)); ++} ++ ++/* ++ * Flash handling. ++ */ ++ ++static int flash_init(void) ++{ ++ return 0; ++} ++ ++static void flash_exit(void) ++{ ++} ++ ++static void flash_set_vpp(int on) ++{ ++} ++ ++static struct flash_platform_data flash_data = { ++ .map_name = "cfi_probe", ++ .width = 4, ++ .init = flash_init, ++ .exit = flash_exit, ++ .set_vpp = flash_set_vpp, ++}; ++ ++static struct resource cfi_flash_resource = { ++ .start = 0x60000000, ++ .end = 0x60000000 + SZ_32M - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device cfi_flash_device = { ++ .name = "flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &cfi_flash_resource, ++}; ++ ++#ifdef CONFIG_LEDS ++ ++#define LED_STATE_ENABLED 1 ++#define LED_STATE_CLAIMED 2 ++ ++static unsigned int led_state; ++static unsigned int hw_led_state; ++ ++#define LED_GREEN 1 ++#define LED_MASK (LED_GREEN) ++ ++void adssphere_leds_event(led_event_t evt) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ switch (evt) { ++ case led_start: ++ led_state = LED_STATE_ENABLED; ++ hw_led_state = LED_GREEN; ++ break; ++ ++ case led_stop: ++ led_state &= ~LED_STATE_ENABLED; ++ hw_led_state = 0; ++ break; ++ ++ case led_claim: ++ led_state |= LED_STATE_CLAIMED; ++ hw_led_state = LED_GREEN; ++ break; ++ ++ case led_release: ++ led_state &= ~LED_STATE_CLAIMED; ++ hw_led_state = 0; ++ break; ++ ++ case led_timer: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state ^= LED_GREEN; ++ break; ++ ++ case led_idle_start: ++ break; ++ ++ case led_idle_end: ++ break; ++ ++ case led_halted: ++ break; ++ ++ case led_green_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_GREEN; ++ break; ++ ++ case led_green_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_GREEN; ++ break; ++ ++ case led_amber_on: ++ break; ++ ++ case led_amber_off: ++ break; ++ ++ case led_red_on: ++ break; ++ ++ case led_red_off: ++ break; ++ ++ default: ++ break; ++ } ++ ++ writel(0x03, GPIO_PEDDR); ++ ++ if (led_state & LED_STATE_ENABLED) ++ writel(hw_led_state, GPIO_PEDR); ++ local_irq_restore(flags); ++} ++ ++#endif ++ ++#ifdef CONFIG_SOUND_EP93XX_AC97 ++void adssphere_audio_power(int on) ++{ ++ unsigned int tmp; ++ ++ tmp = readb(ADSSPHERE_CR1); ++ if (on) { ++ tmp |= ADSSPHERE_CR1_AMP_ON; ++ tmp &= ~ADSSPHERE_CR1_CDC_ON; ++ } else { ++ tmp &= ~ADSSPHERE_CR1_AMP_ON; ++ tmp |= ADSSPHERE_CR1_CDC_ON; ++ } ++ writeb(tmp, ADSSPHERE_CR1); ++} ++ ++#endif ++ ++#ifdef CONFIG_FB_EP93XX ++void adssphere_blank(int blank_mode) ++{ ++ unsigned int tmp; ++ ++ switch (blank_mode) { ++ case FB_BLANK_UNBLANK: ++ case FB_BLANK_NORMAL: ++ /* turn on backlight via enable and pwm */ ++ /* enable fb signals */ ++ tmp = readl(ADSSPHERE_CR1); ++ tmp &= ~ADSSPHERE_CR1_PNL_ON; ++ tmp |= ADSSPHERE_CR1_PNL_EN | ADSSPHERE_CR1_BL_ON; ++ writel(tmp, ADSSPHERE_CR1); ++ ++ writel(100, PWM0_TC); ++ writel(99, PWM0_DC); ++ writel(1, PWM0_EN); ++ ++ break; ++ ++ ++ case FB_BLANK_VSYNC_SUSPEND: ++ case FB_BLANK_HSYNC_SUSPEND: ++ case FB_BLANK_POWERDOWN: ++ ++ /* disable fb signals */ ++ /* turn off backlight via enable and pwm */ ++ tmp = readl(ADSSPHERE_CR1); ++ tmp |= ADSSPHERE_CR1_PNL_ON; ++ tmp &= ~(ADSSPHERE_CR1_PNL_EN | ADSSPHERE_CR1_BL_ON); ++ writel(tmp, ADSSPHERE_CR1); ++ ++ writel(0, PWM0_EN); ++ ++ break; ++ } ++} ++#endif ++ ++static void __init adssphere_init (void) ++{ ++#if 0 ++ printk("physmap_configure\n"); ++ physmap_configure(0x60000000, 0x02000000, 4, NULL); ++#endif ++ printk("platform_device_register\n"); ++ platform_device_register(&cfi_flash_device); ++#ifdef CONFIG_LEDS ++ leds_event = adssphere_leds_event; ++#endif ++ leds_event(led_start); ++#ifdef CONFIG_SOUND_EP93XX_AC97 ++ adssphere_audio_power(1); ++#endif ++} ++ ++MACHINE_START(ADSSPHERE, "adssphere") ++ /* Maintainer: Applied Data Systems */ ++ .phys_ram = SDRAM_START, ++ .phys_io = 0x80000000, ++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, ++ .boot_params = (SDRAM_START + 0x00000100), ++ ++ .map_io = adssphere_map_io, ++ .init_irq = ep93xx_init_irq, ++ .init_machine = adssphere_init, ++ .timer = &ep93xx_timer, ++MACHINE_END ++ +diff --git a/arch/arm/mach-ep93xx/mach-dma03.c b/arch/arm/mach-ep93xx/mach-dma03.c +new file mode 100644 +index 0000000..2223f80 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/mach-dma03.c +@@ -0,0 +1,343 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/mach-dma03.c ++ * Copyright (C) 2005 Michael Burian ++ * ++ * based on arch/arm/mach-ep93xx/mach-edb9315.c ++ * ++ * Copyright (C) 2000 Deep Blue Solutions Ltd ++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * ++ * 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/config.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> ++ ++#ifdef CONFIG_SERIAL_8250 ++#include <linux/serial_8250.h> ++#endif ++ ++#ifdef CONFIG_PARPORT_PC ++#include <linux/parport.h> ++#endif ++ ++#include <asm/mach-types.h> ++#include <asm/memory.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++#include <asm/leds.h> ++#include <asm/system.h> ++#ifdef CONFIG_SERIAL_8250 ++#include <asm/serial.h> ++#endif ++ ++#include <asm/arch/platform.h> ++#include <asm/arch/regmap.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++#include <asm/mach/map.h> ++ ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++#include "ep93xx_gpio_irq.h" ++#endif ++ ++ ++ ++extern void ep93xx_init_irq(void); ++ ++/* break this up into individual register blocks and map them in ++ the associated device drivers */ ++ ++static struct map_desc dma03_io_desc[] __initdata = { ++ {EP93XX_AHB_BASE, __phys_to_pfn(io_v2p(EP93XX_AHB_BASE)), SZ_1M, MT_DEVICE}, ++ {EP93XX_APB_BASE, __phys_to_pfn(io_v2p(EP93XX_APB_BASE)), SZ_8M, MT_DEVICE}, ++#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_PARPORT_PC) ++ { 0xD0000000, __phys_to_pfn(0x70000000), SZ_4K, MT_DEVICE }, /* 2x UARTS, LPT; 16C552 */ ++#endif ++}; ++ ++static void __init dma03_map_io(void) ++{ ++ iotable_init(dma03_io_desc, ARRAY_SIZE(dma03_io_desc)); ++} ++ ++/* ++ * Flash handling. ++ */ ++ ++static int flash_init(void) ++{ ++ return 0; ++} ++ ++static void flash_exit(void) ++{ ++} ++ ++static void flash_set_vpp(int on) ++{ ++} ++ ++static struct flash_platform_data flash_data = { ++ .map_name = "cfi_probe", ++ .width = 4, ++ .init = flash_init, ++ .exit = flash_exit, ++ .set_vpp = flash_set_vpp, ++}; ++ ++static struct resource cfi_flash_resource = { ++ .start = 0x60000000, ++ .end = 0x60000000 + SZ_32M - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device cfi_flash_device = { ++ .name = "flash", ++ .dev = { ++ .platform_data = &flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &cfi_flash_resource, ++}; ++ ++#ifdef CONFIG_LEDS ++ ++#define LED_STATE_ENABLED 1 ++#define LED_STATE_CLAIMED 2 ++ ++static unsigned int led_state; ++static unsigned int hw_led_state; ++ ++#define LED_RED 2 ++#define LED_GREEN 1 ++#define LED_MASK (LED_GREEN | LED_RED) ++ ++void dma03_leds_event(led_event_t evt) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ switch (evt) { ++ case led_start: ++ led_state = LED_STATE_ENABLED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_stop: ++ led_state &= ~LED_STATE_ENABLED; ++ hw_led_state = 0; ++ break; ++ ++ case led_claim: ++ led_state |= LED_STATE_CLAIMED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_release: ++ led_state &= ~LED_STATE_CLAIMED; ++ hw_led_state = 0; ++ break; ++ ++ case led_timer: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state ^= LED_GREEN; ++ break; ++ ++ case led_idle_start: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ case led_idle_end: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_halted: ++ break; ++ ++ case led_green_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_GREEN; ++ break; ++ ++ case led_green_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_GREEN; ++ break; ++ ++ case led_amber_on: ++ break; ++ ++ case led_amber_off: ++ break; ++ ++ case led_red_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_red_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ default: ++ break; ++ } ++ ++ writel(0x03, GPIO_PEDDR); ++ ++ if (led_state & LED_STATE_ENABLED) ++ writel(hw_led_state, GPIO_PEDR); ++ ++ local_irq_restore(flags); ++} ++ ++#endif ++ ++ ++ ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++/* GPIO irq description ++ * IRQs are set up in arch/arm/mach-ep93xx/irq.c ++ * flags can be IRQT_RISING ++ * IRQT_FALLING ++ * IRQT_LOW ++ * IRQT_HIGH ++ * IRQT_PROBE ++ * ++ * On IRQT_PROBE nothing is done in setup irq code ++ */ ++ ++/* For IRQ Demux */ ++ ++#define DISABLED 0 ++#define ENABLED 1 ++struct ep93xx_egpio_irq egpio_irqs[] __initdata = ++{ ++ /* EGPIO IRQ 0 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 1 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 2 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 3 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 4 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 5 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 6 */ ++ { ENABLED, IRQT_HIGH }, /* OKI ML9620 CAN controller can0 */ ++ /* EGPIO IRQ 7 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 8 */ ++ { ENABLED, IRQT_HIGH }, /* 16C552 serial UART 1 */ ++ /* EGPIO IRQ 9 */ ++ { ENABLED, IRQT_HIGH }, /* 16C552 serial UART 2 */ ++ /* EGPIO IRQ 10 */ ++ { ENABLED, IRQT_RISING }, /* 16C552 parallel port 1 */ ++ /* EGPIO IRQ 11 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 12 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 13 */ ++ { ENABLED, IRQT_HIGH }, /* OKI ML9620 CAN controller can1 */ ++ /* EGPIO IRQ 14 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 15 */ ++ { DISABLED, IRQT_PROBE }, ++}; ++#endif ++ ++#ifdef CONFIG_SERIAL_8250 ++static struct plat_serial8250_port serial_platform_data[] = { ++ { ++ .mapbase = 0x70000008, ++ .irq = GPIO_IRQ8, ++ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ, ++ .iotype = UPIO_MEM, ++ .regshift = 0, ++ .uartclk = BASE_BAUD*16, ++ } , { ++ .mapbase = 0x70000010, ++ .irq = GPIO_IRQ9, ++ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ, ++ .iotype = UPIO_MEM, ++ .regshift = 0, ++ .uartclk = BASE_BAUD*16, ++ }, { }, ++}; ++ ++static struct platform_device serial_device = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = serial_platform_data, ++ }, ++}; ++#endif ++ ++static struct platform_device *devices[] __initdata = { ++ &cfi_flash_device, ++#ifdef CONFIG_SERIAL_8250 ++ &serial_device, ++#endif ++}; ++ ++static void __init dma03_init(void) ++{ ++ struct parport *port; ++ physmap_configure(0x60000000, 0x02000000, 4, NULL); ++ platform_add_devices(devices, ARRAY_SIZE(devices)); ++ ++#ifdef CONFIG_PARPORT_PC ++ port = parport_pc_probe_port(0xD0000020, 0, GPIO_IRQ10, 0, NULL); ++// How to register that beast without crashing? ++// if(port) ++// port = parport_register_port(0xD0000020, GPIO_IRQ10, 0, NULL); // note that passing NULL as fops arg is a bad idea(tm) ++// if(port) ++// parport_announce_port(port); ++#endif ++ ++#ifdef CONFIG_LEDS ++ leds_event = dma03_leds_event; ++#endif ++ leds_event(led_start); ++} ++ ++MACHINE_START(DMA03, "dma03") ++ /* Maintainer: Michael Burian */ ++ .phys_ram = SDRAM_START, ++ .phys_io = 0x80000000, ++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, ++ .boot_params = (SDRAM_START + 0x00000100), ++ ++ .map_io = dma03_map_io, ++ .init_irq = ep93xx_init_irq, ++ .init_machine = dma03_init, ++ .timer = &ep93xx_timer, ++MACHINE_END +diff --git a/arch/arm/mach-ep93xx/mach-edb9301.c b/arch/arm/mach-ep93xx/mach-edb9301.c +new file mode 100644 +index 0000000..68004e2 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/mach-edb9301.c +@@ -0,0 +1,219 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/edb9301.c ++ * ++ * Copyright (C) 2000 Deep Blue Solutions Ltd ++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * ++ * 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/config.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-types.h> ++#include <asm/memory.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++#include <asm/leds.h> ++#include <asm/system.h> ++ ++#include <asm/arch/platform.h> ++#include <asm/arch/regmap.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++#include <asm/mach/map.h> ++ ++extern void ep93xx_init_irq(void); ++ ++/* break this up into individual register blocks and map them in ++ the associated device drivers */ ++ ++static struct map_desc edb9301_io_desc[] __initdata = { ++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE }, ++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE }, ++}; ++ ++static void __init edb9301_map_io(void) ++{ ++ iotable_init(edb9301_io_desc, ARRAY_SIZE(edb9301_io_desc)); ++} ++ ++/* ++ * Flash handling. ++ */ ++ ++static int flash_init(void) ++{ ++ return 0; ++} ++ ++static void flash_exit(void) ++{ ++} ++ ++static void flash_set_vpp(int on) ++{ ++} ++ ++static struct flash_platform_data flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++ .init = flash_init, ++ .exit = flash_exit, ++ .set_vpp = flash_set_vpp, ++}; ++ ++static struct resource cfi_flash_resource = { ++ .start = 0x60000000, ++ .end = 0x60000000 + SZ_16M - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device cfi_flash_device = { ++ .name = "flash", ++ .dev = { ++ .platform_data = &flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &cfi_flash_resource, ++}; ++ ++#ifdef CONFIG_LEDS ++ ++#define LED_STATE_ENABLED 1 ++#define LED_STATE_CLAIMED 2 ++ ++static unsigned int led_state; ++static unsigned int hw_led_state; ++ ++#define LED_RED 2 ++#define LED_GREEN 1 ++#define LED_MASK (LED_GREEN | LED_RED) ++ ++void edb9301_leds_event(led_event_t evt) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ switch (evt) { ++ case led_start: ++ led_state = LED_STATE_ENABLED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_stop: ++ led_state &= ~LED_STATE_ENABLED; ++ hw_led_state = 0; ++ break; ++ ++ case led_claim: ++ led_state |= LED_STATE_CLAIMED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_release: ++ led_state &= ~LED_STATE_CLAIMED; ++ hw_led_state = 0; ++ break; ++ ++ case led_timer: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state ^= LED_GREEN; ++ break; ++ ++ case led_idle_start: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ case led_idle_end: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_halted: ++ break; ++ ++ case led_green_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_GREEN; ++ break; ++ ++ case led_green_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_GREEN; ++ break; ++ ++ case led_amber_on: ++ break; ++ ++ case led_amber_off: ++ break; ++ ++ case led_red_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_red_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ default: ++ break; ++ } ++ ++ writel(0x03, GPIO_PEDDR); ++ ++ if (led_state & LED_STATE_ENABLED) ++ writel(hw_led_state, GPIO_PEDR); ++ ++ local_irq_restore(flags); ++} ++ ++#endif ++ ++static void __init edb9301_init(void) ++{ ++ physmap_configure(0x60000000, 0x01000000, 2, NULL); ++ platform_device_register(&cfi_flash_device); ++#ifdef CONFIG_LEDS ++ leds_event = edb9301_leds_event; ++#endif ++ leds_event(led_start); ++} ++ ++MACHINE_START(EDB9301, "edb9301") ++ /* Maintainer: Michael Burian */ ++ .phys_ram = SDRAM_START, ++ .phys_io = 0x80000000, ++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, ++ .boot_params = (SDRAM_START + 0x00000100), ++ ++ .map_io = edb9301_map_io, ++ .init_irq = ep93xx_init_irq, ++ .init_machine = edb9301_init, ++ .timer = &ep93xx_timer, ++MACHINE_END +diff --git a/arch/arm/mach-ep93xx/mach-edb9302.c b/arch/arm/mach-ep93xx/mach-edb9302.c +new file mode 100644 +index 0000000..ac74a1e +--- /dev/null ++++ b/arch/arm/mach-ep93xx/mach-edb9302.c +@@ -0,0 +1,362 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/edb9302.c ++ * ++ * Copyright (C) 2000 Deep Blue Solutions Ltd ++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * ++ * 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/config.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-types.h> ++#include <asm/memory.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++#include <asm/leds.h> ++#include <asm/system.h> ++ ++#include <asm/arch/platform.h> ++#include <asm/arch/regmap.h> ++#include <asm/arch/mach-edb9302.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++#include <asm/mach/map.h> ++ ++extern void ep93xx_init_irq(void); ++ ++/* break this up into individual register blocks and map them in ++ the associated device drivers */ ++ ++static struct map_desc edb9302_io_desc[] __initdata = { ++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE }, ++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE }, ++}; ++ ++static void __init edb9302_map_io(void) ++{ ++ iotable_init(edb9302_io_desc, ARRAY_SIZE(edb9302_io_desc)); ++} ++ ++/* ++ * Flash handling. ++ */ ++ ++static int flash_init(void) ++{ ++ return 0; ++} ++ ++static void flash_exit(void) ++{ ++} ++ ++static void flash_set_vpp(int on) ++{ ++} ++ ++static struct flash_platform_data flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++ .init = flash_init, ++ .exit = flash_exit, ++ .set_vpp = flash_set_vpp, ++}; ++ ++static struct resource cfi_flash_resource = { ++ .start = 0x60000000, ++ .end = 0x60000000 + SZ_16M - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device cfi_flash_device = { ++ .name = "flash", ++ .dev = { ++ .platform_data = &flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &cfi_flash_resource, ++}; ++ ++/* SSP hackery */ ++ ++static void ssp_cs_flash(struct ssp_slave *s, int enable) ++{ ++ unsigned long x = readl(GPIO_PADR); ++ if (enable) ++ x &= ~0x80; ++ else ++ x |= 0x80; ++ writel(x, GPIO_PADR); ++} ++ ++struct ep93xx_ssp_slave ep93xx_ssp_flash = { ++ { ++ LIST_HEAD_INIT(ep93xx_ssp_flash.slave.list), ++ NULL, ++ 0, ++ 0, ++ 8, ++ 1, ++ ssp_cs_flash}, ++ ((0 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_MOTOROLA << SSPCR0_FRF_SHIFT) | ++ SSPCR0_SPO | SSPCR0_SPH | (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)), ++ (SSPC1_SSE | SSPC1_RORIE), ++ 2 ++}; ++ ++EXPORT_SYMBOL(ep93xx_ssp_flash); ++ ++static void ssp_cs_codec(struct ssp_slave *s, int enable) ++{ ++ unsigned long x = readl(GPIO_PADR); ++ if (enable) ++ x &= ~0x40; ++ else ++ x |= 0x40; ++ writel(x, GPIO_PADR); ++} ++ ++struct ep93xx_ssp_slave ep93xx_ssp_codec = { ++ { ++ LIST_HEAD_INIT(ep93xx_ssp_codec.slave.list), ++ NULL, ++ 0, ++ 0, ++ 8, ++ 1, ++ ssp_cs_codec}, ++ ((31 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_TI << SSPCR0_FRF_SHIFT) | ++ (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)), ++ (SSPC1_SSE | SSPC1_RORIE), ++ 48 ++}; ++ ++EXPORT_SYMBOL(ep93xx_ssp_codec); ++ ++#ifdef CONFIG_LEDS ++ ++#define LED_STATE_ENABLED 1 ++#define LED_STATE_CLAIMED 2 ++ ++static unsigned int led_state; ++static unsigned int hw_led_state; ++ ++#define LED_RED 2 ++#define LED_GREEN 1 ++#define LED_MASK (LED_GREEN | LED_RED) ++ ++void edb9302_leds_event(led_event_t evt) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ switch (evt) { ++ case led_start: ++ led_state = LED_STATE_ENABLED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_stop: ++ led_state &= ~LED_STATE_ENABLED; ++ hw_led_state = 0; ++ break; ++ ++ case led_claim: ++ led_state |= LED_STATE_CLAIMED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_release: ++ led_state &= ~LED_STATE_CLAIMED; ++ hw_led_state = 0; ++ break; ++ ++ case led_timer: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state ^= LED_GREEN; ++ break; ++ ++ case led_idle_start: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ case led_idle_end: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_halted: ++ break; ++ ++ case led_green_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_GREEN; ++ break; ++ ++ case led_green_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_GREEN; ++ break; ++ ++ case led_amber_on: ++ break; ++ ++ case led_amber_off: ++ break; ++ ++ case led_red_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_red_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ default: ++ break; ++ } ++ ++ writel(0x03, GPIO_PEDDR); ++ ++ if (led_state & LED_STATE_ENABLED) ++ writel(hw_led_state, GPIO_PEDR); ++ ++ local_irq_restore(flags); ++} ++ ++#endif ++ ++static void __init edb9302_init_gpio(void) ++{ ++ /* port A */ ++ /* EGPIO0-7 */ ++ writel(0xc2, GPIO_PADDR); ++ writel(0xc0, GPIO_PADR); ++ ++ /* port B */ ++ /* EGPIO8-15 */ ++ writel(0x00, GPIO_PBDDR); ++ writel(0x00, GPIO_PBDR); ++ ++ /* port C */ ++ /* GPIO0 */ ++ writel(0x00, GPIO_PCDDR); ++ writel(0x00, GPIO_PCDR); ++ ++ /* port E */ ++ /* RDLED, GRLED */ ++ writel(0x03, GPIO_PEDDR); ++ writel(0x03, GPIO_PEDR); ++ ++ /* port F */ ++ /* GPIO5, GPIO6, GPIO7 */ ++ writel(0x00, GPIO_PFDDR); ++ writel(0x00, GPIO_PFDR); ++ ++ /* port G */ ++ /* EECLK, EEDAT */ ++ writel(0x00, GPIO_PGDDR); ++ writel(0x00, GPIO_PGDR); ++ ++ /* port H */ ++ /* GPIO1, GPIO2, GPIO3, GPIO4 */ ++ writel(0x00, GPIO_PHDDR); ++ writel(0x00, GPIO_PHDR); ++} ++ ++/* looks like this might be more generic than just edb9302... */ ++int ssp_do_asymmetric(struct ep93xx_ssp_slave *ss, void *tx, int tlen, void *rx, ++ int rlen) ++{ ++ struct ssp_slave *s = (struct ssp_slave *)ss; ++ int err; ++ ++ if ((err = ssp_start(s)) < 0) ++ goto out1; ++ ++ ssp_select(s); ++ ++ if ((err = ssp_post(s, tlen, tx, NULL)) < 0) ++ goto out2; ++ ++ ssp_wait(s); ++ ++ if ((err = ssp_post(s, rlen, NULL, rx)) < 0) ++ goto out2; ++ ++ ssp_wait(s); ++ ++ out2: ++ ssp_deselect(s); ++ ssp_finish(s); ++ out1: ++ return err; ++} ++ ++/* start poking at the Atmel AT25F1024 flash chip */ ++void poke_flash(void) ++{ ++ unsigned char rdsr[1] = { 0x05 }; ++ unsigned char rdid[1] = { 0x15 }; ++ unsigned char rsp[10]; ++ ++ ssp_do_asymmetric(&ep93xx_ssp_flash, rdsr, 1, rsp, 1); ++ printk(KERN_WARNING "RDSR returns %02x\n", rsp[0]); ++ ++ ssp_do_asymmetric(&ep93xx_ssp_flash, rdid, 1, rsp, 2); ++ printk(KERN_WARNING "RDID returns %02x:%02x\n", rsp[0], rsp[1]); ++} ++ ++static void __init edb9302_init(void) ++{ ++ physmap_configure(0x60000000, 0x01000000, 2, NULL); ++ platform_device_register(&cfi_flash_device); ++ edb9302_init_gpio(); ++#ifdef CONFIG_LEDS ++ leds_event = edb9302_leds_event; ++#endif ++ leds_event(led_start); ++ if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_flash.slave) < 0) ++ printk(KERN_ERR "EDB9302: unable to add flash slave\n"); ++ if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_codec.slave) < 0) ++ printk(KERN_ERR "EDB9302: unable to add codec slave\n"); ++} ++ ++MACHINE_START(EDB9302, "edb9302") ++ /* Maintainer: Michael Burian */ ++ .phys_ram = SDRAM_START, ++ .phys_io = 0x80000000, ++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, ++ .boot_params = (SDRAM_START + 0x00000100), ++ ++ .map_io = edb9302_map_io, ++ .init_irq = ep93xx_init_irq, ++ .init_machine = edb9302_init, ++ .timer = &ep93xx_timer, ++MACHINE_END +diff --git a/arch/arm/mach-ep93xx/mach-edb9312.c b/arch/arm/mach-ep93xx/mach-edb9312.c +new file mode 100644 +index 0000000..e67b673 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/mach-edb9312.c +@@ -0,0 +1,219 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/edb9312.c ++ * ++ * Copyright (C) 2000 Deep Blue Solutions Ltd ++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * ++ * 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/config.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-types.h> ++#include <asm/memory.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++#include <asm/leds.h> ++#include <asm/system.h> ++ ++#include <asm/arch/platform.h> ++#include <asm/arch/regmap.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++#include <asm/mach/map.h> ++ ++extern void ep93xx_init_irq(void); ++ ++/* break this up into individual register blocks and map them in ++ the associated device drivers */ ++ ++static struct map_desc edb9312_io_desc[] __initdata = { ++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE }, ++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE }, ++}; ++ ++static void __init edb9312_map_io(void) ++{ ++ iotable_init(edb9312_io_desc, ARRAY_SIZE(edb9312_io_desc)); ++} ++ ++/* ++ * Flash handling. ++ */ ++ ++static int flash_init(void) ++{ ++ return 0; ++} ++ ++static void flash_exit(void) ++{ ++} ++ ++static void flash_set_vpp(int on) ++{ ++} ++ ++static struct flash_platform_data flash_data = { ++ .map_name = "cfi_probe", ++ .width = 4, ++ .init = flash_init, ++ .exit = flash_exit, ++ .set_vpp = flash_set_vpp, ++}; ++ ++static struct resource cfi_flash_resource = { ++ .start = 0x60000000, ++ .end = 0x60000000 + SZ_32M - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device cfi_flash_device = { ++ .name = "flash", ++ .dev = { ++ .platform_data = &flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &cfi_flash_resource, ++}; ++ ++#ifdef CONFIG_LEDS ++ ++#define LED_STATE_ENABLED 1 ++#define LED_STATE_CLAIMED 2 ++ ++static unsigned int led_state; ++static unsigned int hw_led_state; ++ ++#define LED_RED 2 ++#define LED_GREEN 1 ++#define LED_MASK (LED_GREEN | LED_RED) ++ ++void edb9312_leds_event(led_event_t evt) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ switch (evt) { ++ case led_start: ++ led_state = LED_STATE_ENABLED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_stop: ++ led_state &= ~LED_STATE_ENABLED; ++ hw_led_state = 0; ++ break; ++ ++ case led_claim: ++ led_state |= LED_STATE_CLAIMED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_release: ++ led_state &= ~LED_STATE_CLAIMED; ++ hw_led_state = 0; ++ break; ++ ++ case led_timer: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state ^= LED_GREEN; ++ break; ++ ++ case led_idle_start: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ case led_idle_end: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_halted: ++ break; ++ ++ case led_green_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_GREEN; ++ break; ++ ++ case led_green_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_GREEN; ++ break; ++ ++ case led_amber_on: ++ break; ++ ++ case led_amber_off: ++ break; ++ ++ case led_red_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_red_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ default: ++ break; ++ } ++ ++ writel(0x03, GPIO_PEDDR); ++ ++ if (led_state & LED_STATE_ENABLED) ++ writel(hw_led_state, GPIO_PEDR); ++ ++ local_irq_restore(flags); ++} ++ ++#endif ++ ++static void __init edb9312_init(void) ++{ ++ physmap_configure(0x60000000, 0x02000000, 4, NULL); ++ platform_device_register(&cfi_flash_device); ++#ifdef CONFIG_LEDS ++ leds_event = edb9312_leds_event; ++#endif ++ leds_event(led_start); ++} ++ ++MACHINE_START(EDB9312, "edb9312") ++ /* Maintainer: Michael Burian */ ++ .phys_ram = SDRAM_START, ++ .phys_io = 0x80000000, ++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, ++ .boot_params = (SDRAM_START + 0x00000100), ++ ++ .map_io = edb9312_map_io, ++ .init_irq = ep93xx_init_irq, ++ .init_machine = edb9312_init, ++ .timer = &ep93xx_timer, ++MACHINE_END +diff --git a/arch/arm/mach-ep93xx/mach-edb9315.c b/arch/arm/mach-ep93xx/mach-edb9315.c +new file mode 100644 +index 0000000..14c680a +--- /dev/null ++++ b/arch/arm/mach-ep93xx/mach-edb9315.c +@@ -0,0 +1,219 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/edb9315.c ++ * ++ * Copyright (C) 2000 Deep Blue Solutions Ltd ++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * ++ * 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/config.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-types.h> ++#include <asm/memory.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++#include <asm/leds.h> ++#include <asm/system.h> ++ ++#include <asm/arch/platform.h> ++#include <asm/arch/regmap.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++#include <asm/mach/map.h> ++ ++extern void ep93xx_init_irq(void); ++ ++/* break this up into individual register blocks and map them in ++ the associated device drivers */ ++ ++static struct map_desc edb9315_io_desc[] __initdata = { ++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE }, ++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE }, ++}; ++ ++static void __init edb9315_map_io(void) ++{ ++ iotable_init(edb9315_io_desc, ARRAY_SIZE(edb9315_io_desc)); ++} ++ ++/* ++ * Flash handling. ++ */ ++ ++static int flash_init(void) ++{ ++ return 0; ++} ++ ++static void flash_exit(void) ++{ ++} ++ ++static void flash_set_vpp(int on) ++{ ++} ++ ++static struct flash_platform_data flash_data = { ++ .map_name = "cfi_probe", ++ .width = 4, ++ .init = flash_init, ++ .exit = flash_exit, ++ .set_vpp = flash_set_vpp, ++}; ++ ++static struct resource cfi_flash_resource = { ++ .start = 0x60000000, ++ .end = 0x60000000 + SZ_32M - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device cfi_flash_device = { ++ .name = "flash", ++ .dev = { ++ .platform_data = &flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &cfi_flash_resource, ++}; ++ ++#ifdef CONFIG_LEDS ++ ++#define LED_STATE_ENABLED 1 ++#define LED_STATE_CLAIMED 2 ++ ++static unsigned int led_state; ++static unsigned int hw_led_state; ++ ++#define LED_RED 2 ++#define LED_GREEN 1 ++#define LED_MASK (LED_GREEN | LED_RED) ++ ++void edb9315_leds_event(led_event_t evt) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ switch (evt) { ++ case led_start: ++ led_state = LED_STATE_ENABLED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_stop: ++ led_state &= ~LED_STATE_ENABLED; ++ hw_led_state = 0; ++ break; ++ ++ case led_claim: ++ led_state |= LED_STATE_CLAIMED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_release: ++ led_state &= ~LED_STATE_CLAIMED; ++ hw_led_state = 0; ++ break; ++ ++ case led_timer: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state ^= LED_GREEN; ++ break; ++ ++ case led_idle_start: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ case led_idle_end: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_halted: ++ break; ++ ++ case led_green_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_GREEN; ++ break; ++ ++ case led_green_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_GREEN; ++ break; ++ ++ case led_amber_on: ++ break; ++ ++ case led_amber_off: ++ break; ++ ++ case led_red_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_red_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ default: ++ break; ++ } ++ ++ writel(0x03, GPIO_PEDDR); ++ ++ if (led_state & LED_STATE_ENABLED) ++ writel(hw_led_state, GPIO_PEDR); ++ ++ local_irq_restore(flags); ++} ++ ++#endif ++ ++static void __init edb9315_init(void) ++{ ++ physmap_configure(0x60000000, 0x02000000, 4, NULL); ++ platform_device_register(&cfi_flash_device); ++#ifdef CONFIG_LEDS ++ leds_event = edb9315_leds_event; ++#endif ++ leds_event(led_start); ++} ++ ++MACHINE_START(EDB9315, "edb9315") ++ /* Maintainer: Michael Burian */ ++ .phys_ram = SDRAM_START, ++ .phys_io = 0x80000000, ++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, ++ .boot_params = (SDRAM_START + 0x00000100), ++ ++ .map_io = edb9315_map_io, ++ .init_irq = ep93xx_init_irq, ++ .init_machine = edb9315_init, ++ .timer = &ep93xx_timer, ++MACHINE_END +diff --git a/arch/arm/mach-ep93xx/mach-ttml.c b/arch/arm/mach-ep93xx/mach-ttml.c +new file mode 100644 +index 0000000..872dd01 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/mach-ttml.c +@@ -0,0 +1,369 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/mach-ttml.c ++ * ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * ++ * 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/config.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-types.h> ++#include <asm/memory.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++#include <asm/leds.h> ++#include <asm/system.h> ++ ++#include <asm/arch/platform.h> ++#include <asm/arch/regmap.h> ++#include <asm/arch/mach-ttml.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++#include <asm/mach/map.h> ++ ++extern void ep93xx_init_irq(void); ++ ++/* break this up into individual register blocks and map them in ++ the associated device drivers */ ++ ++static struct map_desc ttml_io_desc[] __initdata = { ++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE }, ++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE }, ++}; ++ ++static void __init ttml_map_io(void) ++{ ++ iotable_init(ttml_io_desc, ARRAY_SIZE(ttml_io_desc)); ++} ++ ++/* ++ * Flash handling. ++ */ ++ ++static int flash_init(void) ++{ ++ return 0; ++} ++ ++static void flash_exit(void) ++{ ++} ++ ++static void flash_set_vpp(int on) ++{ ++} ++ ++static struct flash_platform_data flash_data = { ++ .map_name = "cfi_probe", ++ .width = 2, ++ .init = flash_init, ++ .exit = flash_exit, ++ .set_vpp = flash_set_vpp, ++}; ++ ++static struct resource cfi_flash_resource = { ++ .start = 0x60000000, ++ .end = 0x60000000 + SZ_16M - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device cfi_flash_device = { ++ .name = "flash", ++ .dev = { ++ .platform_data = &flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &cfi_flash_resource, ++}; ++ ++/* SSP hackery */ ++ ++static void ssp_cs_timicro(struct ssp_slave *s, int enable) ++{ ++ unsigned long x = readl(GPIO_PBDR); ++ if (enable) ++ x &= ~0x10; ++ else ++ x |= 0x10; ++ writel(x, GPIO_PBDR); ++} ++ ++struct ep93xx_ssp_slave ep93xx_ssp_micro = { ++ { ++ LIST_HEAD_INIT(ep93xx_ssp_micro.slave.list), ++ NULL, ++ 0, ++ 0, ++ 8, ++ 1, ++ ssp_cs_timicro}, ++ ((31 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_TI << SSPCR0_FRF_SHIFT) | ++ (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)), ++ (SSPC1_SSE | SSPC1_RORIE), ++ 48 ++}; ++ ++EXPORT_SYMBOL(ep93xx_ssp_micro); ++ ++static void ssp_cs_expansion(struct ssp_slave *s, int enable) ++{ ++ unsigned long x = readl(GPIO_PBDR); ++ if (enable) ++ x &= ~0x20; ++ else ++ x |= 0x20; ++ writel(x, GPIO_PBDR); ++} ++ ++struct ep93xx_ssp_slave ep93xx_ssp_expansion = { ++ { ++ LIST_HEAD_INIT(ep93xx_ssp_expansion.slave.list), ++ NULL, ++ 0, ++ 0, ++ 8, ++ 1, ++ ssp_cs_expansion}, ++ 0, ++ 0, ++ 0 ++}; ++ ++EXPORT_SYMBOL(ep93xx_ssp_expansion); ++ ++/** ++ * ssp_do_ttml - perform a single SSP transaction to the TTML micro ++ * @s: the slave ++ * @len: the number of words to transfer ++ * @tx: a buffer of @len words to clock out to slave ++ * @rx: a buffer of @len words to clock in from slave ++ * ++ * Use the SSP transaction interface to drive the TTML micro. The ++ * first byte back from the micro is the length of the reply, excluding ++ * the len and the csum bytes. @rlen and @rx had better be bigger ++ * than any reply the micro might generate. ++ */ ++int ssp_do_ttml(struct ep93xx_ssp_slave *ss, void *tx, int tlen, void *rx, ++ int rlen) ++{ ++ struct ssp_slave *s = (struct ssp_slave *)ss; ++ int len; ++ int err; ++ ++ if ((err = ssp_start(s)) < 0) ++ goto out1; ++ ++ ssp_select(s); ++ ++ if ((err = ssp_post(s, tlen, tx, NULL)) < 0) ++ goto out2; ++ ++ ssp_wait(s); ++ ++ if ((err = ssp_post(s, 1, NULL, rx)) < 0) ++ goto out2; ++ ++ ssp_wait(s); ++ ++ { ++ char *b = rx; ++ len = ((b[0] >> 4) & 0x07) + 2; ++ } ++ ++ if (len > rlen) { ++ printk(KERN_WARNING "SSP: rx buffer truncated\n"); ++ len = rlen; ++ } ++ ++ if ((err = ssp_post(s, len - 1, NULL, rx + 1)) < 0) ++ goto out2; ++ ++ err = ssp_wait(s); ++ ++ out2: ++ ssp_deselect(s); ++ out1: ++ ssp_finish(s); ++ return err; ++} ++ ++EXPORT_SYMBOL(ssp_do_ttml); ++ ++#ifdef CONFIG_LEDS ++ ++#define LED_STATE_ENABLED 1 ++#define LED_STATE_CLAIMED 2 ++ ++static unsigned int led_state; ++static unsigned int hw_led_state; ++ ++#define LED_RED 2 ++#define LED_GREEN 1 ++#define LED_MASK (LED_GREEN | LED_RED) ++ ++void ttml_leds_event(led_event_t evt) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ switch (evt) { ++ case led_start: ++ led_state = LED_STATE_ENABLED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_stop: ++ led_state &= ~LED_STATE_ENABLED; ++ hw_led_state = 0; ++ break; ++ ++ case led_claim: ++ led_state |= LED_STATE_CLAIMED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_release: ++ led_state &= ~LED_STATE_CLAIMED; ++ hw_led_state = 0; ++ break; ++ ++ case led_timer: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state ^= LED_GREEN; ++ break; ++ ++ case led_idle_start: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ case led_idle_end: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_halted: ++ break; ++ ++ case led_green_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_GREEN; ++ break; ++ ++ case led_green_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_GREEN; ++ break; ++ ++ case led_amber_on: ++ break; ++ ++ case led_amber_off: ++ break; ++ ++ case led_red_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_red_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ default: ++ break; ++ } ++ ++ writel(0x03, GPIO_PEDDR); ++ ++ if (led_state & LED_STATE_ENABLED) ++ writel(hw_led_state, GPIO_PEDR); ++ ++ local_irq_restore(flags); ++} ++ ++#endif ++ ++static void __init ttml_init_gpio(void) ++{ ++ /* port A */ ++ writel(0x00, GPIO_PADDR); ++ ++ /* port B */ ++ writel(0xf1, GPIO_PBDDR); ++ writel(0xf1, GPIO_PBDR); ++ ++ /* port C */ ++ writel(0x01, GPIO_PCDDR); ++ writel(0x01, GPIO_PCDR); ++ ++ /* port E */ ++ writel(0x03, GPIO_PEDDR); ++ writel(0x03, GPIO_PEDR); ++ ++ /* port F */ ++ writel(0x00, GPIO_PFDDR); ++ writel(0x00, GPIO_PFDR); ++ ++ /* port G */ ++ writel(0x00, GPIO_PGDDR); ++ writel(0x00, GPIO_PGDR); ++ ++ /* port H */ ++ writel(0x04, GPIO_PHDDR); ++ writel(0x00, GPIO_PHDR); ++} ++ ++static void __init ttml_init(void) ++{ ++ physmap_configure(0x60000000, 0x01000000, 2, NULL); ++ platform_device_register(&cfi_flash_device); ++ ttml_init_gpio(); ++#ifdef CONFIG_LEDS ++ leds_event = ttml_leds_event; ++#endif ++ leds_event(led_start); ++ ++ if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_micro.slave) < 0) ++ printk(KERN_ERR "EP93XX: unable to add micro slave\n"); ++ ++ if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_expansion.slave) < 0) ++ printk(KERN_ERR "EP93XX: unable to add expansion slave\n"); ++ ++} ++ ++MACHINE_START(EDB9301, "ttml") ++ /* Maintainer: Michael Burian */ ++ .phys_ram = SDRAM_START, ++ .phys_io = 0x80000000, ++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, ++ .boot_params = (SDRAM_START + 0x00000100), ++ ++ .map_io = ttml_map_io, ++ .init_irq = ep93xx_init_irq, ++ .init_machine = ttml_init, ++ .timer = &ep93xx_timer, ++MACHINE_END +diff --git a/arch/arm/mach-ep93xx/mach-zefeerdzb.c b/arch/arm/mach-ep93xx/mach-zefeerdzb.c +new file mode 100644 +index 0000000..c224ca1 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/mach-zefeerdzb.c +@@ -0,0 +1,237 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/zefeerdzb.c ++ * ++ * Copyright (C) 2004, 2005 DAVE Srl <www.dave-tech.it> ++ * ++ * 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/config.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-types.h> ++#include <asm/memory.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++#include <asm/leds.h> ++#include <asm/system.h> ++ ++#include <asm/arch/platform.h> ++#include <asm/arch/regmap.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++#include <asm/mach/map.h> ++ ++extern void ep93xx_init_irq(void); ++ ++/* break this up into individual register blocks and map them in ++ the associated device drivers */ ++ ++static struct map_desc zefeerdzb_io_desc[] __initdata = { ++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE }, ++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE }, ++}; ++ ++static void __init zefeerdzb_map_io(void) ++{ ++ iotable_init(zefeerdzb_io_desc, ARRAY_SIZE(zefeerdzb_io_desc)); ++} ++ ++#ifdef CONFIG_LEDS ++ ++#define LED_STATE_ENABLED 1 ++#define LED_STATE_CLAIMED 2 ++ ++static unsigned int led_state; ++static unsigned int hw_led_state; ++ ++#define LED_RED 2 ++#define LED_GREEN 1 ++#define LED_MASK (LED_GREEN | LED_RED) ++ ++void zefeerdzb_leds_event(led_event_t evt) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ switch (evt) { ++ case led_start: ++ led_state = LED_STATE_ENABLED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_stop: ++ led_state &= ~LED_STATE_ENABLED; ++ hw_led_state = 0; ++ break; ++ ++ case led_claim: ++ led_state |= LED_STATE_CLAIMED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_release: ++ led_state &= ~LED_STATE_CLAIMED; ++ hw_led_state = 0; ++ break; ++ ++ case led_timer: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state ^= LED_GREEN; ++ break; ++ ++ case led_idle_start: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ case led_idle_end: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_halted: ++ break; ++ ++ case led_green_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_GREEN; ++ break; ++ ++ case led_green_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_GREEN; ++ break; ++ ++ case led_amber_on: ++ break; ++ ++ case led_amber_off: ++ break; ++ ++ case led_red_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_red_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ default: ++ break; ++ } ++ ++ writel(0x03, GPIO_PEDDR); ++ ++ if (led_state & LED_STATE_ENABLED) ++ writel(hw_led_state, GPIO_PEDR); ++ ++ local_irq_restore(flags); ++} ++ ++#endif ++ ++static void __init zefeerdzb_init(void) ++{ ++ /* ++ physmap_configure(0x60000000, 0x01000000, 2, NULL); ++ platform_device_register(&cfi_flash_device); ++ */ ++ ++#ifdef CONFIG_LEDS ++ leds_event = zefeerdzb_leds_event; ++#endif ++ leds_event(led_start); ++} ++ ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++#include "ep93xx_gpio_irq.h" ++#endif ++ ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++/* GPIO irq description ++ * IRQs are set up in arch/arm/mach-ep93xx/irq.c ++ * flags can be IRQT_RISING ++ * IRQT_FALLING ++ * IRQT_LOW ++ * IRQT_HIGH ++ * IRQT_PROBE ++ * ++ * On IRQT_PROBE nothing is done in setup irq code ++ */ ++ ++/* For IRQ Demux */ ++ ++#define DISABLED 0 ++#define ENABLED 1 ++struct ep93xx_egpio_irq egpio_irqs[] __initdata = ++{ ++ /* EGPIO IRQ 0 */ ++ { DISABLED , IRQT_PROBE }, ++ /* EGPIO IRQ 1 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 2 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 3 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 4 */ ++ { ENABLED, IRQT_LOW }, /* CAN 0 GPIO IRQ */ ++ /* EGPIO IRQ 5 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 6 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 7 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 8 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 9 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 10 */ ++ { ENABLED, IRQT_LOW }, /* CAN 1 GPIO IRQ */ ++ /* EGPIO IRQ 11 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 12 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 13 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 14 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 15 */ ++ { DISABLED, IRQT_PROBE }, ++}; ++#endif ++ ++MACHINE_START(ZEFEERDZB, "Zefeer DZB") ++ /* Maintainer: DAVE Srl <www.dave-tech.it> */ ++ .phys_ram = SDRAM_START, ++ .phys_io = 0x80000000, ++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, ++ .boot_params = (SDRAM_START + 0x00000100), ++ ++ .map_io = zefeerdzb_map_io, ++ .init_irq = ep93xx_init_irq, ++ .init_machine = zefeerdzb_init, ++ .timer = &ep93xx_timer, ++MACHINE_END +diff --git a/arch/arm/mach-ep93xx/mach-zefeerdzq.c b/arch/arm/mach-ep93xx/mach-zefeerdzq.c +new file mode 100644 +index 0000000..4cae7a7 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/mach-zefeerdzq.c +@@ -0,0 +1,279 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/zefeerdzq.c ++ * ++ * Copyright (C) 2004, 2005 DAVE Srl <www.dave-tech.it> ++ * ++ * 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/config.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/device.h> ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-types.h> ++#include <asm/memory.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/sizes.h> ++#include <asm/leds.h> ++#include <asm/system.h> ++ ++#include <asm/arch/platform.h> ++#include <asm/arch/regmap.h> ++ ++#include <asm/mach/arch.h> ++#include <asm/mach/flash.h> ++#include <asm/mach/map.h> ++ ++extern void ep93xx_init_irq(void); ++ ++/* break this up into individual register blocks and map them in ++ the associated device drivers */ ++ ++static struct map_desc zefeerdzq_io_desc[] __initdata = { ++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE }, ++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE }, ++}; ++ ++static void __init zefeerdzq_map_io(void) ++{ ++ iotable_init(zefeerdzq_io_desc, ARRAY_SIZE(zefeerdzq_io_desc)); ++} ++ ++/* ++ * Flash handling. ++ */ ++ ++/* ++static int flash_init(void) ++{ ++ return 0; ++} ++ ++static void flash_exit(void) ++{ ++} ++ ++static void flash_set_vpp(int on) ++{ ++} ++ ++static struct flash_platform_data flash_data = { ++ .map_name = "cfi_probe", ++ .width = 4, ++ .init = flash_init, ++ .exit = flash_exit, ++ .set_vpp = flash_set_vpp, ++}; ++ ++static struct resource cfi_flash_resource = { ++ .start = 0x60000000, ++ .end = 0x60000000 + SZ_32M - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device cfi_flash_device = { ++ .name = "ZefeerDZQ Boot Flash", ++ .dev = { ++ .platform_data = &flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &cfi_flash_resource, ++}; ++*/ ++ ++#ifdef CONFIG_LEDS ++ ++#define LED_STATE_ENABLED 1 ++#define LED_STATE_CLAIMED 2 ++ ++static unsigned int led_state; ++static unsigned int hw_led_state; ++ ++#define LED_RED 2 ++#define LED_GREEN 1 ++#define LED_MASK (LED_GREEN | LED_RED) ++ ++void zefeerdzq_leds_event(led_event_t evt) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ++ switch (evt) { ++ case led_start: ++ led_state = LED_STATE_ENABLED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_stop: ++ led_state &= ~LED_STATE_ENABLED; ++ hw_led_state = 0; ++ break; ++ ++ case led_claim: ++ led_state |= LED_STATE_CLAIMED; ++ hw_led_state = LED_RED | LED_GREEN; ++ break; ++ ++ case led_release: ++ led_state &= ~LED_STATE_CLAIMED; ++ hw_led_state = 0; ++ break; ++ ++ case led_timer: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state ^= LED_GREEN; ++ break; ++ ++ case led_idle_start: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ case led_idle_end: ++ if (!(led_state & LED_STATE_CLAIMED)) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_halted: ++ break; ++ ++ case led_green_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_GREEN; ++ break; ++ ++ case led_green_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_GREEN; ++ break; ++ ++ case led_amber_on: ++ break; ++ ++ case led_amber_off: ++ break; ++ ++ case led_red_on: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state |= LED_RED; ++ break; ++ ++ case led_red_off: ++ if (led_state & LED_STATE_CLAIMED) ++ hw_led_state &= ~LED_RED; ++ break; ++ ++ default: ++ break; ++ } ++ ++ writel(0x03, GPIO_PEDDR); ++ ++ if (led_state & LED_STATE_ENABLED) ++ writel(hw_led_state, GPIO_PEDR); ++ ++ local_irq_restore(flags); ++} ++ ++#endif ++ ++static void __init zefeerdzq_init(void) ++{ ++ /* ++ physmap_configure(0x60000000, 0x01000000, 2, NULL); ++ platform_device_register(&cfi_flash_device); ++ */ ++ ++#ifdef CONFIG_LEDS ++ leds_event = zefeerdzq_leds_event; ++#endif ++ leds_event(led_start); ++} ++ ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++#include "ep93xx_gpio_irq.h" ++#endif ++ ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++/* GPIO irq description ++ * IRQs are set up in arch/arm/mach-ep93xx/irq.c ++ * flags can be IRQT_RISING ++ * IRQT_FALLING ++ * IRQT_LOW ++ * IRQT_HIGH ++ * IRQT_PROBE ++ * ++ * On IRQT_PROBE nothing is done in setup irq code ++ */ ++ ++/* For IRQ Demux */ ++ ++#define DISABLED 0 ++#define ENABLED 1 ++struct ep93xx_egpio_irq egpio_irqs[] __initdata = ++{ ++ /* EGPIO IRQ 0 */ ++ { DISABLED , IRQT_PROBE }, ++ /* EGPIO IRQ 1 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 2 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 3 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 4 */ ++ { ENABLED, IRQT_LOW }, /* CAN 0 GPIO IRQ */ ++ /* EGPIO IRQ 5 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 6 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 7 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 8 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 9 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 10 */ ++ { ENABLED, IRQT_LOW }, /* CAN 1 GPIO IRQ */ ++ /* EGPIO IRQ 11 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 12 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 13 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 14 */ ++ { DISABLED, IRQT_PROBE }, ++ /* EGPIO IRQ 15 */ ++ { DISABLED, IRQT_PROBE }, ++}; ++#endif ++ ++MACHINE_START(ZEFEERDZQ, "Zefeer DZQ") ++ /* Maintainer: DAVE Srl <www.dave-tech.it> */ ++ .phys_ram = SDRAM_START, ++ .phys_io = 0x80000000, ++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc, ++ .boot_params = (SDRAM_START + 0x00000100), ++ ++ .map_io = zefeerdzq_map_io, ++ .init_irq = ep93xx_init_irq, ++ .init_machine = zefeerdzq_init, ++ .timer = &ep93xx_timer, ++MACHINE_END +diff --git a/arch/arm/mach-ep93xx/ssp-cirrus.c b/arch/arm/mach-ep93xx/ssp-cirrus.c +new file mode 100644 +index 0000000..853c6c4 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/ssp-cirrus.c +@@ -0,0 +1,646 @@ ++/* ++ * FILE: ssp.c ++ * ++ * DESCRIPTION: SSP Interface Driver Module implementation ++ * ++ * Copyright Cirrus Logic Corporation, 2001-2003. All rights reserved ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License 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 ++ */ ++ ++/* ++ * This driver provides a way to read and write devices on the SSP ++ * interface. ++ * ++ * For Tx devices, EGPIO7 is used as an address pin: ++ * I2S Codec CS4228 = EGPIO7 == 1 ++ * Serial Flash AT25F1024 = EGPIO7 == 0 ++ */ ++#include <linux/delay.h> ++#include <linux/interrupt.h> ++ ++#include <asm/irq.h> ++#include <asm/semaphore.h> ++#include <asm/uaccess.h> ++#include <asm/io.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/ssp-cirrus.h> ++ ++#undef DEBUG ++/* #define DEBUG 1 */ ++#ifdef DEBUG ++#define DPRINTK( x... ) printk( ##x ) ++#else ++#define DPRINTK( x... ) ++#endif ++ ++#define EP93XX_KEY_TIMER_PERIOD_MSEC 20 ++ ++static int SSP_Open(enum SSPDeviceType Device, SSPDataCallback Callback); ++static int SSP_Close(int Handle); ++static int SSP_Read(int Handle, unsigned int Addr, unsigned int *pValue); ++static int SSP_Write(int Handle, unsigned int Addr, unsigned int Value); ++static int CheckHandle(int Handle); ++ ++static void SetSSPtoPS2(void); ++static void SetSSPtoI2S(void); ++static int ReadIntoBuffer(void); ++ ++static int SSP_Write_I2SCodec(int Handle, unsigned int RegAddr, ++ unsigned int RegValue); ++ ++/* ++ * Key buffer... ++ */ ++#define KEYBUF_SIZE 256 ++static unsigned int uiKeyBuffer[KEYBUF_SIZE]; ++ ++static spinlock_t ssp_spinlock = SPIN_LOCK_UNLOCKED; ++ ++enum SSPmodes { ++ SSP_MODE_UNKNOWN = 0, ++ SSP_MODE_PS2, ++ SSP_MODE_I2S, ++ SSP_MODE_FLASH, ++}; ++ ++static struct timer_list g_KbdTimer; ++static enum SSPmodes gSSPmode = SSP_MODE_UNKNOWN; ++static SSPDataCallback gKeyCallback = NULL; ++static int gHookedInterrupt = 0; ++ ++/* ++ * Keep the last valid handle for SSP for kbd, i2s, and flash ++ */ ++static int iLastValidHandle = -1; ++static int KeyboardHandle = 0; ++static int I2SHandle = 0; ++static int FlashHandle = 0; ++ ++#define SSP_DEVICE_MASK 0xf0000000 ++#define SSP_DEVICE_SHIFT 28 ++ ++SSP_DRIVER_API SSPinstance = { ++ SSP_Open, ++ SSP_Read, ++ SSP_Write, ++ SSP_Close, ++}; ++ ++/* ++ * The only instance of this driver. ++ */ ++SSP_DRIVER_API *SSPDriver = &SSPinstance; ++ ++/** ++ * SSPIrqHandler - get all of the keys out of the SPI FIFO. ++ */ ++irqreturn_t SSPIrqHandler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ /* ++ * Get key codes from SSP and send them to the keyboard callback. ++ */ ++ ReadIntoBuffer(); ++ ++ /* ++ * Clear the interrupt. ++ */ ++ writel(0, SSPIIR); ++ return IRQ_HANDLED; ++} ++ ++/** ++ * TimerRoutine ++ * ++ * This function is called periodically to make sure that no keys are stuck in ++ * the SPI FIFO. This is necessary because the SPI only interrupts on half ++ * full FIFO which can leave up to one keyboard event in the FIFO until another ++ * key is pressed. ++ */ ++static void TimerRoutine(unsigned long Data) ++{ ++ int keycount; ++ ++ /* ++ * Get key codes from SSP and send them to the keyboard callback. ++ */ ++ keycount = ReadIntoBuffer(); ++ ++ /* ++ * If no keys were received, call the Data callback anyway so it can ++ * check for stuck keys. ++ */ ++ if ((keycount == 0) && gKeyCallback) ++ gKeyCallback(-1); ++ ++ /* ++ * Reschedule our timer in another 20 mSec. ++ */ ++ g_KbdTimer.expires = ++ jiffies + MSECS_TO_JIFFIES(EP93XX_KEY_TIMER_PERIOD_MSEC); ++ add_timer(&g_KbdTimer); ++} ++ ++/** ++ * HookInterrupt ++ * ++ * Requests SSP interrupt, sets up interrupt handler, sets up keyboard polling ++ * timer. ++ */ ++static int HookInterrupt(void) ++{ ++ if (gHookedInterrupt) { ++ printk(KERN_ERR "SSP driver interrupt already hooked\n"); ++ return -1; ++ } ++ ++ if (request_irq ++ (IRQ_SSPRX, SSPIrqHandler, SA_INTERRUPT, "ep93xxsspd", NULL)) { ++ printk(KERN_ERR "SSP driver failed to get IRQ handler\n"); ++ return -1; ++ } ++ ++ gHookedInterrupt = 1; ++ ++ /* ++ * Initialize the timer that we will use to poll the SPI. ++ */ ++ init_timer(&g_KbdTimer); ++ g_KbdTimer.function = TimerRoutine; ++ g_KbdTimer.data = 1; ++ g_KbdTimer.expires = ++ jiffies + MSECS_TO_JIFFIES(EP93XX_KEY_TIMER_PERIOD_MSEC); ++ ++ add_timer(&g_KbdTimer); ++ ++ return 0; ++} ++ ++static int SSP_Open(enum SSPDeviceType Device, SSPDataCallback Callback) ++{ ++ int Handle; ++ ++ /* ++ * Generate a handle and pass it back. ++ * ++ * Increment the last valid handle. ++ * Check for wraparound (unlikely, but we like to be complete). ++ */ ++ iLastValidHandle++; ++ ++ /* ++ * If we wrapped around start over. Unlikely. ++ */ ++ if ((iLastValidHandle & ~SSP_DEVICE_MASK) == 0) ++ iLastValidHandle = 1; ++ ++ Handle = iLastValidHandle | (Device << SSP_DEVICE_SHIFT); ++ ++ switch (Device) { ++ case PS2_KEYBOARD: ++ { ++ DPRINTK("SSP_Open - PS2_KEYBOARD\n"); ++ if (KeyboardHandle) ++ return -1; ++ ++ DPRINTK("Handle:%08x Callback:%08x -- Success\n", ++ Handle, (unsigned int)Callback); ++ ++ KeyboardHandle = Handle; ++ /* Hook the interrupt if we have not yet. */ ++ HookInterrupt(); ++ SetSSPtoPS2(); ++ gKeyCallback = Callback; ++ ++ break; ++ } ++ case I2S_CODEC: ++ { ++ DPRINTK("SSP_Open - I2S_CODEC\n"); ++ if (I2SHandle) ++ return -1; ++ ++ DPRINTK("Handle:%08x Callback:%08x -- Success\n", ++ Handle, (unsigned int)Callback); ++ ++ I2SHandle = Handle; ++ break; ++ } ++ case SERIAL_FLASH: ++ { ++ DPRINTK("SSP_Open - SERIAL_FLASH\n"); ++ if (FlashHandle) ++ return -1; ++ ++ DPRINTK("Handle:%08x Callback:%08x -- Success\n", ++ Handle, (unsigned int)Callback); ++ ++ FlashHandle = Handle; ++ break; ++ } ++ default: ++ { ++ return -1; ++ } ++ } ++ ++ return Handle; ++} ++ ++/** ++ * SSP_Close ++ * ++ * Release that Handle! ++ */ ++static int SSP_Close(int Handle) ++{ ++ /* ++ * Find out which device this API was called for. ++ */ ++ switch (CheckHandle(Handle)) { ++ case PS2_KEYBOARD: ++ { ++ DPRINTK("SSP_Open - PS2_KEYBOARD\n"); ++ del_timer(&g_KbdTimer); ++ free_irq(IRQ_SSPRX, NULL); ++ gKeyCallback = NULL; ++ KeyboardHandle = 0; ++ gHookedInterrupt = 0; ++ break; ++ } ++ case I2S_CODEC: ++ { ++ DPRINTK("SSP_Open - I2S_CODEC\n"); ++ I2SHandle = 0; ++ break; ++ } ++ case SERIAL_FLASH: ++ { ++ DPRINTK("SSP_Open - SERIAL_FLASH\n"); ++ FlashHandle = 0; ++ break; ++ } ++ default: ++ { ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++static int SSP_Read(int Handle, unsigned int Addr, unsigned int *pValue) ++{ ++ DPRINTK("SSP_Read\n"); ++ return 0; ++} ++ ++static int SSP_Write(int Handle, unsigned int Addr, unsigned int Value) ++{ ++ int iRet = 0; ++ /* DPRINTK("SSP_Write - Handle:0x%08x Addr:0x%08x Value:0x%08x\n", ++ Handle, Addr, Value ); */ ++ ++ /* ++ * Find out which device this API was called for. ++ */ ++ switch (CheckHandle(Handle)) { ++ case PS2_KEYBOARD: ++ { ++ break; ++ } ++ case I2S_CODEC: ++ { ++ iRet = SSP_Write_I2SCodec(Handle, Addr, Value); ++ break; ++ } ++ case SERIAL_FLASH: ++ { ++ break; ++ } ++ default: ++ { ++ return -1; ++ } ++ } ++ ++ return iRet; ++} ++ ++static void SetSSPtoPS2(void) ++{ ++ unsigned int uiRegTemp; ++ ++ if (gSSPmode == SSP_MODE_PS2) ++ return; ++ ++ /* ++ * Disable the SSP, disable interrupts ++ */ ++ writel(0, SSPCR1); ++ ++ /* ++ * It takes almost a millisecond for a key to come in so ++ * make sure we have completed all transactions. ++ */ ++ mdelay(1); ++ ++ /* ++ * Set EGPIO7 to disable EEPROM device on EDB9312. ++ */ ++ uiRegTemp = readl(GPIO_PADDR); ++ writel(uiRegTemp | 0x80, GPIO_PADDR); ++ ++ uiRegTemp = readl(GPIO_PADR); ++ writel(uiRegTemp | 0x80, GPIO_PADR); ++ ++ /* ++ * Still haven't enabled the keyboard. So anything in ++ * the rx fifo is garbage. Time to take out the trash. ++ */ ++ while (readl(SSPSR) & SSPSR_RNE) { ++ uiRegTemp = readl(SSPDR); ++ } ++ ++ /* ++ * SPICR0_SPO - SCLKOUT Polarity ++ * SPICR0_SPH - SCLKOUT Phase ++ * Motorola format, 11 bit, one start, 8 data, one bit for ++ * parity, one stop bit. ++ */ ++ writel((SSPCR0_FRF_MOTOROLA | SSPCR0_SPH | SSPCR0_SPO | ++ SSPCR0_DSS_11BIT), SSPCR0); ++ /* ++ * Configure the device as a slave, Clear FIFO overrun interrupts, ++ * enable interrupts and reset the device. ++ */ ++ writel((SSPC1_MS | SSPC1_RIE | SSPC1_SOD), SSPCR1); ++ writel(0, SSPIIR); ++ writel((SSPC1_MS | SSPC1_RIE | SSPC1_SOD | SSPC1_SSE), ++ SSPCR1); ++ ++ /* ++ * Configure EGPIO pins 12 and 14 as outputs because they are used ++ * as buffer enables for the SPI interface to the ps2 keyboard. ++ * Clear EGPIO pins 12 and 14, this will enable the SPI keyboard. ++ */ ++ uiRegTemp = readl(GPIO_PBDDR); ++ writel(uiRegTemp | 0x50, GPIO_PBDDR); ++ ++ uiRegTemp = readl(GPIO_PBDR); ++ writel(uiRegTemp & ~0x50, GPIO_PBDR); ++ ++ gSSPmode = SSP_MODE_PS2; ++} ++ ++static void SetSSPtoI2S(void) ++{ ++ unsigned int uiRegTemp; ++ ++ if (gSSPmode == SSP_MODE_I2S) ++ return; ++ ++ /* ++ * Disable recieve interrupts. ++ */ ++ writel((SSPC1_MS | SSPC1_SSE), SSPCR1); ++ ++ /* ++ * Set GPIO pins 12 and 14, this will bring the clock line low ++ * which signals to the keyboard to buffer keystrokes. ++ * Note that EGPIO 14 is the clock line and EGPIO 12 is data line. ++ */ ++ uiRegTemp = readl(GPIO_PBDR); ++ writel(0x50 | uiRegTemp, GPIO_PBDR); ++ ++ /* ++ * It takes almost a millisecond for an partial keystrokes to come in. ++ * Delay to make sure we have completed all transactions. ++ */ ++ mdelay(1); ++ ++ /* ++ * Anything we just recieved is garbage. Time to take out the trash. ++ */ ++ while (readl(SSPSR) & SSPSR_RNE) { ++ uiRegTemp = readl(SSPDR); ++ } ++ ++ /* ++ * Disable the SSP and disable interrupts ++ */ ++ writel(0, SSPCR1); ++ ++ /* ++ * Clock will be 14.7 MHz divided by 4. ++ */ ++ writel(2, SSPCPSR); ++ ++ /* ++ * Configure EGPIO7 as an output and set it. This selects ++ * I2S codec as the device on the SSP output instead of ++ * the serial flash. ++ */ ++ uiRegTemp = readl(GPIO_PADDR); ++ writel(uiRegTemp | 0x80, GPIO_PADDR); ++ ++ uiRegTemp = readl(GPIO_PADR); ++ writel(uiRegTemp | 0x80, GPIO_PADR); ++ ++ /* ++ * Motorola format, 8 bit. ++ */ ++ writel((SSPCR0_SPO | SSPCR0_SPH | SSPCR0_FRF_MOTOROLA | ++ SSPCR0_DSS_8BIT), SSPCR0); ++ ++ /* ++ * Configure the device as master, reenable the device. ++ */ ++ writel(SSPC1_SSE, SSPCR1); ++ ++ gSSPmode = SSP_MODE_I2S; ++ ++ udelay(10); ++} ++ ++/** ++ * CheckHandle ++ * ++ * If Handle is valid, returns 0. Otherwise it returns -1. ++ */ ++static int CheckHandle(int Handle) ++{ ++ int iRet; ++ ++ if ((Handle != KeyboardHandle) && ++ (Handle != I2SHandle) && (Handle != FlashHandle)) { ++ DPRINTK("OOPS! Invalid SSP Handle!\n"); ++ return -1; ++ } ++ ++ /* ++ * Get the SSP driver instance number from the handle. ++ */ ++ iRet = (((int)Handle & SSP_DEVICE_MASK) >> SSP_DEVICE_SHIFT); ++ ++#if 0 ++ switch (iRet) { ++ case PS2_KEYBOARD: ++ DPRINTK("CheckHandle - valid - Keyboard\n"); ++ break; ++ ++ case I2S_CODEC: ++ DPRINTK("CheckHandle - valid - I2S\n"); ++ break; ++ ++ case SERIAL_FLASH: ++ DPRINTK("CheckHandle - valid - Keyboard\n"); ++ break; ++ } ++#endif ++ ++ return iRet; ++} ++ ++/** ++ * ReadIntoBuffer ++ * ++ * Drains the SSP rx fifo into a buffer here. If we overflow this buffer ++ * then something's wrong. ++ */ ++static int ReadIntoBuffer(void) ++{ ++ unsigned int count, index, saved_count, uiRegTemp; ++ ++ count = 0; ++ index = 0; ++ ++ if (gSSPmode != SSP_MODE_PS2) ++ return 0; ++ ++ /* ++ * This spinlock will prevent I2S from grabbing the SSP to do a ++ * write while we are using the SSP for PS2. ++ * ++ * There is a slight chance that we are in the beginning phase ++ * of doing an I2S write but the mode flag hadn't yet switched ++ * to I2S. If that happens we will end up waiting on I2S to ++ * finish a write. Not great. ++ */ ++ spin_lock(&ssp_spinlock); ++ ++ while (readl(SSPSR) & SSPSR_RNE) { ++ /* ++ * Read in the value from the SPI controller into ++ * the partial key buffer. ++ */ ++ uiKeyBuffer[count] = readl(SSPDR); ++ if (((uiKeyBuffer[count] & 0x3fc) != 0x3e0) && ++ ((uiKeyBuffer[count] & 0x3fc) != 0x3c0)) { ++ /* ++ * Set GPIO pins 12 and 14, this will bring the clock line low ++ * which signals to the keyboard to buffer keystrokes. ++ * Note that EGPIO 14 is the clock line and EGPIO 12 is data line. ++ */ ++ uiRegTemp = readl(GPIO_PBDR); ++ writel(0x50 | uiRegTemp, GPIO_PBDR); ++ ++ writel(0, SSPCR1); ++ writel((SSPC1_MS | SSPC1_RIE | SSPC1_SSE), ++ SSPCR1); ++ ++ /* ++ * Clear EGPIO pins 12 and 14, this will enable the SPI keyboard. ++ */ ++ uiRegTemp = readl(GPIO_PBDR); ++ writel(uiRegTemp & ~0x50, GPIO_PBDR); ++ ++ count++; ++ break; ++ } ++ count++; ++ } ++ ++ saved_count = count; ++ index = 0; ++ while (count) { ++ /* ++ * No callback, dump data. ++ */ ++ if (gKeyCallback) ++ gKeyCallback(uiKeyBuffer[index++]); ++ ++ count--; ++ } ++ ++ spin_unlock(&ssp_spinlock); ++ ++ return saved_count; ++} ++ ++/** ++ * SSP_Write_I2SCodec ++ * ++ */ ++static int SSP_Write_I2SCodec ++ (int Handle, unsigned int RegAddr, unsigned int RegValue) { ++ enum SSPmodes saved_mode; ++ ++ DPRINTK("SSP_Write_I2SCodec\n"); ++ ++ spin_lock(&ssp_spinlock); ++ ++ /* ++ * Save the SSP mode. Switch to I2S mode if we're not ++ * already in I2S mode. ++ */ ++ saved_mode = gSSPmode; ++ SetSSPtoI2S(); ++ ++ /* ++ * Let TX fifo clear out. Poll the Transmit Fifo Empty bit. ++ */ ++ while (!(readl(SSPSR) & SSPSR_TFE)) ; ++ ++ /* ++ * Write the data out to the tx fifo. ++ */ ++ writel(0x20, SSPDR); /* chip address for CS4228 */ ++ writel((RegAddr & 0xff), SSPDR); ++ writel((RegValue & 0xff), SSPDR); ++ ++ /* ++ * Let TX fifo clear out. Poll the Transmit Fifo Empty bit. ++ */ ++ while (!(readl(SSPSR) & SSPSR_TFE)) ; ++ ++ /* ++ * Delay to let stuff make it out of the SR before doing ++ * anthing else to the SSP. It takes 6.8 uSec to do a ++ * I2S codec register write. ++ */ ++ udelay(10); ++ ++ /* ++ * If we were in PS2 mode, switch back to PS2 mode. ++ * If we weren't in PS2 mode, that means we didn't compile in ++ * the PS2 keyboard support, so no need to switch to PS2 mode. ++ */ ++ if (saved_mode == SSP_MODE_PS2) ++ SetSSPtoPS2(); ++ ++ spin_unlock(&ssp_spinlock); ++ ++ return 0; ++} +diff --git a/arch/arm/mach-ep93xx/ssp.c b/arch/arm/mach-ep93xx/ssp.c +new file mode 100644 +index 0000000..4e1b973 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/ssp.c +@@ -0,0 +1,246 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/ssp.c ++ * ++ * Generic SSP driver. This provides shared access to the SSP ++ * interface operating in master mode. ++ * ++ * Copyright (C) 2004 Ray Lehtiniemi. ++ * Copyright (C) 2004 Siconix, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/errno.h> ++#include <linux/init.h> ++ ++#include <asm/arch/ssp.h> ++ ++/* ================================================================ ++ Front End Interface ++ ================================================================ */ ++ ++/*** ++ * ssp_add_slave - register an ssp_slave with an ssp_master ++ * @m: the master ++ * @s: the slave ++ * ++ * Grabs the frontend lock and adds slave to list. ++ */ ++int ssp_add_slave(struct ssp_master *m, struct ssp_slave *s) ++{ ++ if (s->master != NULL) ++ return -EBUSY; ++ down(&m->sem); ++ list_add(&s->list, &m->slave); ++ s->master = m; ++ up(&m->sem); ++ return 0; ++} ++ ++EXPORT_SYMBOL(ssp_add_slave); ++ ++/*** ++ * ssp_remove_slave - de-register an ssp_slave from its master ++ * @m: the master ++ * @s: the slave ++ * ++ * Grabs the frontend lock and removes slave from list. ++ */ ++void ssp_remove_slave(struct ssp_master *m, struct ssp_slave *s) ++{ ++ if (s->master != m) ++ return; ++ down(&m->sem); ++ list_del(&s->list); ++ s->master = NULL; ++ up(&m->sem); ++} ++ ++EXPORT_SYMBOL(ssp_remove_slave); ++ ++/*** ++ * ssp_do - perform a single SSP transaction on the slave ++ * @s: the slave ++ * @len: the number of words to transfer ++ * @tx: a buffer of @len words to clock out to slave ++ * @rx: a buffer of @len words to clock in from slave ++ * ++ * Grabs the frontend lock, configures the ssp master as required ++ * by the slave, asserts the slave devices chip select line, and ++ * schedules the backend to perform the transfer. ++ * ++ * Once the backend signals completion, the chip select is negated ++ * and the frontend lock is released. ++ * ++ * The backend will transfer @len * @s->nbytes from @tx and ++ * into @rx. Make sure your buffers are big enough! If @tx ++ * or @rx are null, then null data will be clocked in and/or out. ++ */ ++int ssp_do(struct ssp_slave *s, int len, void *tx, void *rx) ++{ ++ int err; ++ ++ if ((err = ssp_start(s)) < 0) ++ goto out1; ++ ++ ssp_select(s); ++ ++ if ((err = ssp_post(s, len, tx, rx)) < 0) ++ goto out2; ++ ++ err = ssp_wait(s); ++ ++ out2: ++ ssp_deselect(s); ++ ssp_finish(s); ++ out1: ++ return err; ++} ++ ++EXPORT_SYMBOL(ssp_do); ++ ++/* ================================================================ ++ Transaction Interface ++ ================================================================ */ ++ ++static int __ssp_txn_start(struct ssp_slave *s); ++ ++/*** ++ * ssp_start - Grab and configure the SSP bus (blocking) ++ * @s: the slave ++ * ++ * This call will grab and initialize the SSP bus, blocking ++ * until the bus is ready. ++ */ ++int ssp_start(struct ssp_slave *s) ++{ ++ down(&s->master->sem); ++ return __ssp_txn_start(s); ++} ++ ++EXPORT_SYMBOL(ssp_start); ++ ++/*** ++ * ssp_trystart - Grab and configure the SSP bus (non-blocking) ++ * @s: the slave ++ * ++ * This call will grab and initialize the SSP bus, returning ++ * with an error if the bus is not free. ++ */ ++int ssp_trystart(struct ssp_slave *s) ++{ ++ if (!down_trylock(&s->master->sem)) ++ return -EBUSY; ++ return __ssp_txn_start(s); ++} ++ ++EXPORT_SYMBOL(ssp_trystart); ++ ++static int __ssp_txn_start(struct ssp_slave *s) ++{ ++ return s->master->ops->configure(s); ++} ++ ++/*** ++ * ssp_select - assert the slave CS line ++ * @s: the slave ++ * ++ * assert the device-specific CS line ++ */ ++void ssp_select(struct ssp_slave *s) ++{ ++ s->chip_select(s, 1); ++} ++ ++EXPORT_SYMBOL(ssp_select); ++ ++/*** ++ * ssp_post - start the backend for the slave's master ++ * @s: the slave ++ * ++ * Start the backend data transfer for this master. ++ */ ++int ssp_post(struct ssp_slave *s, int len, void *tx, void *rx) ++{ ++ struct ssp_transfer *t; ++ ++ t = &s->master->transfer; ++ ++ t->size = s->nbytes; ++ t->len = len; ++ t->rlen = len; ++ t->tx = tx; ++ t->rx = rx; ++ t->c = &s->master->completion; ++ init_completion(t->c); ++ ++ return s->master->ops->enable(t); ++} ++ ++EXPORT_SYMBOL(ssp_post); ++ ++/*** ++ * ssp_wait - block until the SP transfer is complete ++ * @s: the slave ++ * ++ * block until the SP transfer is complete. ++ */ ++int ssp_wait(struct ssp_slave *s) ++{ ++ wait_for_completion(&s->master->completion); ++ return s->master->ops->disable(); ++} ++ ++EXPORT_SYMBOL(ssp_wait); ++ ++/*** ++ * ssp_deselect - assert the slave CS line ++ * @s: the slave ++ * ++ * negate the device-specific CS line ++ */ ++void ssp_deselect(struct ssp_slave *s) ++{ ++ s->chip_select(s, 0); ++} ++ ++EXPORT_SYMBOL(ssp_deselect); ++ ++/*** ++ * ssp_finish - release the ssp bus ++ * @s: the slave ++ * ++ * Releases the frontend lock. ++ */ ++void ssp_finish(struct ssp_slave *s) ++{ ++ up(&s->master->sem); ++} ++ ++EXPORT_SYMBOL(ssp_finish); ++ ++/* ================================================================ ++ Module Stuff ++ ================================================================ */ ++ ++int __init ssp_init(void) ++{ ++ printk(KERN_INFO "Generic SSP Support version 0.1\n"); ++ return 0; ++} ++ ++void __exit ssp_exit(void) ++{ ++} ++ ++module_init(ssp_init); ++module_exit(ssp_exit); ++ ++MODULE_AUTHOR("Ray Lehtiniemi"); ++MODULE_DESCRIPTION("Generic SSP driver"); ++MODULE_LICENSE("GPL"); +diff --git a/arch/arm/mach-ep93xx/ssp2.c b/arch/arm/mach-ep93xx/ssp2.c +new file mode 100644 +index 0000000..6a4ff10 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/ssp2.c +@@ -0,0 +1,354 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/ssp.c ++ * ++ * EP93xx SSP driver. This provides shared access to the SSP ++ * interface operating in master mode. ++ * ++ * Copyright (C) 2004 Ray Lehtiniemi. ++ * Copyright (C) 2004 Siconix, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/errno.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/ioport.h> ++#include <linux/spinlock.h> ++ ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <asm/hardware.h> ++ ++#include <asm/arch/ssp.h> ++#include <asm/arch/ssp2.h> ++ ++/* print out all chars tx, rx, and dropped */ ++#define _(x...) /* printk(KERN_WARNING x); printk("\n") */ ++ ++/* the current transfer */ ++static struct ssp_transfer *transfer; ++ ++/* stupid SSP gives rx int only when rx fifo > half full :-P */ ++static void do_rx_poll(void *x); ++static DECLARE_WORK(work, do_rx_poll, NULL); ++ ++/* also implement a timeout in the worker, to prevent hard lockups ++ if something goes south... */ ++static int timeout; ++ ++/* serialize the rx irq and the work poller routines */ ++static spinlock_t spinlock = SPIN_LOCK_UNLOCKED; ++ ++/* ----------------- Hardware Control --------------------- */ ++ ++/* send a word */ ++static __inline__ void x_ssp_send(__u16 dat) ++{ ++ writel(dat, SSPDR); ++ _("\ttx %08x", dat); ++} ++ ++/* send a word to clock the recv */ ++static __inline__ void x_ssp_clock(void) ++{ ++ writel(0, SSPDR); ++ _("\tt- --------"); ++} ++ ++/* recv a word */ ++static __inline__ __u16 x_ssp_recv(void) ++{ ++ unsigned long dat = readl(SSPDR); ++ _("\trx %08lx", dat); ++ return dat & 0xffff; ++} ++ ++/* discard a word */ ++static __inline__ void x_ssp_discard(void) ++{ ++#if 1 ++ unsigned long dat = readl(SSPDR); ++ _("\tr- %08lx (discard)", dat); ++#else ++ (void)readl(SSPDR); ++ _("\tr- --------"); ++#endif ++} ++ ++/* are there chars in the rx fifo? */ ++static __inline__ int x_ssp_available(void) ++{ ++ return (readl(SSPSR) & SSPSR_RNE) ? 1 : 0; ++} ++ ++/* is there room in the tx fifo? */ ++static __inline__ int x_ssp_has_room(void) ++{ ++ return (readl(SSPSR) & SSPSR_TNF) ? 1 : 0; ++} ++ ++/* is the transmitter busy? */ ++static __inline__ int x_ssp_busy(void) ++{ ++ return (readl(SSPSR) & SSPSR_BSY) ? 1 : 0; ++} ++ ++/* flush the RX and TX fifos */ ++static void x_ssp_flush(void) ++{ ++ do { ++ while (x_ssp_available()) ++ x_ssp_discard(); ++ } while (x_ssp_busy()); ++ ++ /* just in case there is a race... in any event, this should be harmless */ ++ x_ssp_discard(); ++} ++ ++/* set up all regs as required by the slave */ ++static void x_ssp_configure(struct ep93xx_ssp_slave *s) ++{ ++ writel(s->cr1, SSPCR1); ++ writel(s->cr0, SSPCR0); ++ writel(s->cpsr, SSPCPSR); ++ writel(s->cr1 & ~SSPC1_SSE, SSPCR1); ++ writel(s->cr1, SSPCR1); ++} ++ ++/* enable chip select and all ints */ ++static __inline__ void x_ssp_enable(void) ++{ ++ unsigned long x = readl(SSPCR1); ++ writel(x | SSPC1_TIE | SSPC1_RIE | SSPC1_RORIE, SSPCR1); ++} ++ ++/* disable chip select and all ints */ ++static __inline__ void x_ssp_disable(void) ++{ ++ unsigned long x = readl(SSPCR1); ++ writel(x & ~(SSPC1_TIE | SSPC1_RIE | SSPC1_RORIE), SSPCR1); ++} ++ ++/* disable tx int */ ++static __inline__ void x_ssp_stop_tx(void) ++{ ++ unsigned long x = readl(SSPCR1); ++ writel(x & ~SSPC1_TIE, SSPCR1); ++} ++ ++/* ---------------------- Master Methods ------------------------- */ ++ ++static int ep93xx_ssp_configure(struct ssp_slave *ss) ++{ ++ struct ep93xx_ssp_slave *s = (struct ep93xx_ssp_slave *)ss; ++ _("SSP transfer"); ++ x_ssp_configure(s); ++ return 0; ++} ++ ++static int ep93xx_ssp_enable(struct ssp_transfer *t) ++{ ++ _("{"); ++ transfer = t; ++ timeout = 0; ++ schedule_delayed_work(&work, 1); ++ x_ssp_enable(); ++ return 0; ++} ++ ++static int ep93xx_ssp_disable(void) ++{ ++ x_ssp_disable(); ++ cancel_delayed_work(&work); ++ transfer = NULL; ++ _("}"); ++ return 0; ++} ++ ++static struct ssp_master_ops my_ops = { ++ .configure = ep93xx_ssp_configure, ++ .enable = ep93xx_ssp_enable, ++ .disable = ep93xx_ssp_disable, ++}; ++ ++/* ----------------- Registration Stuff FIXME ------------- */ ++ ++#include <linux/completion.h> ++#include <asm/types.h> ++#include <asm/semaphore.h> ++ ++struct ssp_master ep93xx_ssp_master = { ++ __MUTEX_INITIALIZER(ep93xx_ssp_master.sem), ++ COMPLETION_INITIALIZER(ep93xx_ssp_master.completion), ++ LIST_HEAD_INIT(ep93xx_ssp_master.slave), ++ { ++ 0, ++ 0, ++ 0, ++ NULL, ++ NULL, ++ NULL}, ++ &my_ops ++}; ++ ++EXPORT_SYMBOL(ep93xx_ssp_master); ++ ++/* -------------------- Bottom Half ----------------------- */ ++ ++static void do_tx(void) ++{ ++ if (transfer == NULL) { ++ printk(KERN_WARNING "Null tx transfer...\n"); ++ return; ++ } ++ ++ while (transfer->len != 0) { ++ ++ if (!x_ssp_has_room()) ++ return; ++ ++ if (transfer->tx == NULL) { ++ x_ssp_clock(); ++ ++ } else if (transfer->size == 1) { ++ __u8 *t = transfer->tx; ++ x_ssp_send(*t); ++ transfer->tx += 1; ++ ++ } else if (transfer->size == 2) { ++ __u16 *t = transfer->tx; ++ x_ssp_send(*t); ++ transfer->tx += 2; ++ ++ } else if (transfer->size == 4) { ++ __u32 *t = transfer->tx; ++ x_ssp_send(*t); ++ transfer->tx += 4; ++ } ++ ++ transfer->len--; ++ } ++ ++ x_ssp_stop_tx(); ++} ++ ++static void __do_rx(void) ++{ ++ if (transfer == NULL) { ++ printk(KERN_WARNING "Null rx transfer...\n"); ++ return; ++ } ++ ++ while (transfer->rlen != 0) { ++ ++ if (!x_ssp_available()) ++ return; ++ ++ if (transfer->rx == NULL) { ++ x_ssp_discard(); ++ ++ } else if (transfer->size == 1) { ++ __u8 *t = transfer->rx; ++ *t = x_ssp_recv(); ++ transfer->rx += 1; ++ ++ } else if (transfer->size == 2) { ++ __u16 *t = transfer->rx; ++ *t = x_ssp_recv(); ++ transfer->rx += 2; ++ ++ } else if (transfer->size == 4) { ++ __u32 *t = transfer->rx; ++ *t = x_ssp_recv(); ++ transfer->rx += 4; ++ } ++ ++ transfer->rlen--; ++ timeout = 0; ++ } ++ ++ complete(transfer->c); ++} ++ ++static void do_rx(void) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&spinlock, flags); ++ __do_rx(); ++ spin_unlock_irqrestore(&spinlock, flags); ++} ++ ++static void do_rx_poll(void *x) ++{ ++ unsigned long flags; ++ spin_lock_irqsave(&spinlock, flags); ++ __do_rx(); ++ timeout++; ++ if (timeout == 100) { ++ x_ssp_disable(); ++ complete(transfer->c); ++ } else { ++ schedule_delayed_work(&work, 1); ++ } ++ spin_unlock_irqrestore(&spinlock, flags); ++} ++ ++static irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ unsigned int status = readl(SSPIIR); ++ ++ if (transfer == NULL) { ++ printk(KERN_WARNING "SSP: no active transfer\n"); ++ x_ssp_flush(); ++ x_ssp_disable(); ++ } ++ ++ if (status & SSPIIR_RORIS) ++ printk(KERN_WARNING "SSP: receiver overrun\n"); ++ ++ if (status & SSPIIR_TIS) ++ do_tx(); ++ ++ if (status & SSPIIR_RIS) ++ do_rx(); ++ ++ writel(0, SSPICR); ++ ++ return status ? IRQ_HANDLED : IRQ_NONE; ++} ++ ++/* -------------------- Module Stuff ---------------------- */ ++ ++int __init ep93xx_ssp_init(void) ++{ ++ int i; ++ ++ if (readl(SYSCON_DEVCFG) & SYSCON_DEVCFG_I2SonSSP) ++ return -ENODEV; ++ ++ i = request_irq(IRQ_SSP, irq_handler, 0, "SSP", NULL); ++ ++ if (i) ++ printk(KERN_ERR ++ "EP93XX: unable to grab SSP interrupt, error %d\n", i); ++ ++ printk(KERN_INFO "EP93xx SSP driver version 0.1\n"); ++ return 0; ++} ++ ++void __exit ep93xx_ssp_exit(void) ++{ ++ free_irq(IRQ_SSP, NULL); ++} ++ ++module_init(ep93xx_ssp_init); ++module_exit(ep93xx_ssp_exit); ++ ++MODULE_AUTHOR("Ray Lehtiniemi"); ++MODULE_DESCRIPTION("EP93xx SSP driver"); ++MODULE_LICENSE("GPL"); +diff --git a/arch/arm/mach-ep93xx/time.c b/arch/arm/mach-ep93xx/time.c +new file mode 100644 +index 0000000..459a179 +--- /dev/null ++++ b/arch/arm/mach-ep93xx/time.c +@@ -0,0 +1,40 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/time.c ++ * ++ * Copyright (C) 2000-2001 Deep Blue Solutions ++ * ++ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA. All rights reserved. ++ * Copyright (C) 2002-2003 Cirrus Logic, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/init.h> ++ ++#include <asm/hardware.h> ++#include <asm/io.h> ++ ++extern int (*set_rtc) (void); ++ ++static int ep93xx_set_rtc(void) ++{ ++ writel(xtime.tv_sec, RTCLR); ++ return 1; ++} ++ ++static int ep93xx_rtc_init(void) ++{ ++ writel(0, RTCCR); ++ writel(0, RTCEOI); ++ ++ writel(xtime.tv_sec, RTCDR); ++ ++ set_rtc = ep93xx_set_rtc; ++ ++ return 0; ++} ++ ++__initcall(ep93xx_rtc_init); +diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig +index e84fdde..85c90bf 100644 +--- a/arch/arm/mm/Kconfig ++++ b/arch/arm/mm/Kconfig +@@ -62,8 +62,8 @@ config CPU_ARM720T + # ARM920T + config CPU_ARM920T + bool "Support ARM920T processor" if !ARCH_S3C2410 +- depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 +- default y if ARCH_S3C2410 ++ depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_EP93XX ++ default y if ARCH_S3C2410 || ARCH_EP93XX + select CPU_32v4 + select CPU_ABRT_EV4T + select CPU_CACHE_V4WT +diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c +index 8b276ee..cc8aedb 100644 +--- a/arch/arm/mm/init.c ++++ b/arch/arm/mm/init.c +@@ -212,6 +212,10 @@ static __init void reserve_node_zero(pg_ + if (machine_is_integrator() || machine_is_cintegrator()) + res_size = __pa(swapper_pg_dir) - PHYS_OFFSET; + ++ /* TBD vector table and initial stack below pg_dir */ ++ if (machine_is_edb9301() || machine_is_edb9312() || machine_is_edb9315() || machine_is_acc()) ++ res_size = __pa(swapper_pg_dir) - PHYS_OFFSET; ++ + /* + * These should likewise go elsewhere. They pre-reserve the + * screen memory region at the start of main system memory. +diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig +index 84e68cd..c4a267b 100644 +--- a/drivers/char/Kconfig ++++ b/drivers/char/Kconfig +@@ -4,6 +4,16 @@ + + menu "Character devices" + ++config TTML_DEVICES ++ tristate "TTML TripDawg system devices" ++ depends on MACH_TTML ++ default m ++ ---help--- ++ If you say y or m here, you will get several character devices ++ which allow you to use the LEDs, buzzer, speedometer, and so ++ on. These devices are mapped into the 10,{240-254} range, which ++ is reserved for local devices. ++ + config VT + bool "Virtual terminal" if EMBEDDED + select INPUT +@@ -762,6 +772,26 @@ config EFI_RTC + bool "EFI Real Time Clock Services" + depends on IA64 + ++config EP93XX_RTC ++ bool "Cirrus EP93xx Real Time Clock support" ++ depends on ARCH_EP93XX ++ help ++ Provides EFI and legacy RTC support on the Cirrus EP93xx family of ++ devices via the /dev/rtc character node (10/135). ++ ++config DS1337_RTC ++ tristate "Dallas Semiconductor DS1337 Real Time Clock /dev/rtc interface" ++ depends on I2C && EXPERIMENTAL && !EP93XX_RTC ++ select SENSORS_DS1337 ++ help ++ Say Y here you have got a DS1337 real time clock on your I2C bus. ++ This here is just an interface to access it via the /dev/rtc ++ character node (10/135). All the hard work will be done ++ in the I2C driver (drivers/i2c/chips/ds1337.c). ++ ++ This driver can also be built as a module. If so, the module ++ will be called ds1337glue. ++ + config DS1302 + tristate "DS1302 RTC support" + depends on M32R && (PLAT_M32700UT || PLAT_OPSPUT) +@@ -893,6 +923,8 @@ source "drivers/char/drm/Kconfig" + + source "drivers/char/pcmcia/Kconfig" + ++source "drivers/char/can/Kconfig" ++ + config MWAVE + tristate "ACP Modem (Mwave) support" + depends on X86 +diff --git a/drivers/char/Makefile b/drivers/char/Makefile +index 4aeae68..579570d 100644 +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni + + obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o + ++obj-$(CONFIG_TTML_DEVICES) += ttml.o + obj-$(CONFIG_LEGACY_PTYS) += pty.o + obj-$(CONFIG_UNIX98_PTYS) += pty.o + obj-y += misc.o +@@ -65,6 +66,8 @@ obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o + obj-$(CONFIG_DS1302) += ds1302.o + obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o + obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o ++obj-$(CONFIG_EP93XX_RTC) += ep93xx-rtc.o ++obj-$(CONFIG_DS1337_RTC) += ds1337glue.o + ifeq ($(CONFIG_GENERIC_NVRAM),y) + obj-$(CONFIG_NVRAM) += generic_nvram.o + else +@@ -119,3 +122,6 @@ $(obj)/defkeymap.c $(obj)/qtronixmap.c: + rm $@.tmp + + endif ++ ++obj-$(CONFIG_CAN_BUS) += can/ ++ +diff --git a/drivers/char/can/Kconfig b/drivers/char/can/Kconfig +new file mode 100644 +index 0000000..9834c66 +--- /dev/null ++++ b/drivers/char/can/Kconfig +@@ -0,0 +1,46 @@ ++# ++# CAN bus character devices configuration ++# ++ ++menu "CAN bus devices" ++ ++config CAN_BUS ++ bool "CAN bus character devices" ++ help ++ If you say y here, you will get support for CAN bus ++ character device drivers. ++ ++config OKI_CAN_ML9620 ++ tristate "OKI ML9620 CAN BUS" ++ depends on CAN_BUS ++ help ++ If you say y or m here, you will get support for OKI ML9620 ++ character device based CAN driver for one CAN bus. ++ ++choice ++ prompt "OKI ML9620 configuration" ++ depends on OKI_CAN_ML9620 ++ help ++ Specific configuration for OKI ML9620 configuration. ++ ++config OKI_CAN_ML9620_MICRO9 ++ bool "OKI ML9620 Contec Hypercontrol Micro9 configuration" ++ depends on OKI_CAN_ML9620 ++ help ++ Select this if you have Contec Hypercontrol Micro9 board. ++ ++config OKI_CAN_ML9620_GASSNER ++ bool "OKI ML9620 Gassner configuration" ++ help ++ Select this if you want to have Gassner specific changes. ++ ++endchoice ++ ++config OKI_CAN_ML9620_2DEV ++ bool "OKI ML9620 CAN BUS 2nd DEVICE" ++ depends on OKI_CAN_ML9620 ++ help ++ If you say y here, you will get support for a second ++ OKI ML9620 CAN bus. ++ ++endmenu +diff --git a/drivers/char/can/Makefile b/drivers/char/can/Makefile +new file mode 100644 +index 0000000..f9bcf2a +--- /dev/null ++++ b/drivers/char/can/Makefile +@@ -0,0 +1,4 @@ ++# ++# Makefile for CAN BUS character devices ++# ++obj-$(CONFIG_OKI_CAN_ML9620) += oki_ml9620.o +diff --git a/drivers/char/can/oki_ml9620.c b/drivers/char/can/oki_ml9620.c +new file mode 100644 +index 0000000..d60cca4 +--- /dev/null ++++ b/drivers/char/can/oki_ml9620.c +@@ -0,0 +1,1006 @@ ++/* ++ * drivers/char/can/oki_ml9620_core.c ++ * ++ * OKI ML9620 CAN Controler driver ++ * ++ * Author: Manfred Gruber <manfred.gruber@contec.at> ++ * ++ * Copyright 2004 (c) Manfred Gruber ++ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H ++ * Kufstein/Austria www.contec.at ++ * ++ * This driver was written for Contec Hypercontrol Micro9 Board: ++ * 1. CAN Controller is on Hypercontrol Micro9 CPU board ++ * 2. CAN Controller is on Hypercontrol Micro9 Eval board ++ * ++ * Contec uses this driver on their Hypercontrol Micro9 boards based on ++ * Cirrus Logic EP93XX, we have changed Adr-/Databus timing to use OKI ML9620. ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ * ++ */ ++ ++/*Versions: ++ - 0.01 Inital version Only worked CAN1 ++ - 0.02 CAN1/CAN2 worked, EVAL-board and CPU-BOARD Micro9 ++ - 0.03 changes from Michael Burian to correct: ++ errors, functions, adr/databus-problems - thanks a lot Michael ++ changed to correct name oki_ml9620_X and put in drivers/char/can/ ++ deleted some wrong statements ++ - 0.04 Michael Burian: read/write expect/return count in bytes now, cleanups ++ - 0.05 Michael Burian: use mux'd IRQs for both devices now ++ - 0.06 Michael Burian: only queue messages when /dev/can[01] is open ++ - 0.07 Michael Burian: implement non-blocking read ++ - 0.08 Michael Burian: replace completion with waitq, implement poll support ++*/ ++ ++/*Todo: ++ - Baudrate over /proc configure ++ - remove potential infinite loop in write / make write return immediately ++ (no longer wait for hardware, do this in background) ++ - implement fsync to allow waiting till hardware has written, if desired ++ - implement poll for write ++ - implement buffered write ++ - use kfifo for buffering read ++ - use kfifo for buffering write ++ - look for a more elegant solution for ++*/ ++ ++/* Enable for debugging */ ++/*#define OKI_DEBUG */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/signal.h> ++#include <linux/errno.h> ++#include <linux/mm.h> ++#include <linux/major.h> ++#include <linux/config.h> ++#include <linux/moduleparam.h> ++#include <linux/types.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/stddef.h> /* offsetof(), etc. */ ++#include <linux/completion.h> ++#include <linux/poll.h> ++#include <linux/can/oki_ml9620_ctrl.h> ++#include <asm/segment.h> ++#include <asm/hardware.h> ++#include <asm/bitops.h> ++#include <asm/uaccess.h> ++#include <asm/io.h> ++#include <asm/arch/regmap.h> ++#include "oki_ml9620.h" ++ ++/* fops */ ++static int oki_read(struct file *file, char *buf, size_t count,loff_t *ppos); ++static int oki_write(struct file *file, const char *buf, size_t count,loff_t *ppos); ++static int oki_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); ++static int oki_open(struct inode *inode, struct file *file); ++static int oki_release(struct inode *inode, struct file *file); ++static unsigned int oki_poll(struct file *file, poll_table *wait); ++ ++/* IRQ */ ++static irqreturn_t oki_irqhandler(int irq, void *dev_id, struct pt_regs *regs); ++ ++/* CAN */ ++static void hw_init(struct can_device *c); ++static int set_baudrate(struct can_device *c, int baud); ++static int check_status(struct can_device *c); ++static int activate(struct can_device *c, unsigned char new_status); ++static void store_data_in_buffer(struct can_device *c, struct can_msg *data); ++ ++void store_data_in_buffer(struct can_device *c, struct can_msg *data) ++{ ++ /* No need to fill up the queue when nobody cares. */ ++ if (atomic_read(&c->can_opened)) ++ return; ++ ++ DBG_OKI(KERN_INFO, "DATA Stored: ID 0x%x dlc 0x%x rtr 0x%x ext 0x%x DATA: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",data->id,data->dlc,data->rtr,data->ext,data->data[0],data->data[1],data->data[2],data->data[3],data->data[4],data->data[5],data->data[6],data->data[7]); ++ ++ if (memcpy(&c->tail->msg, data, sizeof(struct can_msg)) != NULL) { ++ c->tail->next = kmalloc(sizeof(struct recbuf), GFP_KERNEL); ++ if (c->tail->next != NULL) { ++ c->tail->next->prev = c->tail; ++ c->tail = c->tail->next; ++ /* up sema to allow read */ ++ wake_up_interruptible(&c->rx_waitq); ++ return; ++ } ++ } ++} ++ ++int set_baudrate(struct can_device *c, int baud) ++{ ++ unsigned long v = (unsigned long)c->virt_addr_can; ++ int index = 0; ++ ++ /* unlock hardware */ ++ c->reg.cancont = readb(v + CANCONT); ++ c->reg.cancont |= CONT_FLAG_INIT; ++ writeb(c->reg.cancont, v + CANCONT); ++ ++ c->reg.cancont = readb(v + CANCONT); ++ c->reg.cancont |= CONT_FLAG_CCE; ++ writeb(c->reg.cancont, v + CANCONT); ++ ++ DBG_OUT(KERN_DEBUG, ": /dev/can%d set_baudrate %dkb\n", c->minor, baud); ++ ++ /* Lookuptable baudrate => Timing array index */ ++ switch (baud){ ++ case 10: index = 0; break; ++ case 20: index = 1; break; ++ case 50: index = 2; break; ++ case 100: index = 3; break; ++ case 125: index = 4; break; ++ case 250: index = 5; break; ++ case 500: index = 6; break; ++ case 800: index = 7; break; ++ case 1000: index = 8; break; ++ default: index = 4; break; ++ } ++ ++ /* set baudrate */ ++ c->reg.canbitt[0] = bd_tbl[index].btiming0; ++ c->reg.canbitt[1] = bd_tbl[index].btiming1; ++ c->reg.canbpre = bd_tbl[index].bpre; ++ writeb(c->reg.canbitt[0], v + CANBITT0); ++ writeb(c->reg.canbitt[1], v + CANBITT1); ++ writeb(c->reg.canbpre, v + CANBPRE); ++ ++ /* lock hardware */ ++ c->reg.cancont = readb(v + CANCONT); ++ c->reg.cancont &= ~CONT_FLAG_CCE; ++ writeb(c->reg.cancont, v + CANCONT); ++ ++ c->reg.cancont = readb(v + CANCONT); ++ c->reg.cancont &= ~CONT_FLAG_INIT; ++ writeb(c->reg.cancont, v + CANCONT); ++ ++ return baud; ++} ++ ++void hw_init(struct can_device *c) ++{ ++ unsigned char i; ++ unsigned long v = (unsigned long)c->virt_addr_can; ++ ++ spin_lock_init(&c->can_lock); ++ ++ c->reg.cancont |= CONT_FLAG_INIT; ++ writeb(c->reg.cancont, v + CANCONT); ++ ++ /* All Messages disabled with MsgVal = 0 */ ++ c->reg.if1id[3] = 0x00; ++ writeb(c->reg.if1id[3], v + IF1ID3); ++ ++ /* set, so that ID Register will get transfered */ ++ c->reg.if1cmask = 0x38; ++ writeb(c->reg.if1cmask, v + IF1CMASK); ++ ++ for (i = 1; i < (NUM_MSG + 1); i++) { ++ while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ; ++ c->reg.if1creq = i; ++ writeb(c->reg.if1creq, v + IF1CREQ); ++ } ++ ++ for (i = CAN_STD_RX_BUFFER_START; i < (CAN_STD_RX_BUFFER_END + 1); i++) { ++ c->reg.if1id[3] = 0x80; ++ writeb(c->reg.if1id[3], v + IF1ID3); ++ ++ c->reg.if1id[2] = 0x00; ++ writeb(c->reg.if1id[2], v + IF1ID2); ++ ++ /*c->reg.if1mask[3] = 0x00; */ ++ c->reg.if1mask[3] = 0x20; ++ writeb(c->reg.if1mask[3], v + IF1MASK3); ++ ++ c->reg.if1mask[2] = 0x00; ++ writeb(c->reg.if1mask[2], v + IF1MASK2); ++ ++ /* Transfer Controll u. ID bits */ ++ c->reg.if1cmask = 0xF8; ++ writeb(c->reg.if1cmask, v + IF1CMASK); ++ ++ if (i == CAN_STD_RX_BUFFER_END) { ++ c->reg.if1mcont[0] = 0x80; /* FIFO END */ ++ writeb(c->reg.if1mcont[0], v + IF1MCONT0); ++ } else { ++ c->reg.if1mcont[0] = 0x00; ++ writeb(c->reg.if1mcont[0], v + IF1MCONT0); ++ } ++ ++ c->reg.if1mcont[1] = 0x14; /* this MsgObj trig. Int on Rx */ ++ writeb(c->reg.if1mcont[1], v + IF1MCONT1); ++ ++ c->reg.if1creq = i; ++ writeb(c->reg.if1creq, v + IF1CREQ); ++ ++ while ((c->reg.if1busy = readb(v + IF1BUSY) & 0x80)) ; ++ } ++ ++ /* Extended Frames */ ++ c->reg.if1id[3] = 0xC0; ++ writeb(c->reg.if1id[3], v + IF1ID3); ++ ++ c->reg.if1id[2] = 0x00; ++ writeb(c->reg.if1id[2], v + IF1ID2); ++ ++ c->reg.if1id[1] = 0x00; ++ writeb(c->reg.if1id[1], v + IF1ID1); ++ ++ c->reg.if1id[0] = 0x00; ++ writeb(c->reg.if1id[0], v + IF1ID0); ++ ++ c->reg.if1mask[3] = 0x00; ++ writeb(c->reg.if1mask[3], v + IF1MASK3); ++ ++ c->reg.if1mask[2] = 0x00; ++ writeb(c->reg.if1mask[2], v + IF1MASK2); ++ ++ c->reg.if1mask[1] = 0x00; ++ writeb(c->reg.if1mask[1], v + IF1MASK1); ++ ++ c->reg.if1mask[0] = 0x00; ++ writeb(c->reg.if1mask[0], v + IF1MASK0); ++ ++ /* Transfer Control and ID bits */ ++ c->reg.if1cmask = 0xF8; ++ writeb(c->reg.if1cmask, v + IF1CMASK); ++ ++ c->reg.if1mcont[0] = 0x80; /* EOB = 1 */ ++ writeb(c->reg.if1mcont[0], v + IF1MCONT0); ++ ++ c->reg.if1mcont[1] = 0x14; /* this MsgObj trig. Int on Rx */ ++ writeb(c->reg.if1mcont[1], v + IF1MCONT1); ++ ++ c->reg.if1creq = CAN_EXT_RX_BUFFER; ++ writeb(c->reg.if1creq, v + IF1CREQ); ++ ++ /* Wait till everything has been written */ ++ while ((c->reg.if1busy = readb(v + IF1BUSY) & 0x80)) ; ++ ++ c->reg.cancont = readl(v + CANCONT); ++ c->reg.cancont |= CONT_FLAG_IE + CONT_FLAG_SIE + CONT_FLAG_EIE; ++ writeb(c->reg.cancont, v + CANCONT); ++ ++ /*End Init */ ++ c->reg.cancont = readb(v + CANCONT); ++ c->reg.cancont &= ~CONT_FLAG_INIT; ++ writeb(c->reg.cancont, v + CANCONT); ++ ++ /* store baudrate default 125 kBit/sec */ ++ c->baudrate = (unsigned short)set_baudrate(c, 125); ++ ++ /* reset overrun counter */ ++ c->overrun = 0; ++} ++ ++static irqreturn_t oki_irqhandler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ unsigned short int_type = 0; ++ unsigned short i; ++ unsigned char stat_reg, k; ++ struct can_msg msg; ++ struct can_device *c = dev_id; ++ unsigned long v = (unsigned long)c->virt_addr_can; ++ int minor = c->minor; ++ unsigned long flags; ++ int irq_count = 0; ++ ++ spin_lock_irqsave(&c->can_lock, flags); ++ ++ /* ++ * read can interrupt register1, ++ * we only want to detect if it is a status interrupt! ++ */ ++ int_type += (readb(v + CANINT1) << 8); ++ ++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ 0x%x occured, virt addr:0x%08x\n",minor,int_type,v); ++ ++ /* STATUS IRQ */ ++ if (int_type & 0x8000) { ++ c->reg.canstat = stat_reg = readb(v + CANSTAT); ++ c->reg.canstat = 0x00; ++ writeb(c->reg.canstat, v + CANSTAT); ++ ++ DBG_OKI(KERN_ERR, "/dev/can%d IRQ is STATUS IRQ BSTAT is 0x%x\n",minor,stat_reg); ++ ++ /*if ((stat_reg & 0xE0) == 0xE0) */ ++ /* changed back to get bus off state */ ++ if ((stat_reg & 0x80) == 0x80) { ++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is BUS OFF\n",minor); ++ /* set "Bus off" flag */ ++ c->status |= CAN_STS_BUS_OFF; ++ /* clear flag */ ++ c->status &= ~CAN_STS_TXOK; ++ ++ c->last_error_code = 10; ++ } else { ++ /* clear "Bus off" flag */ ++ c->status &= ~CAN_STS_BUS_OFF; ++ } ++ ++ if ((stat_reg & 0x60) == 0x60) { ++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS CAN_STS_WARNING %x \n",minor,(stat_reg & 0x7)); ++ c->last_error_code = (stat_reg & 0x7); ++ /* set WARNING flag */ ++ c->status |= CAN_STS_WARNING; ++ } else { ++ /* clear WARNING flag */ ++ c->status &= ~CAN_STS_WARNING; ++ } ++ ++ /* TXOK */ ++ if ((stat_reg & 0x08) == 0x08) { ++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS TXOK\n",minor); ++ ++ /* clear error */ ++ c->last_error_code_write = 0; ++ /* clear error --> no error */ ++ c->last_error_code = 0; ++ /* clear error var for debug */ ++ c->last_error_code_debug = 0; ++ } ++ ++ /* ROK */ ++ if ((stat_reg & 0x10) == 0x10) { ++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS IRQ RXOK\n",minor); ++ ++ /* clear error --> no error */ ++ c->last_error_code = 0; ++ /* clear error var for debug */ ++ c->last_error_code_debug = 0; ++ } ++ ++ if((c->last_error_code >= 1 && c->last_error_code <= 7) || c->last_error_code == 10){ ++ if(c->last_error_code < 10 && ((stat_reg & 0x80) == 0x80) && (c->last_error_code != c->last_error_code_debug)){ ++ c->last_error_code_debug = 10; ++ DBG_OUT(KERN_ERR, ": /dev/can%d Error BUS OFF, do ioctl STATUS\n",minor); ++ ++ } ++ ++ if (c->last_error_code != c->last_error_code_debug) { ++ c->last_error_code_debug = c->last_error_code; ++ DBG_OUT(KERN_ERR, ": /dev/can%d %s\n",minor,err[c->last_error_code]); ++ } ++ ++ if (c->last_error_code > 0) { ++ /* switch off controller, warning state is higher than 1 */ ++ /* so CAN message has a form error or was not */ ++ /* acknwledged by other devices or we are in bus off state */ ++ activate(c, CAN_STS_CNTRL_OFF); ++ } ++ goto out; ++ } ++ ++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS IRQ END \n",minor); ++ } ++ ++ /* read next IRQ */ ++ /* only read can interrupt register0, we don't want detect a status interrupt here! */ ++ int_type = readb(v + CANINT0); ++ ++ while (int_type && (irq_count++ < OKI_CAN_MAX_IRQS)) { ++ switch (int_type) { ++ case CAN_TX_BUFFER: ++ case CAN_RTX_BUFFER: ++ ++ DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_TX_BUFFER/CAN_RTX_BUFFER IRQ 0x%x\n",minor,int_type); ++ while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ; ++ ++ /* Clear Int Pnd */ ++ c->reg.if1cmask = 0x08; ++ writeb(c->reg.if1cmask, v + IF1CMASK); ++ ++ c->reg.if1creq = (unsigned char)int_type; ++ writeb(c->reg.if1creq, v + IF1CREQ); ++ ++ CAN_DEBUG(IF1CMASK,"CAN_TX_BUFFER/CAN_RTX_BUFFER IF1CMASK"); ++ CAN_DEBUG(IF1CREQ,"CAN_TX_BUFFER/CAN_RTX_BUFFER IF1CREQ"); ++ ++ /* Wait till everything has been written */ ++ while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ; ++ c->status |= CAN_STS_TXOK; ++ c->tx_in_progress = 0; ++ DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_TX_BUFFER/CAN_RTX_BUFFER IRQ 0x%x END\n",minor,int_type); ++ break; ++ case CAN_STD_RX_BUFFER_START: ++ case 2: ++ case 3: ++ case 4: ++ case 5: ++ case 6: ++ case 7: ++ case 8: ++ case 9: ++ case 10: ++ case 11: ++ case CAN_STD_RX_BUFFER_END: ++ DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_STD_RX_BUFFER_START/CAN_STD_RX_BUFFER_END IRQ 0x%x\n",minor,int_type); ++ do { ++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80); ++ /* Get all unsigned chars */ ++ c->reg.if2cmask = 0x3F; ++ writeb(c->reg.if2cmask, v + IF2CMASK); ++ c->reg.if2creq = (unsigned char)int_type; ++ writeb(c->reg.if2creq, v + IF2CREQ); ++ ++ /* Wait till everything has been written */ ++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80); ++ /* is NewData set? */ ++ if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x80) { ++ /* Extended Frame? */ ++ if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x40) ++ msg.ext = 1; ++ else ++ msg.ext = 0; ++ ++ msg.dlc = ((c->reg.if2mcont[0] = readb(v + IF2MCONT0)) & 0x0F); ++ msg.id = (((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x1F) << 6); ++ msg.id += ((c->reg.if2id[2] = readb(v + IF2ID2)) >> 2); ++ ++ k = (unsigned char)((msg.dlc <= 8) ? (msg.dlc) : 8); ++ for (i = 0; i < k; i++) ++ msg.data[i] = c->reg.if2data[i] = readb(v + IF2DATA0 +i); ++ ++ /* Is MsgLost set? */ ++ if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x40) ++ c->status |= CAN_STS_OVERRUN; ++ else ++ c->status &= ~CAN_STS_OVERRUN; ++ /* is DIR set? */ ++ if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x20) ++ msg.rtr = 1; ++ else ++ msg.rtr = 0; ++ /* clear MsgLst */ ++ c->reg.if2mcont[1] &= 0xBF; ++ writeb(c->reg.if2mcont[1], v + IF2MCONT1); ++ c->reg.if2cmask = 0x10; ++ writeb(c->reg.if2cmask, v + IF2CMASK); ++ c->reg.if2creq = (unsigned char)int_type; ++ writeb(c->reg.if2creq, v + IF2CREQ); ++ ++ /* Wait till everything has been written */ ++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80); ++ ++ /* Store Data */ ++ store_data_in_buffer(c,&msg); ++ } else { ++ /* exit while loop */ ++ break; ++ } ++ int_type++; ++ } ++ while (int_type <= CAN_STD_RX_BUFFER_END); ++ DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_STD_RX_BUFFER_START/CAN_STD_RX_BUFFER_END IRQ 0x%x\n",minor,int_type); ++ break; ++ /* Extended Frames */ ++ case CAN_EXT_RX_BUFFER: ++ DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_EXT_RX_BUFFER IRQ 0x%x\n",minor,int_type); ++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80); ++ /* Get all unsigned chars */ ++ c->reg.if2cmask = 0x3F; ++ writeb(c->reg.if2cmask, v + IF2CMASK); ++ c->reg.if2creq = (unsigned char)int_type; ++ writeb(c->reg.if2creq, v + IF2CREQ); ++ /* Wait till everything has been written */ ++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80) ; ++ /* is NewData set? */ ++ if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x80) { ++ /* Extended Frame? */ ++ if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x40) ++ msg.ext = 1; ++ else ++ msg.ext = 0; ++ ++ msg.dlc = ((c->reg.if2mcont[0] = readb(v + IF2MCONT0)) & 0x0F); ++ msg.id = c->reg.if2id[0] = readb(v + IF2ID0); ++ msg.id += ((c->reg.if2id[1] = readb(v + IF2ID1)) << 8); ++ msg.id += ((c->reg.if2id[2] = readb(v + IF2ID2)) << 16); ++ msg.id += (((c->reg.if2id[3] = readb(v + IF2ID2)) & 0x1F) << 24); ++ ++ k = (unsigned char)((msg.dlc <= 8) ? (msg.dlc) : 8); ++ for (i = 0; i < k; i++) ++ msg.data[i] = c->reg.if2data[i] = readb(v + IF2DATA0 + i); ++ /* Is MsgLost set? */ ++ if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x40) ++ c->status |= CAN_STS_OVERRUN; ++ else ++ c->status &= ~CAN_STS_OVERRUN; ++ ++ /* clear MsgLst */ ++ c->reg.if2mcont[1] &= 0xBF; ++ writeb(c->reg.if2mcont[1], v + IF2MCONT1); ++ c->reg.if2cmask = 0x10; ++ writeb(c->reg.if2cmask, v + IF2CMASK); ++ c->reg.if2creq = (unsigned char)int_type; ++ writeb(c->reg.if2creq, v + IF2CREQ); ++ ++ /* Wait till everything has been written */ ++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80); ++ /* Store Data */ ++ store_data_in_buffer(c, &msg); ++ } ++ DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_EXT_RX_BUFFER IRQ 0x%x\n",minor,int_type); ++ break; ++ default: ++ DBG_OKI(KERN_ERR, " /dev/can%d IRQ is default 0x%x\n",minor,int_type); ++ goto out; ++ break; ++ } ++ /* read next IRQ */ ++ /* only read can interrupt register0, we don't want detect a status interrupt here! */ ++ int_type = readb(v + CANINT0); ++ } /* while */ ++out: ++ spin_unlock_irqrestore(&c->can_lock, flags); ++ return IRQ_HANDLED; ++} ++ ++static struct file_operations oki_fops = { ++ .owner = THIS_MODULE, ++ .read = oki_read, ++ .write = oki_write, ++ .ioctl = oki_ioctl, ++ .open = oki_open, ++ .release = oki_release, ++ .poll = oki_poll, ++}; ++ ++int oki_read(struct file *file, char *buf, size_t count, loff_t * ppos) ++{ ++ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); ++ struct can_device *c = info_can[minor]; ++ int ret = 0; ++ int i, tmp; ++ ++ if (count < sizeof(struct can_msg)) ++ return -EINVAL; ++ ++ if ((c->head == c->tail) && (file->f_flags & O_NONBLOCK)) ++ return -EAGAIN; ++ ++ ret = wait_event_interruptible(c->rx_waitq, c->head != c->tail); ++ if (ret) ++ return -ERESTARTSYS; ++ ++ for (i = 0; i < (count / sizeof(struct can_msg)); i++) { ++ if (c->head == c->tail) ++ break; ++ ++ tmp = copy_to_user(buf, &c->head->msg, sizeof(struct can_msg)); ++ if (tmp > 0) { ++ printk("copy_to_user could not copy %d bytes", ret); ++ ret = -EIO; ++ } else { ++ buf += sizeof(struct can_msg); ++ ret += sizeof(struct can_msg); ++ } ++ ++ c->head = c->head->next; ++ kfree(c->head->prev); ++ } ++ ++ return ret; ++} ++ ++int oki_write(struct file *file, const char *buf, size_t count, loff_t * ppos) ++{ ++ unsigned char i; /* counter, temp var */ ++ unsigned char k; /* counter */ ++ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); ++ struct can_device *c = info_can[minor]; ++ unsigned long v = (unsigned long)c->virt_addr_can; ++ struct can_msg tmp; ++ struct can_msg *txbuf = &tmp; ++ ++ if (!buf || !count) ++ return 0; ++ ++ /* be stricter than in read here, require multiples of whole msgs */ ++ if (count % sizeof(struct can_msg)) { ++ printk("count must be N * sizeof(struct can_msg)!\n"); ++ return -EINVAL; ++ } ++ ++ /* ++ * This can be removed as soon as we have implemented support for ++ * writing multiple messages ++ */ ++ if (count != sizeof(struct can_msg)) { ++ printk("FIXME: support writing multiple messages at once!\n"); ++ return -EINVAL; ++ } ++ ++ if (0 != copy_from_user(txbuf, buf, count)) { ++ printk("%s: Error: copy from user failed!\n", __FUNCTION__); ++ return -EIO; ++ } ++ ++ DBG_OKI(KERN_ERR, ": WRITE minor %d\n", c->minor); ++ DBG_OKI(KERN_ERR, ": WRITE virt 0x%x\n", c->virt_addr_can); ++ DBG_OKI(KERN_ERR, ": WRITE id %d\n", txbuf->id); ++ DBG_OKI(KERN_ERR, ": WRITE dlc %d\n", txbuf->dlc); ++ DBG_OKI(KERN_ERR, ": WRITE rtr %d\n", txbuf->rtr); ++ DBG_OKI(KERN_ERR, ": WRITE ext %d\n", txbuf->ext); ++ for (i = 0; i < 8; i++) ++ DBG_OKI(KERN_ERR, ": WRITE data[%d] %d\n", i, txbuf->data[i]); ++ ++ c->reg.cancont = readb(v + CANCONT); ++ ++ CAN_DEBUG(CANCONT, "CANCONT"); ++ ++ if ((c->reg.cancont & CONT_FLAG_INIT) == CONT_FLAG_INIT) { ++ if (c->last_error_code_write < 1) { ++ c->last_error_code_write = 1; ++ DBG_OUT(KERN_ERR, ": /dev/can%d not initalised or switched off, do ioctl: COMMAND CAN_STS_CNTRL_ON \n",minor ); ++ } ++ return -EAGAIN; ++ } ++ ++ /* Check the status, so we can handle warning and bus off state */ ++ check_status(c); ++ ++ if (c->status == CAN_STS_WARNING) { ++ if (c->last_error_code_write < 2) { ++ c->last_error_code_write = 2; ++ DBG_OUT(KERN_ERR, ": /dev/can%d is in WARNING State, do ioctl STATUS\n",minor ); ++ } ++ return -EAGAIN; ++ } ++ ++ if (c->status == CAN_STS_BUS_OFF) { ++ if (c->last_error_code_write < 3) { ++ c->last_error_code_write = 3; ++ DBG_OUT(KERN_ERR, ": /dev/can%d is in BUS OFF State, do ioctl STATUS\n",minor ); ++ } ++ return -EAGAIN; ++ } ++ ++ c->status &= ~CAN_STS_TXOK; ++ ++ /* Wait till everything has been written */ ++ if (c->tx_in_progress) { ++ DBG_OKI(KERN_ERR, ": WRITE CAN%d BUSY\n", minor); ++ return -EBUSY; ++ } else { ++ c->tx_in_progress = 1; ++ CAN_DEBUG(IF1BUSY, " WRITE 2 for while IF1BUSY"); ++ while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ; ++ ++ /* set, so that ID Register will get transfered */ ++ c->reg.if1cmask = 0xB7; ++ writeb(c->reg.if1cmask, v + IF1CMASK); ++ CAN_DEBUG(IF1CMASK, " WRITE 3 for while IF1CMASK"); ++ } ++ ++ if (txbuf->ext == 0) { ++ /* DIR and WR */ ++ c->reg.if1id[3] = 0xA0; ++ c->reg.if1id[3] |= (unsigned char)((txbuf->id >> 6) & 0x1F); ++ DBG_OKI(KERN_ERR, "WRITE c->reg.if1id[3] 0x%x\n",c->reg.if1id[3]); ++ writeb(c->reg.if1id[3], v + IF1ID3); ++ CAN_DEBUG(IF1ID3, " WRITE 4 IF1ID3"); ++ c->reg.if1id[2] = (unsigned char)((txbuf->id << 2) & 0xFC); ++ DBG_OKI(KERN_ERR, "WRITE c->reg.if1id[2] 0x%x\n",c->reg.if1id[2]); ++ writeb(c->reg.if1id[2], v + IF1ID2); ++ CAN_DEBUG(IF1ID2, "WRITE 4 IF1ID2"); ++ } else { ++ /* extended Frame */ ++ c->reg.if1id[3] = 0xE0; ++ c->reg.if1id[3] += (unsigned char)((txbuf->id >> 24) & 0x1F); ++ c->reg.if1id[2] = (unsigned char)((txbuf->id >> 16) & 0xFF); ++ c->reg.if1id[1] = (unsigned char)((txbuf->id >> 8) & 0xFF); ++ c->reg.if1id[0] = (unsigned char)(txbuf->id & 0xFF); ++ writeb(c->reg.if1id[3], v + IF1ID3); ++ CAN_DEBUG(IF1ID3, "WRITE 4 IF1ID3"); ++ writeb(c->reg.if1id[2], v + IF1ID2); ++ CAN_DEBUG(IF1ID2, "WRITE 4 IF1ID2"); ++ writeb(c->reg.if1id[1], v + IF1ID1); ++ CAN_DEBUG(IF1ID1, "WRITE 4 IF1ID1"); ++ writeb(c->reg.if1id[0], v + IF1ID0); ++ CAN_DEBUG(IF1ID1, "WRITE 4 IF1ID1"); ++ } ++ ++ k = (unsigned char)(((txbuf->dlc) <= 8) ? (txbuf->dlc) : 8); ++ for (i = 0; i < k; i++) { ++ c->reg.if1data[i] = txbuf->data[i]; ++ writeb(c->reg.if1data[i], v + IF1DATA0 + i); ++ DBG_OKI(KERN_ERR, ": WRITE in for data[%d] %d\n",i,txbuf->data[i]); ++ CAN_DEBUG(IF1DATA0 + i, "WRITE 4 IF1DATA0 + i"); ++ } ++ /* End of Buffer (EOB) */ ++ ++ c->reg.if1mcont[0] = 0x80 + (txbuf->dlc & 0x0F); ++ DBG_OKI(KERN_ERR, ": WRITE 5 if1mcont[0] 0x%x\n", c->reg.if1mcont[0]); ++ writeb(c->reg.if1mcont[0], v + IF1MCONT0); ++ CAN_DEBUG(IF1MCONT0, "WRITE 5 IF1MCONT0"); ++ ++ if (txbuf->rtr == 1) { ++ c->reg.if1id[3] &= 0xDF; ++ DBG_OKI(KERN_ERR, ": WRITE 6 if1id[3] 0x%x\n", c->reg.if1id[3]); ++ writeb(c->reg.if1id[3], v + IF1ID3); ++ CAN_DEBUG(IF1ID3, "WRITE 6 IF1ID3"); ++ /* TXIE, TXRqst and RXIE */ ++ c->reg.if1mcont[1] = 0x0D; ++ DBG_OKI(KERN_ERR, ": WRITE 6 if1mcont[1] 0x%x\n",c->reg.if1mcont[1]); ++ writeb(c->reg.if1mcont[1], v + IF1MCONT1); ++ CAN_DEBUG(IF1MCONT1, "WRITE 6 IF1MCONT1"); ++ c->reg.if1creq = CAN_RTX_BUFFER; ++ DBG_OKI(KERN_ERR, ": WRITE 6 if1creq 0x%x\n", c->reg.if1creq); ++ writeb(c->reg.if1creq, v + IF1CREQ); ++ CAN_DEBUG(IF1CREQ, "WRITE 6 IF1CREQ"); ++ } else { ++ c->reg.if1mcont[1] = 0x09; ++ DBG_OKI(KERN_ERR, ": WRITE 6 if1mcont[1] 0x%x\n",c->reg.if1mcont[1]); ++ writeb(c->reg.if1mcont[1], v + IF1MCONT1); ++ CAN_DEBUG(IF1MCONT1, "WRITE 6 IF1MCONT1"); ++ c->reg.if1creq = CAN_TX_BUFFER; ++ DBG_OKI(KERN_ERR, ": WRITE 6 if1creq 0x%x\n", c->reg.if1creq); ++ writeb(c->reg.if1creq, v + IF1CREQ); ++ CAN_DEBUG(IF1CREQ, "WRITE 6 IF1CREQ"); ++ } ++ return count; ++} ++ ++int oki_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ unsigned int minor = iminor(inode); ++ struct can_device *c = info_can[minor]; /* better ideas than using globals anyone? */ ++ int ret = -ENOIOCTLCMD; ++ int new_options = 0; ++ void __user *argp = (void __user *)arg; ++ int __user *p = argp; ++ int cntr_ret; ++ ++ switch (cmd) { ++ case COMMAND: ++ { ++ if (get_user(new_options, p) != 0) ++ return -EFAULT; ++ ++ DBG_OKI(KERN_ERR, ": IOCTL COMMAND WITH %d\n", new_options); ++ cntr_ret = activate(c, new_options); ++ if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0) ++ return 0; ++ else ++ return ret; ++ ++ break; ++ } ++ case CONFIG: ++ { ++ if (get_user(new_options, p) != 0) ++ return -EFAULT; ++ ++ cntr_ret = set_baudrate(c, new_options); ++ if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0) ++ return 0; ++ else ++ return ret; ++ ++ break; ++ } ++ case SEND: ++ break; ++ case RECEIVE: ++ break; ++ case STATUS: ++ { ++ int cntr_ret; ++ /* Check status */ ++ cntr_ret = check_status(c); ++ if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0) ++ return 0; ++ else ++ return ret; ++ break; ++ } ++ default: ++ return -ENOIOCTLCMD; ++ break; ++ } ++ ++ return -ENOIOCTLCMD; ++} ++ ++static unsigned int oki_poll(struct file *file, poll_table * wait) ++{ ++ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); ++ struct can_device *c = info_can[minor]; ++ unsigned int mask = 0; ++ ++ poll_wait(file, &c->rx_waitq, wait); ++ if (c->head != c->tail) ++ mask |= POLLIN | POLLRDNORM; ++ return mask; ++} ++ ++int check_status(struct can_device *c) ++{ ++ int stat_reg; ++ unsigned long v = (unsigned long)c->virt_addr_can; ++ ++ stat_reg = readb(v + CANSTAT); ++ DBG_OKI(KERN_DEBUG, "check_status canstat 0x%x\n", stat_reg); ++ ++ /* Bus is in "Error Passive" state */ ++ if ((stat_reg & 0x20) == 0) { ++ c->status &= ~CAN_STS_WARNING; ++ c->status &= ~CAN_STS_BUS_OFF; ++ } ++ ++ if ((stat_reg & 0x60) == 0x60) { ++ if (c->last_error_code != (stat_reg & 0x7)) { ++ c->last_error_code = (stat_reg & 0x7); ++ } ++ c->status |= CAN_STS_WARNING; ++ } ++ ++ if ((stat_reg & 0x80) == 0x80) { ++ if (c->last_error_code < 10) { ++ c->last_error_code = 10; ++ } ++ c->status |= CAN_STS_BUS_OFF; ++ } ++ ++ /* clear overrun */ ++ c->status &= ~CAN_STS_OVERRUN; ++ return c->status; ++} ++ ++int activate(struct can_device *c, unsigned char new_status) ++{ ++ unsigned long v = (unsigned long)c->virt_addr_can; ++ ++ switch (new_status) { ++ case CAN_STS_CNTRL_OFF: ++ do { ++ c->reg.cancont |= CONT_FLAG_INIT; ++ writeb(c->reg.cancont, v + CANCONT); ++ } ++ while (!((c->reg.cancont = readb(v + CANCONT)) & CONT_FLAG_INIT)); ++ ++ c->status |= CAN_STS_RESET; ++ ++ DBG_OKI(KERN_DEBUG, " /dev/can%d activate CAN_STS_CNTRL_OFF CANCONT 0x%x\n",c->minor,c->reg.cancont); ++ break; ++ case CAN_STS_CNTRL_ON: ++ do { ++ c->reg.cancont &= ~CONT_FLAG_INIT; ++ writeb(c->reg.cancont, v + CANCONT); ++ } ++ while (((c->reg.cancont = readb(v + CANCONT)) & CONT_FLAG_INIT)); ++ ++ c->status &= ~CAN_STS_RESET; ++ ++ DBG_OKI(KERN_DEBUG, " /dev/can%d activate CAN_STS_CNTRL_ON CANCONT 0x%x\n",c->minor,c->reg.cancont); ++ break; ++ case CAN_STS_CNTRL_SLEEP: ++ break; ++ case CAN_STS_CNTRL_AWAKE: ++ break; ++ default: ++ break; ++ } ++ ++ return c->status; ++} ++ ++int oki_open(struct inode *inode, struct file *file) ++{ ++ unsigned int minor = iminor(inode); ++ struct can_device *c = info_can[minor]; /* better ideas than using globals anyone? */ ++ ++ if (!atomic_dec_and_test(&c->can_opened)) { ++ DBG_OUT(KERN_ERR, ": /dev/can%d already opened.\n", minor); ++ atomic_inc(&c->can_opened); ++ return -EBUSY; ++ } ++ return 0; ++} ++ ++int oki_release(struct inode *inode, struct file *file) ++{ ++ unsigned int minor = iminor(inode); ++ struct can_device *c = info_can[minor]; /* better ideas than using globals anyone? */ ++ ++ atomic_dec(&c->can_opened); ++ if (!atomic_inc_and_test(&c->can_opened)) { ++ DBG_OUT(KERN_ERR, ": /dev/can%d open, busy.\n", minor); ++ return -EBUSY; ++ } ++ ++ atomic_inc(&c->can_opened); ++ return 0; ++} ++ ++int can_register(struct can_device *c) ++{ ++ atomic_set(&c->can_opened, 1); ++ ++ /* map memory */ ++ c->virt_addr_can = ioremap(c->phys_addr_can, c->phys_size_can); ++ if (!c->virt_addr_can) { ++ DBG_OUT(KERN_ERR, ": Unable to remap /dev/can%d memory.\n", c->minor); ++ return -ENOMEM; ++ } ++ ++ DBG_OUT(KERN_INFO, ": remap /dev/can%d memory physical 0x%x to virtual 0x%x.\n",c->minor,c->phys_addr_can,c->virt_addr_can); ++ ++ /* Message buffers */ ++ c->tail = kzalloc(sizeof(struct recbuf), GFP_KERNEL); ++ c->head = c->tail; ++ ++ /* CAN init */ ++ hw_init(c); ++ ++ /* waitq init */ ++ init_waitqueue_head(&c->rx_waitq); ++ ++ /* Install IRQ handler */ ++ if(0 != request_irq(c->irq, oki_irqhandler, c->irq_flags, "OKI_CAN", (void *)c)){ ++ DBG_OUT(KERN_ERR, ": /dev/can%d cannot install IRQ-handler\n",c->minor); ++ return -ENOMEM; ++ } ++ ++ DBG_OUT(KERN_INFO, ": /dev/can%d IRQ-handler installed.\n", c->minor); ++ ++ return 0; ++} ++ ++int __init oki_init(void) ++{ ++ can_register(info_can[0]); ++#ifdef CONFIG_OKI_CAN_ML9620_2DEV ++ can_register(info_can[1]); ++#endif ++ ++ /* Register char device */ ++ if (register_chrdev(OKI_CAN_CHAR_MAJOR, OKI_CAN_DEVICE_NAME, &oki_fops)) { ++ DBG_OUT(KERN_ERR, "Can't allocate major number %d for CAN driver.\n",OKI_CAN_CHAR_MAJOR); ++ return -EIO; ++ } ++ ++ DBG_OUT(KERN_INFO, ": Version: " OKI_CAN_VERSION " registered successfully.\n"); ++ /*DBG_OUT(KERN_INFO, "Installed %d IRQ handlers for %d CAN devices.\n",irq_nr,can_dev); */ ++ ++ printk(KERN_INFO "Contec Steuerungstechnik und Automation Ges.m.b.H\n"); ++ printk(KERN_INFO "Waldeck 1 / 6330 Kufstein / Austria\n"); ++ ++ return 0; ++} ++ ++module_init(oki_init); ++ ++void unregister_can(struct can_device *c) ++{ ++ DBG_OUT(KERN_INFO, ": unregister /dev/can%d .\n", c->minor); ++ free_irq(c->irq, (void *)c); ++ ++ if (c->virt_addr_can != NULL) { ++ iounmap(c->virt_addr_can); ++ } else { ++ DBG_OUT(KERN_ERR, ": /dev/can%d was not mapped, skipping iounmap!\n", c->minor); ++ } ++} ++ ++void __exit oki_exit(void) ++{ ++ unregister_can(info_can[0]); ++#ifdef CONFIG_OKI_CAN_ML9620_2DEV ++ unregister_can(info_can[1]); ++#endif ++ unregister_chrdev(OKI_CAN_CHAR_MAJOR, OKI_CAN_DEVICE_NAME); ++} ++ ++module_exit(oki_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Manfred Gruber <manfred.gruber@contec.at>"); ++MODULE_DESCRIPTION("OKI ML9620 CAN Driver"); +diff --git a/drivers/char/can/oki_ml9620.h b/drivers/char/can/oki_ml9620.h +new file mode 100644 +index 0000000..f8ece1e +--- /dev/null ++++ b/drivers/char/can/oki_ml9620.h +@@ -0,0 +1,397 @@ ++/* ++ * drivers/char/can/oki_ml9620_core.h ++ * ++ * OKI ML9620 CAN Controler driver ++ * ++ * Author: Manfred Gruber <manfred.gruber@contec.at> ++ * ++ * Copyright 2004 (c) Manfred Gruber ++ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H ++ * Kufstein/Austria www.contec.at ++ * ++ * This driver was written for Contec Hypercontrol Micro9 Board: ++ * 1. CAN Controller is on Hypercontrol Micro9 CPU board ++ * 2. CAN Controller is on Hypercontrol Micro9 Eval board ++ * ++ * Contec uses this driver on their Hypercontrol Micro9 boards based on ++ * Cirrus Logic EP93XX,we have changed Adr-/Databus timinig to use OKI ML9620. ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ * ++ */ ++ ++#ifndef _OKI_ML9620_CORE_H_ ++#define _OKI_ML9620_CORE_H_ ++ ++#include <linux/can/oki_ml9620_ctrl.h> ++#include <linux/kernel.h> ++ ++#define OKI_CAN_CHAR_MAJOR 91 ++#define OKI_CAN_DEVICE_NAME "oki_ml9260" ++#define OKI_CAN_VERSION "0.08" ++ ++#define OKI_CAN_MAX_IRQS 20 ++#define PHYS_SIZE_CAN 0x00000100 ++ ++/* Contec */ ++#ifdef CONFIG_OKI_CAN_ML9620_MICRO9 ++#define CAN_CLOCK_8MHZ ++#define PHYS_ADDR_CAN0 0x20000000 ++#define PHYS_ADDR_CAN1 0x21000000 ++#define IRQ_CAN0 GPIO_IRQ4 ++#define IRQ_CAN1 GPIO_IRQ10 ++#ifdef CONFIG_GENERIC_HARDIRQS ++#define IRQ_FLAGS_CAN0 (SA_INTERRUPT) ++#define IRQ_FLAGS_CAN1 (SA_INTERRUPT) ++#else ++#define IRQ_FLAGS_CAN0 (SA_INTERRUPT | SA_SHIRQ) ++#define IRQ_FLAGS_CAN1 (SA_INTERRUPT | SA_SHIRQ) ++#endif ++#endif /* CONFIG_OKI_CAN_ML9620_MICRO9 */ ++ ++/* Gassner */ ++#ifdef CONFIG_OKI_CAN_ML9620_GASSNER ++#define CAN_CLOCK_8MHZ ++#define PHYS_ADDR_CAN0 0x10000000 ++#define PHYS_ADDR_CAN1 0x30000000 ++#define IRQ_CAN0 GPIO_IRQ6 /* Line EGPIO6 (multiplexed) */ ++#define IRQ_CAN1 GPIO_IRQ13 /* Line EGPIO13 (multiplexed) */ ++#define IRQ_FLAGS_CAN0 (SA_INTERRUPT | SA_SHIRQ) ++#define IRQ_FLAGS_CAN1 (SA_INTERRUPT | SA_SHIRQ) ++#endif /* CONFIG_OKI_CAN_ML9620_GASSNER */ ++ ++char *err[7] = { ++ "Warning 1, Stuff Error", ++ "Warning 2, Form Error", ++ "Warning 3, ACK Error", ++ "Warning 4, Bits 1 Error", ++ "Warning 5, Bits 0 Error", ++ "Warning 6, CRC Error", ++ "Warning 7, MCU has produced this Error", ++}; ++ ++#define DRIVER_MAX_MINOR 2 ++ ++struct CANML9620REG { ++ unsigned char cancont; ++ unsigned char reserve1; ++ unsigned char canstat; ++ unsigned char reserve2; ++ unsigned char cantxerrc; ++ unsigned char canrxerrc; ++ unsigned char canbitt[2]; ++ unsigned char canint[2]; ++ unsigned char canopt; ++ unsigned char reserve3; ++ unsigned char canbpre; ++ unsigned char reserve4[3]; ++ ++ unsigned char if1creq; ++ unsigned char if1busy; ++ unsigned char if1cmask; ++ unsigned char reserve5; ++ unsigned char if1mask[4]; ++ unsigned char if1id[4]; ++ unsigned char if1mcont[2]; ++ unsigned char if1data[8]; ++ unsigned char reserve6[26]; ++ ++ unsigned char if2creq; ++ unsigned char if2busy; ++ unsigned char if2cmask; ++ unsigned char reserve7; ++ unsigned char if2mask[4]; ++ unsigned char if2id[4]; ++ unsigned char if2mcont[2]; ++ unsigned char if2data[8]; ++ unsigned char reserve8[42]; ++ ++ unsigned char cantreq[4]; ++ unsigned char reserve9[12]; ++ ++ unsigned char canndata[4]; ++ unsigned char reserve10[12]; ++ ++ unsigned char canipend[4]; ++ unsigned char reserve11[12]; ++ ++ unsigned char canmval[4]; ++ unsigned char reserve12[12]; ++ ++ unsigned char canstby; ++ unsigned char reserve13[12]; ++}; ++ ++#define CANCONT 0x0 ++#define RESERVE1 0x1 ++#define CANSTAT 0x2 ++#define RESERVE2 0x3 ++#define CANTXERRC 0x4 ++#define CANRXERRC 0x5 ++#define CANBITT0 0x6 ++#define CANBITT1 0x7 ++#define CANINT0 0x8 ++#define CANINT1 0x9 ++#define CANOPT 0xA ++ ++#define CANBPRE 0xC ++ ++#define IF1CREQ 0x10 ++#define IF1BUSY 0x11 ++#define IF1CMASK 0x12 ++ ++#define IF1MASK0 0x14 ++#define IF1MASK1 0x15 ++#define IF1MASK2 0x16 ++#define IF1MASK3 0x17 ++ ++#define IF1ID0 0x18 ++#define IF1ID1 0x19 ++#define IF1ID2 0x1A ++#define IF1ID3 0x1B ++ ++#define IF1MCONT0 0x1C ++#define IF1MCONT1 0x1D ++ ++#define IF1DATA0 0x1E ++#define IF1DATA1 0x1F ++#define IF1DATA2 0x20 ++#define IF1DATA3 0x21 ++#define IF1DATA4 0x22 ++#define IF1DATA5 0x23 ++#define IF1DATA6 0x24 ++#define IF1DATA7 0x25 ++ ++#define IF2CREQ 0x40 ++#define IF2BUSY 0x41 ++#define IF2CMASK 0x42 ++ ++#define IF2MASK0 0x44 ++#define IF2MASK1 0x45 ++#define IF2MASK2 0x46 ++#define IF2MASK3 0x47 ++ ++#define IF2ID0 0x48 ++#define IF2ID1 0x49 ++#define IF2ID2 0x4A ++#define IF2ID3 0x4B ++ ++#define IF2MCONT0 0x4C ++#define IF2MCONT1 0x4D ++ ++#define IF2DATA0 0x4E ++#define IF2DATA1 0x4F ++#define IF2DATA2 0x50 ++#define IF2DATA3 0x51 ++#define IF2DATA4 0x52 ++#define IF2DATA5 0x53 ++#define IF2DATA6 0x54 ++#define IF2DATA7 0x55 ++ ++#define CANTREQ0 0x80 ++#define CANTREQ1 0x81 ++#define CANTREQ2 0x82 ++#define CANTREQ3 0x83 ++ ++#define CANNDATA0 0x90 ++#define CANNDATA1 0x91 ++#define CANNDATA2 0x92 ++#define CANNDATA3 0x93 ++ ++#define CANIPEND0 0xA0 ++#define CANIPEND1 0xA1 ++#define CANIPEND2 0xA2 ++#define CANIPEND3 0xA3 ++ ++#define CANMVAL0 0xB0 ++#define CANMVAL1 0xB1 ++#define CANMVAL2 0xB2 ++#define CANMVAL3 0xB3 ++ ++#define CANSTBY 0xC0 ++struct recbuf { ++ struct can_msg msg; ++ struct recbuf *next; ++ struct recbuf *prev; ++}; ++ ++struct can_device { ++ /* Phys addresses and size */ ++ unsigned long phys_addr_can; ++ unsigned long phys_size_can; ++ /* IRQ */ ++ unsigned int irq; ++ unsigned long irq_flags; ++ ++ /* Device node */ ++ int minor; ++ ++ /* waitqueue for read, poll */ ++ wait_queue_head_t rx_waitq; ++ ++ atomic_t can_opened; ++ ++ struct recbuf *tail; ++ struct recbuf *head; ++ ++ /* Virt addresses size */ ++ unsigned char __iomem *virt_addr_can; ++ ++ /* CAN-Baustein */ ++ struct CANML9620REG reg; ++ unsigned short baudrate; /* baudrate */ ++ unsigned short overrun; /* overrun counter */ ++ struct can_msg msg; /* CAN message buffer */ ++ int status; /* actual CAN status */ ++ int last_error_code_write; ++ unsigned char tx_in_progress; ++ unsigned char last_error_code; /* LEC */ ++ unsigned char last_error_code_debug; /* LEC when printed out */ ++ spinlock_t can_lock; ++}; ++ ++/* Global Device Struct can0 */ ++static struct can_device info_can0 = { ++ .phys_addr_can = PHYS_ADDR_CAN0, ++ .phys_size_can = PHYS_SIZE_CAN, ++ .irq = IRQ_CAN0, ++ .minor = 0, ++ .irq_flags = IRQ_FLAGS_CAN0, ++ .can_opened = ATOMIC_INIT(1), ++ .status = CAN_STS_NORMAL, ++}; ++ ++/* Global Device Struct can1 */ ++static struct can_device info_can1 = { ++ .phys_addr_can = PHYS_ADDR_CAN1, ++ .phys_size_can = PHYS_SIZE_CAN, ++ .irq = IRQ_CAN1, ++ .irq_flags = IRQ_FLAGS_CAN1, ++ .minor = 1, ++ .can_opened = ATOMIC_INIT(1), ++ .status = CAN_STS_NORMAL, ++}; ++ ++static struct can_device *info_can[] = { &info_can0, &info_can1 }; ++ ++#define NUM_MSG 32 ++ ++#define CONT_FLAG_INIT 0x01 ++#define CONT_FLAG_IE 0x02 ++#define CONT_FLAG_SIE 0x04 ++#define CONT_FLAG_EIE 0x08 ++#define CONT_FLAG_CCE 0x40 ++ ++/* message buffers */ ++ ++#define CAN_STD_RX_BUFFER_START 1 /* CAN standard receive buffer */ ++#define CAN_STD_RX_BUFFER_END 12 /* CAN standard receive buffer */ ++#define CAN_EXT_RX_BUFFER 13 /* CAN extended receive buffer */ ++ ++#define CAN_TX_BUFFER 14 /* CAN transmit buffer */ ++#define CAN_RTX_BUFFER 15 /* CAN remote frame transmit buffer */ ++ ++struct ML9620BDRATE { ++ unsigned char btiming0; ++ unsigned char btiming1; ++ unsigned char bpre; ++}; ++ ++const struct ML9620BDRATE bd_tbl[9] = { ++#ifdef CAN_CLOCK_16MHZ ++/* for 16 Mhz Quarz */ ++/* bus timing 0 | bus timing 1 */ ++/* SJW PRESCALER | SAM TSEG1 TSEG2 */ ++ {0x23, 0x1C}, /* 10K bit/s */ ++ {0x31, 0x1C}, /* 20K bit/s */ ++ {0x13, 0x1C}, /* 50K bit/s */ ++ {0x09, 0x1C}, /* 100K bit/s */ ++ {0x07, 0x1C}, /* 125K bit/s */ ++ {0x03, 0x1C}, /* 250K bit/s */ ++ {0x01, 0x1C}, /* 500K bit/s */ ++ {0x01, 0x16}, /* 800K bit/s */ ++ {0x01, 0x14} /* 1M bit/s */ ++#endif ++#ifdef CAN_CLOCK_8MHZ ++/* for 8 Mhz Quarz */ ++/* bus timing 0 | bus timing 1 */ ++/* SJW PRESCALER | SAM TSEG1 TSEG2 | CANBRPE */ ++ {0x31, 0x1C, 0x01}, /* 10K bit/s */ ++ {0x18, 0x1C, 0x00}, /* 20K bit/s */ ++ {0x09, 0x1C, 0x00}, /* 50K bit/s */ ++ {0x04, 0x1C, 0x00}, /* 100K bit/s */ ++ {0x03, 0x1C, 0x00}, /* 125K bit/s */ ++ {0x01, 0x1C, 0x00}, /* 250K bit/s */ ++ {0x00, 0x1C, 0x00}, /* 500K bit/s */ ++ {0x00, 0x16, 0x00}, /* 800K bit/s */ ++ {0x00, 0x14, 0x00} /* 1M bit/s */ ++#endif ++}; ++ ++/* DEBUG STUFF */ ++ ++#ifdef OKI_DEBUG ++#define CAN_DEBUG(REG,string) \ ++{ \ ++ DBG_OUT(KERN_ERR, " %s 0x%x\n",string,readb(v+REG)); \ ++} ++#else ++#define CAN_DEBUG(REG,string) ++#endif ++ ++#ifdef OKI_DEBUG ++#define DBG_OKI DBG_OUT ++#else ++#define DBG_OKI(...) ++#endif ++ ++int drv_dbg = 7; ++ ++void DBG_OUT(const char *type, const char *dbg_msg, ...) ++{ ++ va_list ap; ++ char buf[1024]; ++ int len; ++ unsigned int level; ++ ++ va_start(ap, dbg_msg); ++ len = vsprintf(buf, dbg_msg, ap); ++ va_end(ap); ++ buf[len] = '\0'; ++ ++ if (0 == sscanf(type, "<%i>", &level)) ++ printk(KERN_ALERT "%s", buf); ++ ++ if (level > drv_dbg) ++ return; ++ ++ switch (level) { ++ case 0: ++ printk(KERN_EMERG OKI_CAN_DEVICE_NAME "EMERG: %s", buf); ++ break; ++ case 1: ++ printk(KERN_ALERT OKI_CAN_DEVICE_NAME "%s", buf); ++ break; ++ case 2: ++ printk(KERN_CRIT OKI_CAN_DEVICE_NAME "%s", buf); ++ break; ++ case 3: ++ printk(KERN_ERR OKI_CAN_DEVICE_NAME "%s", buf); ++ break; ++ case 4: ++ printk(KERN_WARNING OKI_CAN_DEVICE_NAME "%s", buf); ++ break; ++ case 5: ++ printk(KERN_NOTICE OKI_CAN_DEVICE_NAME "%s", buf); ++ break; ++ case 6: ++ printk(KERN_INFO OKI_CAN_DEVICE_NAME "%s", buf); ++ break; ++ case 7: ++ printk(KERN_DEBUG OKI_CAN_DEVICE_NAME "%s", buf); ++ break; ++ } ++} ++#endif /* _OKI_ML9620_CORE_H_ */ +diff --git a/drivers/char/ds1337glue.c b/drivers/char/ds1337glue.c +new file mode 100644 +index 0000000..c7d168b +--- /dev/null ++++ b/drivers/char/ds1337glue.c +@@ -0,0 +1,69 @@ ++/* ++ * linux/arch/arm/mach-ep93xx/ds1337glue.c ++ * ++ * Copyright (C) 2005 Michael Burian ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * /dev/rtc interface for Dallas Semiconductor DS133[79]RTC I2C driver ++ * ++ * Also see "drivers/i2c/chips/ds1337.c" ++ * ++ */ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/rtc.h> ++#include <linux/miscdevice.h> ++#include <linux/poll.h> ++ ++#include <asm/rtc.h> ++ ++/* FIXME BEGIN: include this from "ds1337.h" as soon as there exists one */ ++#warning FIXME: no official ds1337 interface available, hardcoding defaults. ++#define DS1337_GET_DATE 0 ++#define DS1337_SET_DATE 1 ++extern int ds1337_do_command(int bus, int cmd, void *arg); ++/* FIXME END */ ++ ++static int rtc_read_time(struct rtc_time *tm) ++{ ++ return ds1337_do_command(0, DS1337_GET_DATE, (void*)(tm)); ++} ++ ++static int rtc_set_time(struct rtc_time *tm) ++{ ++ return ds1337_do_command(0, DS1337_SET_DATE, (void*)(tm)); ++} ++ ++static struct rtc_ops dma03_rtc_ops = { ++ .owner = THIS_MODULE, ++ .read_time = rtc_read_time, ++ .set_time = rtc_set_time, ++}; ++ ++static int __init rtc_interface_init(void) ++{ ++ int err; ++ printk(KERN_INFO "registering /dev/rtc interface for DS133[79]\n"); ++ ++ err = register_rtc(&dma03_rtc_ops); ++ if(err) ++ printk(KERN_ERR "could not register DS1337 /dev/rtc interface:" ++ " error=%d!\n",err); ++ ++ return err; ++} ++ ++static void __exit rtc_interface_exit(void) ++{ ++ unregister_rtc(&dma03_rtc_ops); ++} ++ ++MODULE_AUTHOR("Michael Burian"); ++MODULE_DESCRIPTION("/dev/rtc interface for ds1337.c"); ++MODULE_LICENSE("GPL"); ++ ++module_init(rtc_interface_init); ++module_exit(rtc_interface_exit); +diff --git a/drivers/char/ep93xx-rtc.c b/drivers/char/ep93xx-rtc.c +new file mode 100644 +index 0000000..399d0b0 +--- /dev/null ++++ b/drivers/char/ep93xx-rtc.c +@@ -0,0 +1,376 @@ ++/* ++ * Real Time Clock for Cirrus EP93xx ++ * ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * ++ * Support for realtime clock device on the Cirrus ++ * EP93xx family of devices. ++ * ++ * Based on rtc.c, and other rtc drivers. ++ */ ++ ++#include <linux/config.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/errno.h> ++#include <linux/module.h> ++#include <linux/sysctl.h> ++#include <linux/rtc.h> ++#include <linux/poll.h> ++#include <linux/miscdevice.h> ++ ++#include <asm/io.h> ++#include <asm/arch/regmap.h> ++ ++#define RTC_VERSION "0.01" ++ ++#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ ++ ++extern spinlock_t rtc_lock; /* seems to be only present in older rtc header? */ ++static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED; ++static rtc_task_t *rtc_callback = NULL; ++static unsigned long rtc_status = 0; ++static unsigned long rtc_irq_data = 0; ++static DECLARE_WAIT_QUEUE_HEAD(rtc_wait); ++ ++/* ++ * the 1 Hz real time interrupt ++ */ ++ ++irqreturn_t interrupt_1hz(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ static unsigned long x = 0; ++ static int i = 0; ++ ++ rtc_irq_data += 0x100; ++ rtc_irq_data &= ~0xff; ++ ++ wake_up_interruptible(&rtc_wait); ++ ++ printk(KERN_ERR); ++ printk(" delta: %04ld", jiffies - x); ++ printk(" data: %08x", readl(RTCDR)); ++ printk(" match: %08x", readl(RTCMR)); ++ printk(" stat: %08x", readl(RTCSTAT)); ++ printk(" load: %08x", readl(RTCLR)); ++ printk(" ctrl: %08x", readl(RTCCR)); ++ printk(" comp: %08x", readl(RTCSCOMP)); ++ printk("\n"); ++ ++ x = jiffies; ++ i++; ++ ++ if ((i & 0x7) == 0) { ++ writel(i << 5, RTCLR); ++ printk(KERN_ERR "NEW LOAD VALUE: %08x\n", i << 5); ++ } ++ ++ writel(0, RTCEOI); ++ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * the RTC match interrupt ++ */ ++ ++irqreturn_t interrupt_match(int irq, void *dev_id, struct pt_regs * regs) ++{ ++ return IRQ_HANDLED; ++} ++ ++/* ++ * the bulk of the usr interface is done here ++ */ ++ ++static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) ++{ ++ return -ENOSYS; ++} ++ ++/* ++ * file operations for character device node ++ */ ++ ++static ssize_t rtc_read(struct file *file, char __user * buf, size_t count, ++ loff_t * ppos) ++{ ++ unsigned long data; ++ ssize_t retval; ++ DECLARE_WAITQUEUE(wait, current); ++ ++ if (count < sizeof(unsigned int)) ++ return -EINVAL; ++ ++ add_wait_queue(&rtc_wait, &wait); ++ ++ do { ++ __set_current_state(TASK_INTERRUPTIBLE); ++ ++ spin_lock_irq(&rtc_lock); ++ data = rtc_irq_data; ++ rtc_irq_data = 0; ++ spin_unlock_irq(&rtc_lock); ++ ++ if (data != 0) ++ break; ++ ++ if (file->f_flags & O_NONBLOCK) { ++ retval = -EAGAIN; ++ goto out; ++ } ++ ++ if (signal_pending(current)) { ++ retval = -ERESTARTSYS; ++ goto out; ++ } ++ ++ schedule(); ++ } while (1); ++ ++ if (count < sizeof(unsigned long)) ++ retval = ++ put_user(data, (unsigned int __user *)buf) ? : sizeof(int); ++ else ++ retval = ++ put_user(data, ++ (unsigned long __user *)buf) ? : sizeof(long); ++ ++ out: ++ current->state = TASK_RUNNING; ++ remove_wait_queue(&rtc_wait, &wait); ++ ++ return retval; ++} ++ ++static unsigned int rtc_poll(struct file *file, poll_table * wait) ++{ ++ return -ENOSYS; ++} ++ ++static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ return rtc_do_ioctl(cmd, arg, 0); ++} ++ ++static int rtc_open(struct inode *inode, struct file *file) ++{ ++ spin_lock_irq(&rtc_lock); ++ ++ if (rtc_status & RTC_IS_OPEN) { ++ spin_unlock_irq(&rtc_lock); ++ return -EBUSY; ++ } ++ ++ rtc_status |= RTC_IS_OPEN; ++ rtc_irq_data = 0; ++ enable_irq(IRQ_1HZ); ++ ++ spin_unlock_irq(&rtc_lock); ++ return 0; ++} ++ ++static int rtc_release(struct inode *inode, struct file *file) ++{ ++ spin_lock_irq(&rtc_lock); ++ ++ disable_irq(IRQ_1HZ); ++ rtc_irq_data = 0; ++ rtc_status &= ~RTC_IS_OPEN; ++ ++ spin_unlock_irq(&rtc_lock); ++ ++ return 0; ++} ++ ++static int rtc_fasync(int fd, struct file *filp, int on) ++{ ++ return -ENOSYS; ++} ++ ++static struct file_operations rtc_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .read = rtc_read, ++ .poll = rtc_poll, ++ .ioctl = rtc_ioctl, ++ .open = rtc_open, ++ .release = rtc_release, ++ .fasync = rtc_fasync, ++}; ++ ++static struct miscdevice rtc_dev = { ++ RTC_MINOR, ++ "rtc", ++ &rtc_fops ++}; ++ ++/* ++ * sysctl-tuning infrastructure. ++ */ ++ ++int no_proc(ctl_table * table, int write, struct file *filp, ++ void __user * buffer, size_t * lenp, loff_t * ppos) ++{ ++ return -ENOSYS; ++} ++ ++static ctl_table rtc_table[] = { ++ { ++ .ctl_name = 1, ++ .procname = "max-user-freq", ++ .data = NULL, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = &no_proc, ++ }, ++ {.ctl_name = 0} ++}; ++ ++static ctl_table rtc_root[] = { ++ { ++ .ctl_name = 1, ++ .procname = "rtc", ++ .maxlen = 0, ++ .mode = 0555, ++ .child = rtc_table, ++ }, ++ {.ctl_name = 0} ++}; ++ ++static ctl_table dev_root[] = { ++ { ++ .ctl_name = CTL_DEV, ++ .procname = "dev", ++ .maxlen = 0, ++ .mode = 0555, ++ .child = rtc_root, ++ }, ++ {.ctl_name = 0} ++}; ++ ++static struct ctl_table_header *sysctl_header; ++ ++static int __init init_sysctl(void) ++{ ++ sysctl_header = register_sysctl_table(dev_root, 0); ++ return 0; ++} ++ ++static void __exit cleanup_sysctl(void) ++{ ++ unregister_sysctl_table(sysctl_header); ++} ++ ++/* ++ * Public functions from rtc.h ++ */ ++ ++EXPORT_SYMBOL(rtc_register); ++EXPORT_SYMBOL(rtc_unregister); ++EXPORT_SYMBOL(rtc_control); ++ ++int rtc_register(rtc_task_t * task) ++{ ++ if (task == NULL || task->func == NULL) ++ return -EINVAL; ++ ++ spin_lock_irq(&rtc_lock); ++ ++ if (rtc_status & RTC_IS_OPEN) { ++ spin_unlock_irq(&rtc_lock); ++ return -EBUSY; ++ } ++ ++ spin_lock(&rtc_task_lock); ++ ++ if (rtc_callback) { ++ spin_unlock(&rtc_task_lock); ++ spin_unlock_irq(&rtc_lock); ++ return -EBUSY; ++ } ++ ++ rtc_status |= RTC_IS_OPEN; ++ rtc_callback = task; ++ ++ spin_unlock(&rtc_task_lock); ++ spin_unlock_irq(&rtc_lock); ++ ++ return 0; ++} ++ ++int rtc_unregister(rtc_task_t * task) ++{ ++ spin_lock_irq(&rtc_lock); ++ spin_lock(&rtc_task_lock); ++ ++ if (rtc_callback != task) { ++ spin_unlock(&rtc_task_lock); ++ spin_unlock_irq(&rtc_lock); ++ return -ENXIO; ++ } ++ ++ /* disable PIE/AIE/UIE interrupts */ ++ ++ rtc_status &= ~RTC_IS_OPEN; ++ rtc_callback = NULL; ++ ++ spin_unlock(&rtc_task_lock); ++ spin_unlock_irq(&rtc_lock); ++ ++ return 0; ++} ++ ++int rtc_control(rtc_task_t * task, unsigned int cmd, unsigned long arg) ++{ ++ spin_lock_irq(&rtc_task_lock); ++ ++ if (rtc_callback != task) { ++ spin_unlock_irq(&rtc_task_lock); ++ return -ENXIO; ++ } ++ ++ spin_unlock_irq(&rtc_task_lock); ++ ++ return rtc_do_ioctl(cmd, arg, 1); ++} ++ ++void rtc_get_rtc_time(struct rtc_time *rtc_tm) ++{ ++} ++ ++/* ++ * Module init/exit ++ */ ++ ++static int __init rtc_init(void) ++{ ++ if (request_irq(IRQ_1HZ, interrupt_1hz, SA_INTERRUPT, "rtc-1hz", NULL)) { ++ printk(KERN_ERR "rtc: IRQ %d is not free.\n", IRQ_1HZ); ++ return -EIO; ++ } ++ ++ if (misc_register(&rtc_dev)) { ++ free_irq(IRQ_1HZ, NULL); ++ return -ENODEV; ++ } ++ ++ init_sysctl(); ++ ++ printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n"); ++ return 0; ++} ++ ++static void __exit rtc_exit(void) ++{ ++ cleanup_sysctl(); ++ misc_deregister(&rtc_dev); ++ free_irq(IRQ_1HZ, NULL); ++} ++ ++module_init(rtc_init); ++module_exit(rtc_exit); ++ ++MODULE_AUTHOR("Ray Lehtiniemi"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/char/ttml.c b/drivers/char/ttml.c +new file mode 100644 +index 0000000..ba2cb8e +--- /dev/null ++++ b/drivers/char/ttml.c +@@ -0,0 +1,643 @@ ++/* ++ * linux/drivers/char/ttml.c ++ * ++ * TTML TripDawg system devices. ++ * ++ * Copyright 2004, Ray Lehtiniemi ++ * Copyright 2004, Siconix, Inc ++ */ ++ ++#include <linux/module.h> ++#include <linux/config.h> ++ ++#include <linux/spinlock.h> ++#include <linux/fs.h> ++#include <linux/device.h> ++#include <linux/cdev.h> ++#include <linux/major.h> ++#include <linux/init.h> ++#include <linux/errno.h> ++#include <linux/poll.h> ++#include <linux/ttml.h> ++#include <linux/timer.h> ++#include <linux/slab.h> ++ ++#include <asm/io.h> ++#include <asm/uaccess.h> ++ ++#include <asm/arch/regmap.h> ++#include <asm/arch/ssp.h> ++#include <asm/arch/ssp2.h> ++#include <asm/arch/mach-ttml.h> ++ ++/* device open/release stuff */ ++static DECLARE_MUTEX(mutex); ++static struct cdev ttml_cdev; ++static struct class *ttml_class; ++static int is_open[MAX_TTML_MINORS]; ++ ++#define minor_get(minor) is_open[(minor)-TTML_MINOR_LED] = 1 ++#define minor_put(minor) is_open[(minor)-TTML_MINOR_LED] = 0 ++#define minor_busy(minor) (is_open[(minor)-TTML_MINOR_LED] != 0) ++ ++static struct { ++ int minor; ++ char *name; ++} devlist[] = { ++ { ++ TTML_MINOR_LED, "led"}, { ++ TTML_MINOR_BUZZER, "buzzer"}, { ++ TTML_MINOR_SPEEDO, "speedo"}, { ++ TTML_MINOR_GPIO, "gpio"}, { ++ TTML_MINOR_BUTTON, "button"}, { ++TTML_MINOR_WD, "wd"},}; ++ ++/* button and gpio event handling */ ++static kmem_cache_t *event_cachep; ++static spinlock_t event_lock = SPIN_LOCK_UNLOCKED; ++static LIST_HEAD(button_events); ++static LIST_HEAD(gpio_events); ++static DECLARE_WAIT_QUEUE_HEAD(button_wait); ++static DECLARE_WAIT_QUEUE_HEAD(gpio_wait); ++ ++enum ttml_events { ++ TTML_BUTTON_PRESS, ++ TTML_BUTTON_RELEASE, ++ TTML_PTO_RISE, ++ TTML_PTO_FALL, ++ TTML_IGNITION_RISE, ++ TTML_IGNITION_FALL, ++ TTML_SPARE_RISE, ++ TTML_SPARE_FALL, ++}; ++ ++struct ttml_event { ++ struct list_head l; ++ struct timeval t; ++ enum ttml_events e; ++}; ++ ++/* Button and GPIO event monitoring timer */ ++ ++static struct timer_list monitor_timer; ++static void handle_timer(unsigned long); ++ ++static void setup_timer(void) ++{ ++ monitor_timer.expires = jiffies + 1; ++ monitor_timer.data = 0; ++ monitor_timer.function = handle_timer; ++ add_timer(&monitor_timer); ++} ++ ++static void handle_timer_button(void) ++{ ++ static int state = 0; ++ int portf = readl(GPIO_PFDR); ++ int new = (portf & 0x04) ? 0 : 1; ++ ++ if (state ^ new) { ++ struct ttml_event *b = ++ kmem_cache_alloc(event_cachep, GFP_KERNEL); ++ if (b != NULL) { ++ do_gettimeofday(&b->t); ++ b->t.tv_usec |= ++ ((new ? TTML_BUTTON_PRESS : TTML_BUTTON_RELEASE) << ++ 24); ++ list_add(&b->l, &button_events); ++ wake_up_interruptible(&button_wait); ++ } ++ state = new; ++ } ++} ++ ++static void handle_timer_pto(void) ++{ ++ static int state = 0; ++ int portf = readl(GPIO_PFDR); ++ int new = (portf & 0x08) ? 1 : 0; ++ ++ if (state ^ new) { ++ struct ttml_event *b = ++ kmem_cache_alloc(event_cachep, GFP_KERNEL); ++ if (b != NULL) { ++ do_gettimeofday(&b->t); ++ b->t.tv_usec |= ++ ((new ? TTML_PTO_RISE : TTML_PTO_FALL) << 24); ++ list_add(&b->l, &gpio_events); ++ wake_up_interruptible(&gpio_wait); ++ } ++ state = new; ++ } ++} ++ ++static void handle_timer_ignition(void) ++{ ++ static int state = 0; ++ int portf = readl(GPIO_PFDR); ++ int new = (portf & 0x02) ? 1 : 0; ++ ++ if (state ^ new) { ++ struct ttml_event *b = ++ kmem_cache_alloc(event_cachep, GFP_KERNEL); ++ if (b != NULL) { ++ do_gettimeofday(&b->t); ++ b->t.tv_usec |= ++ ((new ? TTML_IGNITION_RISE : TTML_IGNITION_FALL) << ++ 24); ++ list_add(&b->l, &gpio_events); ++ wake_up_interruptible(&gpio_wait); ++ } ++ state = new; ++ } ++} ++ ++static void handle_timer_spare(void) ++{ ++ static int state = 0; ++ int porta = readl(GPIO_PADR); ++ int new = (porta & 0x08) ? 1 : 0; ++ ++ if (state ^ new) { ++ struct ttml_event *b = ++ kmem_cache_alloc(event_cachep, GFP_KERNEL); ++ if (b != NULL) { ++ do_gettimeofday(&b->t); ++ b->t.tv_usec |= ++ ((new ? TTML_SPARE_RISE : TTML_SPARE_FALL) << 24); ++ list_add(&b->l, &gpio_events); ++ wake_up_interruptible(&gpio_wait); ++ } ++ state = new; ++ } ++} ++ ++static void handle_timer(unsigned long foo) ++{ ++ handle_timer_button(); ++ handle_timer_pto(); ++ handle_timer_ignition(); ++ handle_timer_spare(); ++ setup_timer(); ++} ++ ++static int ttml_read_gpio(struct file *filp, char __user * buf, size_t size, ++ loff_t * off); ++static int ttml_read_button(struct file *filp, char __user * buf, size_t size, ++ loff_t * off); ++static unsigned int ttml_poll_gpio(struct file *filp, ++ struct poll_table_struct *poll); ++static unsigned int ttml_poll_button(struct file *filp, ++ struct poll_table_struct *poll); ++static int ttml_ioctl(struct inode *inode, struct file *filp, ++ unsigned int command, unsigned long arg); ++static int ttml_open(struct inode *inode, struct file *filp); ++static int ttml_release(struct inode *inode, struct file *filp); ++ ++static struct file_operations ttml_fops = { ++ .owner = THIS_MODULE, ++ .ioctl = ttml_ioctl, ++ .open = ttml_open, ++ .release = ttml_release, ++}; ++ ++static struct file_operations ttml_fops_gpio = { ++ .owner = THIS_MODULE, ++ .read = ttml_read_gpio, ++ .poll = ttml_poll_gpio, ++ .ioctl = ttml_ioctl, ++ .open = ttml_open, ++ .release = ttml_release, ++}; ++ ++static struct file_operations ttml_fops_button = { ++ .owner = THIS_MODULE, ++ .read = ttml_read_button, ++ .poll = ttml_poll_button, ++ .ioctl = ttml_ioctl, ++ .open = ttml_open, ++ .release = ttml_release, ++}; ++ ++static int do_get_led(void __user * arg) ++{ ++ struct ttml_ioctl_led a; ++ int porte = readl(GPIO_PEDR); ++ int portb = readl(GPIO_PBDR); ++ ++ a.blue = (portb & 0x01) ? 1 : 0; ++ a.red = (porte & 0x02) ? 1 : 0; ++ a.yellow = (porte & 0x01) ? 1 : 0; ++ ++ return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0; ++} ++ ++static int do_get_buzzer(void __user * arg) ++{ ++ struct ttml_ioctl_buzzer a; ++ ++ a.buzzer1 = 0; /* FIXME */ ++ ++ return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0; ++} ++ ++static int do_get_speedo(void __user * arg) ++{ ++ struct ttml_ioctl_speedo a; ++ unsigned char msg[3] = { 0xaa, 0x82, 0xd7 }; ++ unsigned char reply[10]; ++ int err; ++ ++ err = ssp_do_ttml(&ep93xx_ssp_micro, msg, 3, reply, 10); ++ ++ if (err != 0) ++ return err; ++ ++ a.instant = 0; /* FIXME */ ++ a.average = (reply[1] << 8) | (reply[2]); ++ ++ return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0; ++} ++ ++static int do_get_gpio(void __user * arg) ++{ ++ struct ttml_ioctl_gpio a; ++ int porta = readl(GPIO_PADR); ++ int portf = readl(GPIO_PFDR); ++ ++ a.pto = (portf & 0x08) ? 0 : 1; ++ a.ignition = (portf & 0x02) ? 0 : 1; ++ a.spare = (porta & 0x08) ? 0 : 1; ++ ++ return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0; ++} ++ ++static int do_get_button(void __user * arg) ++{ ++ struct ttml_ioctl_button a; ++ int portf = readl(GPIO_PFDR); ++ ++ a.button1 = (portf & 0x04) ? 0 : 1; ++ ++ return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0; ++} ++ ++static int do_set_led(void __user * arg) ++{ ++ struct ttml_ioctl_led a; ++ int porte = readl(GPIO_PEDR); ++ int portb = readl(GPIO_PBDR); ++ ++ if (copy_from_user(&a, arg, sizeof(a))) ++ return -EIO; ++ ++ if (a.yellow) ++ porte |= 0x01; ++ else ++ porte &= ~0x01; ++ ++ if (a.red) ++ porte |= 0x02; ++ else ++ porte &= ~0x02; ++ ++ if (a.blue) ++ portb |= 0x01; ++ else ++ portb &= ~0x01; ++ ++ writel(porte, GPIO_PEDR); ++ writel(portb, GPIO_PBDR); ++ ++ return 0; ++} ++ ++static int do_set_buzzer(void __user * arg) ++{ ++ struct ttml_ioctl_buzzer a; ++ unsigned char msg0[4] = { 0xaa, 0x93, 0x00, 0xc6 }; ++ unsigned char msg1[4] = { 0xaa, 0x93, 0x01, 0xc7 }; ++ unsigned char reply[10]; ++ int err = 0; ++ ++ if (copy_from_user(&a, arg, sizeof(a))) ++ return -EIO; ++ ++ if (a.buzzer1) ++ err = ssp_do_ttml(&ep93xx_ssp_micro, msg1, 4, reply, 10); ++ else ++ err = ssp_do_ttml(&ep93xx_ssp_micro, msg0, 4, reply, 10); ++ ++ return err; ++} ++ ++static int ttml_read_gpio(struct file *filp, char __user * buf, size_t size, ++ loff_t * off) ++{ ++ DECLARE_WAITQUEUE(wait, current); ++ struct ttml_event *g = NULL; ++ int retval = -EINVAL; ++ ++ if (size != sizeof(struct timeval)) ++ return -EINVAL; ++ ++ add_wait_queue(&gpio_wait, &wait); ++ ++ while (1) { ++ unsigned long flags; ++ ++ __set_current_state(TASK_INTERRUPTIBLE); ++ ++ spin_lock_irqsave(&event_lock, flags); ++ if (!list_empty(&gpio_events)) ++ list_for_each_entry(g, &gpio_events, l) { ++ list_del(&g->l); ++ break; ++ } ++ ++ spin_unlock_irqrestore(&event_lock, flags); ++ ++ if (g != NULL) ++ break; ++ ++ if (filp->f_flags & O_NONBLOCK) { ++ retval = -EAGAIN; ++ goto out; ++ } ++ ++ if (signal_pending(current)) { ++ retval = -ERESTARTSYS; ++ goto out; ++ } ++ ++ schedule(); ++ ++ }; ++ ++ if (copy_to_user(buf, &g->t, sizeof(struct timeval))) ++ retval = -EFAULT; ++ else ++ retval = sizeof(struct timeval); ++ ++ kmem_cache_free(event_cachep, g); ++ ++ out: ++ current->state = TASK_RUNNING; ++ remove_wait_queue(&gpio_wait, &wait); ++ ++ return retval; ++} ++ ++static unsigned int ttml_poll_gpio(struct file *filp, ++ struct poll_table_struct *poll) ++{ ++ unsigned long flags; ++ int retval = 0; ++ ++ poll_wait(filp, &gpio_wait, poll); ++ ++ spin_lock_irqsave(&event_lock, flags); ++ if (!list_empty(&gpio_events)) ++ retval = (POLLIN | POLLRDNORM); ++ spin_unlock_irqrestore(&event_lock, flags); ++ ++ return retval; ++} ++ ++static int ttml_read_button(struct file *filp, char __user * buf, size_t size, ++ loff_t * off) ++{ ++ DECLARE_WAITQUEUE(wait, current); ++ struct ttml_event *b = NULL; ++ int retval = -EINVAL; ++ ++ if (size != sizeof(struct timeval)) ++ return -EINVAL; ++ ++ add_wait_queue(&button_wait, &wait); ++ ++ while (1) { ++ unsigned long flags; ++ ++ __set_current_state(TASK_INTERRUPTIBLE); ++ ++ spin_lock_irqsave(&event_lock, flags); ++ if (!list_empty(&button_events)) { ++ list_for_each_entry(b, &button_events, l) { ++ list_del(&b->l); ++ break; ++ } ++ } ++ spin_unlock_irqrestore(&event_lock, flags); ++ ++ if (b != NULL) ++ break; ++ ++ if (filp->f_flags & O_NONBLOCK) { ++ retval = -EAGAIN; ++ goto out; ++ } ++ ++ if (signal_pending(current)) { ++ retval = -ERESTARTSYS; ++ goto out; ++ } ++ ++ schedule(); ++ ++ }; ++ ++ if (copy_to_user(buf, &b->t, sizeof(struct timeval))) ++ retval = -EFAULT; ++ else ++ retval = sizeof(struct timeval); ++ ++ kmem_cache_free(event_cachep, b); ++ ++ out: ++ current->state = TASK_RUNNING; ++ remove_wait_queue(&button_wait, &wait); ++ ++ return retval; ++} ++ ++static unsigned int ttml_poll_button(struct file *filp, ++ struct poll_table_struct *poll) ++{ ++ unsigned long flags; ++ int retval = 0; ++ ++ poll_wait(filp, &button_wait, poll); ++ ++ spin_lock_irqsave(&event_lock, flags); ++ if (!list_empty(&button_events)) ++ retval = (POLLIN | POLLRDNORM); ++ spin_unlock_irqrestore(&event_lock, flags); ++ ++ return retval; ++} ++ ++static int ttml_ioctl(struct inode *inode, struct file *filp, ++ unsigned int command, unsigned long arg) ++{ ++ void __user *p = (void __user *)arg; ++ const int minor = iminor(inode); ++ int err = -ENOSYS; ++ ++ switch (command) { ++ case TTML_GET_LED: ++ if (minor == TTML_MINOR_LED) ++ err = do_get_led(p); ++ break; ++ case TTML_GET_BUZZER: ++ if (minor == TTML_MINOR_BUZZER) ++ err = do_get_buzzer(p); ++ break; ++ case TTML_GET_SPEEDO: ++ if (minor == TTML_MINOR_SPEEDO) ++ err = do_get_speedo(p); ++ break; ++ case TTML_GET_GPIO: ++ if (minor == TTML_MINOR_GPIO) ++ err = do_get_gpio(p); ++ break; ++ case TTML_GET_BUTTON: ++ if (minor == TTML_MINOR_BUTTON) ++ err = do_get_button(p); ++ break; ++ case TTML_SET_LED: ++ if (minor == TTML_MINOR_LED) ++ err = do_set_led(p); ++ break; ++ case TTML_SET_BUZZER: ++ if (minor == TTML_MINOR_BUZZER) ++ err = do_set_buzzer(p); ++ break; ++ } ++ ++ return err; ++} ++ ++static int ttml_open(struct inode *inode, struct file *filp) ++{ ++ const int minor = iminor(inode); ++ int err = -EBUSY; ++ ++ if (minor == TTML_MINOR_WD) { ++ unsigned char msg[3] = { 0xaa, 0x82, 0xd7 }; ++ unsigned char reply[10]; ++ ssp_do_ttml(&ep93xx_ssp_micro, msg, 3, reply, 10); ++ } ++ ++ down(&mutex); ++ if (minor_busy(minor)) ++ goto err; ++ minor_get(minor); ++ if (minor == TTML_MINOR_GPIO) ++ filp->f_op = &ttml_fops_gpio; ++ if (minor == TTML_MINOR_BUTTON) ++ filp->f_op = &ttml_fops_button; ++ err = 0; ++ ++ err: ++ up(&mutex); ++ return err; ++} ++ ++static int ttml_release(struct inode *inode, struct file *filp) ++{ ++ down(&mutex); ++ minor_put(iminor(inode)); ++ up(&mutex); ++ return 0; ++} ++ ++static int __init ttml_init(void) ++{ ++ dev_t dev = MKDEV(TTML_MAJOR, 240); ++ int err = -EIO; ++ int i; ++ ++ err = -ENOMEM; ++ event_cachep = kmem_cache_create("ttml_event", ++ sizeof(struct ttml_event), ++ 0, 0, NULL, NULL); ++ if (event_cachep == NULL) ++ goto err; ++ ++ err = -EIO; ++ if (register_chrdev_region(dev, MAX_TTML_MINORS, "ttml")) ++ goto err_uncache; ++ ++ cdev_init(&ttml_cdev, &ttml_fops); ++ ++ if (cdev_add(&ttml_cdev, dev, MAX_TTML_MINORS)) { ++ kobject_put(&ttml_cdev.kobj); ++ goto err_unreg; ++ } ++ ++ ttml_class = class_create(THIS_MODULE, "ttml"); ++ ++ if (IS_ERR(ttml_class)) { ++ err = PTR_ERR(ttml_class); ++ cdev_del(&ttml_cdev); ++ goto err_unreg; ++ } ++ ++ for (i = 0; i < ARRAY_SIZE(devlist); i++) ++ class_device_create(ttml_class, ++ MKDEV(TTML_MAJOR, devlist[i].minor), ++ NULL, "%s", devlist[i].name); ++ ++ init_timer(&monitor_timer); ++ setup_timer(); ++ ++ printk(KERN_INFO "TTML system devices version 0.1\n"); ++ return 0; ++ ++ err_unreg: ++ unregister_chrdev_region(dev, MAX_TTML_MINORS); ++ err_uncache: ++ kmem_cache_destroy(event_cachep); ++ err: ++ printk(KERN_WARNING "unable to register ttml devices\n"); ++ return err; ++} ++ ++static void __exit ttml_exit(void) ++{ ++ struct ttml_event *b; ++ int i; ++ ++ /* stop our button polling timer */ ++ del_timer_sync(&monitor_timer); ++ ++ /* delete any events captured but not yet read */ ++ list_for_each_entry(b, &button_events, l) { ++ list_del(&b->l); ++ kmem_cache_free(event_cachep, b); ++ } ++ ++ list_for_each_entry(b, &gpio_events, l) { ++ list_del(&b->l); ++ kmem_cache_free(event_cachep, b); ++ } ++ ++ /* free up the event cache */ ++ kmem_cache_destroy(event_cachep); ++ ++ /* clean up the device */ ++ for (i = 0; i < ARRAY_SIZE(devlist); i++) ++ class_device_destroy(ttml_class, ++ MKDEV(TTML_MAJOR, devlist[i].minor)); ++ class_destroy(ttml_class); ++ cdev_del(&ttml_cdev); ++ unregister_chrdev_region(MKDEV(TTML_MAJOR, 240), MAX_TTML_MINORS); ++} ++ ++module_init(ttml_init); ++module_exit(ttml_exit); ++ ++MODULE_AUTHOR("Ray Lehtiniemi"); ++MODULE_DESCRIPTION("TTML system devices"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig +index 344001b..b5a7a90 100644 +--- a/drivers/char/watchdog/Kconfig ++++ b/drivers/char/watchdog/Kconfig +@@ -148,6 +148,17 @@ config MPCORE_WATCHDOG + To compile this driver as a module, choose M here: the + module will be called mpcore_wdt. + ++config EP93XX_WATCHDOG ++ tristate "EP93xx Watchdog" ++ depends on WATCHDOG && ARCH_EP93XX ++ help ++ Say Y here if to include support for the watchdog timer ++ in the Cirrus EP93xx family of devices. This driver can ++ be built as a module by choosing M. The module will ++ be called ep93xx_wdt. ++ ++ Say N if you are unsure. ++ + # X86 (i386 + ia64 + x86_64) Architecture + + config ACQUIRE_WDT +diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile +index cfd0a39..061671b 100644 +--- a/drivers/char/watchdog/Makefile ++++ b/drivers/char/watchdog/Makefile +@@ -25,6 +25,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb. + # ARM Architecture + obj-$(CONFIG_21285_WATCHDOG) += wdt285.o + obj-$(CONFIG_977_WATCHDOG) += wdt977.o ++obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o + obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o + obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o + obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o +diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c +new file mode 100644 +index 0000000..a2a7a49 +--- /dev/null ++++ b/drivers/char/watchdog/ep93xx_wdt.c +@@ -0,0 +1,210 @@ ++/* ++ * drivers/watchdog/ep93xx_wdt.c ++ * ++ * Watchdog driver for Cirrus EP93xx family of devices. ++ * ++ * Author: Ray Lehtiniemi <rayl@mail.com> ++ * ++ * Copyright 2004 (c) Ray Lehtiniemi ++ * Based on ep93xx driver. ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++/* ++ Todo: ++ ++ - test last rst from watchdog status ++ - test module loading ++ - test nowayout ++ - test all ioctl, add missing ones ++ */ ++ ++#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/fs.h> ++#include <linux/miscdevice.h> ++#include <linux/watchdog.h> ++#include <linux/init.h> ++ ++#include <asm/hardware.h> ++#include <asm/bitops.h> ++#include <asm/uaccess.h> ++#include <asm/io.h> ++#include <asm/arch/regmap.h> ++ ++#define WD_VERSION "0.01" ++ ++#ifdef CONFIG_WATCHDOG_NOWAYOUT ++static int nowayout = 1; ++#else ++static int nowayout = 0; ++#endif ++ ++static unsigned long wdt_status; ++static unsigned long boot_status; ++ ++#define WDT_IN_USE 0 ++#define WDT_OK_TO_CLOSE 1 ++ ++static void wdt_enable(void) ++{ ++ writel(0xaaaa, WATCHDOG); ++} ++ ++static void wdt_disable(void) ++{ ++ writel(0xaa55, WATCHDOG); ++} ++ ++static void wdt_ping(void) ++{ ++ writel(0x5555, WATCHDOG); ++} ++ ++static int ep93xx_wdt_open(struct inode *inode, struct file *file) ++{ ++ if (test_and_set_bit(WDT_IN_USE, &wdt_status)) ++ return -EBUSY; ++ ++ clear_bit(WDT_OK_TO_CLOSE, &wdt_status); ++ ++ wdt_enable(); ++ ++ return 0; ++} ++ ++static ssize_t ++ep93xx_wdt_write(struct file *file, const char __user * data, size_t len, ++ loff_t * ppos) ++{ ++ /* Can't seek (pwrite) on this device */ ++ if (*ppos != file->f_pos) ++ return -ESPIPE; ++ ++ if (len) { ++ if (!nowayout) { ++ size_t i; ++ ++ clear_bit(WDT_OK_TO_CLOSE, &wdt_status); ++ ++ for (i = 0; i != len; i++) { ++ char c; ++ ++ if (get_user(c, data + i)) ++ return -EFAULT; ++ ++ if (c == 'V') ++ set_bit(WDT_OK_TO_CLOSE, &wdt_status); ++ else ++ clear_bit(WDT_OK_TO_CLOSE, &wdt_status); ++ } ++ } ++ wdt_ping(); ++ } ++ ++ return len; ++} ++ ++static struct watchdog_info ident = { ++ .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE, ++ .identity = "EP93xx Watchdog", ++}; ++ ++static int ++ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ++ unsigned long arg) ++{ ++ int ret = -ENOIOCTLCMD; ++ ++ switch (cmd) { ++ case WDIOC_GETSUPPORT: ++ ret = copy_to_user((struct watchdog_info __user *)arg, &ident, ++ sizeof(ident)) ? -EFAULT : 0; ++ break; ++ ++ case WDIOC_GETSTATUS: ++ ret = put_user(0, (int __user *)arg); ++ break; ++ ++ case WDIOC_GETBOOTSTATUS: ++ ret = put_user(boot_status, (int __user *)arg); ++ break; ++ ++ case WDIOC_GETTIMEOUT: ++ /* actually, it is 0.250 seconds.... */ ++ ret = put_user(1, (int __user *)arg); ++ break; ++ ++ case WDIOC_KEEPALIVE: ++ wdt_ping(); ++ ret = 0; ++ break; ++ } ++ return ret; ++} ++ ++static int ep93xx_wdt_release(struct inode *inode, struct file *file) ++{ ++ if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) ++ wdt_disable(); ++ else ++ printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " ++ "timer will not stop\n"); ++ ++ clear_bit(WDT_IN_USE, &wdt_status); ++ clear_bit(WDT_OK_TO_CLOSE, &wdt_status); ++ ++ return 0; ++} ++ ++static struct file_operations ep93xx_wdt_fops = { ++ .owner = THIS_MODULE, ++ .write = ep93xx_wdt_write, ++ .ioctl = ep93xx_wdt_ioctl, ++ .open = ep93xx_wdt_open, ++ .release = ep93xx_wdt_release, ++}; ++ ++static struct miscdevice ep93xx_wdt_miscdev = { ++ .minor = WATCHDOG_MINOR, ++ .name = "EP93xx Watchdog", ++ .fops = &ep93xx_wdt_fops, ++}; ++ ++static int __init ep93xx_wdt_init(void) ++{ ++ int ret; ++ ++ ret = misc_register(&ep93xx_wdt_miscdev); ++ ++ boot_status = readl(WATCHDOG) & 0x01 ? 1 : 0; ++ ++ printk("EP93xx Watchdog: Version " WD_VERSION "%s\n", ++ (readl(WATCHDOG) & 0x08) ? " (nCS1 disable detected)" ++ : ""); ++ ++ return ret; ++} ++ ++static void __exit ep93xx_wdt_exit(void) ++{ ++ misc_deregister(&ep93xx_wdt_miscdev); ++} ++ ++module_init(ep93xx_wdt_init); ++module_exit(ep93xx_wdt_exit); ++ ++MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>"); ++MODULE_DESCRIPTION("EP93xx Watchdog"); ++ ++module_param(nowayout, int, 0); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); ++ ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig +index 4010fe9..895dfa8 100644 +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -95,6 +95,19 @@ config I2C_ELEKTOR + This support is also available as a module. If so, the module + will be called i2c-elektor. + ++config I2C_EP93XX ++ tristate "Cirrus EP93XX interface" ++ depends on I2C && ARCH_EP93XX ++ select I2C_ALGOBIT ++ help ++ This supports the Cirrus EP93xx CPU family I2C bus. Choose this ++ if you want to access I2C devices connected to EECLK and EEDAT pins ++ of your EP93XX. ++ ++ This support is also available as a module. If so, the module ++ will be called i2c-ep93xx. ++ ++ + config I2C_HYDRA + tristate "CHRP Apple Hydra Mac I/O I2C interface" + depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL +diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile +index f1df00f..fbb35f7 100644 +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -10,6 +10,7 @@ obj-$(CONFIG_I2C_AMD756_S4882) += i2c-am + obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o + obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o + obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o ++obj-$(CONFIG_I2C_EP93XX) += i2c-ep93xx.o + obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o + obj-$(CONFIG_I2C_I801) += i2c-i801.o + obj-$(CONFIG_I2C_I810) += i2c-i810.o +diff --git a/drivers/i2c/busses/i2c-ep93xx.c b/drivers/i2c/busses/i2c-ep93xx.c +new file mode 100644 +index 0000000..1477bf3 +--- /dev/null ++++ b/drivers/i2c/busses/i2c-ep93xx.c +@@ -0,0 +1,180 @@ ++/* ------------------------------------------------------------------------ * ++ * i2c-ep933xx.c I2C bus glue for Cirrus EP93xx * ++ * ------------------------------------------------------------------------ * ++ ++ Copyright (C) 2004 Michael Burian ++ ++ Based on i2c-parport-light.c ++ Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.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, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ------------------------------------------------------------------------ */ ++ ++#include <linux/config.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/delay.h> ++#include <linux/i2c.h> ++#include <linux/i2c-algo-bit.h> ++#include <asm/io.h> ++#include <asm/arch/regmap.h> ++ ++/* 1/(2*clockfrequency) */ ++#define EE_DELAY_USEC 50 ++#define GPIOG_EECLK 1 ++#define GPIOG_EEDAT 2 ++ ++/* ----- I2C algorithm call-back functions and structures ----------------- */ ++ ++static void ep93xx_setscl(void *data, int state) ++{ ++ unsigned int val, dir; ++ ++ val = readl(GPIO_PGDR); ++ dir = readl(GPIO_PGDDR); ++ ++ /* Configure the clock line as output. */ ++ dir |= GPIOG_EECLK; ++ writel(dir, GPIO_PGDDR); ++ ++ /* Set clock line to state */ ++ if (state) ++ val |= GPIOG_EECLK; ++ else ++ val &= ~GPIOG_EECLK; ++ ++ writel(val, GPIO_PGDR); ++} ++ ++static void ep93xx_setsda(void *data, int state) ++{ ++ unsigned int val, dir; ++ val = readl(GPIO_PGDR); ++ dir = readl(GPIO_PGDDR); ++ ++ /* Configure the data line as output. */ ++ dir |= GPIOG_EEDAT; ++ writel(dir, GPIO_PGDDR); ++ ++ /* Set data line to state */ ++ if (state) ++ val |= GPIOG_EEDAT; ++ else ++ val &= ~GPIOG_EEDAT; ++ ++ writel(val, GPIO_PGDR); ++} ++ ++static int ep93xx_getscl(void *data) ++{ ++ unsigned int val, dir; ++ val = readl(GPIO_PGDR); ++ dir = readl(GPIO_PGDDR); ++ ++ /* Configure the clock line as input */ ++ dir &= ~GPIOG_EECLK; ++ writel(dir, GPIO_PGDDR); ++ ++ /* Return state of the clock line */ ++ return (readl(GPIO_PGDR) & GPIOG_EECLK) ? 1 : 0; ++} ++ ++static int ep93xx_getsda(void *data) ++{ ++ unsigned int val, dir; ++ val = readl(GPIO_PGDR); ++ dir = readl(GPIO_PGDDR); ++ ++ /* Configure the data line as input */ ++ dir &= ~GPIOG_EEDAT; ++ writel(dir, GPIO_PGDDR); ++ ++ /* Return state of the data line */ ++ return (readl(GPIO_PGDR) & GPIOG_EEDAT) ? 1 : 0; ++} ++ ++static struct i2c_algo_bit_data ep93xx_algo_data = { ++ .setsda = ep93xx_setsda, ++ .setscl = ep93xx_setscl, ++ .getsda = ep93xx_getsda, ++ .getscl = ep93xx_getscl, ++ .udelay = EE_DELAY_USEC, ++ .mdelay = EE_DELAY_USEC * 1000, ++ .timeout = HZ, ++}; ++ ++/* ----- I2c structure ---------------------------------------------------- */ ++ ++static struct i2c_adapter ep93xx_adapter = { ++ .owner = THIS_MODULE, ++ .class = I2C_CLASS_HWMON, ++ .id = I2C_HW_B_LP, ++ .algo_data = &ep93xx_algo_data, ++ .name = "EP93XX I2C interface", ++}; ++ ++/* ----- Module loading, unloading and information ------------------------ */ ++ ++static int __init i2c_ep93xx_init(void) ++{ ++ unsigned long uiVal, uiDDR; ++ ++ /* Read the current value of the GPIO data and data direction registers. */ ++ uiVal = readl(GPIO_PGDR); ++ uiDDR = readl(GPIO_PGDDR); ++ ++ /* If the GPIO pins have not been configured since reset, the data ++ * and clock lines will be set as inputs and with data value of 0. ++ * External pullup resisters are pulling them high. ++ * Set them both high before configuring them as outputs. */ ++ uiVal |= (GPIOG_EEDAT | GPIOG_EECLK); ++ writel(uiVal, GPIO_PGDR); ++ ++ /* Delay to meet the EE Interface timing specification. */ ++ udelay(EE_DELAY_USEC); ++ ++ /* Configure the EE data and clock lines as outputs. */ ++ writel(0x3, GPIO_EEDRIVE); /* use open drain outputs! */ ++ uiDDR |= (GPIOG_EEDAT | GPIOG_EECLK); ++ writel(uiDDR, GPIO_PGDDR); ++ ++ /* Delay to meet the EE Interface timing specification. */ ++ udelay(EE_DELAY_USEC); ++ ++ /* Reset hardware to a sane state (SCL and SDA high) */ ++ ep93xx_setsda(NULL, 1); ++ ep93xx_setscl(NULL, 1); ++ ++ if (i2c_bit_add_bus(&ep93xx_adapter) < 0) { ++ printk(KERN_ERR "i2c-ep93xx: Unable to register with I2C\n"); ++ return -ENODEV; ++ } ++ ++ return 0; ++} ++ ++static void __exit i2c_ep93xx_exit(void) ++{ ++ i2c_bit_del_bus(&ep93xx_adapter); ++} ++ ++MODULE_AUTHOR("Michael Burian"); ++MODULE_DESCRIPTION("I2C bus glue for Cirrus EP93xx processors"); ++MODULE_LICENSE("GPL"); ++ ++module_init(i2c_ep93xx_init); ++module_exit(i2c_ep93xx_exit); +diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig +index f9fae28..45f9286 100644 +--- a/drivers/i2c/chips/Kconfig ++++ b/drivers/i2c/chips/Kconfig +@@ -25,6 +25,18 @@ config SENSORS_DS1374 + This driver can also be built as a module. If so, the module + will be called ds1374. + ++config SENSORS_DS1307 ++ tristate "Dallas Semiconductor DS1307 RTC" ++ depends on I2C && EXPERIMENTAL ++ help ++ If you say yes here you get support for the Dallas Semiconductor ++ DS1307 RTC. Usually only embedded devices will need this. ++ ++ Only say yes here if your sure you have such a chip. ++ ++ This driver can also be built as a module. If so, the module ++ will be called ds1307. ++ + config SENSORS_EEPROM + tristate "EEPROM reader" + depends on I2C && EXPERIMENTAL +diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile +index 46178b5..90be351 100644 +--- a/drivers/i2c/chips/Makefile ++++ b/drivers/i2c/chips/Makefile +@@ -3,6 +3,7 @@ + # + + obj-$(CONFIG_SENSORS_DS1337) += ds1337.o ++obj-$(CONFIG_SENSORS_DS1307) += ds1307.o + obj-$(CONFIG_SENSORS_DS1374) += ds1374.o + obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o + obj-$(CONFIG_SENSORS_MAX6875) += max6875.o +diff --git a/drivers/i2c/chips/ds1307.c b/drivers/i2c/chips/ds1307.c +new file mode 100644 +index 0000000..76ea8b8 +--- /dev/null ++++ b/drivers/i2c/chips/ds1307.c +@@ -0,0 +1,651 @@ ++/* ++ * ds1307.c ++ * ++ * Device driver for Dallas Semiconductor's Real Time Controller DS1307. ++ * ++ * Copyright (C) 2002 Intrinsyc Software Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/version.h> ++ ++#include <linux/kernel.h> ++#include <linux/poll.h> ++#include <linux/i2c.h> ++#include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/rtc.h> ++#include <linux/string.h> ++#include <linux/miscdevice.h> ++#include <linux/proc_fs.h> ++ ++#include "ds1307.h" ++ ++#undef DEBUG ++#ifdef DEBUG ++static unsigned int rtc_debug = DEBUG; ++#define DPRINTK(i,x...) do { if (rtc_debug > (i)) printk(x); } while (0) ++#else ++#define rtc_debug 0 /* gcc will remove all the debug code for us */ ++#define DPRINTK(i,x...) do { } while (0) ++#endif ++ ++static unsigned short slave_address = DS1307_I2C_SLAVE_ADDR; ++ ++struct i2c_driver ds1307_driver; ++struct i2c_client *ds1307_i2c_client = 0; ++ ++static unsigned short ignore[] = { I2C_CLIENT_END }; ++static unsigned short normal_addr[] = { DS1307_I2C_SLAVE_ADDR, I2C_CLIENT_END }; ++ ++static struct i2c_client_address_data addr_data = { ++ normal_i2c: normal_addr, ++ probe: ignore, ++ ignore: ignore, ++ force: ignore, ++}; ++ ++static int ds1307_rtc_ioctl( struct inode *, struct file *, unsigned int, unsigned long); ++static int ds1307_rtc_open(struct inode *inode, struct file *file); ++static int ds1307_rtc_release(struct inode *inode, struct file *file); ++ ++static struct file_operations rtc_fops = { ++ owner: THIS_MODULE, ++ ioctl: ds1307_rtc_ioctl, ++ open: ds1307_rtc_open, ++ release: ds1307_rtc_release, ++}; ++ ++static struct miscdevice ds1307_rtc_miscdev = { ++ RTC_MINOR, ++ "rtc", ++ &rtc_fops ++}; ++ ++static int ds1307_probe(struct i2c_adapter *adap); ++static int ds1307_detach(struct i2c_client *client); ++static int ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg); ++ ++struct i2c_driver ds1307_driver = { ++ .owner = THIS_MODULE, ++ .name = "DS1307", ++ .id = I2C_DRIVERID_DS1307, ++ .flags = I2C_DF_NOTIFY, ++ .attach_adapter = ds1307_probe, ++ .detach_client = ds1307_detach, ++ .command = ds1307_command, ++}; ++ ++static spinlock_t ds1307_rtc_lock = SPIN_LOCK_UNLOCKED; ++ ++static int ++ds1307_readram( char *buf, int len) ++{ ++ unsigned long flags; ++ unsigned char ad[1] = { 0 }; ++ int ret; ++ struct i2c_msg msgs[2] = { ++ { ds1307_i2c_client->addr , 0, 1, ad }, ++ { ds1307_i2c_client->addr , I2C_M_RD, len, buf } }; ++ ++ spin_lock_irqsave(&ds1307_rtc_lock, flags); ++ ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2); ++ spin_unlock_irqrestore(&ds1307_rtc_lock,flags); ++ ++ return ret; ++} ++ ++static void ++ds1307_dumpram( void) ++{ ++ unsigned char buf[DS1307_RAM_SIZE]; ++ int ret; ++ ++ ret = ds1307_readram( buf, DS1307_RAM_SIZE); ++ ++ if( ret > 0) ++ { ++ int i; ++ for( i=0; i<DS1307_RAM_SIZE; i++) ++ { ++ printk ("%02X ", buf[i]); ++ if( (i%8) == 7) printk ("\n"); ++ } ++ printk ("\n"); ++ } ++} ++ ++static void ++ds1307_enable_clock( int enable) ++{ ++ unsigned char buf[2], ad[1] = { 0 }; ++ struct i2c_msg msgs[2] = { ++ { ds1307_i2c_client->addr , 0, 1, ad }, ++ { ds1307_i2c_client->addr , I2C_M_RD, 1, buf } ++ }; ++ unsigned char ctrl_info; ++ int ret; ++ ++ DPRINTK(1, "%s()\n", __FUNCTION__); ++ ++ if (enable) ++ ctrl_info = SQW_ENABLE | RATE_32768HZ; ++ else ++ ctrl_info = SQW_DISABLE; ++ ret = ds1307_command(ds1307_i2c_client, DS1307_SETCTRL, &ctrl_info); ++ DPRINTK(2, "%s: set ctrl rtn'd %d\n", __FUNCTION__, ret); ++ ++ /* read addr 0 (Clock-Halt bit and second counter */ ++ ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2); ++ DPRINTK(2, "%s: %s msg xfer rtn'd %d\n", __FUNCTION__, enable ? "enable" : "disable", ret); ++ ++ if (enable) ++ buf[1] = buf[0] & ~CLOCK_HALT; /* clear Clock-Halt bit */ ++ else ++ buf[1] = buf[0] | CLOCK_HALT; /* set Clock-Halt bit */ ++ buf[0] = 0; /* control register address on DS1307 */ ++ ++ ret = i2c_master_send(ds1307_i2c_client, (char *)buf, 2); ++ DPRINTK(2, "%s: master send rtn'd %d\n", __FUNCTION__, ret); ++} ++ ++static int ++ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt); ++ ++static int ++ds1307_attach(struct i2c_adapter *adap, int addr, int kind) ++{ ++ struct i2c_client *c; ++ ++ DPRINTK(1, "%s()\n", __FUNCTION__); ++ ++ c = (struct i2c_client *)kmalloc(sizeof(*c), GFP_KERNEL); ++ if (!c) ++ return -ENOMEM; ++ memset(c, 0, sizeof(*c)); ++ ++ strcpy(c->name, "DS1307"); ++ c->flags = 0; ++ c->addr = addr; ++ c->adapter = adap; ++ c->driver = &ds1307_driver; ++ ++ ds1307_i2c_client = c; ++ ds1307_enable_clock(1); ++ ++#define DS1307_SET_TIME_ON_BOOT ++#ifdef DS1307_SET_TIME_ON_BOOT ++ { ++ struct rtc_time dt; ++ ds1307_get_datetime(c, &dt); ++ xtime.tv_sec = mktime(dt.tm_year + 1900, ++ dt.tm_mon + 1, /* tm_mon starts from 0 */ ++ dt.tm_mday, ++ dt.tm_hour, ++ dt.tm_min, ++ dt.tm_sec); ++ } ++#endif ++ ++ return i2c_attach_client(c); ++} ++ ++static int ++ds1307_probe(struct i2c_adapter *adap) ++{ ++ DPRINTK(1, "%s()\n", __FUNCTION__); ++ ++ return i2c_probe(adap, &addr_data, ds1307_attach); ++} ++ ++static int ++ds1307_detach(struct i2c_client *client) ++{ ++ DPRINTK(1, "%s()\n", __FUNCTION__); ++ ++ i2c_detach_client(client); ++ ds1307_enable_clock(0); ++ ++ return 0; ++} ++ ++static void ++ds1307_convert_to_time( struct rtc_time *dt, char *buf) ++{ ++ dt->tm_sec = BCD_TO_BIN(buf[0]); ++ dt->tm_min = BCD_TO_BIN(buf[1]); ++ ++ if ( TWELVE_HOUR_MODE(buf[2]) ) ++ { ++ dt->tm_hour = HOURS_12(buf[2]); ++ if (HOURS_AP(buf[2])) /* PM */ ++ { ++ dt->tm_hour += 12; ++ } ++ } ++ else /* 24-hour-mode */ ++ { ++ dt->tm_hour = HOURS_24(buf[2]); ++ } ++ ++ dt->tm_mday = BCD_TO_BIN(buf[4]); ++ /* dt->tm_mon is zero-based */ ++ dt->tm_mon = BCD_TO_BIN(buf[5]) - 1; ++ /* year is 1900 + dt->tm_year */ ++ dt->tm_year = BCD_TO_BIN(buf[6]) + 100; ++ ++ if (rtc_debug > 1) ++ { ++ printk("ds1307_get_datetime: year = %d\n", dt->tm_year); ++ printk("ds1307_get_datetime: mon = %d\n", dt->tm_mon); ++ printk("ds1307_get_datetime: mday = %d\n", dt->tm_mday); ++ printk("ds1307_get_datetime: hour = %d\n", dt->tm_hour); ++ printk("ds1307_get_datetime: min = %d\n", dt->tm_min); ++ printk("ds1307_get_datetime: sec = %d\n", dt->tm_sec); ++ } ++} ++ ++static int ++ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt) ++{ ++ unsigned char buf[7], addr[1] = { 0 }; ++ struct i2c_msg msgs[2] = { ++ { 0, 0, 1, addr }, ++ { 0, I2C_M_RD, 7, buf } ++ }; ++ int ret = -EIO; ++ ++ DPRINTK(1, "%s()\n", __FUNCTION__); ++ ++ if (client) { ++ ++ msgs[0].addr = client->addr; ++ msgs[1].addr = client->addr; ++ ++ memset(buf, 0, sizeof(buf)); ++ ++ ret = i2c_transfer(client->adapter, msgs, 2); ++ ++ if (ret == 2) { ++ ds1307_convert_to_time( dt, buf); ++ ret = 0; ++ } else { ++ DPRINTK(0, "%s: i2c_transfer() returned %d\n", __FUNCTION__, ret); ++ } ++ } ++ return ret; ++} ++ ++static int ++ds1307_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo) ++{ ++ unsigned char buf[8]; ++ int ret, len = 4; ++ ++ DPRINTK(1, "%s()\n", __FUNCTION__); ++ ++ if (!client) return -EIO; ++ ++ if (rtc_debug > 1) ++ { ++ printk("ds1307_set_datetime: tm_year = %d\n", dt->tm_year); ++ printk("ds1307_set_datetime: tm_mon = %d\n", dt->tm_mon); ++ printk("ds1307_set_datetime: tm_mday = %d\n", dt->tm_mday); ++ printk("ds1307_set_datetime: tm_hour = %d\n", dt->tm_hour); ++ printk("ds1307_set_datetime: tm_min = %d\n", dt->tm_min); ++ printk("ds1307_set_datetime: tm_sec = %d\n", dt->tm_sec); ++ } ++ ++ buf[0] = 0; /* register address on DS1307 */ ++ buf[1] = (BIN_TO_BCD(dt->tm_sec)); ++ buf[2] = (BIN_TO_BCD(dt->tm_min)); ++ buf[3] = (BIN_TO_BCD(dt->tm_hour)); ++ ++ if (datetoo) { ++ len = 8; ++ /* we skip buf[4] as we don't use day-of-week. */ ++ buf[5] = (BIN_TO_BCD(dt->tm_mday)); ++ buf[6] = (BIN_TO_BCD(dt->tm_mon + 1)); ++ /* The year only ranges from 0-99, we are being passed an offset from 1900, ++ * and the chip calulates leap years based on 2000, thus we adjust by 100. ++ */ ++ buf[7] = (BIN_TO_BCD(dt->tm_year - 100)); ++ } ++ ret = i2c_master_send(client, (char *)buf, len); ++ if (ret == len) ++ ret = 0; ++ else ++ DPRINTK(0, "%s: i2c_master_send() returned %d\n", __FUNCTION__, ret); ++ ++ return ret; ++} ++ ++static int ++ds1307_get_ctrl(struct i2c_client *client, unsigned char *ctrl) ++{ ++ unsigned char addr[1] = { 7 }; /* control register address on DS1307 */ ++ struct i2c_msg msgs[2] = { ++ { 0, 0, 1, addr }, ++ { 0, I2C_M_RD, 1, ctrl } ++ }; ++ int ret = -EIO; ++ ++ DPRINTK(1, "%s()\n", __FUNCTION__); ++ ++ if (client) { ++ ++ msgs[0].addr = client->addr; ++ msgs[1].addr = client->addr; ++ ++ *ctrl = 0; ++ ++ ret = i2c_transfer(client->adapter, msgs, 2); ++ ++ if (ret == 2) { ++ DPRINTK(2, "%s: info %d\n", __FUNCTION__, *ctrl); ++ ret = 0; ++ } else { ++ DPRINTK(0, "%s: i2c_transfer() returned %d\n", __FUNCTION__, ret); ++ } ++ } ++ ++ return ret; ++} ++ ++static int ++ds1307_set_ctrl(struct i2c_client *client, unsigned char *cinfo) ++{ ++ unsigned char buf[2]; ++ int ret; ++ ++ buf[0] = 7; /* control register address on DS1307 */ ++ buf[1] = *cinfo; ++ ++ DPRINTK(2, "%s: info %d\n", __FUNCTION__, buf[1]); ++ ++ ret = i2c_master_send(client, (char *)buf, 2); ++ ++ return ret; ++} ++ ++static int ++ds1307_read_mem(struct i2c_client *client, struct rtc_mem *mem) ++{ ++ unsigned char addr[1]; ++ struct i2c_msg msgs[2] = { ++ { client->addr, 0, 1, addr }, ++ { client->addr, I2C_M_RD, mem->nr, mem->data } ++ }; ++ ++ if ( (mem->loc < DS1307_RAM_ADDR_START) || ++ ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) ) ++ return -EINVAL; ++ ++ addr[0] = mem->loc; ++ ++ return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; ++} ++ ++static int ++ds1307_write_mem(struct i2c_client *client, struct rtc_mem *mem) ++{ ++ unsigned char addr[1]; ++ struct i2c_msg msgs[2] = { ++ { client->addr, 0, 1, addr }, ++ { client->addr, 0, mem->nr, mem->data } ++ }; ++ ++ if ( (mem->loc < DS1307_RAM_ADDR_START) || ++ ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) ) ++ return -EINVAL; ++ ++ addr[0] = mem->loc; ++ ++ return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO; ++} ++ ++static int ++ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg) ++{ ++ DPRINTK(1, "%s: cmd %d\n", __FUNCTION__, cmd); ++ ++ switch (cmd) { ++ case DS1307_GETDATETIME: ++ return ds1307_get_datetime(client, arg); ++ ++ case DS1307_SETTIME: ++ return ds1307_set_datetime(client, arg, 0); ++ ++ case DS1307_SETDATETIME: ++ return ds1307_set_datetime(client, arg, 1); ++ ++ case DS1307_GETCTRL: ++ return ds1307_get_ctrl(client, arg); ++ ++ case DS1307_SETCTRL: ++ return ds1307_set_ctrl(client, arg); ++ ++ case DS1307_MEM_READ: ++ return ds1307_read_mem(client, arg); ++ ++ case DS1307_MEM_WRITE: ++ return ds1307_write_mem(client, arg); ++ ++ default: ++ return -EINVAL; ++ } ++} ++ ++static int ++ds1307_rtc_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int ++ds1307_rtc_release(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int ++ds1307_rtc_ioctl( struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ unsigned long flags; ++ struct rtc_time wtime; ++ int status = 0; ++ ++ DPRINTK(2, "%s: cmd %c %x\n", __FUNCTION__, (char)(cmd>>8)&0xff, cmd&0xff); ++ ++ switch (cmd) { ++ default: ++ case RTC_UIE_ON: ++ case RTC_UIE_OFF: ++ case RTC_PIE_ON: ++ case RTC_PIE_OFF: ++ case RTC_AIE_ON: ++ case RTC_AIE_OFF: ++ case RTC_ALM_SET: ++ case RTC_ALM_READ: ++ case RTC_IRQP_READ: ++ case RTC_IRQP_SET: ++ case RTC_EPOCH_READ: ++ case RTC_EPOCH_SET: ++ case RTC_WKALM_SET: ++ case RTC_WKALM_RD: ++ status = -EINVAL; ++ break; ++ ++ case RTC_RD_TIME: ++ spin_lock_irqsave(&ds1307_rtc_lock, flags); ++ ds1307_command( ds1307_i2c_client, DS1307_GETDATETIME, &wtime); ++ spin_unlock_irqrestore(&ds1307_rtc_lock,flags); ++ ++ if( copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time))) ++ status = -EFAULT; ++ break; ++ ++ case RTC_SET_TIME: ++ if (!capable(CAP_SYS_TIME)) ++ { ++ status = -EACCES; ++ break; ++ } ++ ++ if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) ) ++ { ++ status = -EFAULT; ++ break; ++ } ++ ++ spin_lock_irqsave(&ds1307_rtc_lock, flags); ++ ds1307_command( ds1307_i2c_client, DS1307_SETDATETIME, &wtime); ++ spin_unlock_irqrestore(&ds1307_rtc_lock,flags); ++ break; ++ } ++ ++ return status; ++} ++ ++static char * ++ds1307_mon2str( unsigned int mon) ++{ ++ char *mon2str[12] = { ++ "Jan", "Feb", "Mar", "Apr", "May", "Jun", ++ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ++ }; ++ if( mon > 11) return "error"; ++ else return mon2str[ mon]; ++} ++ ++static int ds1307_rtc_proc_output( char *buf) ++{ ++#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no") ++ unsigned char ram[DS1307_RAM_SIZE]; ++ int ret; ++ ++ char *p = buf; ++ ++ ret = ds1307_readram( ram, DS1307_RAM_SIZE); ++ if( ret > 0) ++ { ++ int i; ++ struct rtc_time dt; ++ char text[9]; ++ ++ p += sprintf(p, "DS1307 (64x8 Serial Real Time Clock)\n"); ++ ++ ds1307_convert_to_time( &dt, ram); ++ p += sprintf(p, "Date/Time : %02d-%s-%04d %02d:%02d:%02d\n", ++ dt.tm_mday, ds1307_mon2str(dt.tm_mon), dt.tm_year + 1900, ++ dt.tm_hour, dt.tm_min, dt.tm_sec); ++ ++ p += sprintf(p, "Clock halted : %s\n", CHECK(ram[0],0x80)); ++ p += sprintf(p, "24h mode : %s\n", CHECK(ram[2],0x40)); ++ p += sprintf(p, "Square wave enabled : %s\n", CHECK(ram[7],0x10)); ++ p += sprintf(p, "Freq : "); ++ ++ switch( ram[7] & 0x03) ++ { ++ case RATE_1HZ: ++ p += sprintf(p, "1Hz\n"); ++ break; ++ case RATE_4096HZ: ++ p += sprintf(p, "4.096kHz\n"); ++ break; ++ case RATE_8192HZ: ++ p += sprintf(p, "8.192kHz\n"); ++ break; ++ case RATE_32768HZ: ++ default: ++ p += sprintf(p, "32.768kHz\n"); ++ break; ++ ++ } ++ ++ p += sprintf(p, "RAM dump:\n"); ++ text[8]='\0'; ++ for( i=0; i<DS1307_RAM_SIZE; i++) ++ { ++ p += sprintf(p, "%02X ", ram[i]); ++ ++ if( (ram[i] < 32) || (ram[i]>126)) ram[i]='.'; ++ text[i%8] = ram[i]; ++ if( (i%8) == 7) p += sprintf(p, "%s\n",text); ++ } ++ p += sprintf(p, "\n"); ++ } ++ else ++ { ++ p += sprintf(p, "Failed to read RTC memory!\n"); ++ } ++ ++ return p - buf; ++} ++ ++static int ds1307_rtc_read_proc(char *page, char **start, off_t off, ++ int count, int *eof, void *data) ++{ ++ int len = ds1307_rtc_proc_output (page); ++ if (len <= off+count) *eof = 1; ++ *start = page + off; ++ len -= off; ++ if (len>count) len = count; ++ if (len<0) len = 0; ++ return len; ++} ++ ++static __init int ds1307_init(void) ++{ ++ int retval=0; ++ ++ DPRINTK(1, "%s()\n", __FUNCTION__); ++ ++ if (slave_address != 0xffff) ++ { ++ DPRINTK(2, "%s: slave address is %#x\n", __FUNCTION__, slave_address); ++ normal_addr[0] = slave_address; ++ } ++ ++ if (normal_addr[0] == 0xffff) ++ { ++ printk(KERN_ERR"I2C: Invalid slave address for DS1307 RTC (%#x)\n", ++ normal_addr[0]); ++ return -EINVAL; ++ } ++ ++ retval = i2c_add_driver(&ds1307_driver); ++ ++ if (retval==0) ++ { ++ misc_register (&ds1307_rtc_miscdev); ++ create_proc_read_entry (PROC_DS1307_NAME, 0, 0, ds1307_rtc_read_proc, NULL); ++ printk("I2C: DS1307 RTC driver successfully loaded\n"); ++ if (rtc_debug > 2) ds1307_dumpram(); ++ } ++ return retval; ++} ++ ++static __exit void ds1307_exit(void) ++{ ++ DPRINTK(1, "%s()\n", __FUNCTION__); ++ remove_proc_entry (PROC_DS1307_NAME, NULL); ++ misc_deregister(&ds1307_rtc_miscdev); ++ i2c_del_driver(&ds1307_driver); ++} ++ ++module_init(ds1307_init); ++module_exit(ds1307_exit); ++ ++MODULE_PARM (slave_address, "i"); ++MODULE_PARM_DESC (slave_address, "I2C slave address for DS1307 RTC."); ++ ++MODULE_AUTHOR ("Intrinsyc Software Inc."); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/i2c/chips/ds1307.h b/drivers/i2c/chips/ds1307.h +new file mode 100644 +index 0000000..bf8cc20 +--- /dev/null ++++ b/drivers/i2c/chips/ds1307.h +@@ -0,0 +1,54 @@ ++/* ++ * ds1307.h ++ * ++ * Copyright (C) 2002 Intrinsyc Software Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++#ifndef DS1307_H ++#define DS1307_H ++ ++#define DS1307_I2C_SLAVE_ADDR 0x68 ++ ++#define DS1307_RAM_ADDR_START 0x08 ++#define DS1307_RAM_ADDR_END 0x3F ++#define DS1307_RAM_SIZE 0x40 ++ ++#define PROC_DS1307_NAME "driver/ds1307" ++ ++struct rtc_mem { ++ unsigned int loc; ++ unsigned int nr; ++ unsigned char *data; ++}; ++ ++#define DS1307_GETDATETIME 0 ++#define DS1307_SETTIME 1 ++#define DS1307_SETDATETIME 2 ++#define DS1307_GETCTRL 3 ++#define DS1307_SETCTRL 4 ++#define DS1307_MEM_READ 5 ++#define DS1307_MEM_WRITE 6 ++ ++#define SQW_ENABLE 0x10 /* Square Wave Enable */ ++#define SQW_DISABLE 0x00 /* Square Wave disable */ ++ ++#define RATE_32768HZ 0x03 /* Rate Select 32.768KHz */ ++#define RATE_8192HZ 0x02 /* Rate Select 8.192KHz */ ++#define RATE_4096HZ 0x01 /* Rate Select 4.096KHz */ ++#define RATE_1HZ 0x00 /* Rate Select 1Hz */ ++ ++#define CLOCK_HALT 0x80 /* Clock Halt */ ++ ++#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10) ++#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10) ++ ++#define TWELVE_HOUR_MODE(n) (((n)>>6)&1) ++#define HOURS_AP(n) (((n)>>5)&1) ++#define HOURS_12(n) BCD_TO_BIN((n)&0x1F) ++#define HOURS_24(n) BCD_TO_BIN((n)&0x3F) ++ ++#endif +diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c +index 02682fb..6a28f08 100644 +--- a/drivers/i2c/chips/ds1337.c ++++ b/drivers/i2c/chips/ds1337.c +@@ -338,12 +338,37 @@ exit: + static void ds1337_init_client(struct i2c_client *client) + { + s32 val; ++ u8 status, control; ++ ++ /* On some boards, the RTC isn't configured by boot firmware. ++ * Handle that case by starting/configuring the RTC now. ++ */ ++ status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS); ++ control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); ++ ++ if ((status & 0x80) || (control & 0x80)) { ++ /* RTC not running */ ++ u8 buf[16]; ++ struct i2c_msg msg[1]; ++ ++ dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__); ++ ++ /* Initialize all, including STATUS and CONTROL to zero */ ++ memset(buf, 0, sizeof(buf)); ++ msg[0].addr = client->addr; ++ msg[0].flags = 0; ++ msg[0].len = sizeof(buf); ++ msg[0].buf = &buf[0]; ++ ++ i2c_transfer(client->adapter, msg, 1); ++ } else { ++ /* Running: ensure that device is set in 24-hour mode */ ++ val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR); ++ if ((val >= 0) && (val & (1 << 6))) ++ i2c_smbus_write_byte_data(client, DS1337_REG_HOUR, ++ val & 0x3f); ++ } + +- /* Ensure that device is set in 24-hour mode */ +- val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR); +- if ((val >= 0) && (val & (1 << 6))) +- i2c_smbus_write_byte_data(client, DS1337_REG_HOUR, +- val & 0x3f); + } + + static int ds1337_detach_client(struct i2c_client *client) +diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig +index 1c81174..e0fcc08 100644 +--- a/drivers/ide/Kconfig ++++ b/drivers/ide/Kconfig +@@ -314,6 +314,18 @@ config BLK_DEV_CMD640_ENHANCED + and your BIOS does not already do this for you, then say Y here. + Otherwise say N. + ++config BLK_DEV_EP93XX ++ bool "EP93xx support" ++ depends on (ARCH_EP9312 || ARCH_EP9315) ++ help ++ If you want IDE support for your EP93xx based board say Y here. ++ ++config BLK_DEV_IDEDMA_EP93XX ++ bool "EP93xx DMA support" ++ depends on BLK_DEV_EP93XX && EP93XX_DMA ++ help ++ If you want DMA support for your EP93xx based board say Y here. ++ + config BLK_DEV_IDEPNP + bool "PNP EIDE support" + depends on PNP +@@ -813,7 +825,7 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ + depends BLK_DEV_IDE_AU1XXX + + config IDE_ARM +- def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK) ++ def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK || BLK_DEV_EP93XX) + + config BLK_DEV_IDE_ICSIDE + tristate "ICS IDE interface support" +@@ -1047,7 +1059,7 @@ config BLK_DEV_UMC8672 + endif + + config BLK_DEV_IDEDMA +- def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA ++ def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA || BLK_DEV_IDEDMA_EP93XX + + config IDEDMA_IVB + bool "IGNORE word93 Validation BITS" +diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile +index 6a78f07..cf0f91a 100644 +--- a/drivers/ide/arm/Makefile ++++ b/drivers/ide/arm/Makefile +@@ -2,5 +2,6 @@ + obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o + obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o + obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o ++obj-$(CONFIG_BLK_DEV_EP93XX) += ide-ep93xx.o + + EXTRA_CFLAGS := -Idrivers/ide +diff --git a/drivers/ide/arm/ide-ep93xx.c b/drivers/ide/arm/ide-ep93xx.c +new file mode 100644 +index 0000000..75fbbf5 +--- /dev/null ++++ b/drivers/ide/arm/ide-ep93xx.c +@@ -0,0 +1,1957 @@ ++/***************************************************************************** ++ * ++ * drivers/ide/ide-ep93xx.c ++ * ++ * Copyright (c) 2003 Cirrus Logic, Inc. ++ * ++ * Some code based in whole or in part on: ++ * ++ * linux/drivers/ide/ide-dma.c Version 4.13 May 21, 2003 ++ * ++ * Copyright (c) 1999-2000 Andre Hedrick <andre@linux-ide.org> ++ * May be copied or modified under the terms of the GNU General Public License ++ * ++ * Portions Copyright Red Hat 2003 ++ * ++ * Special Thanks to Mark for his Six years of work. ++ * ++ * Copyright (c) 1995-1998 Mark Lord ++ * May be copied or modified under the terms of the GNU General Public License ++ * ++ * ++ * Some code taken from the PowerMac implentation ++ * ++ * Copyright (C) 1998-2001 Paul Mackerras & Ben. Herrenschmidt ++ * ++ * 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 ++ * ++ * *************************************************************************** ++ * ++ * Cirrus Logic's EP93XX architecture specific ide driver. This driver ++ * supports the following ide transfer modes: ++ * PIO modes 0 - 4 ++ * MDMA modes 0 - 2 ++ * UDMA modes 0 - 4 ++ * ++ * 2/17/04 - TO - Initial DMA support. Only UDMA on ATA hard drives for now. ++ * ++ ****************************************************************************/ ++#include <linux/ide.h> ++#include <linux/delay.h> ++#include <asm/io.h> ++#include <asm/ide.h> ++#include <asm/io.h> ++ ++#include <asm/arch/ide.h> ++ ++#include <asm/arch/dma.h> ++#include <asm/hardware.h> ++ ++/***************************************************************************** ++ * ++ * Debugging macros ++ * ++ ****************************************************************************/ ++#undef DEBUG ++ /* #define DEBUG 1 */ ++#ifdef DEBUG ++#define DPRINTK( x... ) printk( ##x ) ++#else ++#define DPRINTK( x... ) ++#endif ++ ++/* ++ * IDE control register mask used when setting the CS0n, CS1n and DA bits ++ * in this register. ++ */ ++#define IDECR_REG_MASK (IDECtrl_CS0n | IDECtrl_CS1n | IDECtrl_DA_MASK) ++ ++/***************************************************************************** ++ * ++ * Functions and macros for handling dma transfers. ++ * ++ ****************************************************************************/ ++#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX ++ ++/***************************************************************************** ++ * ++ * Our Physical Region Descriptor (PRD) table should be large enough ++ * to handle the biggest I/O request we are likely to see. Since requests ++ * can have no more than 256 sectors, and since the typical blocksize is ++ * two or more sectors, we could get by with a limit of 128 entries here for ++ * the usual worst case. Most requests seem to include some contiguous blocks, ++ * further reducing the number of table entries required. ++ * ++ * The driver reverts to PIO mode for individual requests that exceed ++ * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling ++ * 100% of all crazy scenarios here is not necessary. ++ * ++ * As it turns out though, we must allocate a full 4KB page for this, ++ * so the two PRD tables (ide0 & ide1) will each get half of that, ++ * allowing each to have about 256 entries (8 bytes each) from this. ++ * ++ ****************************************************************************/ ++#define PRD_BYTES 8 ++#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES)) ++ ++/***************************************************************************** ++ * ++ * Global to keep track of the number of entries in the dma buffer ++ * table for each transfer. ++ * ++ ****************************************************************************/ ++static int g_prd_count; ++static unsigned int g_prd_total; ++static unsigned int g_prd_returned; ++static unsigned int g_dma_table_base; ++ ++/***************************************************************************** ++ * ++ * Global to set during the dma callback function to indicate that from ++ * the dma perspective, the transfer is complete. ++ * ++ ****************************************************************************/ ++static unsigned int g_done; ++ ++/***************************************************************************** ++ * ++ * The following is directly from ide-dma.c. ++ * ++ ****************************************************************************/ ++struct drive_list_entry { ++ const char *id_model; ++ const char *id_firmware; ++}; ++ ++static const struct ++drive_list_entry drive_whitelist[] = { ++ {"Micropolis 2112A", "ALL"}, ++ {"CONNER CTMA 4000", "ALL"}, ++ {"CONNER CTT8000-A", "ALL"}, ++ {"ST34342A", "ALL"}, ++ {NULL, NULL} ++}; ++ ++static const struct ++drive_list_entry drive_blacklist[] = { ++ {"WDC AC11000H", "ALL"}, ++ {"WDC AC22100H", "ALL"}, ++ {"WDC AC32500H", "ALL"}, ++ {"WDC AC33100H", "ALL"}, ++ {"WDC AC31600H", "ALL"}, ++ {"WDC AC32100H", "24.09P07"}, ++ {"WDC AC23200L", "21.10N21"}, ++ {"Compaq CRD-8241B", "ALL"}, ++ {"CRD-8400B", "ALL"}, ++ {"CRD-8480B", "ALL"}, ++ {"CRD-8480C", "ALL"}, ++ {"CRD-8482B", "ALL"}, ++ {"CRD-84", "ALL"}, ++ {"SanDisk SDP3B", "ALL"}, ++ {"SanDisk SDP3B-64", "ALL"}, ++ {"SANYO CD-ROM CRD", "ALL"}, ++ {"HITACHI CDR-8", "ALL"}, ++ {"HITACHI CDR-8335", "ALL"}, ++ {"HITACHI CDR-8435", "ALL"}, ++ {"Toshiba CD-ROM XM-6202B", "ALL"}, ++ {"CD-532E-A", "ALL"}, ++ {"E-IDE CD-ROM CR-840", "ALL"}, ++ {"CD-ROM Drive/F5A", "ALL"}, ++ {"RICOH CD-R/RW MP7083A", "ALL"}, ++ {"WPI CDD-820", "ALL"}, ++ {"SAMSUNG CD-ROM SC-148C", "ALL"}, ++ {"SAMSUNG CD-ROM SC-148F", "ALL"}, ++ {"SAMSUNG CD-ROM SC", "ALL"}, ++ {"SanDisk SDP3B-64", "ALL"}, ++ {"SAMSUNG CD-ROM SN-124", "ALL"}, ++ {"PLEXTOR CD-R PX-W8432T", "ALL"}, ++ {"ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL"}, ++ {"_NEC DV5800A", "ALL"}, ++ {NULL, NULL} ++}; ++ ++/***************************************************************************** ++ * ++ * This is directly from ide-dma.c ++ * ++ * in_drive_list - look for drive in black/white list ++ * @id: drive identifier ++ * @drive_table: list to inspect ++ * ++ * Look for a drive in the blacklist and the whitelist tables ++ * Returns 1 if the drive is found in the table. ++ * ++ ****************************************************************************/ ++static int ++in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table) ++{ ++ for (; drive_table->id_model; drive_table++) ++ if ((!strcmp(drive_table->id_model, id->model)) && ++ ((!strstr(drive_table->id_firmware, id->fw_rev)) || ++ (!strcmp(drive_table->id_firmware, "ALL")))) ++ return 1; ++ return 0; ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_intr() is the handler for disk read/write DMA interrupts ++ * ++ ****************************************************************************/ ++ide_startstop_t ep93xx_ide_dma_intr(ide_drive_t * drive) ++{ ++ int i; ++ byte stat, dma_stat; ++ ++ DPRINTK("\n dma_intr \n"); ++ ++ /* ++ * Disable the dma for this transfer and cleanup. ++ */ ++ dma_stat = ep93xx_ide_dma_end(drive); ++ ++ /* ++ * Get status from the ide device. ++ */ ++ stat = HWIF(drive)->INB(IDE_STATUS_REG); ++ ++ if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) { ++ if (!dma_stat) { ++ struct request *rq = HWGROUP(drive)->rq; ++ ++ for (i = rq->nr_sectors; i > 0;) { ++ i -= rq->current_nr_sectors; ++ DRIVER(drive)->end_request(drive, 1); ++ } ++ ++ return ide_stopped; ++ } ++ ++ printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", ++ drive->name, dma_stat); ++ } ++ ++ return DRIVER(drive)->error(drive, __FUNCTION__, stat); ++} ++ ++/***************************************************************************** ++ * ++ * ide_build_sglist() ++ * ++ * Builds a table of buffers to be used by the dma. Each buffer consists ++ * of a region of memory which is contiguous in virtual memory. ++ * ++ ****************************************************************************/ ++static int ide_build_sglist(ide_hwif_t * hwif, struct request *rq) ++{ ++ struct buffer_head *buf_head; ++ struct scatterlist *sg = hwif->sg_table; ++ int nents = 0; ++ ++ if (hwif->sg_dma_active) ++ BUG(); ++ ++ DPRINTK("\nbuild_sglist: sg_table 0x%x, ", hwif->sg_table); ++ ++ /* ++ * Set up the direction of the command ++ */ ++ if (rq->cmd == READ) { ++ hwif->sg_dma_direction = EP93XX_DMA_FROMDEVICE; ++ } else { ++ hwif->sg_dma_direction = EP93XX_DMA_TODEVICE; ++ } ++ ++ /* ++ * Get a pointer to the buffer head. ++ */ ++ buf_head = rq->bh; ++ ++ do { ++ unsigned char *virt_addr = buf_head->b_data; ++ unsigned int size = buf_head->b_size; ++ ++ if (nents >= PRD_ENTRIES) { ++ return 0; ++ } ++ ++ while ((buf_head = buf_head->b_reqnext) != NULL) { ++ if ((virt_addr + size) != ++ (unsigned char *)buf_head->b_data) { ++ break; ++ } ++ ++ size += buf_head->b_size; ++ } ++ memset(&sg[nents], 0, sizeof(*sg)); ++ sg[nents].address = virt_addr; ++ sg[nents].length = size; ++ nents++; ++ } while (buf_head != NULL); ++ ++ /* ++ * This call to map_sg will return the number of entries ++ * for which DMAable memory could be mapped. ++ */ ++ return ep93xx_map_sg(sg, nents, hwif->sg_dma_direction); ++} ++ ++/**************************************************************************** ++ * ++ * report_drive_dmaing() ++ * ++ ****************************************************************************/ ++int report_drive_dmaing(ide_drive_t * drive) ++{ ++ struct hd_driveid *id = drive->id; ++ ++ if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && ++ (id->dma_ultra & (id->dma_ultra >> 14) & 3)) { ++ if ((id->dma_ultra >> 15) & 1) { ++ /* ++ * UDMA enabled ++ */ ++ printk(", UDMA(mode 7)"); ++ } else { ++ /* ++ * UDMA enabled. ++ */ ++ printk(", UDMA(133)"); ++ } ++ } else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) && ++ (id->dma_ultra & (id->dma_ultra >> 11) & 7)) { ++ DPRINTK("\n report_drive_dmaing: %d \n", id->dma_ultra); ++ if ((id->dma_ultra >> 13) & 1) { ++ /* ++ * UDMA enabled! ++ */ ++ printk(", UDMA(100)"); ++ } else if ((id->dma_ultra >> 12) & 1) { ++ /* ++ * UDMA enabled. ++ */ ++ printk(", UDMA(66)"); ++ } else { ++ /* ++ * UDMA enabled. ++ */ ++ printk(", UDMA(44)"); ++ } ++ } else if ((id->field_valid & 4) && ++ (id->dma_ultra & (id->dma_ultra >> 8) & 7)) { ++ if ((id->dma_ultra >> 10) & 1) { ++ /* ++ * UDMA enabled. ++ */ ++ printk(", UDMA(33)"); ++ } else if ((id->dma_ultra >> 9) & 1) { ++ /* ++ * UDMA enabled. ++ */ ++ printk(", UDMA(25)"); ++ } else { ++ /* ++ * UDMA enabled. ++ */ ++ printk(", UDMA(16)"); ++ } ++ } else if (id->field_valid & 4) { ++ /* ++ * Can be enabled. ++ */ ++ printk(", (U)DMA capable, but not enabled"); ++ } else { ++ /* ++ * maybe MDMA? ++ */ ++ printk(", DMA"); ++ } ++ ++ return 1; ++} ++ ++/***************************************************************************** ++ * ++ * ide_build_dmatable() prepares a dma request. ++ * Returns 0 if all went okay, returns 1 otherwise. ++ * ++ ****************************************************************************/ ++int ide_build_dmatable(ide_drive_t * drive) ++{ ++ unsigned int *table = HWIF(drive)->dmatable_cpu; ++ unsigned int count = 0; ++ int i; ++ struct scatterlist *sg; ++ unsigned int is_trm290_chipset = 0; ++ ++ HWIF(drive)->sg_nents = i = ++ ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq); ++ ++ if (!i) ++ return 0; ++ ++ sg = HWIF(drive)->sg_table; ++ ++ while (i && sg_dma_len(sg)) { ++ u32 cur_addr; ++ u32 cur_len; ++ ++ cur_addr = sg_dma_address(sg); ++ cur_len = sg_dma_len(sg); ++ ++ /* 1 ++ * Fill in the dma table, without crossing any 64kB boundaries. ++ * Most hardware requires 16-bit alignment of all blocks, ++ * but the trm290 requires 32-bit alignment. ++ */ ++ while (cur_len) { ++ ++ if (count++ >= PRD_ENTRIES) { ++ printk("%s: DMA table too small\n", ++ drive->name); ++ goto use_pio_instead; ++ } else { ++ u32 xcount, bcount = ++ 0x10000 - (cur_addr & 0xffff); ++ ++ if (bcount > cur_len) ++ bcount = cur_len; ++ *table++ = cpu_to_le32(cur_addr); ++ xcount = bcount & 0xffff; ++ if (is_trm290_chipset) ++ xcount = ((xcount >> 2) - 1) << 16; ++ if (xcount == 0x0000) { ++ /* ++ * Most chipsets correctly interpret a length of 0x0000 as 64KB, ++ * but at least one (e.g. CS5530) misinterprets it as zero (!). ++ * So here we break the 64KB entry into two 32KB entries instead. ++ */ ++ if (count++ >= PRD_ENTRIES) { ++ printk ++ ("%s: DMA table too small\n", ++ drive->name); ++ goto use_pio_instead; ++ } ++ *table++ = cpu_to_le32(0x8000); ++ *table++ = ++ cpu_to_le32(cur_addr + 0x8000); ++ xcount = 0x8000; ++ } ++ *table++ = cpu_to_le32(xcount); ++ cur_addr += bcount; ++ cur_len -= bcount; ++ } ++ } ++ sg++; ++ i--; ++ } ++ ++ if (count) { ++ if (!is_trm290_chipset) ++ *--table |= cpu_to_le32(0x80000000); ++ return count; ++ } ++ printk("%s: empty DMA table?\n", drive->name); ++ ++ use_pio_instead: ++ /* ++ * Revert to PIO for this request. ++ */ ++ HWIF(drive)->sg_dma_active = 0; ++ return 0; ++} ++ ++/***************************************************************************** ++ * ++ * ide_destroy_dmatable() ++ * ++ * Teardown mappings after DMA has completed. ++ * ++ ****************************************************************************/ ++void ide_destroy_dmatable(ide_drive_t * drive) ++{ ++ /* ++ * Restore the original dma table base address. ++ */ ++ HWIF(drive)->dmatable_cpu = g_dma_table_base; ++ ++ /* ++ * Nothing much to do here. ++ */ ++ HWIF(drive)->sg_dma_active = 0; ++} ++ ++/***************************************************************************** ++ * ++ * ide_release_dma() ++ * ++ * This function releases the memory allocated for the scatter gather list ++ * and for the dma table, and frees the dma channel. ++ * ++ ****************************************************************************/ ++void ep93xx_ide_release_dma(ide_hwif_t * hwif) ++{ ++ /* ++ * Check if we have a valid dma handle. ++ */ ++ if (hwif->hw.dma != NULL) { ++ /* ++ * Pause the DMA channel. ++ */ ++ ep93xx_dma_pause(hwif->hw.dma, 1, 0); ++ ++ /* ++ * Flush the DMA channel ++ */ ++ ep93xx_dma_flush(hwif->hw.dma); ++ } ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_callback() ++ * ++ * Registered with the ep93xx dma driver and called at the end of the dma ++ * interrupt handler, this function should process the dma buffers. ++ * ++ ****************************************************************************/ ++ ++static void ++ep93xx_ide_callback(ep93xx_dma_int_t dma_int, ep93xx_dma_dev_t device, ++ unsigned int user_data) ++{ ++ ide_drive_t *drive = (ide_drive_t *) user_data; ++ ide_hwif_t *hwif = HWIF(drive); ++ unsigned int temp; ++ ++ /* ++ * Retrieve from the dma interface as many used buffers as are ++ * available. ++ */ ++ while (ep93xx_dma_remove_buffer(hwif->hw.dma, &temp) == 0) { ++ g_prd_returned++; ++ ++ } ++ ++ /* ++ * Add new buffers if we have any available. ++ */ ++ while (g_prd_count) { ++ /* ++ * Check if this is a read or write operation. ++ */ ++ if (hwif->sg_dma_direction == 2) { ++ /* ++ * Set up buffers for a read op. ++ */ ++ temp = ++ ep93xx_dma_add_buffer(hwif->hw.dma, hwif->dma_base, ++ *hwif->dmatable_cpu++, ++ *hwif->dmatable_cpu++, 0, ++ g_prd_count); ++ } else { ++ /* ++ * Set up buffers for a write op. ++ */ ++ temp = ++ ep93xx_dma_add_buffer(hwif->hw.dma, ++ *hwif->dmatable_cpu++, ++ hwif->dma_base, ++ *hwif->dmatable_cpu++, 0, ++ g_prd_count); ++ } ++ ++ /* ++ * Add a buffer to the dma interface. ++ */ ++ if (temp != 0) { ++ /* ++ * This buffer didn't make it into the dma ++ * interface, so move the dma table pointer ++ * to the start of the current entry. ++ */ ++ hwif->dmatable_cpu -= 4; ++ break; ++ } ++ ++ /* ++ * Decrement the count of dmatable entries ++ */ ++ g_prd_count--; ++ } ++ ++ /* ++ * Check if the transfer is complete. ++ */ ++ if (dma_int == DONE) { ++ g_done = 1; ++ } ++ ++ if (g_prd_returned == g_prd_total) { ++ g_done = 1; ++ } ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_dma_timer_expiry() ++ * ++ * ++ * dma_timer_expiry - handle a DMA timeout ++ * @drive: Drive that timed out ++ * ++ * An IDE DMA transfer timed out. In the event of an error we ask ++ * the driver to resolve the problem, if a DMA transfer is still ++ * in progress we continue to wait (arguably we need to add a ++ * secondary 'I dont care what the drive thinks' timeout here) ++ * Finally if we have an interrupt we let it complete the I/O. ++ * But only one time - we clear expiry and if it's still not ++ * completed after WAIT_CMD, we error and retry in PIO. ++ * This can occur if an interrupt is lost or due to hang or bugs. ++ * ++ * ++ ****************************************************************************/ ++static int ep93xx_idedma_timer_expiry(ide_drive_t * drive) ++{ ++ ide_hwif_t *hwif = HWIF(drive); ++ u8 dev_stat = hwif->INB(IDE_ALTSTATUS_REG); ++ u8 irq_stat = ep93xx_ide_regs->IDECR.Value & IDECtrl_INTRQ; ++ ++ printk(KERN_WARNING ++ "%s: dma_timer_expiry: dev status == 0x%02x, done= %d, irq= %d\n", ++ drive->name, dev_stat, g_done, irq_stat); ++ ++ /* ++ * Check if the device is busy, or the dma engine is still working. ++ */ ++ if ((dev_stat & 0x80) || !g_done) /* BUSY Stupid Early Timer !! */ ++ return (2 * WAIT_CMD); ++ ++ /* ++ * Clear the expiry handler in case we decide to wait more, ++ * next time timer expires it is an error ++ */ ++ HWGROUP(drive)->expiry = NULL; ++ ++ /* ++ * the device is not busy, so check if there's an error, or if the ++ * interrupt is asserted. ++ */ ++ if (dev_stat & 0x01) /* ERROR */ ++ return -1; ++ ++ if (irq_stat || g_done) /* Got an Interrupt or the dma is done */ ++ return WAIT_CMD; ++ ++ return 0; /* Unknown status -- reset the bus */ ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_config_ide_dma() ++ * ++ * This function allocates dma-able memory and configures the ep93xx dma ++ * interface for use with the ide interface. This only need be done ++ * once for the interface. So, if this is the second drive, we don't have ++ * much to do here. ++ * ++ ****************************************************************************/ ++static int ep93xx_config_ide_dma(ide_drive_t * drive) ++{ ++ DPRINTK("ep93xx_config_ide_dma\n"); ++ ++ /* ++ * Success. ++ */ ++ return 0; ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_config_ide_device() ++ * ++ * This function sets up the ep93xx ide device for a dma transfer by first ++ * probing to find the best dma mode supported by the device. ++ * ++ * Returns a 0 for success, and a 1 otherwise. ++ * ++ ****************************************************************************/ ++static unsigned int ep93xx_config_ide_device(ide_drive_t * drive) ++{ ++ struct hd_driveid *id = drive->id; ++ byte transfer = 0; ++ ++ DPRINTK("%s: ep93xx_config_ide_device - dma on\n", HWIF(drive)->name); ++ ++ /* ++ * check if the device supports a udma mode. ++ */ ++ if (transfer = (id->dma_ultra & 0x001F)) { ++ DPRINTK("IDE: udma xfer support, transfer = %d \n", transfer); ++ ++ /* ++ * UDMA mode 4 support. ++ */ ++ if (transfer & 0x10) { ++ transfer = XFER_UDMA_4; ++ } ++ /* ++ * UDMA mode 3 support. ++ */ ++ else if (transfer & 0x08) { ++ transfer = XFER_UDMA_3; ++ } ++ /* ++ * UDMA mode 2. ++ */ ++ else if (transfer & 0x04) { ++ transfer = XFER_UDMA_2; ++ } ++ /* ++ * UDMA mode 1. ++ */ ++ else if (transfer & 0x02) { ++ transfer = XFER_UDMA_1; ++ } ++ /* ++ * UDMA mode 0. ++ */ ++ else if (transfer & 0x01) { ++ transfer = XFER_UDMA_0; ++ } ++ } ++ /* ++ * The device doesn't support a udma mode, so check if it ++ * supports an mdma mode. ++ */ ++ else if (transfer = (drive->id->dma_mword & 0x0007)) { ++ DPRINTK("IDE: mdma support, transfer = %d \n", transfer); ++ ++ /* ++ * MDMA mode 2. ++ */ ++ if (transfer & 0x04) { ++ transfer = XFER_MW_DMA_2; ++ } ++ /* ++ * MDMA mode 1. ++ */ ++ else if (transfer & 0x02) { ++ transfer = XFER_MW_DMA_1; ++ } ++ /* ++ * MDMA mode 0. ++ */ ++ else if (transfer & 0x01) { ++ transfer = XFER_MW_DMA_0; ++ } ++ } ++ ++ if (transfer == 0) { ++ DPRINTK("IDE: config device failed \n"); ++ ++ /* ++ * Fail. ++ */ ++ return 1; ++ } ++ ++ if (ide_config_drive_speed(drive, transfer) == 0) { ++ printk("%s: %s selected\n", drive->name, ++ ide_xfer_verbose(transfer)); ++ ++ /* ++ * Hold on to this value for use later. ++ */ ++ drive->current_speed = transfer; ++ ++ /* ++ * Success, so turn on DMA. ++ */ ++ return ep93xx_ide_dma_on(drive); ++ } else { ++ return ep93xx_ide_dma_off(drive); ++ } ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_set_pio() ++ * ++ * Configures the ep93xx controller for a PIO mode transfer. ++ * ++ ****************************************************************************/ ++static void ep93xx_set_pio(void) ++{ ++ /* ++ * Disable the interface. ++ */ ++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 0; ++ ++ /* ++ * Enable PIO mode of operation. ++ */ ++ ep93xx_ide_regs->IDECFG.Field.PIO = 1; ++ ep93xx_ide_regs->IDECFG.Field.UDMA = 0; ++ ep93xx_ide_regs->IDECFG.Field.MDMA = 0; ++ ++ /* ++ * Enable the IDE interface. ++ */ ++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 1; ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_rwproc() ++ * ++ * Initializes the ep93xx IDE controller interface with the transfer type, ++ * transfer mode, and transfer direction. ++ * ++ ****************************************************************************/ ++static void ep93xx_rwproc(ide_drive_t * drive, int action) ++{ ++ unsigned int temp; ++ ++ DPRINTK("\nep93xx_rwproc \n"); ++ /* ++ * Configure the IDE controller for the specified transfer mode. ++ */ ++ switch (drive->current_speed) { ++ /* ++ * Configure for an MDMA operation. ++ */ ++ case XFER_MW_DMA_0: ++ case XFER_MW_DMA_1: ++ case XFER_MW_DMA_2: ++ { ++ DPRINTK("\n ep93xx set up for MDMA \n"); ++ ep93xx_ide_regs->IDECFG.Field.PIO = 0; ++ ep93xx_ide_regs->IDECFG.Field.UDMA = 0; ++ ep93xx_ide_regs->IDECFG.Field.MDMA = 1; ++ ep93xx_ide_regs->IDECFG.Field.MODE = ++ (0x3 & drive->current_speed); ++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 1; ++ ep93xx_ide_regs->IDEMDMAOP.Field.RWOP = action; ++ ep93xx_ide_regs->IDEMDMAOP.Field.MEN = 1; ++ break; ++ } ++ ++ /* ++ * Configure for a UDMA operation. ++ */ ++ case XFER_UDMA_0: ++ case XFER_UDMA_1: ++ case XFER_UDMA_2: ++ case XFER_UDMA_3: ++ case XFER_UDMA_4: ++ { ++ DPRINTK("\n ep93xx set up for UDMA \n"); ++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 0; ++ ep93xx_ide_regs->IDEUDMAOP.Field.UEN = 0; ++ ep93xx_ide_regs->IDECFG.Field.PIO = 0; ++ ep93xx_ide_regs->IDECFG.Field.MDMA = 0; ++ ep93xx_ide_regs->IDECFG.Field.UDMA = 0; ++ ep93xx_ide_regs->IDECFG.Field.WST = 0; ++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 1; ++ ++ ep93xx_ide_regs->IDECFG.Field.MODE = ++ (0x7 & drive->current_speed); ++ ep93xx_ide_regs->IDECFG.Field.UDMA = 1; ++ ep93xx_ide_regs->IDEUDMAOP.Field.RWOP = action; ++ temp = ep93xx_ide_regs->IDEUDMAOP.Value; ++ ep93xx_ide_regs->IDEUDMAOP.Field.UEN = 1; ++ temp = ep93xx_ide_regs->IDEUDMAOP.Value; ++ ++ DPRINTK("\nIDE Regs: config - 0x%x, udmaop - 0x%x \n", ++ ep93xx_ide_regs->IDECFG.Value, ++ ep93xx_ide_regs->IDEUDMAOP.Value); ++ ++ break;; ++ } ++ ++ default: ++ { ++ break; ++ } ++ } ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_check() ++ * ++ * This function determines if the device supports dma transfers, and if it ++ * does, then enables dma. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_check(ide_drive_t * drive) ++{ ++ ide_hwif_t *hwif = HWIF(drive); ++ struct hd_driveid *id = drive->id; ++ ++ DPRINTK("%s: ep93xx_ide_dma_check \n", drive->name); ++ ++ if (!id || !(id->capability & 1) || !hwif->autodma) { ++ /* ++ * Disable dma for this drive. ++ */ ++ ep93xx_ide_dma_off(drive); ++ } ++ ++ /* ++ * Consult the list of known "bad" drives ++ */ ++ if (in_drive_list(id, drive_blacklist)) { ++ printk("%s: Disabling DMA for %s (blacklisted)\n", ++ drive->name, id->model); ++ ++ /* ++ * Disable dma for this drive. ++ */ ++ ep93xx_ide_dma_off(drive); ++ } ++ ++ /* ++ * Check if the drive supports multiword dma or udma modes. ++ * If it does, then set the device up for that ++ * type of dma transfer, and call ep93xx_ide_dma_on. ++ */ ++ return ep93xx_config_ide_device(drive); ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_host_off() ++ * ++ * This function disables dma for the host. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_host_off(ide_drive_t * drive) ++{ ++ ide_hwif_t *hwif = HWIF(drive); ++ ++ /* ++ * TODO: what's to be done here? ++ */ ++ DPRINTK("%s: ep93xx_ide_dma_host_off() \n", drive->name); ++ ++ /* ++ * Release the dma channel and all memory allocated for dma ++ * purposes. ++ */ ++ ep93xx_ide_release_dma(hwif); ++ ++ return 0; ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_off_quietly() ++ * ++ * This function, without announcing it, disables dma for the device. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_off_quietly(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_off_quietly: \n", drive->name); ++ ++ /* ++ * Clear the using_dma field to indicate that dma is disabled ++ * for this drive. ++ */ ++ drive->using_dma = 0; ++ ++ /* ++ * Disable dma on the host side. ++ */ ++ ep93xx_ide_dma_host_off(drive); ++ ++ return 0; ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_off() ++ * ++ * This function disables dma for the device. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_off(ide_drive_t * drive) ++{ ++ printk("%s: DMA disabled\n", drive->name); ++ ++ return ep93xx_ide_dma_off_quietly(drive); ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_on() ++ * ++ * This function enables dma for the device. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_on(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_on: \n", drive->name); ++ ++ if (drive->using_dma) { ++ DPRINTK("%s: ep93xx_ide_dma_on, already on! \n", drive->name); ++ return 0; ++ } ++ ++ /* ++ * Set the using_dma field to indicate that dma is enabled. ++ */ ++ drive->using_dma = 1; ++ ++ /* ++ * Enable DMA on the host side. ++ */ ++ return ep93xx_ide_dma_host_on(drive); ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_host_on() ++ * ++ * This function enables dma for the device. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_host_on(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_host_on: \n", drive->name); ++ ++ /* ++ * Enable the ep93xx dma interface for use with IDE. ++ */ ++ return ep93xx_config_ide_dma(drive); ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_read() ++ * ++ * This function sets up a dma read operation. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_read(ide_drive_t * drive) ++{ ++ unsigned int flags, result; ++ ide_hwif_t *hwif = HWIF(drive); ++ ++ DPRINTK("%s: ep93xx_ide_dma_read: \n", drive->name); ++ ++ /* ++ * Check if we are already transferring on this dma channel. ++ */ ++ BUG_ON(hwif->sg_dma_active); ++ ++ /* ++ * Configure DMA M2M channel flags for a source address hold, h/w ++ * initiated P2M transfer. ++ */ ++ flags = (SOURCE_HOLD | TRANSFER_MODE_HW_P2M); ++ ++ if (drive->current_speed & 0x20) { ++ flags |= (WS_IDE_MDMA_READ_WRITE << WAIT_STATES_SHIFT); ++ ++ /* ++ * MDMA data register address. ++ */ ++ hwif->dma_base = 0x800A001C; ++ } else { ++ flags |= (WS_IDE_UDMA_READ << WAIT_STATES_SHIFT); ++ ++ /* ++ * UDMA data register address. ++ */ ++ hwif->dma_base = 0x800a0024; ++ } ++ ++ /* ++ * Configure the dma interface for this IDE operation. ++ */ ++ if (ep93xx_dma_config(hwif->hw.dma, 0, flags, ep93xx_ide_callback, ++ (unsigned int)drive) != 0) { ++ DPRINTK("%s: ep93xx_ide_dma_read: ERROR- dma config failed", ++ drive->name); ++ ++ /* ++ * Fail. ++ */ ++ return 1; ++ } ++ ++ /* ++ * Build the table of dma-able buffers. ++ */ ++ if (!(g_prd_count = ide_build_dmatable(drive))) { ++ DPRINTK ++ ("%s: ep93xx_ide_dma_read: ERROR- failed to build dma table", ++ drive->name); ++ ++ /* ++ * Fail, try PIO instead of DMA ++ */ ++ return 1; ++ } ++ ++ /* ++ * Indicate that we're waiting for dma. ++ */ ++ drive->waiting_for_dma = 1; ++ ++ hwif->sg_dma_active = 1; ++ ++ /* ++ * test stuff ++ */ ++ g_prd_total = g_prd_count; ++ g_prd_returned = 0; ++ g_dma_table_base = hwif->dmatable_cpu; ++ ++ /* ++ * Prepare the dma interface with some buffers from the ++ * dma_table. ++ */ ++ do { ++ /* ++ * Add a buffer to the dma interface. ++ */ ++ result = ep93xx_dma_add_buffer(hwif->hw.dma, hwif->dma_base, ++ *hwif->dmatable_cpu++, ++ *hwif->dmatable_cpu++, 0, ++ g_prd_count); ++ ++ if (result != 0) { ++ /* ++ * This buffer didn't make it into the dma ++ * interface, so move the dma table pointer ++ * to the start of the current entry. ++ */ ++ hwif->dmatable_cpu -= 4; ++ break; ++ } ++ ++ /* ++ * Decrement the count of dmatable entries ++ */ ++ g_prd_count--; ++ ++ } while (g_prd_count); ++ ++ /* ++ * Check if this is a disk or cd drive. ++ */ ++ if (drive->media == ide_disk) { ++ /* ++ * Send the read command to the device. ++ */ ++ ide_execute_command(drive, WIN_READDMA, &ep93xx_ide_dma_intr, ++ 4 * WAIT_CMD, &ep93xx_idedma_timer_expiry); ++ ++ } ++ ++ /* ++ * Configure the ep93xx ide controller for a dma read operation. ++ */ ++ ep93xx_rwproc(drive, 0); ++ ++ /* ++ * initiate the dma transfer. ++ */ ++ return ep93xx_ide_dma_begin(drive); ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_write() ++ * ++ * This function sets up a dma write operation. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_write(ide_drive_t * drive) ++{ ++ unsigned int flags, result; ++ ide_hwif_t *hwif = HWIF(drive); ++ ++ DPRINTK("%s: ep93xx_ide_dma_write: \n", drive->name); ++ ++ /* ++ * Check if we are already transferring on this dma channel. ++ */ ++ BUG_ON(hwif->sg_dma_active); ++ ++ /* ++ * Configure DMA M2M channel flags for a destination address ++ * hold, h/w initiated M2P transfer. ++ */ ++ flags = (DESTINATION_HOLD | TRANSFER_MODE_HW_M2P); ++ ++ /* ++ * Determine if we need the MDMA or UDMA data register. ++ */ ++ if (drive->current_speed & 0x20) { ++ flags |= (WS_IDE_MDMA_READ_WRITE << WAIT_STATES_SHIFT); ++ ++ /* ++ * MDMA data register address. ++ */ ++ hwif->dma_base = 0x800A0018; ++ } else { ++ flags |= (WS_IDE_UDMA_WRITE << WAIT_STATES_SHIFT); ++ ++ /* ++ * UDMA data register address. ++ */ ++ hwif->dma_base = 0x800a0020; ++ } ++ ++ /* ++ * Configure the dma interface for this IDE operation. ++ */ ++ if (ep93xx_dma_config(hwif->hw.dma, 0, flags, ep93xx_ide_callback, ++ (unsigned int)drive) != 0) { ++ return 1; ++ } ++ ++ /* ++ * Build the table of dma-able buffers. ++ */ ++ if (!(g_prd_count = ide_build_dmatable(drive))) { ++ /* ++ * Fail, try PIO instead of DMA ++ */ ++ return 1; ++ } ++ ++ /* ++ * Indicate that we're waiting for dma. ++ */ ++ drive->waiting_for_dma = 1; ++ ++ hwif->sg_dma_active = 1; ++ ++ /* ++ * test stuff ++ */ ++ g_prd_total = g_prd_count; ++ g_prd_returned = 0; ++ g_dma_table_base = hwif->dmatable_cpu; ++ ++ /* ++ * Prepare the dma interface with some buffers from the ++ * dma_table. ++ */ ++ do { ++ /* ++ * Add a buffer to the dma interface. ++ */ ++ result = ++ ep93xx_dma_add_buffer(hwif->hw.dma, *hwif->dmatable_cpu++, ++ hwif->dma_base, *hwif->dmatable_cpu++, ++ 0, g_prd_count); ++ ++ if (result != 0) { ++ /* ++ * This buffer didn't make it into the dma ++ * interface, so move the dma table pointer ++ * to the start of the current entry. ++ */ ++ hwif->dmatable_cpu -= 4; ++ break; ++ } ++ ++ /* ++ * Decrement the count of dmatable entries ++ */ ++ g_prd_count--; ++ ++ } while (g_prd_count); ++ ++ /* ++ * Check if this is a disk or cd drive. ++ */ ++ if (drive->media == ide_disk) { ++ /* ++ * Send the write dma command to the device. ++ */ ++ ide_execute_command(drive, WIN_WRITEDMA, &ep93xx_ide_dma_intr, ++ 4 * WAIT_CMD, &ep93xx_idedma_timer_expiry); ++ } ++ ++ /* ++ * Configure the ep93xx ide controller for a dma read operation. ++ */ ++ ep93xx_rwproc(drive, 1); ++ ++ /* ++ * initiate the dma transfer. ++ */ ++ return ep93xx_ide_dma_begin(drive); ++ ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_begin() ++ * ++ * This function initiates a dma transfer. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_begin(ide_drive_t * drive) ++{ ++ ide_hwif_t *hwif = HWIF(drive); ++ ++ DPRINTK("%s: ep93xx_ide_dma_begin: \n", drive->name); ++ ++ /* Note that this is done *after* the cmd has ++ * been issued to the drive, as per the BM-IDE spec. ++ * The Promise Ultra33 doesn't work correctly when ++ * we do this part before issuing the drive cmd. ++ */ ++ g_done = 0; ++ ++ /* ++ * Start the dma transfer. ++ */ ++ ep93xx_dma_start(hwif->hw.dma, 1, NULL); ++ ++ /* ++ * TODO: not sure if we need to keep track of the end ++ * of the transfer from the dma perspective, but ++ * for now, let's do it. ++ */ ++ return 0; ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_end() ++ * ++ * This function performs any tasks needed to cleanup after a dma transfer. ++ * Returns 1 if an error occured, and 0 otherwise. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_end(ide_drive_t * drive) ++{ ++ unsigned char dev_stat; ++ ide_hwif_t *hwif = HWIF(drive); ++ ++ DPRINTK("%s: ep93xx_ide_dma_end: \n", drive->name); ++ ++ /* ++ * Indicate there's no dma transfer currently in progress. ++ */ ++ drive->waiting_for_dma = 0; ++ ++ /* ++ * Put the dma interface into pause mode. ++ */ ++ ep93xx_dma_pause(hwif->hw.dma, 1, 0); ++ ep93xx_dma_flush(hwif->hw.dma); ++ ++ /* ++ * Enable PIO mode on the IDE interface. ++ */ ++ ep93xx_set_pio(); ++ ++ /* ++ * Read the ide device status register. This clears the interrupt. ++ * TODO: should I read the alt status instead to prevent clearing ++ * an asserted interrupt?? ++ */ ++ dev_stat = hwif->INB(IDE_STATUS_REG); ++ ++ /* ++ * Purge the contents of the dma table of buffer entries. ++ */ ++ ide_destroy_dmatable(drive); ++ ++ hwif->sg_dma_active = 0; ++ ++ /* ++ * If the error bit is set in the device status register, ++ * return a positive value. ++ */ ++ if (dev_stat & ERR_STAT) { ++ printk("ide_dma_end: device error \n"); ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_test_irq() ++ * ++ * This function checks if the IDE interrupt is asserted and returns a ++ * 1 if it is, and 0 otherwise.. ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_test_irq(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_test_irq: \n", drive->name); ++ ++ if (!drive->waiting_for_dma) ++ printk(KERN_WARNING "%s: (%s) called while not waiting\n", ++ drive->name, __FUNCTION__); ++ ++ /* ++ * TODO: need to use the io macros to get this value. ++ * Return the value of the IDE interrupt bit. ++ */ ++ return (ep93xx_ide_regs->IDECR.Value & IDECtrl_INTRQ); ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_bad_drive() ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_bad_drive(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_bad_drive: \n", drive->name); ++ ++ return 0; ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_good_drive() ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_good_drive(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_good_drive: \n", drive->name); ++ ++ /* ++ * TODO: need to implement. ++ */ ++ return 0; ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_count() ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_count(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_count: \n", drive->name); ++ ++ return 0; ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_verbose() ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_verbose(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_verbose: \n", drive->name); ++ ++ printk(", %s ", ide_xfer_verbose(drive->current_speed)); ++ ++ return 1; ++ ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_bad_timeout() ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_timeout(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_timeout: \n", drive->name); ++ ++ printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name); ++ if (HWIF(drive)->ide_dma_test_irq(drive)) ++ return 0; ++ return HWIF(drive)->ide_dma_end(drive); ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_retune() ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_retune(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_retune\n", drive->name); ++ return 1; ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_dma_lostirq() ++ * ++ ****************************************************************************/ ++int ep93xx_ide_dma_lostirq(ide_drive_t * drive) ++{ ++ DPRINTK("%s: ep93xx_ide_dma_lostirq\n", drive->name); ++ printk("%s: DMA interrupt recovery\n", drive->name); ++ ++ return 1; ++} ++ ++#endif /* CONFIG_BLK_DEV_IDEDMA_EP93XX */ ++ ++/***************************************************************************** ++ * ++ * functions to set up the IDE control register and data register to read ++ * or write a byte of data to/from the specified IDE device register. ++ * ++ ****************************************************************************/ ++static void ep93xx_ide_outb(u8 b, unsigned long addr) ++{ ++ unsigned int uiIDECR; ++ ++ DPRINTK("ep93xx_ide_outb, addr:%02lx data: %04x\n", addr, b); ++ ++ /* ++ * Write the address out (CS0n, CS1n, DA) fields only. ++ */ ++ uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK); ++ writel(uiIDECR, IDECtrl); ++ ++ writel((unsigned int)b, IDEDataOut); ++ ++ /* ++ * Toggle Write signal. ++ */ ++ uiIDECR &= ~IDECtrl_DIOWn; ++ writel(uiIDECR, IDECtrl); ++ uiIDECR |= IDECtrl_DIOWn; ++ writel(uiIDECR, IDECtrl); ++} ++ ++static void ep93xx_ide_outbsync(ide_drive_t * drive, u8 b, unsigned long addr) ++{ ++ unsigned int uiIDECR; ++ ++ DPRINTK("ep93xx_ide_outbsync, addr:%02lx data: %04x\n", addr, b); ++ ++ /* ++ * Write the address out (CS0n, CS1n, DA) fields only. ++ */ ++ uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK); ++ writel(uiIDECR, IDECtrl); ++ ++ writel((unsigned int)b, IDEDataOut); ++ ++ /* ++ * Toggle Write signal. ++ */ ++ uiIDECR &= ~IDECtrl_DIOWn; ++ writel(uiIDECR, IDECtrl); ++ uiIDECR |= IDECtrl_DIOWn; ++ writel(uiIDECR, IDECtrl); ++} ++ ++static unsigned char ep93xx_ide_inb(unsigned long addr) ++{ ++ unsigned int uiIDECR; ++ ++ DPRINTK("ep93xx_ide_inb addr: %04lx ", addr); ++ ++ /* ++ * Write the address out (CS0n, CS1n, DA) fields only. ++ */ ++ uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK); ++ writel(uiIDECR, IDECtrl); ++ ++ /* ++ * Toggle Read signal. ++ */ ++ uiIDECR &= ~IDECtrl_DIORn; ++ writel(uiIDECR, IDECtrl); ++ uiIDECR |= IDECtrl_DIORn; ++ writel(uiIDECR, IDECtrl); ++ ++ DPRINTK("data: %02x\n", readl(IDEDataIn)); ++ return (unsigned char)readl(IDEDataIn); ++} ++ ++/***************************************************************************** ++ * ++ * functions to set up the IDE control register and data restister to read ++ * or write 16 bits of data to/from the specified IDE device register. ++ * These functions should only be used when reading/writing data to/from ++ * the data register. ++ * ++ ****************************************************************************/ ++static void ep93xx_ide_outw(u16 w, unsigned long addr) ++{ ++ unsigned int uiIDECR; ++ ++ DPRINTK("ep93xx_ide_outw addr: %04lx data: %04x\n", addr, w); ++ ++ /* ++ * Write the address out (CS0n, CS1n, DA) fields only. ++ */ ++ uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK); ++ writel(uiIDECR, IDECtrl); ++ ++ writel((unsigned int)w, IDEDataOut); ++ ++ /* ++ * Toggle Write signal. ++ */ ++ uiIDECR &= ~IDECtrl_DIOWn; ++ writel(uiIDECR, IDECtrl); ++ uiIDECR |= IDECtrl_DIOWn; ++ writel(uiIDECR, IDECtrl); ++} ++ ++static u16 ep93xx_ide_inw(unsigned long addr) ++{ ++ unsigned int uiIDECR; ++ ++ DPRINTK("ep93xx_ide_inw addr: %04lx ", addr); ++ ++ /* ++ * Write the address out (CS0n, CS1n, DA) fields only. ++ */ ++ uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK); ++ writel(uiIDECR, IDECtrl); ++ ++ /* ++ * Toggle Read signal. ++ */ ++ uiIDECR &= ~IDECtrl_DIORn; ++ writel(uiIDECR, IDECtrl); ++ uiIDECR |= IDECtrl_DIORn; ++ writel(uiIDECR, IDECtrl); ++ ++ DPRINTK("data: %04x\n", readl(IDEDataIn)); ++ return (unsigned short)readl(IDEDataIn); ++} ++ ++/***************************************************************************** ++ * ++ * functions to read/write a block of data to/from the ide device using ++ * PIO mode. ++ * ++ ****************************************************************************/ ++static void ep93xx_ide_insw(unsigned long addr, void *buf, u32 count) ++{ ++ unsigned short *data = (unsigned short *)buf; ++ unsigned char status; ++ DPRINTK("ep93xx_ide_insw\n"); ++ ++ /* ++ * Read in data from the data register 16 bits at a time. ++ */ ++ while (count) { ++ /* ++ * Read the status register. ++ */ ++ status = ep93xx_ide_inb((STATUSREGISTER << 2) + 2); ++ ++ /* ++ * Check for the BSY to be clear and DRQ to be set. ++ */ ++ if ((status & ATADRQ) && !(status & ATABSY)) { ++ *data = ep93xx_ide_inw(addr); ++ data++; ++ count--; ++ } ++ } ++} ++ ++static void ep93xx_ide_outsw(unsigned long addr, void *buf, u32 count) ++{ ++ unsigned short *data = (unsigned short *)buf; ++ unsigned char status; ++ ++ DPRINTK("ep93xx_ide_outsw\n"); ++ ++ /* ++ * Write out data to the data register 16 bits at a time. ++ */ ++ while (count) { ++ /* ++ * Read the status register. ++ */ ++ status = ep93xx_ide_inb((STATUSREGISTER << 2) + 2); ++ ++ /* ++ * Check for the BSY to be clear and DRQ to be set. ++ */ ++ if ((status & ATADRQ) && !(status & ATABSY)) { ++ ep93xx_ide_outw(*data, addr); ++ data++; ++ count--; ++ } ++ } ++} ++ ++static void ep93xx_ide_outl(u32 l, unsigned long addr) ++{ ++ printk("ep93xx_ide_outl\n"); ++} ++ ++static u32 ep93xx_ide_inl(unsigned long addr) ++{ ++ printk("ep93xx_ide_inl\n"); ++ return 0; ++} ++ ++static void ep93xx_ide_outsl(unsigned long addr, void *buf, u32 count) ++{ ++ printk("ep93xx_ide_inl\n"); ++} ++ ++static void ep93xx_ide_insl(unsigned long addr, void *buf, u32 count) ++{ ++ printk("ep93xx_ide_inl\n"); ++} ++ ++/***************************************************************************** ++ * ++ * Functions to read/write a block of data to/from the ide device using ++ * PIO mode, using an ATAPI interface. ++ * ++ ****************************************************************************/ ++static void ep93xx_ide_insw_atapi(unsigned int addr, void *buf, int count) ++{ ++ DPRINTK("ep93xx_ide_insw_atapi \n"); ++ ++ /* ++ * Convert count from bytes to half words. ++ */ ++ if (count % 2) { ++ count = count / 2; ++ count++; ++ } else { ++ count = count / 2; ++ } ++ ++ /* ++ * Call the function which will read in the data. ++ */ ++ ep93xx_ide_insw(addr, buf, count); ++} ++ ++static void ep93xx_ide_outsw_atapi(unsigned int addr, void *buf, int count) ++{ ++ DPRINTK("ep93xx_ide_outsw_atapi \n"); ++ ++ /* ++ * Convert count from bytes to half words. ++ */ ++ if (count % 2) { ++ count = count / 2; ++ count++; ++ } else { ++ count = count / 2; ++ } ++ ++ /* ++ * Call the function which will write out the data. ++ */ ++ ep93xx_ide_outsw(addr, buf, count); ++} ++ ++void ep93xx_ata_input_data(ide_drive_t * drive, void *buffer, u32 count) ++{ ++ DPRINTK("ep93xx_ata_input_data \n"); ++ ++ /* ++ * Read in the specified number of half words from the ide interface. ++ */ ++ ep93xx_ide_insw(IDE_DATA_REG, buffer, count << 1); ++} ++ ++void ep93xx_ata_output_data(ide_drive_t * drive, void *buffer, u32 count) ++{ ++ DPRINTK("ep93xx_ata_output_data \n"); ++ ++ /* ++ * write the specified number of half words from the ide interface ++ * to the ide device. ++ */ ++ ep93xx_ide_outsw(IDE_DATA_REG, buffer, count << 1); ++} ++ ++void ep93xx_atapi_input_bytes(ide_drive_t * drive, void *buffer, u32 count) ++{ ++ DPRINTK("ep93xx_atapi_input_bytes \n"); ++ ++ /* ++ * read in the specified number of bytes from the ide interface. ++ */ ++ ep93xx_ide_insw_atapi(IDE_DATA_REG, buffer, count); ++} ++ ++void ep93xx_atapi_output_bytes(ide_drive_t * drive, void *buffer, u32 count) ++{ ++ DPRINTK("ep93xx_atapi_output_bytes \n"); ++ ++ /* ++ * Write the specified number of bytes from the ide interface ++ * to the ide device. ++ */ ++ ep93xx_ide_outsw_atapi(IDE_DATA_REG, buffer, count); ++} ++ ++/***************************************************************************** ++ * ++ * ep93xx_ide_init() ++ * ++ * This function sets up a pointer to the ep93xx specific ideproc funciton. ++ * ++ ****************************************************************************/ ++void ep93xx_ide_init(struct hwif_s *hwif) ++{ ++ ++ DPRINTK("ep93xx_ide_init \n"); ++ ++ /* ++ * Set up the HW interface function pointers with the ep93xx specific ++ * function. ++ */ ++ hwif->ata_input_data = ep93xx_ata_input_data; ++ hwif->ata_output_data = ep93xx_ata_output_data; ++ hwif->atapi_input_bytes = ep93xx_atapi_input_bytes; ++ hwif->atapi_output_bytes = ep93xx_atapi_output_bytes; ++ ++ hwif->OUTB = ep93xx_ide_outb; ++ hwif->OUTBSYNC = ep93xx_ide_outbsync; ++ hwif->OUTW = ep93xx_ide_outw; ++ hwif->OUTL = ep93xx_ide_outl; ++ hwif->OUTSW = ep93xx_ide_outsw; ++ hwif->OUTSL = ep93xx_ide_outsl; ++ ++ hwif->INB = ep93xx_ide_inb; ++ hwif->INW = ep93xx_ide_inw; ++ hwif->INL = ep93xx_ide_inl; ++ hwif->INSW = ep93xx_ide_insw; ++ hwif->INSL = ep93xx_ide_insl; ++ ++#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX ++ ++ DPRINTK("ep93xx_ide_init- dma enabled \n"); ++ ++ printk(" %s: SG-DMA", hwif->name); ++ ++ /* ++ * Allocate dma-able memory space, in one consistent chunk. The call ++ * to alloc_consistent will return a virtual address and fill in a dma ++ * physical address. (arch/arm/mm/consistent.c) ++ * ++ */ ++ hwif->dmatable_cpu = consistent_alloc(GFP_KERNEL | GFP_DMA, ++ PRD_ENTRIES * PRD_BYTES, ++ &hwif->dmatable_dma); ++ ++ /* ++ * Check if we allocated memory for dma ++ */ ++ if (hwif->dmatable_cpu == NULL) { ++ printk(" -- disabled, UNABLE TO ALLOCATE DMA TABLES\n"); ++ return; ++ } ++ ++ DPRINTK(" %s: EP93XX-DMA at 0x%x - 0x%x \n", hwif->name, ++ hwif->dmatable_dma, ++ (unsigned int)(hwif->dmatable_dma + (PRD_ENTRIES * PRD_BYTES))); ++ ++ /* ++ * Allocate memory for the scatterlist structures. ++ */ ++ hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES, ++ GFP_KERNEL); ++ ++ /* ++ * Check if we allocated the memory we expected to. ++ */ ++ if (hwif->sg_table == NULL) { ++ /* ++ * Fail, so clean up. ++ */ ++ consistent_free(hwif->dmatable_cpu, PRD_ENTRIES * PRD_BYTES, ++ hwif->dmatable_dma); ++ printk(" -- disabled, UNABLE TO ALLOCATE DMA TABLES\n"); ++ return; ++ } ++ ++ /* ++ * Init the dma handle to 0. This field is used to hold a handle to the ++ * dma instance. ++ */ ++ hwif->hw.dma = NULL; ++ ++ /* ++ * Open an instance of the ep93xx dma interface. ++ */ ++ if (ep93xx_dma_request(&hwif->hw.dma, hwif->name, DMA_IDE) != 0) { ++ /* ++ * Fail, so clean up. ++ */ ++ consistent_free(hwif->dmatable_cpu, PRD_ENTRIES * PRD_BYTES, ++ hwif->dmatable_dma); ++ kfree(hwif->sg_table); ++ printk(" -- disabled, unable to allocate DMA channel.\n"); ++ } ++ ++ /* ++ * Now that we've got a dma channel allocated, set up the rest of the ++ * dma specific stuff. ++ */ ++ else { ++ DPRINTK("\n ide init- dma channel allocated: %d \n", ++ hwif->hw.dma); ++ ++ /* ++ * Enable dma support for atapi devices. ++ */ ++ hwif->atapi_dma = 1; ++ ++ /* ++ * TODO: how are these used? ++ */ ++ hwif->mwdma_mask = 7; /* MW0..2 */ ++ hwif->ultra_mask = 7; /* SW0..2 */ ++ ++ hwif->speedproc = NULL; ++ hwif->autodma = 1; ++ ++ hwif->ide_dma_check = ep93xx_ide_dma_check; ++ hwif->ide_dma_host_off = ep93xx_ide_dma_host_off; ++ hwif->ide_dma_off_quietly = ep93xx_ide_dma_off_quietly; ++ hwif->ide_dma_off = ep93xx_ide_dma_off; ++ hwif->ide_dma_host_on = ep93xx_ide_dma_host_on; ++ hwif->ide_dma_on = ep93xx_ide_dma_on; ++ hwif->ide_dma_read = ep93xx_ide_dma_read; ++ hwif->ide_dma_write = ep93xx_ide_dma_write; ++ hwif->ide_dma_count = ep93xx_ide_dma_count; ++ hwif->ide_dma_begin = ep93xx_ide_dma_begin; ++ hwif->ide_dma_end = ep93xx_ide_dma_end; ++ hwif->ide_dma_test_irq = ep93xx_ide_dma_test_irq; ++ hwif->ide_dma_verbose = ep93xx_ide_dma_verbose; ++ hwif->ide_dma_timeout = ep93xx_ide_dma_timeout; ++ hwif->ide_dma_lostirq = ep93xx_ide_dma_lostirq; ++ ++ printk(" capable%s\n", hwif->autodma ? ", auto-enable" : ""); ++ } ++ ++#endif ++} +diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c +index 23488c4..cc411c2 100644 +--- a/drivers/ide/arm/ide_arm.c ++++ b/drivers/ide/arm/ide_arm.c +@@ -20,6 +20,15 @@ + # define IDE_ARM_HOST (1) + #endif + ++/* FIXME: Part 1 of dirty hack to get IDE working for EP93XX Processor */ ++#ifdef CONFIG_BLK_DEV_EP93XX ++#include <asm/arch/ide.h> ++#ifndef IRQ_HARDDISK ++# define IRQ_HARDDISK -1 ++#endif ++#endif ++/* END OF HACK */ ++ + #ifdef CONFIG_ARCH_CLPS7500 + # include <asm/arch/hardware.h> + # +@@ -36,8 +45,15 @@ void __init ide_arm_init(void) + hw_regs_t hw; + + memset(&hw, 0, sizeof(hw)); ++ ++/* FIXME: Part 2 of dirty hack to get IDE working for EP93XX Processor */ ++#ifdef CONFIG_BLK_DEV_EP93XX ++ old_ide_init_default_hwifs(); ++#else + ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206); + hw.irq = IDE_ARM_IRQ; + ide_register_hw(&hw, NULL); ++#endif + } ++ + } +diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig +index 4a91774..68c06fa 100644 +--- a/drivers/input/keyboard/Kconfig ++++ b/drivers/input/keyboard/Kconfig +@@ -193,4 +193,38 @@ config KEYBOARD_HIL + This driver implements support for HIL-keyboards attached + to your machine, so normally you should say Y here. + ++config KEYBOARD_EP93XX ++ tristate "EP93xx Keyboard support" ++ depends on ARCH_EP93XX && INPUT && INPUT_KEYBOARD ++ default y ++ help ++ This is support for the Cirrus EP93xx Keyboards. Say yes here if you ++ have such a CPU, and choose some drivers below. ++ ++config KEYBOARD_EP93XX_SPI ++ bool "EP93xx PS2 Keyboard support" ++ depends on KEYBOARD_EP93XX ++ help ++ Say Y here if you want support for a PS2 keyboard connected via SPI. ++ ++config KEYBOARD_EP93XX_8X8 ++ bool "EP93xx 8x8 keypad matrix support" ++ depends on KEYBOARD_EP93XX ++ help ++ Say Y here if you have a 8x8 keypad connected to your EP93xx. ++ You might want to generate a custom keymap for it. ++ If you do not have such a keypad, say N. ++ ++config KEYBOARD_EP93XX_8X8_CYCLING ++ bool "EP93xx 8x8 keypad matrix keycode cycling support" ++ depends on KEYBOARD_EP93XX_8X8 ++ help ++ Key cycling feature - assign more than one keycode per key. ++ If you press such a key more than twice per second, alternative ++ keycodes will be cycled through. ++ This should result in a behavoir similar to some mobile phones. ++ You might want to generate a custom keymap for this feature, too. ++ See the sourcecode for known limitations. ++ Say N unless you really need it. ++ + endif +diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile +index 9ce0b87..7ac6fca 100644 +--- a/drivers/input/keyboard/Makefile ++++ b/drivers/input/keyboard/Makefile +@@ -17,4 +17,6 @@ obj-$(CONFIG_KEYBOARD_CORGI) += corgikb + obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o + obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o + obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o ++obj-$(CONFIG_KEYBOARD_EP93XX_8X8) += ep93xx_kbd_8x8.o ++obj-$(CONFIG_KEYBOARD_EP93XX_SPI) += ep93xx_spi_kbd.o + +diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8.c b/drivers/input/keyboard/ep93xx_kbd_8x8.c +new file mode 100644 +index 0000000..d772381 +--- /dev/null ++++ b/drivers/input/keyboard/ep93xx_kbd_8x8.c +@@ -0,0 +1,482 @@ ++/****************************************************************************** ++ * ++ * File: linux/drivers/input/keyboard/ep93xx_kbd_8x8.c ++ * ++ * Purpose: Support for Cirrus EP93xx architecture core keyboard scanner. ++ * ++ * ++ * History: 2005-08-10 Michael Burian added "cycling keys" support ++ * 2004-05-28 Michael Burian ported to 2.6.6 ++ * ++ * 010406 Norman Farquhar at LynuxWorks ++ * ++ * Initial version ++ * - Will scan keyboard and feed keyboard.c, which translates ++ * to input codes and puts them into tty console queue. ++ * - Raw mode tbd ++ * - keymaps other than default not supported ++ * - does not support standby mode yet ++ * ++ * Limitations: ++ * 1. The EP93xx is limited to supporting small keyboards ++ * and cannot handle full PC style keyboards and key usage: ++ * a) 64 key limit: 8x8 key matrix ++ * b) limited to 2 keys down MAXIMUM, ++ * which makes it impossible to support SHIFT+SHIFT+KEY ++ * states like shift-control or control-alt keys. ++ * 2. This means the default keyboard, 83key CherryG84-4001QAU/02, ++ * will have some dead keys. ++ * ++ * ++ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA. All rights reserved. ++ * ++ *============================================================================= ++ * Overview of EP93xx Scan Keyboard driver ++ *============================================================================= ++ * ++ * The EP93xx scanned keyboard driver is a low-level hardware driver which ++ * supports the core logic scanned keyboard controller block of the ++ * EP93xx. These machines are embedded systems and this keyboard driver ++ * can support small keyboards. ++ * ++ * The keyboard driver does not have a normal device driver interface ++ * and instead interfaces to the keyboard.c driver through function calls. ++ * Note that not all interface function calls are implemented at this time. ++ * (see /asm/arch/keyboard.h for function definitions): ++ * ++ * ep93xxkbd_init ++ * initializes the scan keyboard hw. ++ * ++ * handle_scancode ++ * when scan controller generates interrupt, handler ++ * used to pass scan codes to queue in keyboard.c with this function call. ++ * ++ * UPDATE: Now this is inplemented right here and just used as a ++ * wrapper for the input layer ++ * ++ * Note that key scan codes will be delivered by this driver on both ++ * key down and key up events, using a coding similar to PC XT keyboard. ++ * ++ * Note however that scan compatibility and key code compatibility ++ * to PC standard are not required by Linux, and are not guaranteed. ++ * ++ ******************************************************************************/ ++#include <linux/config.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/sched.h> ++#include <linux/interrupt.h> ++#include <linux/input.h> ++#include <linux/init.h> ++#include <asm/io.h> ++#include <asm/uaccess.h> ++#include <asm/arch/keyboard.h> ++#include <asm/hardware.h> ++ ++#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING ++#include "ep93xx_kbd_8x8_keymap-cycling.h" ++#else ++#include "ep93xx_kbd_8x8_keymap.h" ++#endif ++ ++#define EP93XX_KEYMAP_SIZE (8*8) ++ ++/* #define DEBUG */ ++ ++#define KEYREG_KEY1_MASK 0x0000003F ++#define KEYREG_KEY1_SHIFT 0 ++#define KEYREG_KEY2_MASK 0x00000Fc0 ++#define KEYREG_KEY2_SHIFT 6 ++ ++#define KEYREG_KEY1ROW_MASK 0x00000007 ++#define KEYREG_KEY1ROW_SHIFT 0 ++#define KEYREG_KEY1COL_MASK 0x00000038 ++#define KEYREG_KEY1COL_SHIFT 3 ++ ++#define KEYREG_KEY2ROW_MASK 0x000001c0 ++#define KEYREG_KEY2ROW_SHIFT 6 ++#define KEYREG_KEY2COL_MASK 0x00000E00 ++#define KEYREG_KEY2COL_SHIFT 9 ++ ++#define KEYREG_1KEY 0x00001000 ++#define KEYREG_2KEYS 0x00002000 ++#define KEYREG_INT 0x00004000 ++#define KEYREG_K 0x00008000 ++ ++#define SCANINIT_DIS3KY 0x00008000 ++ ++static struct input_dev *dev; ++ ++#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING ++struct last_key_event { ++ unsigned long jiffies; ++ unsigned char scancode; ++}; ++ ++static struct last_key_event lke; ++ ++/** ++ * handle_scancode - wrapper ++ * ++ * We need to do two things here: ++ * 1. wrap old style (2.4.x) to 2.6.x input subsystem ++ * 2. also implement the key cycling feature here. ++ * CYCLING FEATURE: ++ * If the same key is pressed withing 500ms, we send a delete ++ * character to delete the former key, and use the keycode from the next layer ++ * instead. This should result "mobile phone" like behavior. ++ * KNOWN BUG: ++ * This will mess up anything that depends on single keystrokes ++ * (raw mode, non canonical mode, hotkeys, ...) ++ * TODO 1: ++ * A possible fix would be to delay till we know for sure what key it is ++ * and send just that key, but in that case the user would have to type ++ * blindly. :( ++ * TODO 2: ++ * A possible enhancement to the fix would be to provide some kind of preview ++ * with an additional character device and write some userspace app to display ++ * it in a seperate dialog. ++ * ++ */ ++static void handle_scancode(unsigned char scancode, int down) ++{ ++ unsigned char row = (scancode & 0xF) - 1; ++ unsigned char col = ((scancode & 0x70) >> 4); ++ unsigned char index = row * 8 + col; ++ static int layer = 0; ++ ++ /* ++ * straight forward processing in case of: ++ * "up" events ++ * repeated keypress events that happen after more than 500ms ++ * after different key has been pressed ( ignore up/down! ) ++ * there are no alternative keycodes available ++ */ ++ if (!down || time_before(lke.jiffies + msecs_to_jiffies(500), jiffies) ++ || (lke.scancode & 0x7f) != (scancode &0x7F) || ++ (keycode[1][index] == KEY_RESERVED) ) { ++ /* no cycling: process straightforward */ ++ input_report_key(dev, keycode[0][index], down); ++ input_sync(dev); ++ ++ /* end cycling on all but up events */ ++ if(down) ++ layer=0; ++ } else { ++ /* ++ * cycling mode: ++ * ++ * if we have an alternative keycode available: ++ * 1. pretend the former key was wrong (and delete it) ++ * 2. replace with the keycode from the next layer ++ */ ++ ++ /* suppress real "up" events, as we fake immediate "up" here */ ++ if (!down) ++ return; ++ ++ /* switch to next layer, with wraparound */ ++ if(++layer >= 16) ++ layer = 0; ++ ++ /* if alternative keycodes are available */ ++ if (keycode[layer][index] != KEY_RESERVED) { ++ /* pretend former key was wrong and delete it */ ++ input_report_key(dev, KEY_BACKSPACE, 1); ++ input_report_key(dev, KEY_BACKSPACE, 0); ++ } else { ++ /* no more valid keycodes? => switch to layer 0 */ ++ layer=0; ++ return; ++ } ++ ++ /* send alternative keycode */ ++ input_report_key(dev, keycode[layer][index], 1); ++ input_report_key(dev, keycode[layer][index], 0); ++ input_sync(dev); ++ ++ ++ } ++ lke.scancode = scancode; ++ lke.jiffies = jiffies; ++} ++#else ++/** ++ * handle_scancode - wrapper ++ * ++ * wrap old style (2.4.x) to 2.6.x input subsystem ++ */ ++static void handle_scancode(unsigned char scancode, int down) ++{ ++ /* printk("handle_scancode(scancode=%04X, down=%d); %02X ", scancode, down, scancode &0x7f); */ ++ ++ unsigned char row = (scancode & 0xF) - 1; ++ unsigned char col = ((scancode & 0x70) >> 4); ++ unsigned char index = row * 8 + col; ++ ++ input_report_key(dev, keycode[index], down); ++ input_sync(dev); ++ ++ /* printk("index=%02X\n", index); */ ++} ++#endif ++ ++static irqreturn_t ep93xxkbd_irq_handler(int irq, void *dev_id, ++ struct pt_regs *regs) ++{ ++ unsigned int keystat, key1, key2; ++ static unsigned int lastkeystat = 0, lastkey1 = 0, lastkey2 = 0; ++ ++ /* Note: IRQ_KEY automatically disabled before entry, */ ++ /* and reenabled after exit by Linux interrupt code. */ ++ ++ /* Reading status clears keyboard interrupt */ ++ ++ keystat = readl(KEY_REG) & ++ (KEYREG_KEY1COL_MASK | KEYREG_KEY1ROW_MASK | ++ KEYREG_KEY2COL_MASK | KEYREG_KEY2ROW_MASK | ++ KEYREG_1KEY | KEYREG_2KEYS); ++ ++#ifdef DEBUG /* DEBUGGING */ ++ if (keystat == lastkeystat) ++ printk("ep93xx_scan_keyb: spurious interrupt, stat %x\n", ++ keystat); ++ else ++ printk("ep93xx_scan_keyb: interrupt, stat %x\n", keystat); ++#endif ++ if (keystat & KEYREG_1KEY) ++ key1 = ++ KEYCODE((keystat & KEYREG_KEY1ROW_MASK) >> ++ KEYREG_KEY1ROW_SHIFT, ++ (keystat & KEYREG_KEY1COL_MASK) >> ++ KEYREG_KEY1COL_SHIFT); ++ else ++ key1 = 0; /* invalid */ ++ ++ if (keystat & KEYREG_2KEYS) ++ key2 = ++ KEYCODE((keystat & KEYREG_KEY2ROW_MASK) >> ++ KEYREG_KEY2ROW_SHIFT, ++ (keystat & KEYREG_KEY2COL_MASK) >> ++ KEYREG_KEY2COL_SHIFT); ++ else ++ key2 = 0; /* invalid */ ++ ++ /* ++ * This 'monster' decision tree is used to decide what to report ++ * when last key state has changed to current key state. ++ * This may involve up to 4 keys changing state simultaneously: ++ * lastkey1, lastkey2 going up and key1, key2 going down. ++ * ++ * We use keyboard scanner hardware guarantees to simplify the logic: ++ * key1 < key2 if both are valid ++ * key1 is valid if key2 is valid ++ * ++ * handle_scancode called with down and up scancodes ++ * scancode = keycode when down ++ * scancode = keycode|KBUP when up ++ * ++ * Note that if more than one keys change state in the same scan period, ++ * then we really do NOT know the order in which the key events occurred. ++ * Our default behavior is to always report key up events before key down ++ * events. However, multiple key up events or multiple key down events ++ * will be reported in no special order. ++ */ ++ if (!(lastkeystat & (KEYREG_1KEY | KEYREG_2KEYS))) { /* No keys down lasttime */ ++ if (key1) ++ handle_scancode(key1, 1); ++ if (key2) ++ handle_scancode(key2, 1); ++ } else if (lastkey1 == key1) { /* means key still down */ ++ /* no change for key1 or lastkey1, both valid */ ++ if (lastkey2 != key2) { ++ /* lastkey2 went up if valid, key2 went down if valid */ ++ if (lastkey2) ++ handle_scancode(lastkey2 | KBUP, 0); ++ if (key2) ++ handle_scancode(key2, 1); ++ } ++ /* else no change for all keys */ ++ } else if (key1) ++ { /* key1 valid and */ ++ /* lastkey1 valid (because NOT no keys lasttime) */ ++ if (lastkey1 == key2) { ++ /* no change for lastkey1 or key2 */ ++ /* lastkey2 went up if valid, key1 went down */ ++ if (lastkey2) ++ handle_scancode(lastkey2 | KBUP, 0); ++ handle_scancode(key1, 1); ++ ++ } else { ++ /* we know: lastkey1 valid and went up, key1 valid */ ++ handle_scancode(lastkey1 | KBUP, 0); ++ ++ if (lastkey2 == key1) { ++ /* no change for lastkey2 or key1 */ ++ /* key2 went down if valid */ ++ if (key2) ++ handle_scancode(key2, 1); ++ ++ } else { ++ if (lastkey2 != key2) { ++ /* lastkey2 went up if valid */ ++ /* key2 went down if valid */ ++ if (lastkey2) ++ handle_scancode(lastkey2 | KBUP, ++ 0); ++ if (key2) ++ handle_scancode(key2, 1); ++ } ++ /* else no change for lastkey2 or key2 */ ++ ++ /* key1 valid and went down */ ++ handle_scancode(key1, 1); ++ } ++ } ++ } else { ++ /* key1 not valid and */ ++ /* lastkey1 valid (because NOT no keys lasttime) */ ++ ++ /* key1 not valid means both key1, key2 not valid */ ++ /* so lastkey1 went up and lastkey2 went up if valid */ ++ handle_scancode(lastkey1 | KBUP, 0); ++ if (lastkey2) ++ handle_scancode(lastkey2 | KBUP, 0); ++ } ++ ++ lastkeystat = keystat; ++ lastkey1 = key1; ++ lastkey2 = key2; ++ return IRQ_HANDLED; ++} ++ ++int __init ep93xxkbd_init(void) ++{ ++ int i = 3; ++ unsigned int uiTemp; ++ int error = 0; ++ ++ dev = input_allocate_device(); ++ if (!dev) { ++ printk(KERN_ERR "ep93xx_kbd_8x8: not enough memory for input device\n"); ++ return -ENOMEM; ++ } ++ ++ dev->name = "Cirrus EP93xx 8x8 keypad matrix driver"; ++ dev->phys = "input0"; ++ dev->id.bustype = BUS_HOST; ++ dev->evbit[0] = BIT(EV_KEY); ++ ++ printk("%s\n", dev->name); ++ ++ /* Make sure scanner enabled, active and that */ ++ /* Keyboard ROW/COL interface enabled. */ ++ ++ uiTemp = readl(SYSCON_DEVCFG); ++ ++ uiTemp &= ~(SYSCON_DEVCFG_KEYS | SYSCON_DEVCFG_GONK); ++ ++ SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(uiTemp)); ++ ++ /* SYSCON locked automatically now after RSTCR written */ ++ ++ /* Enable Keyboard Clock and select clock rate ++ * ++ * TBD Boot ROM has already inited KTDIV = 0x20018004 ++ * TBD Measured default 64usec scan period with scope. ++ ++ * Assume that GPIO registers do not impact row,col pins since ++ * they are assigned to keyboard scanner. ++ ++ * Setup Keyboard Scanner ++ * ++ * Note that we change the scanner parameters on the fly ++ * while it is running, which is okay. No need to disable ++ * scanner while tweaking these. ++ * ++ * TBD Keyboard scan rate will change as master clocks/dividers change ++ * ++ * For now, this gives us measured rate of about 480Hz row scan rate, ++ * which implies 60Hz full kbd scan rate. Together with debounce ++ * count of 3, means debounce period = 3/60Hz = 50ms>30ms recommended, ++ * so okay. ++ */ ++ writel((0x00FC00FA | SCANINIT_DIS3KY), SCANINIT); ++ ++ /*TBD If too much capacitance on keyboard */ ++ /* writel( (0x00FC0020 | SCBACK | SCDIS3KEY), SCANINIT ); */ ++ ++ uiTemp = readl(SYSCON_KTDIV) | SYSCON_KTDIV_KEN; ++ ++ SysconSetLocked(SYSCON_KTDIV, uiTemp); ++ ++ error = ++ request_irq(IRQ_KEY, ep93xxkbd_irq_handler, 0, ++ "ep93xx_keypad_handler", ++ (void *)(ep93xxkbd_irq_handler)); ++ if (error) { ++ printk("Error: %s could not allocate IRQ%d\n", dev->name, IRQ_KEY); ++ return error; ++ } ++ /* Note: request_irq has just enabled IRQ_KEY for us. */ ++ ++ /* Warning: We have initialized last key status to indicate ++ * all keys up which may not be the current hardware state. ++ * ++ * TBD If this is important to detect, to alert user ++ * TBD to a possibly faulty keyboard, then we could ++ * TBD manually scan the keyboard to verify all keys up. ++ * ++ ++ * Three common cases here: ++ * 1. All keys up. This is normal, expected status of keyboard. ++ * 2. All keys up, although at some time ago during initialization ++ * a key was momentarily pressed, causing the hardware to latch it. ++ * 3. Some key is being held down now. ++ * ++ * Reading status clears any pending keyboard interrupt. ++ */ ++ ++ i = readl(KEY_REG); ++ ++ /* ++ * We believe this will have the following impact on common cases: ++ * ++ * 1. No impact. ++ * 2. Momentary presses will be cleared out so they do not ++ * bother us. Although we get a spurious key up immediately because ++ * the keyboard hardware will see change from last ++ * latched status and current status, higher level keyboard driver ++ * should ignore. ++ * 3. Key being held will generate a new pending key down ++ * event which is acceptable. ++ * ++ * Now keyboard is active and will generate interrupts ++ * on key presses. Driver only needs to handle interrupts. ++ * There are NO driver ioctl or deinit functions in lowlevel. ++ */ ++ ++#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING ++ for (i = 0; i < EP93XX_KEYMAP_SIZE * 16; i++) ++ set_bit(keycode[i/EP93XX_KEYMAP_SIZE][i%EP93XX_KEYMAP_SIZE], dev->keybit); ++#else ++ for (i = 0; i < EP93XX_KEYMAP_SIZE; i++) ++ set_bit(keycode[i], dev->keybit); ++#endif ++ ++ input_register_device(dev); ++ ++ return 0; ++} ++ ++static void __exit ep93xxkbd_cleanup(void) ++{ ++ writel(0x000000AA, SYSCON_SWLOCK); /* unlock SYSCON Software Lock */ ++ writel(readl(SYSCON_KTDIV) & 0xFFFF7FFF, SYSCON_KTDIV); /* disable Key Matrix Clock KEN */ ++ free_irq(IRQ_KEY, NULL); ++ input_unregister_device(dev); ++} ++ ++module_init(ep93xxkbd_init); ++module_exit(ep93xxkbd_cleanup); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h +new file mode 100644 +index 0000000..31fd4db +--- /dev/null ++++ b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h +@@ -0,0 +1,146 @@ ++static unsigned char keycode[16][0x40] = ++{{ ++ KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, 0, 0, ++ KEY_ESC, KEY_BACKSPACE, KEY_7, KEY_8, KEY_9, 0, 0, 0, ++ KEY_PROG1, KEY_PROG2, KEY_4, KEY_5, KEY_6, 0, 0, 0, ++ KEY_MENU, KEY_0, KEY_1, KEY_2, KEY_3, 0, 0, 0, ++ KEY_LEFTSHIFT, KEY_UP, KEY_TAB, 0, 0, 0, 0, 0, ++ KEY_LEFT, KEY_LEFTALT, KEY_RIGHT, 0, 0, 0, 0, 0, ++ KEY_LEFTCTRL, KEY_DOWN, KEY_ENTER, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, KEY_A, KEY_D, KEY_G, 0, 0, 0, ++ 0, 0, KEY_J, KEY_M, KEY_P, 0, 0, 0, ++ 0, KEY_DOT, KEY_S, KEY_V, KEY_Y, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, KEY_B, KEY_E, KEY_H, 0, 0, 0, ++ 0, 0, KEY_K, KEY_N, KEY_Q, 0, 0, 0, ++ 0, KEY_COMMA, KEY_T, KEY_W, KEY_Z, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, KEY_C, KEY_F, KEY_I, 0, 0, 0, ++ 0, 0, KEY_L, KEY_O, KEY_R, 0, 0, 0, ++ 0, KEY_SLASH, KEY_U, KEY_X, KEY_SPACE, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, KEY_KPASTERISK, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, KEY_KPPLUS, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, KEY_KPMINUS, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, KEY_EQUAL, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, KEY_SEMICOLON, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, KEY_APOSTROPHE, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, KEY_KPLEFTPAREN, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, KEY_KPRIGHTPAREN, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, KEY_LEFTBRACE, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, KEY_RIGHTBRACE, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ }, { ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++}}; +diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h +new file mode 100644 +index 0000000..65dca77 +--- /dev/null ++++ b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h +@@ -0,0 +1,11 @@ ++static unsigned char keycode[0x40] = ++{ ++ KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, 0, 0, ++ KEY_ESC, KEY_BACKSPACE, KEY_7, KEY_8, KEY_9, 0, 0, 0, ++ KEY_PROG1, KEY_PROG2, KEY_4, KEY_5, KEY_6, 0, 0, 0, ++ KEY_MENU, KEY_0, KEY_1, KEY_2, KEY_3, 0, 0, 0, ++ KEY_LEFTSHIFT, KEY_UP, KEY_TAB, 0, 0, 0, 0, 0, ++ KEY_LEFT, KEY_LEFTALT, KEY_RIGHT, 0, 0, 0, 0, 0, ++ KEY_LEFTCTRL, KEY_DOWN, KEY_ENTER, 0, 0, 0, 0, 0, ++ 0, 0, 0, 0, 0, 0, 0, 0, ++}; +diff --git a/drivers/input/keyboard/ep93xx_spi_kbd.c b/drivers/input/keyboard/ep93xx_spi_kbd.c +new file mode 100644 +index 0000000..b6ad607 +--- /dev/null ++++ b/drivers/input/keyboard/ep93xx_spi_kbd.c +@@ -0,0 +1,407 @@ ++/****************************************************************************** ++ * ++ * File: linux/drivers/char/ep93xx_spi_kbd.c ++ * ++ * Purpose: Support for SPI Keyboard for a Cirrus Logic EP93xx ++ * ++ * History: ++ * ++ * Limitations: ++ * Break and Print Screen keys not handled yet! ++ * ++ * ++ * Copyright 2003 Cirrus Logic 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 ++ * ++ ******************************************************************************/ ++ ++/* ++ * FIXME: There are more parity problems than there ought to be. ++ * TODO: Track down ++ * WHERE: grep for "BAD_PARITY" ++ * ++ * WORKAROUND: Do not press too many keys and do not type too fast ++ * type key another time if it got lost ++ * ++ * WORKAROUND2: Use USB Keyboards or 8x8 matrix keypad instead ++ * ++ * FIXME2: Keymap should be done properly ++ */ ++ ++#include <linux/config.h> ++#include <linux/init.h> ++#include <linux/input.h> ++#include <linux/module.h> ++#include <asm/io.h> ++#include <asm/uaccess.h> ++#include <asm/hardware.h> ++#include <asm/arch/ssp-cirrus.h> ++ ++#include "ep93xx_spi_kbd.h" ++ ++#define EP93XX_MAX_KEY_DOWN_COUNT 6 ++ ++void DataCallback(unsigned int Data); ++static int g_SSP_Handle; ++static struct input_dev *ep93xxkbd_dev; ++ ++#undef UART_HACK_DEBUG ++/* #define UART_HACK_DEBUG 1 */ ++ ++#if defined(UART_HACK_DEBUG) && defined(CONFIG_DEBUG_LL) ++char szBuf[256]; ++#define DPRINTK( x... ) \ ++ sprintf( szBuf, ##x ); \ ++ printascii( szBuf ); ++#else ++#define DPRINTK( x... ) ++#endif ++ ++struct key_down_tracker_t { ++ unsigned char scancode; ++ unsigned char count; ++}; ++ ++/* ++ * In the interest of efficiency, let's only allow 5 keys to be down ++ * at a time, maximum. So if anybody is having a temper tantrum on ++ * their keyboard, they may get stuck keys, but that's to be expected. ++ */ ++ ++#define MAX_KEYS_DOWN 8 ++static struct key_down_tracker_t KeyTracker[MAX_KEYS_DOWN]; ++ ++static unsigned char SPI2KScan(unsigned int uiSPIValue, int *pValid); ++static void InitSniffer(void); ++static void KeySniffer(unsigned char scancode, int down); ++static void Check4StuckKeys(void); ++ ++/** ++ * handle_scancode - wrapper ++ * ++ * wrap old style (2.4.x) to 2.6.x input subsystem ++ */ ++static void handle_scancode(unsigned char scancode, int down) ++{ ++ DPRINTK("handle_scancode(scancode=%04X, down=%d); %02X ", scancode, ++ down, scancode & 0x7f); ++ ++ if (scancode > KSCAN_TABLE_SIZE) ++ scancode &= ~EXTENDED_KEY; ++ ++ input_report_key(ep93xxkbd_dev, KScanCodeToVKeyTable[scancode], down); ++ input_sync(ep93xxkbd_dev); ++ ++ DPRINTK("(virtual) scancode=%02X\n", scancode); ++} ++ ++/** ++ * InitSniffer ++ * ++ * Clear our struct to indicate that no keys are down now. ++ * If somebody boots this thing while holding down keys, then they'll ++ * get what they deserve. ++ * ++ */ ++static void InitSniffer(void) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_KEYS_DOWN; i++) { ++ KeyTracker[i].count = 0; ++ KeyTracker[i].scancode = 0; ++ } ++} ++ ++/** ++ * KeySniffer ++ * ++ * To prevent stuck keys, keep track of what keys are down. This information ++ * is used by Check4StuckKeys(). ++ */ ++static void KeySniffer(unsigned char scancode, int down) ++{ ++ int i; ++ ++ /* ++ * There are certain keys that will definately get held down ++ * and we can't interfere with that. ++ */ ++ switch (scancode) { ++ case 0x12: /* left shift */ ++ case 0x59: /* right shift */ ++ case 0x14: /* left ctrl */ ++ case 0x94: /* right ctrl */ ++ case 0x11: /* left alt */ ++ case 0x91: /* right alt */ ++ case 0x58: /* caps lock */ ++ case 0x77: /* Num lock */ ++ /* printk("Snuff - %02x, %d\n", scancode, down); */ ++ handle_scancode(scancode, down); ++ return; ++ ++ default: ++ break; ++ } ++ ++ /* printk("Sniff - %02x, %d\n", scancode, down ); */ ++ ++ /* ++ * Go thru our array, looking for the key. If it already ++ * is recorded, update its count. ++ * Also look for empty cells in the array in case we ++ * need one. ++ */ ++ for (i = 0; i < MAX_KEYS_DOWN; i++) { ++ /* If this is a key up in our list then we are done. */ ++ if (down == 0) { ++ if (KeyTracker[i].scancode == scancode) { ++ KeyTracker[i].count = 0; ++ KeyTracker[i].scancode = 0; ++ handle_scancode(scancode, down); ++ break; ++ } ++ } ++ /* Hey here's an unused cell. Save its index. */ ++ else if (KeyTracker[i].count == 0) { ++ KeyTracker[i].scancode = scancode; ++ KeyTracker[i].count = 1; ++ handle_scancode(scancode, down); ++ break; ++ } ++ } ++} ++ ++/** ++ * Check4StuckKeys ++ * ++ * When a key is held down longer than 1/2 sec, it start repeating ++ * 10 times a second. What we do is watch how long each key is ++ * held down. If longer than X where X is less than 1/2 second ++ * then we assume it is stuck and issue the key up. If we were ++ * wrong and the key really is being held down, no problem because ++ * the keyboard is about to start sending it to us repeatedly ++ * anyway. ++ */ ++static void Check4StuckKeys(void) ++{ ++ int i; ++ ++ for (i = 0; i < MAX_KEYS_DOWN; i++) { ++ if (KeyTracker[i].count) { ++ KeyTracker[i].count++; ++ if (KeyTracker[i].count >= EP93XX_MAX_KEY_DOWN_COUNT) { ++ handle_scancode(KeyTracker[i].scancode, 0); ++ KeyTracker[i].count = 0; ++ KeyTracker[i].scancode = 0; ++ } ++ } ++ } ++} ++ ++/** ++ * HandleKeyPress ++ * ++ * Checks if there are any keys in the FIFO and processes them if there are. ++ */ ++void HandleKeyPress(unsigned int Data) ++{ ++ static unsigned char ucKScan[4] = { 0, 0, 0, 0 }; ++ static unsigned int ulNum = 0; ++ int bParityValid; ++ ++ /* ++ * No keys to decode, but the timer went off and is calling us ++ * to check for stuck keys. ++ */ ++ if (Data == -1) { ++ Check4StuckKeys(); ++ return; ++ } ++ /* ++ * Read in the value from the SPI controller. ++ */ ++ ucKScan[ulNum++] = SPI2KScan(Data, &bParityValid); ++ ++ /* ++ * Bad parity? We should read the rest of the fifo and ++ * throw it away, because it will all be bad. Then the ++ * SSP will be reset when we close the SSP driver and ++ * all will be good again. ++ */ ++ if (!bParityValid) { ++ /* printk("_BAD_PARITY_"); */ ++ ulNum = 0; ++ } ++ /* If we have one character in the array, do the following. */ ++ if (ulNum == 1) { ++ /* ++ * If it is a simple key without the extended scan code perform ++ * following. ++ */ ++ if (ucKScan[0] < KSCAN_TABLE_SIZE) { ++ DPRINTK("1:Dn %02x\n", ucKScan[0]); ++ KeySniffer(ucKScan[0], 1); ++ ulNum = 0; ++ } ++ /* ++ * I don't know what type of character this is so erase the ++ * keys stored in the buffer and continue. ++ */ ++ else if ((ucKScan[0] != 0xF0) && (ucKScan[0] != 0xE0)) { ++ DPRINTK("1:oops - %02x\n", ucKScan[0]); ++ ulNum = 0; ++ } ++ } else if (ulNum == 2) { ++ /* ++ * 0xF0 means that a key has been released. ++ */ ++ if (ucKScan[0] == 0xF0) { ++ /* ++ * If it is a simple key without the extended scan code ++ * perform the following. ++ */ ++ if (ucKScan[1] < KSCAN_TABLE_SIZE) { ++ DPRINTK("2:Up %02x %02x\n", ucKScan[0], ++ ucKScan[1]); ++ KeySniffer(ucKScan[1], 0); ++ ulNum = 0; ++ } ++ /* ++ * If it a extended kscan continue to get the next byte. ++ */ ++ else if (ucKScan[1] != 0xE0) { ++ DPRINTK("2:oops - %02x %02x\n", ucKScan[0], ++ ucKScan[1]); ++ ulNum = 0; ++ } ++ } ++ /* ++ * Find out what extended code it is. ++ */ ++ else if (ucKScan[0] == 0xE0 && ucKScan[1] != 0xF0) { ++ DPRINTK("2:Dn %02x %02x\n", ucKScan[0], ucKScan[1]); ++ KeySniffer(EXTENDED_KEY | ucKScan[1], 1); ++ ulNum = 0; ++ } ++ } ++ /* This means that an extended code key has been released. */ ++ else if (ulNum == 3) { ++ /* 0xF0 means that a key has been released. */ ++ if (ucKScan[0] == 0xE0 && ucKScan[1] == 0xF0) { ++ DPRINTK("3:Up %02x %02x %02x", ++ ucKScan[0], ucKScan[1], ucKScan[2]); ++ KeySniffer(EXTENDED_KEY | ucKScan[2], 0); ++ } else { ++ DPRINTK("3:oops - %02x %02x %02x\n", ++ ucKScan[0], ucKScan[1], ucKScan[2]); ++ } ++ ulNum = 0; ++ } ++} ++ ++/** ++ * SPI2KScan - Get a character from the spi port if it is available. ++ * ++ * Below is a picture of the spi signal from the PS2. ++ * ++ * CK HHllllHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHllll ++ * DA HHHllllll000000111111222222333333444444555555666666777777ppppppssssssLLLLHHH ++ * ^ ^ ++ * start bit important bit ++ * ++ * where: l = 8042 driving the line ++ * L = KEYBOARD driving the line ++ * 1..7 data ++ * = Parity 8042 driving ++ * s = stop 8042 driving ++ * = PARITY KEYBOARD driving the line ++ * S = STOP KEYBOARD driving the line ++ * ++ * In our design the value comes high bit first and is inverted. So we must ++ * convert it to low byte first and then inverted it back. ++ * ++ */ ++static unsigned char SPI2KScan(unsigned int uiSPIValue, int *pValid) ++{ ++ unsigned char ucKScan = 0; ++ unsigned int uiParity = 0; ++ unsigned int uiCount = 0; ++ ++ for (uiCount = 1; uiCount < 10; uiCount++) { ++ uiParity += (uiSPIValue >> uiCount) & 0x1; ++ } ++ ++ if (!(uiParity & 0x1) && (uiSPIValue & 0x401) == 0x400) { ++ *pValid = 1; ++ ++ /* Invert the pattern. */ ++ uiSPIValue = ~uiSPIValue; ++ ++ /* Read in the value from the motorola spi file */ ++ ucKScan = (unsigned char)((uiSPIValue & 0x004) << 5); ++ ucKScan |= (unsigned char)((uiSPIValue & 0x008) << 3); ++ ucKScan |= (unsigned char)((uiSPIValue & 0x010) << 1); ++ ucKScan |= (unsigned char)((uiSPIValue & 0x020) >> 1); ++ ucKScan |= (unsigned char)((uiSPIValue & 0x040) >> 3); ++ ucKScan |= (unsigned char)((uiSPIValue & 0x080) >> 5); ++ ucKScan |= (unsigned char)((uiSPIValue & 0x100) >> 7); ++ ucKScan |= (unsigned char)((uiSPIValue & 0x200) >> 9); ++ } else { ++ *pValid = 0; ++ } ++ ++ return ucKScan; ++} ++ ++int __init EP93XXSpiKbdInit(void) ++{ ++ int i; ++ ++ ep93xxkbd_dev = input_allocate_device(); ++ if (!ep93xxkbd_dev) { ++ printk(KERN_ERR "ep93xxkbd: not enough memory for input device\n"); ++ return -ENOMEM; ++ } ++ ++ ep93xxkbd_dev->name = "Cirrus EP93xx PS/2 keyboard driver"; ++ printk("%s\n", ep93xxkbd_dev->name); ++ ++ ep93xxkbd_dev->evbit[0] = BIT(EV_KEY); ++ ++ for (i = 0; i < KSCAN_TABLE_SIZE; i++) ++ set_bit(KScanCodeToVKeyTable[i], ep93xxkbd_dev->keybit); ++ ++ input_register_device(ep93xxkbd_dev); ++ ++ /* Open SSP driver for Keyboard input. */ ++ g_SSP_Handle = SSPDriver->Open(PS2_KEYBOARD, HandleKeyPress); ++ ++ InitSniffer(); ++ ++ DPRINTK("Leaving EP93XXSpiKbdInit()\n"); ++ ++ return 0; ++} ++ ++void __exit EP93XXSpiKbdCleanup(void) ++{ ++ SSPDriver->Close(g_SSP_Handle); ++ input_unregister_device(ep93xxkbd_dev); ++} ++ ++module_init(EP93XXSpiKbdInit); ++module_exit(EP93XXSpiKbdCleanup); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/input/keyboard/ep93xx_spi_kbd.h b/drivers/input/keyboard/ep93xx_spi_kbd.h +new file mode 100644 +index 0000000..7f4bd90 +--- /dev/null ++++ b/drivers/input/keyboard/ep93xx_spi_kbd.h +@@ -0,0 +1,147 @@ ++/* ++ * ep93xx_spi_kbd.h Keymap definitions (to be cleaned up) ++ */ ++ ++#define KSCAN_TABLE_SIZE 0x88 ++ ++#define EXTENDED_KEY 0x80 ++ ++/* This table is used to map the scan code to the Linux default keymap. */ ++static unsigned int const KScanCodeToVKeyTable[KSCAN_TABLE_SIZE] = { ++ KEY_RESERVED, /* Scan Code 0x0 */ ++ KEY_F9, /* Scan Code 0x1 */ ++ KEY_RESERVED, /* Scan Code 0x2 */ ++ KEY_F5, /* Scan Code 0x3 */ ++ KEY_F3, /* Scan Code 0x4 */ ++ KEY_F1, /* Scan Code 0x5 */ ++ KEY_F2, /* Scan Code 0x6 */ ++ KEY_F12, /* Scan Code 0x7 */ ++ KEY_RESERVED, /* Scan Code 0x8 */ ++ KEY_F10, /* Scan Code 0x9 */ ++ KEY_F8, /* Scan Code 0xA */ ++ KEY_F6, /* Scan Code 0xB */ ++ KEY_F4, /* Scan Code 0xC */ ++ KEY_TAB, /* Scan Code 0xD Tab */ ++ KEY_GRAVE, /* Scan Code 0xE ' */ ++ KEY_RESERVED, /* Scan Code 0xF */ ++ KEY_RESERVED, /* Scan Code 0x10 */ ++ KEY_LEFTALT, /* Scan Code 0x11 Left Menu */ ++ KEY_LEFTSHIFT, /* Scan Code 0x12 Left Shift */ ++ KEY_RESERVED, /* Scan Code 0x13 */ ++ KEY_LEFTCTRL, /* Scan Code 0x14 */ ++ KEY_Q, /* Scan Code 0x15 */ ++ KEY_1, /* Scan Code 0x16 */ ++ KEY_RESERVED, /* Scan Code 0x17 */ ++ KEY_RESERVED, /* Scan Code 0x18 */ ++ KEY_RESERVED, /* Scan Code 0x19 */ ++ KEY_Z, /* Scan Code 0x1A */ ++ KEY_S, /* Scan Code 0x1B */ ++ KEY_A, /* Scan Code 0x1C */ ++ KEY_W, /* Scan Code 0x1D */ ++ KEY_2, /* Scan Code 0x1E */ ++ KEY_RESERVED, /* Scan Code 0x1F */ ++ KEY_RESERVED, /* Scan Code 0x20 */ ++ KEY_C, /* Scan Code 0x21 */ ++ KEY_X, /* Scan Code 0x22 */ ++ KEY_D, /* Scan Code 0x23 */ ++ KEY_E, /* Scan Code 0x24 */ ++ KEY_4, /* Scan Code 0x25 */ ++ KEY_3, /* Scan Code 0x26 */ ++ KEY_RESERVED, /* Scan Code 0x27 */ ++ KEY_RESERVED, /* Scan Code 0x28 */ ++ KEY_SPACE, /* Scan Code 0x29 Space */ ++ KEY_V, /* Scan Code 0x2A */ ++ KEY_F, /* Scan Code 0x2B */ ++ KEY_T, /* Scan Code 0x2C */ ++ KEY_R, /* Scan Code 0x2D */ ++ KEY_5, /* Scan Code 0x2E */ ++ KEY_RESERVED, /* Scan Code 0x2F */ ++ KEY_RESERVED, /* Scan Code 0x30 */ ++ KEY_N, /* Scan Code 0x31 */ ++ KEY_B, /* Scan Code 0x32 B */ ++ KEY_H, /* Scan Code 0x33 */ ++ KEY_G, /* Scan Code 0x34 */ ++ KEY_Y, /* Scan Code 0x35 */ ++ KEY_6, /* Scan Code 0x36 */ ++ KEY_RESERVED, /* Scan Code 0x37 */ ++ KEY_RESERVED, /* Scan Code 0x38 */ ++ KEY_RESERVED, /* Scan Code 0x39 */ ++ KEY_M, /* Scan Code 0x3A */ ++ KEY_J, /* Scan Code 0x3B */ ++ KEY_U, /* Scan Code 0x3C */ ++ KEY_7, /* Scan Code 0x3D */ ++ KEY_8, /* Scan Code 0x3E */ ++ KEY_RESERVED, /* Scan Code 0x3F */ ++ KEY_RESERVED, /* Scan Code 0x40 */ ++ KEY_COMMA, /* Scan Code 0x41 */ ++ KEY_K, /* Scan Code 0x42 */ ++ KEY_I, /* Scan Code 0x43 */ ++ KEY_O, /* Scan Code 0x44 */ ++ KEY_0, /* Scan Code 0x45 */ ++ KEY_9, /* Scan Code 0x46 */ ++ KEY_RESERVED, /* Scan Code 0x47 */ ++ KEY_RESERVED, /* Scan Code 0x48 */ ++ KEY_DOT, /* Scan Code 0x49 */ ++ KEY_SLASH, /* Scan Code 0x4A */ ++ KEY_L, /* Scan Code 0x4B */ ++ KEY_SEMICOLON, /* Scan Code 0x4C */ ++ KEY_P, /* Scan Code 0x4D */ ++ KEY_MINUS, /* Scan Code 0x4E */ ++ KEY_RESERVED, /* Scan Code 0x4F */ ++ KEY_RESERVED, /* Scan Code 0x50 */ ++ KEY_RESERVED, /* Scan Code 0x51 */ ++ KEY_APOSTROPHE, /* Scan Code 0x52 */ ++ KEY_RESERVED, /* Scan Code 0x53 */ ++ KEY_LEFTBRACE, /* Scan Code 0x54 */ ++ KEY_EQUAL, /* Scan Code 0x55 */ ++ KEY_BACKSPACE, /* Scan Code 0x56 */ ++ KEY_RESERVED, /* Scan Code 0x57 */ ++ KEY_CAPSLOCK, /* Scan Code 0x58 Caps Lock */ ++ KEY_RIGHTSHIFT, /* Scan Code 0x59 Right Shift */ ++ KEY_ENTER, /* Scan Code 0x5A */ ++ KEY_RIGHTBRACE, /* Scan Code 0x5B */ ++ KEY_RESERVED, /* Scan Code 0x5C */ ++ KEY_BACKSLASH, /* Scan Code 0x5D */ ++ KEY_RESERVED, /* Scan Code 0x5E */ ++ KEY_RESERVED, /* Scan Code 0x5F */ ++ KEY_RESERVED, /* Scan Code 0x60 */ ++ KEY_BACKSLASH, /* Scan Code 0x61 ?? VK_BSLH, */ ++ KEY_RESERVED, /* Scan Code 0x62 */ ++ KEY_RESERVED, /* Scan Code 0x63 */ ++ KEY_RESERVED, /* Scan Code 0x64 */ ++ KEY_RESERVED, /* Scan Code 0x65 */ ++ KEY_BACKSPACE, /* Scan Code 0x66 ?? VK_BKSP, */ ++ KEY_RESERVED, /* Scan Code 0x67 */ ++ KEY_RESERVED, /* Scan Code 0x68 */ ++ KEY_KP1, /* Scan Code 0x69 */ ++ KEY_RESERVED, /* Scan Code 0x6A */ ++ KEY_KP4, /* Scan Code 0x6B */ ++ KEY_KP7, /* Scan Code 0x6C */ ++ KEY_RESERVED, /* Scan Code 0x6D */ ++ KEY_RESERVED, /* Scan Code 0x6E */ ++ KEY_RESERVED, /* Scan Code 0x6F */ ++ KEY_KP0, /* Scan Code 0x70 */ ++ KEY_KPDOT, /* Scan Code 0x71 DECIMAL?? */ ++ KEY_KP2, /* Scan Code 0x72 */ ++ KEY_KP5, /* Scan Code 0x73 */ ++ KEY_KP6, /* Scan Code 0x74 */ ++ KEY_KP8, /* Scan Code 0x75 */ ++ KEY_ESC, /* Scan Code 0x76 */ ++ KEY_NUMLOCK, /* Scan Code 0x77 */ ++ KEY_F11, /* Scan Code 0x78 */ ++ KEY_KPPLUS, /* Scan Code 0x79 */ ++ KEY_KP3, /* Scan Code 0x7A */ ++ KEY_KPMINUS, /* Scan Code 0x7B */ ++ KEY_KPASTERISK, /* Scan Code 0x7C */ ++ KEY_KP9, /* Scan Code 0x7D */ ++ KEY_SCROLLLOCK, /* Scan Code 0x7E */ ++ KEY_RESERVED, /* Scan Code 0x7F */ ++ KEY_RESERVED, /* Scan Code 0x80 */ ++ KEY_RESERVED, /* Scan Code 0x81 */ ++ KEY_RESERVED, /* Scan Code 0x82 */ ++ KEY_F7, /* Scan Code 0x83 */ ++ KEY_RESERVED, /* Scan Code 0x84 */ ++ KEY_RESERVED, /* Scan Code 0x85 */ ++ KEY_RESERVED, /* Scan Code 0x86 */ ++ KEY_RESERVED /* Scan Code 0x87 */ ++}; +diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig +index 21d55ed..5453395 100644 +--- a/drivers/input/touchscreen/Kconfig ++++ b/drivers/input/touchscreen/Kconfig +@@ -95,4 +95,15 @@ config TOUCHSCREEN_HP600 + To compile this driver as a module, choose M here: the + module will be called hp680_ts_input. + ++config TOUCHSCREEN_EP93XX ++ tristate "EP93xx touchscreen" ++ depends on ARCH_EP93XX ++ help ++ Say Y here if you have a touchscreen connected to your EP93xx CPU. ++ ++ If unsure, say N. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called ep93xx_ts. ++ + endif +diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile +index 6842869..f8e6eb4 100644 +--- a/drivers/input/touchscreen/Makefile ++++ b/drivers/input/touchscreen/Makefile +@@ -11,3 +11,4 @@ obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o + obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o + obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o + obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o ++obj-$(CONFIG_TOUCHSCREEN_EP93XX) += ep93xx_ts.o +diff --git a/drivers/input/touchscreen/ep93xx_ts.c b/drivers/input/touchscreen/ep93xx_ts.c +new file mode 100644 +index 0000000..fc4622e +--- /dev/null ++++ b/drivers/input/touchscreen/ep93xx_ts.c +@@ -0,0 +1,748 @@ ++/* ++ * linux/drivers/char/ep93xx_ts.c ++ * ++ * Copyright (C) 2003-2004 Cirrus Corp. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/delay.h> ++#include <linux/sched.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/timer.h> ++#include <linux/input.h> ++#include <linux/pci.h> ++ ++#include <asm/irq.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++ ++/* ++ * To customize for a new touchscreen, there are various macros that ++ * have to be set. If you allow UART_HACK_DEBUG to be defined, you ++ * will get real time ts data scrolling up your serial terminal ++ * screen that will help you empirically determine good values for these. ++ * ++ * ++ * These are used as trigger levels to know when we have pen up/down ++ * ++ * The rules: ++ * 1. TS_HEAVY_INV_PRESSURE < TS_LIGHT_INV_PRESSURE because these ++ * are Inverse pressure. ++ * 2. Any touch lighter than TS_LIGHT_INV_PRESSURE is a pen up. ++ * 3. Any touch heavier than TS_HEAVY_INV_PRESSURE is a pen down. ++ */ ++#define TS_HEAVY_INV_PRESSURE (0x1000 - pressure_max) ++#define TS_LIGHT_INV_PRESSURE (0x1000 - pressure_min) ++ ++/* ++ * If the x, y, or inverse pressure changes more than these values ++ * between two succeeding points, the point is not reported. ++ */ ++#define TS_MAX_VALID_PRESSURE_CHANGE (pressure_jitter) ++#define TS_MAX_VALID_XY_CHANGE (xy_jitter) ++ ++/* old defaults */ ++#if 0 ++#define TS_X_MIN 0 ++#define TS_Y_MIN 0 ++#define TS_X_MAX 0xfff ++#define TS_Y_MAX 0xfff ++#endif ++ ++/* "improved" defaults */ ++#define TS_X_MIN 0x2d9 ++#define TS_Y_MIN 0xd0a ++#define TS_X_MAX 0xd42 ++#define TS_Y_MAX 0x2e0 ++ ++static uint16_t pressure_min = 0x001; ++static uint16_t pressure_max = 0x010; ++static uint16_t pressure_jitter = 0x300; ++static uint16_t xy_jitter = 0x100; ++module_param(pressure_min, ushort, 0); ++module_param(pressure_max, ushort, 0); ++module_param(pressure_jitter, ushort, 0); ++module_param(xy_jitter, ushort, 0); ++MODULE_PARM_DESC(pressure_min, "Minimum pressure (0 - 4095)"); ++MODULE_PARM_DESC(pressure_max, "Maximum pressure (0 - 4095)"); ++MODULE_PARM_DESC(pressure_jitter, "Minimum pressure jitter (0 - 4095)"); ++MODULE_PARM_DESC(xy_jitter, "Minimum X-Y jitter (0 - 4095)"); ++ ++/* This is the minimum Z1 Value that is valid. */ ++#define MIN_Z1_VALUE 0x50 ++ ++/* ++ * Settling delay for taking each ADC measurement. Increase this ++ * if ts is jittery. ++ */ ++#define EP93XX_TS_ADC_DELAY_USEC 2000 ++ ++/* Delay between TS points. */ ++ ++#define EP93XX_TS_PER_POINT_DELAY_USEC 10000 ++ ++/*----------------------------------------------------------------------------- ++ * Debug messaging thru the UARTs ++ *----------------------------------------------------------------------------- ++ * ++ * Hello there! Are you trying to get this driver to work with a new ++ * touschscreen? Turn this on and you will get useful info coming ++ * out of your serial port. ++ */ ++ ++/* #define PRINT_CALIBRATION_FACTORS */ ++#ifdef PRINT_CALIBRATION_FACTORS ++#define UART_HACK_DEBUG 1 ++int iMaxX = 0, iMaxY = 0, iMinX = 0xfff, iMinY = 0xfff; ++#endif ++ ++/* ++ * For debugging, let's spew messages out serial port 1 or 3 at 57,600 baud. ++ */ ++#undef UART_HACK_DEBUG ++#if defined(UART_HACK_DEBUG) && defined (CONFIG_DEBUG_LL) ++static char szBuf[256]; ++void UARTWriteString(char *msg); ++extern void printascii(const char *msg); ++#define DPRINTK( x... ) \ ++ sprintf( szBuf, ##x ); \ ++ printascii( szBuf ); ++#else ++#define DPRINTK( x... ) ++#endif ++ ++#define TSSETUP_DEFAULT ( TSSETUP_NSMP_32 | TSSETUP_DEV_64 | \ ++ ((128<<TSSETUP_SDLY_SHIFT) & TSSETUP_SDLY_MASK) | \ ++ ((128<<TSSETUP_DLY_SHIFT) & TSSETUP_DLY_MASK) ) ++ ++#define TSSETUP2_DEFAULT (TSSETUP2_NSIGND) ++ ++static unsigned int guiLastX, guiLastY; ++static unsigned int guiLastInvPressure; ++static int bCurrentPenDown; ++static DECLARE_MUTEX(open_sem); ++ ++enum ts_mode_t { ++ TS_MODE_UN_INITIALIZED, ++ TS_MODE_HARDWARE_SCAN, ++ TS_MODE_SOFT_SCAN ++}; ++ ++static enum ts_mode_t gScanningMode; ++ ++enum ts_states_t { ++ TS_STATE_STOPPED = 0, ++ TS_STATE_Z1, ++ TS_STATE_Z2, ++ TS_STATE_Y, ++ TS_STATE_X, ++ TS_STATE_DONE ++}; ++ ++struct ts_struct_t { ++ unsigned int uiX; ++ unsigned int uiY; ++ unsigned int uiZ1; ++ unsigned int uiZ2; ++ enum ts_states_t state; ++}; ++ ++static struct ts_struct_t sTouch; ++ ++/* ++ * From the spec, here's how to set up the touch screen's switch registers. ++ */ ++struct SwitchStructType { ++ unsigned int uiDetect; ++ unsigned int uiDischarge; ++ unsigned int uiXSample; ++ unsigned int uiYSample; ++ unsigned int uiSwitchZ1; ++ unsigned int uiSwitchZ2; ++}; ++ ++/* ++ * Here's the switch settings for a 4-wire touchscreen. See the spec ++ * for how to handle a 4, 7, or 8-wire. ++ */ ++const static struct SwitchStructType sSwitchSettings = ++/* s28en=0 ++ * TSDetect TSDischarge TSXSample TSYSample SwitchZ1 SwitchZ2 ++ */ ++{ 0x00403604, 0x0007fe04, 0x00081604, 0x00104601, 0x00101601, 0x00101608 }; ++ ++static void ep93xx_ts_set_direct(unsigned int uiADCSwitch); ++static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id, struct pt_regs *regs); ++static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id, ++ struct pt_regs *regs); ++static void ep93xx_hw_setup(void); ++static void ep93xx_hw_shutdown(void); ++static unsigned int CalculateInvPressure(void); ++static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff); ++static void TS_Soft_Scan_Mode(void); ++static void TS_Hardware_Scan_Mode(void); ++static void ProcessPointData(struct input_dev *dev); ++static void Set_Timer2_uSec(unsigned int Delay_mSec); ++static void Stop_Timer2(void); ++ ++static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ DPRINTK("isr\n"); ++ ++ /* ++ * Note that we don't clear the interrupt here. The interrupt ++ * gets cleared in TS_Soft_Scan_Mode when the TS ENABLE ++ * bit is cleared. ++ * ++ ++ * ++ * Set the ts to manual polling mode and schedule a callback. ++ * That way we can return from the isr in a reasonable amount of ++ * time and process the touch in the callback after a brief delay. ++ */ ++ TS_Soft_Scan_Mode(); ++ return IRQ_HANDLED; ++} ++ ++static int ep93xx_ts_open(struct input_dev *dev) ++{ ++ int err; ++ ++ if (down_trylock(&open_sem)) ++ return -EBUSY; ++ ++ err = ++ request_irq(IRQ_TOUCH, ep93xx_ts_isr, SA_INTERRUPT, "ep93xx_ts", ++ dev); ++ if (err) { ++ printk(KERN_WARNING ++ "ep93xx_ts: failed to get touchscreen IRQ\n"); ++ return err; ++ } ++ ++ err = request_irq(IRQ_TIMER2, ep93xx_timer2_isr, ++ SA_INTERRUPT, "ep93xx_timer2", dev); ++ if (err) { ++ printk(KERN_WARNING "ep93xx_ts: failed to get timer2 IRQ\n"); ++ free_irq(IRQ_TOUCH, dev); ++ return err; ++ } ++ ++ ep93xx_hw_setup(); ++ ++ return 0; ++} ++ ++static void ep93xx_ts_close(struct input_dev *dev) ++{ ++ Stop_Timer2(); ++ ++ ep93xx_hw_shutdown(); ++ ++ free_irq(IRQ_TIMER2, dev); ++ free_irq(IRQ_TOUCH, dev); ++ ++ up(&open_sem); ++} ++ ++static void ep93xx_hw_setup(void) ++{ ++ unsigned int uiKTDIV, uiTSXYMaxMin; ++ ++ /* ++ * Set the TSEN bit in KTDIV so that we are enabling the clock ++ * for the touchscreen. ++ */ ++ uiKTDIV = readl(SYSCON_KTDIV); ++ uiKTDIV |= SYSCON_KTDIV_TSEN; ++ SysconSetLocked(SYSCON_KTDIV, uiKTDIV); ++ ++ writel(TSSETUP_DEFAULT, TSSetup); ++ writel(TSSETUP2_DEFAULT, TSSetup2); ++ ++ /* Set the the touch settings. */ ++ writel(0xaa, TSSWLock); ++ writel(sSwitchSettings.uiDischarge, TSDirect); ++ ++ writel(0xaa, TSSWLock); ++ writel(sSwitchSettings.uiDischarge, TSDischarge); ++ ++ writel(0xaa, TSSWLock); ++ writel(sSwitchSettings.uiSwitchZ1, TSXSample); ++ ++ writel(0xaa, TSSWLock); ++ writel(sSwitchSettings.uiSwitchZ2, TSYSample); ++ ++ writel(0xaa, TSSWLock); ++ writel(sSwitchSettings.uiDetect, TSDetect); ++ ++ /* ++ * X,YMin set to 0x40 = have to drag that many pixels for a new irq. ++ * X,YMax set to 0x40 = 1024 pixels is the maximum movement within the ++ * time scan limit. ++ */ ++ uiTSXYMaxMin = (50 << TSMAXMIN_XMIN_SHIFT) & TSMAXMIN_XMIN_MASK; ++ uiTSXYMaxMin |= (50 << TSMAXMIN_YMIN_SHIFT) & TSMAXMIN_YMIN_MASK; ++ uiTSXYMaxMin |= (0xff << TSMAXMIN_XMAX_SHIFT) & TSMAXMIN_XMAX_MASK; ++ uiTSXYMaxMin |= (0xff << TSMAXMIN_YMAX_SHIFT) & TSMAXMIN_YMAX_MASK; ++ writel(uiTSXYMaxMin, TSXYMaxMin); ++ ++ bCurrentPenDown = 0; ++ guiLastX = 0; ++ guiLastY = 0; ++ guiLastInvPressure = 0xffffff; ++ ++ /* Enable the touch screen scanning engine. */ ++ ++ TS_Hardware_Scan_Mode(); ++ ++} ++ ++static void ep93xx_hw_shutdown(void) ++{ ++ unsigned int uiKTDIV; ++ ++ DPRINTK("ep93xx_hw_shutdown\n"); ++ ++ sTouch.state = TS_STATE_STOPPED; ++ Stop_Timer2(); ++ ++ /* ++ * Disable the scanning engine. ++ */ ++ writel(0, TSSetup); ++ writel(0, TSSetup2); ++ ++ /* ++ * Clear the TSEN bit in KTDIV so that we are disabling the clock ++ * for the touchscreen. ++ */ ++ uiKTDIV = readl(SYSCON_KTDIV); ++ uiKTDIV &= ~SYSCON_KTDIV_TSEN; ++ SysconSetLocked(SYSCON_KTDIV, uiKTDIV); ++ ++} ++ ++static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id, ++ struct pt_regs *regs) ++{ ++ DPRINTK("%d", (int)sTouch.state); ++ ++ switch (sTouch.state) { ++ case TS_STATE_STOPPED: ++ TS_Hardware_Scan_Mode(); ++ break; ++ ++ /* ++ * Get the Z1 value for pressure measurement and set up ++ * the switch register for getting the Z2 measurement. ++ */ ++ case TS_STATE_Z1: ++ Set_Timer2_uSec(EP93XX_TS_ADC_DELAY_USEC); ++ sTouch.uiZ1 = ADCGetData(2, 200); ++ ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ2); ++ sTouch.state = TS_STATE_Z2; ++ break; ++ ++ /* ++ * Get the Z2 value for pressure measurement and set up ++ * the switch register for getting the Y measurement. ++ */ ++ case TS_STATE_Z2: ++ sTouch.uiZ2 = ADCGetData(2, 200); ++ ep93xx_ts_set_direct(sSwitchSettings.uiYSample); ++ sTouch.state = TS_STATE_Y; ++ break; ++ ++ /* ++ * Get the Y value and set up the switch register for ++ * getting the X measurement. ++ */ ++ case TS_STATE_Y: ++ sTouch.uiY = ADCGetData(4, 20); ++ ep93xx_ts_set_direct(sSwitchSettings.uiXSample); ++ sTouch.state = TS_STATE_X; ++ break; ++ ++ /* ++ * Read the X value. This is the last of the 4 adc values ++ * we need so we continue on to process the data. ++ */ ++ case TS_STATE_X: ++ Stop_Timer2(); ++ ++ sTouch.uiX = ADCGetData(4, 20); ++ ++ writel(0xaa, TSSWLock); ++ writel(sSwitchSettings.uiDischarge, TSDirect); ++ ++ sTouch.state = TS_STATE_DONE; ++ ++ /* Process this set of ADC readings. */ ++ ProcessPointData(dev_id); ++ ++ break; ++ ++ /* Shouldn't get here. But if we do, we can recover... */ ++ case TS_STATE_DONE: ++ TS_Hardware_Scan_Mode(); ++ break; ++ } ++ ++ /* Clear the timer2 interrupt. */ ++ writel(1, TIMER2CLEAR); ++ return IRQ_HANDLED; ++ ++} ++ ++/*--------------------------------------------------------------------- ++ * ProcessPointData ++ * ++ * This routine processes the ADC data into usable point data and then ++ * puts the driver into hw or sw scanning mode before returning. ++ * ++ * We calculate inverse pressure (lower number = more pressure) then ++ * do a hystheresis with the two pressure values 'light' and 'heavy'. ++ * ++ * If we are above the light, we have pen up. ++ * If we are below the heavy we have pen down. ++ * As long as the pressure stays below the light, pen stays down. ++ * When we get above the light again, pen goes back up. ++ * ++ */ ++static void ProcessPointData(struct input_dev *dev) ++{ ++ int bValidPoint = 0; ++ unsigned int uiXDiff, uiYDiff, uiInvPressureDiff; ++ unsigned int uiInvPressure; ++ ++ /* Calculate the current pressure. */ ++ uiInvPressure = CalculateInvPressure(); ++ ++ DPRINTK(" X=0x%x, Y=0x%x, Z1=0x%x, Z2=0x%x, InvPressure=0x%x", ++ sTouch.uiX, sTouch.uiY, sTouch.uiZ1, sTouch.uiZ2, ++ uiInvPressure); ++ ++ /* ++ * If pen pressure is so light that it is greater than the 'max' setting ++ * then we consider this to be a pen up. ++ */ ++ if (uiInvPressure >= TS_LIGHT_INV_PRESSURE) { ++ DPRINTK(" -- up \n"); ++ bCurrentPenDown = 0; ++/* input_report_key(dev, BTN_TOUCH, 0); */ ++ input_report_abs(dev, ABS_PRESSURE, 0); ++ input_sync(dev); ++ TS_Hardware_Scan_Mode(); ++ return; ++ } ++ /* ++ * Hystheresis: ++ * If the pen pressure is hard enough to be less than the 'min' OR ++ * the pen is already down and is still less than the 'max'... ++ */ ++ if ((uiInvPressure < TS_HEAVY_INV_PRESSURE) || ++ (bCurrentPenDown && (uiInvPressure < TS_LIGHT_INV_PRESSURE))) { ++ if (bCurrentPenDown) { ++ /* ++ * If pen was previously down, check the difference between ++ * the last sample and this one... if the difference between ++ * samples is too great, ignore the sample. ++ */ ++ uiXDiff = abs(guiLastX - sTouch.uiX); ++ uiYDiff = abs(guiLastY - sTouch.uiY); ++ uiInvPressureDiff = ++ abs(guiLastInvPressure - uiInvPressure); ++ ++ if ((uiXDiff < TS_MAX_VALID_XY_CHANGE) && ++ (uiYDiff < TS_MAX_VALID_XY_CHANGE) && ++ (uiInvPressureDiff < TS_MAX_VALID_PRESSURE_CHANGE)) ++ { ++ DPRINTK(" -- valid(two) \n"); ++ bValidPoint = 1; ++ } else { ++ DPRINTK(" -- INvalid(two) \n"); ++ } ++ } else { ++ DPRINTK(" -- valid \n"); ++ bValidPoint = 1; ++ } ++ ++ /* ++ * If either the pen was put down or dragged make a note of it. ++ */ ++ if (bValidPoint) { ++ guiLastX = sTouch.uiX; ++ guiLastY = sTouch.uiY; ++ guiLastInvPressure = uiInvPressure; ++ bCurrentPenDown = 1; ++ input_report_abs(dev, ABS_X, sTouch.uiX); ++ input_report_abs(dev, ABS_Y, sTouch.uiY); ++/* input_report_key(dev, BTN_TOUCH, 1); */ ++ input_report_abs(dev, ABS_PRESSURE, 1); ++ input_sync(dev); ++ } ++ ++ TS_Soft_Scan_Mode(); ++ return; ++ } ++ ++ DPRINTK(" -- fallout \n"); ++ TS_Hardware_Scan_Mode(); ++} ++ ++static void ep93xx_ts_set_direct(unsigned int uiADCSwitch) ++{ ++ unsigned int uiResult; ++ ++ /* Set the switch settings in the direct register. */ ++ writel(0xaa, TSSWLock); ++ writel(uiADCSwitch, TSDirect); ++ ++ /* Read and throw away the first sample. */ ++ do { ++ uiResult = readl(TSXYResult); ++ } while (!(uiResult & TSXYRESULT_SDR)); ++ ++} ++ ++static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff) ++{ ++ unsigned int uiResult, uiValue, uiCount, uiLowest, uiHighest, uiSum, ++ uiAve; ++ ++ do { ++ /* Initialize our values. */ ++ uiLowest = 0xfffffff; ++ uiHighest = 0; ++ uiSum = 0; ++ ++ for (uiCount = 0; uiCount < uiSamples; uiCount++) { ++ /* Read the touch screen four more times and average. */ ++ do { ++ uiResult = readl(TSXYResult); ++ } while (!(uiResult & TSXYRESULT_SDR)); ++ ++ uiValue = ++ (uiResult & TSXYRESULT_AD_MASK) >> ++ TSXYRESULT_AD_SHIFT; ++ uiValue = ++ ((uiValue >> 4) + ++ ((1 + ++ TSXYRESULT_X_MASK) >> 1)) & TSXYRESULT_X_MASK; ++ ++ /* Add up the values. */ ++ uiSum += uiValue; ++ ++ /* Get the lowest and highest values. */ ++ if (uiValue < uiLowest) ++ uiLowest = uiValue; ++ ++ if (uiValue > uiHighest) ++ uiHighest = uiValue; ++ ++ } ++ ++ } while ((uiHighest - uiLowest) > uiMaxDiff); ++ ++ /* Calculate the Average value. */ ++ uiAve = uiSum / uiSamples; ++ ++ return uiAve; ++} ++ ++/** ++ * CalculateInvPressure ++ * ++ * Is the Touch Valid. Touch is not valid if the X or Y value is not ++ * in range and the pressure is not enough. ++ * ++ * Touch resistance can be measured by the following formula: ++ * ++ * Rx * X * Z2 ++ * Rtouch = --------- * (-- - 1) ++ * 4096 Z1 ++ * ++ * This is simplified in the ration of Rtouch to Rx. The lower the value, the ++ * higher the pressure. ++ * ++ * Z2 ++ * InvPressure = X * (-- - 1) ++ * Z1 ++ */ ++static unsigned int CalculateInvPressure(void) ++{ ++ unsigned int uiInvPressure; ++ ++ /* Check to see if the point is valid. */ ++ if (sTouch.uiZ1 < MIN_Z1_VALUE) ++ uiInvPressure = 0x10000; ++ ++ /* Can omit the pressure calculation if you need to get rid of the division. */ ++ else { ++ uiInvPressure = ++ ((sTouch.uiX * sTouch.uiZ2) / sTouch.uiZ1) - sTouch.uiX; ++ } ++ ++ return uiInvPressure; ++} ++ ++/** ++ * TS_Hardware_Scan_Mode ++ * Enables the ep93xx ts scanning engine so that when the pen goes down ++ * we will get an interrupt. ++ */ ++static void TS_Hardware_Scan_Mode(void) ++{ ++ unsigned int uiDevCfg; ++ ++ DPRINTK("S\n"); ++ ++ /* Disable the soft scanning engine. */ ++ sTouch.state = TS_STATE_STOPPED; ++ Stop_Timer2(); ++ ++ /* ++ * Clear the TIN (Touchscreen INactive) bit so we can go to ++ * automatic scanning mode. ++ */ ++ uiDevCfg = readl(SYSCON_DEVCFG); ++ SysconSetLocked(SYSCON_DEVCFG, ++ ep93xx_SYSCON_DEVCFG(uiDevCfg & ~SYSCON_DEVCFG_TIN)); ++ ++ /* ++ * Enable the touch screen scanning state machine by setting ++ * the ENABLE bit. ++ */ ++ writel((TSSETUP_DEFAULT | TSSETUP_ENABLE), TSSetup); ++ ++ /* Set the flag to show that we are in interrupt mode. */ ++ gScanningMode = TS_MODE_HARDWARE_SCAN; ++ ++ /* Initialize TSSetup2 register. */ ++ writel(TSSETUP2_DEFAULT, TSSetup2); ++ ++} ++ ++/** ++ * TS_Soft_Scan_Mode - Set the touch screen to manual polling mode. ++ */ ++static void TS_Soft_Scan_Mode(void) ++{ ++ unsigned int uiDevCfg; ++ ++ DPRINTK("M\n"); ++ ++ if (gScanningMode != TS_MODE_SOFT_SCAN) { ++ /* ++ * Disable the touch screen scanning state machine by clearing ++ * the ENABLE bit. ++ */ ++ writel(TSSETUP_DEFAULT, TSSetup); ++ ++ /* Set the TIN bit so we can do manual touchscreen polling. */ ++ uiDevCfg = readl(SYSCON_DEVCFG); ++ SysconSetLocked(SYSCON_DEVCFG, ++ ep93xx_SYSCON_DEVCFG(uiDevCfg | ++ SYSCON_DEVCFG_TIN)); ++ } ++ /* Set the switch register up for the first ADC reading */ ++ ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ1); ++ ++ /* ++ * Initialize our software state machine to know which ADC ++ * reading to take ++ */ ++ sTouch.state = TS_STATE_Z1; ++ ++ /* ++ * Set the timer so after a mSec or two settling delay it will ++ * take the first ADC reading. ++ */ ++ Set_Timer2_uSec(EP93XX_TS_PER_POINT_DELAY_USEC); ++ ++ /* Note that we are in sw scanning mode not hw scanning mode. */ ++ gScanningMode = TS_MODE_SOFT_SCAN; ++ ++} ++ ++static void Set_Timer2_uSec(unsigned int uiDelay_uSec) ++{ ++ unsigned int uiClockTicks; ++ ++ /* ++ * Stop timer 2 ++ */ ++ writel(0, TIMER2CONTROL); ++ ++ uiClockTicks = ((uiDelay_uSec * 508) + 999) / 1000; ++ writel(uiClockTicks, TIMER2LOAD); ++ writel(uiClockTicks, TIMER2VALUE); ++ ++ /* ++ * Set up Timer 2 for 508 kHz clock and periodic mode. ++ */ ++ writel(0xC8, TIMER2CONTROL); ++ ++} ++ ++static void Stop_Timer2(void) ++{ ++ writel(0, TIMER2CONTROL); ++} ++ ++static struct input_dev *ep93xx_ts_dev; ++ ++static int __init ep93xx_ts_init(void) ++{ ++ ep93xx_ts_dev = input_allocate_device(); ++ if (!ep93xx_ts_dev) { ++ printk(KERN_ERR "ep93xx_ts_dev: not enough memory for input device\n"); ++ return -ENOMEM; ++ } ++ ++ ep93xx_ts_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); ++ ep93xx_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); ++ ep93xx_ts_dev->keybit[LONG(BTN_RAW)] = BIT(BTN_RAW); ++ ++ /* untested, I haven't got a touchscreen (yet) :( */ ++ input_set_abs_params(ep93xx_ts_dev, ABS_X, 0, 4095, 0, 0); ++ input_set_abs_params(ep93xx_ts_dev, ABS_Y, 0, 4095, 0, 0); ++ input_set_abs_params(ep93xx_ts_dev, ABS_PRESSURE, 0, 1, 0, 0); ++ ++ ep93xx_ts_dev->open = ep93xx_ts_open; ++ ep93xx_ts_dev->close = ep93xx_ts_close; ++ ep93xx_ts_dev->name = "Cirrus Logic EP93xx Touchscreen"; ++ ep93xx_ts_dev->phys = "ep93xx_ts/input0"; ++ ep93xx_ts_dev->id.bustype = BUS_HOST; ++ ep93xx_ts_dev->id.vendor = PCI_VENDOR_ID_CIRRUS; ++ ep93xx_ts_dev->id.product = 0x9300; ++ ++ input_set_abs_params(ep93xx_ts_dev, ABS_X, TS_X_MIN, TS_X_MAX, 0, 0); ++ input_set_abs_params(ep93xx_ts_dev, ABS_Y, TS_Y_MIN, TS_Y_MAX, 0, 0); ++ input_register_device(ep93xx_ts_dev); ++ ++ sTouch.state = TS_STATE_STOPPED; ++ gScanningMode = TS_MODE_UN_INITIALIZED; ++ ++ printk(KERN_NOTICE ++ "EP93xx touchscreen driver configured for 4-wire operation\n"); ++ return 0; ++} ++ ++static void __exit ep93xx_ts_exit(void) ++{ ++ input_unregister_device(ep93xx_ts_dev); ++} ++ ++module_init(ep93xx_ts_init); ++module_exit(ep93xx_ts_exit); ++ ++MODULE_DESCRIPTION("Cirrus EP93xx touchscreen driver"); ++MODULE_SUPPORTED_DEVICE("touchscreen/ep93xx"); +diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig +index b9b77cf..4e0e427 100644 +--- a/drivers/mtd/maps/Kconfig ++++ b/drivers/mtd/maps/Kconfig +@@ -137,6 +137,13 @@ config MTD_MAINSTONE + This provides a driver for the on-board flash of the Intel + 'Mainstone PXA27x evaluation board. + ++config MTD_ADSFLASH ++ tristate "CFI Flash device mapped on ADS" ++ depends on ARM && MTD_CFI && MACH_ADSSPHERE && MTD_PARTITIONS ++ help ++ This enables access to on-board flash memory on ADS platforms that ++ have an Intel XScale PXA2xx CPU. ++ + config MTD_OCTAGON + tristate "JEDEC Flash device mapped on Octagon 5066 SBC" + depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS +@@ -639,5 +646,19 @@ config MTD_PLATRAM + + This selection automatically selects the map_ram driver. + ++config MTD_ZEFEERDZB ++ tristate "Map driver for DAVE Srl ZefeerDZB processor module" ++ depends on (MTD_CFI && MACH_ZEFEERDZB) ++ select MTD_PARTITIONS ++ help ++ Map driver for DAVE Srl ZefeerDZB processor module. ++ ++config MTD_ZEFEERDZQ ++ tristate "Map driver for DAVE Srl ZefeerDZQ processor module" ++ depends on (MTD_CFI && MACH_ZEFEERDZQ) ++ select MTD_PARTITIONS ++ help ++ Map driver for DAVE Srl ZefeerDZQ processor module. ++ + endmenu + +diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile +index 2f7e254..a821568 100644 +--- a/drivers/mtd/maps/Makefile ++++ b/drivers/mtd/maps/Makefile +@@ -22,6 +22,7 @@ obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom + obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o + obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o + obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o ++obj-$(CONFIG_MTD_ADSFLASH) += ads-flash.o + obj-$(CONFIG_MTD_MAINSTONE) += mainstone-flash.o + obj-$(CONFIG_MTD_MBX860) += mbx860.o + obj-$(CONFIG_MTD_CEIVA) += ceiva.o +@@ -72,3 +73,5 @@ obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o + obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o + obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o + obj-$(CONFIG_MTD_TQM834x) += tqm834x.o ++obj-$(CONFIG_MTD_ZEFEERDZB) += zefeerdzb.o ++obj-$(CONFIG_MTD_ZEFEERDZQ) += zefeerdzq.o +diff --git a/drivers/mtd/maps/ads-flash.c b/drivers/mtd/maps/ads-flash.c +new file mode 100644 +index 0000000..2428e9c +--- /dev/null ++++ b/drivers/mtd/maps/ads-flash.c +@@ -0,0 +1,221 @@ ++/* ++ * Map driver for the ADS PXA Boards. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/device.h> ++#include <linux/dma-mapping.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/map.h> ++#include <linux/mtd/partitions.h> ++#include <asm/io.h> ++#include <asm/hardware.h> ++ ++#ifdef CONFIG_MACH_ADSVIX ++#define NUM_CHIPS 1 ++#else ++#define NUM_CHIPS 2 ++#endif ++ ++#ifdef CONFIG_PXA27x ++#define WINDOW_ADDR 0 ++#elif defined(CONFIG_ARCH_EP93XX) ++#define WINDOW_ADDR 0x60000000 ++#else ++#define WINDOW_ADDR 0x04000000 ++#endif ++ ++#define WINDOW_SIZE (NUM_CHIPS * 32*1024*1024) ++#define BLOCKSIZE (NUM_CHIPS * 0x20000) ++#define BANKWIDTH (NUM_CHIPS * 2) ++ ++static void pxa_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len) ++{ ++ consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE); ++} ++ ++static struct map_info pxa_map = { ++ .name = "pxa", ++ .size = WINDOW_SIZE, ++ .phys = WINDOW_ADDR, ++ .virt = 0, ++ .cached = (void *)NULL, ++ .bankwidth = BANKWIDTH, ++ .inval_cache = pxa_map_inval_cache, ++}; ++ ++static struct mtd_partition ads_partitions[] = { ++ { ++ name: "boot", ++ size: BLOCKSIZE, ++ offset: 0, ++ }, { ++ name: "bootvars", ++ size: BLOCKSIZE, ++ offset: MTDPART_OFS_APPEND, ++ }, { ++ name: "zImage", ++ size: 0x00180000, ++ offset: MTDPART_OFS_APPEND, ++ }, { ++ name: "ramdisk.gz", ++ size: 0x00500000, ++ offset: MTDPART_OFS_APPEND, ++ }, { ++ name: "flashfs1", ++ size: MTDPART_SIZ_FULL, ++ offset: MTDPART_OFS_APPEND ++ } ++}; ++ ++unsigned char ads_flash_serial_id[32+2] = {0}; ++ ++static struct mtd_info *mymtd = NULL; ++static struct mtd_partition *parsed_parts = NULL; ++static int num_parts = 0; ++static const char *probes[] = { ++#ifdef CONFIG_MTD_CMDLINE_PARTS ++ "cmdlinepart", ++#endif ++#ifdef CONFIG_MTD_REDBOOT_PARTS ++ "RedBoot", ++#endif ++ NULL }; ++ ++// This implementation supports 1 or 2 chips. ++static void ads_get_flash_serial_id(int chips) ++{ ++ map_word val; ++ unsigned int addr = 0x81 << chips; ++ unsigned int mask = chips == 1 ? 0xffff : 0xffffffff; ++ unsigned int tmp[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; ++ int i; ++ ++ /* read array mode */ ++ // *(__u32 *)pxa_map.virt = 0x00FF00FF; ++ // *(__u16 *)pxa_map.virt = 0x00ff; ++ val.x[0] = 0x00ff00ff & mask; ++ map_write(&pxa_map, val, 0); ++ ++ /* read id mode */ ++ // *(__u32 *)pxa_map.virt = 0x00900090; ++ // *(__u16 *)pxa_map.virt = 0x0090; ++ val.x[0] = 0x00900090 & mask; ++ map_write(&pxa_map, val, 0); ++ ++ for (i=0; i<8; i++) { ++ // tmp[i] = 0x0000ffff & *(__u32 *)(pxa_map.virt + addr); ++ // tmp[i] = *(__u16 *)(pxa_map.virt + addr); ++ val = map_read(&pxa_map, addr); ++ tmp[i] = val.x[0] & 0xffff; ++ addr += BANKWIDTH; ++ } ++ ++ /* back to read array mode */ ++ // *(__u32 *)pxa_map.virt = 0x00FF00FF; ++ // *(__u16 *)pxa_map.virt = 0x00ff; ++ val.x[0] = 0x00ff00ff & mask; ++ map_write(&pxa_map, val, 0); ++ ++ sprintf(ads_flash_serial_id, "%04x%04x%04x%04x.%04x%04x%04x%04x", ++ tmp[7], tmp[6], tmp[5], tmp[4], tmp[3], tmp[2], tmp[1], tmp[0]); ++ ++} ++ ++static int __init init_pxa_flash(void) ++{ ++ struct mtd_partition *parts; ++ char *part_type; ++ int rtn; ++ ++ printk(KERN_NOTICE "Probing PXA flash at physical address 0x%08x\n", WINDOW_ADDR); ++ pxa_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE); ++ if (!pxa_map.virt) { ++ printk(KERN_ERR "Failed to ioremap flash\n"); ++ return -EIO; ++ } ++ ++ pxa_map.cached = __ioremap(WINDOW_ADDR, WINDOW_SIZE, L_PTE_CACHEABLE, 1); ++ if (!pxa_map.cached) ++ printk(KERN_WARNING "Failed to ioremap cached flash\n"); ++ ++ simple_map_init(&pxa_map); ++ ++ mymtd = do_map_probe("cfi_probe", &pxa_map); ++ if (!mymtd) { ++ if (pxa_map.cached) ++ iounmap((void *)pxa_map.cached); ++ if (pxa_map.virt) ++ iounmap((void *)pxa_map.virt); ++ return -ENXIO; ++ } ++ ++#ifdef CONFIG_MTD_CMDLINE_PARTS ++ pxa_map.name = "pxa"; ++ rtn = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0); ++ if (rtn <= 0) { ++ pxa_map.name = "sa1100"; ++ rtn = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0); ++ } ++ if (rtn > 0) { ++ num_parts = rtn; ++ parts = parsed_parts; ++ part_type = "command line"; ++ goto add_parts; ++ } ++#endif ++ num_parts = ARRAY_SIZE(ads_partitions); ++ parts = ads_partitions; ++ part_type = "static"; ++add_parts: ++ if (num_parts) { ++ printk(KERN_NOTICE "Using %s partition definition\n", part_type); ++ add_mtd_partitions(mymtd, parts, num_parts); ++#if 0 ++ if (mymtd->unlock) { ++ int i; ++ for (i = 0; i < num_parts; i++) { ++ // unlock partition ++ mymtd->unlock(mymtd, parts[num_parts - 1].offset, ++ parts[num_parts - 1].size); ++ } ++ } ++#endif ++ } ++ else { ++ add_mtd_device(mymtd); ++ } ++ ++ ads_get_flash_serial_id(NUM_CHIPS); ++ ++ return 0; ++} ++ ++static void __exit cleanup_pxa_flash(void) ++{ ++ if (mymtd) { ++ if (num_parts) ++ del_mtd_partitions(mymtd); ++ else ++ del_mtd_device(mymtd); ++ map_destroy(mymtd); ++ if (parsed_parts) ++ kfree(parsed_parts); ++ } ++ if (pxa_map.cached) ++ iounmap((void *)pxa_map.cached); ++ if (pxa_map.virt) ++ iounmap((void *)pxa_map.virt); ++} ++ ++module_init(init_pxa_flash); ++module_exit(cleanup_pxa_flash); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/mtd/maps/zefeerdzb.c b/drivers/mtd/maps/zefeerdzb.c +new file mode 100644 +index 0000000..bb47bc6 +--- /dev/null ++++ b/drivers/mtd/maps/zefeerdzb.c +@@ -0,0 +1,134 @@ ++/* ++ * $Id: zefeerdzb.c,v 1.8 2004/07/12 21:59:44 dwmw2 Exp $ ++ * ++ * drivers/mtd/maps/zefeerdzb.c ++ * ++ * FLASH map for the DAVE Srl ZefeerDZB processor module. ++ * ++ * ++ * 2004 (c) DAVE Srl. This file is licensed under ++ * the terms of the GNU General Public License version 2. This program ++ * is licensed "as is" without any warranty of any kind, whether express ++ * or implied. ++ */ ++ ++#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/map.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/io.h> ++ ++#if 0 ++/* Support for ZELK <= 0.9.5 */ ++#define WINDOW_ADDR 0x60000000 ++#else ++#define WINDOW_ADDR 0x00000000 ++#endif ++#define WINDOW_SIZE 0x00400000 ++ ++/* 128 kB U-Boot */ ++#define ZEFEERDZB_PART0_OF 0 ++#define ZEFEERDZB_PART0_SZ 0x20000 ++/* 128 kB U-Boot env #1 */ ++#define ZEFEERDZB_PART1_OF ZEFEERDZB_PART0_OF + ZEFEERDZB_PART0_SZ ++#define ZEFEERDZB_PART1_SZ 0x20000 ++/* 128 kB U-Boot env #2 */ ++#define ZEFEERDZB_PART2_OF ZEFEERDZB_PART1_OF + ZEFEERDZB_PART1_SZ ++#define ZEFEERDZB_PART2_SZ 0x20000 ++/* Linux kernel */ ++#define ZEFEERDZB_PART3_OF ZEFEERDZB_PART2_OF + ZEFEERDZB_PART2_SZ ++#define ZEFEERDZB_PART3_SZ (0x200000 - ZEFEERDZB_PART2_SZ - ZEFEERDZB_PART1_SZ - ZEFEERDZB_PART0_SZ) ++/* spare */ ++#define ZEFEERDZB_PART4_OF ZEFEERDZB_PART3_OF + ZEFEERDZB_PART3_SZ ++#define ZEFEERDZB_PART4_SZ (0x400000 - ZEFEERDZB_PART3_SZ - ZEFEERDZB_PART2_SZ - ZEFEERDZB_PART1_SZ - ZEFEERDZB_PART0_SZ) ++ ++static struct mtd_partition zefeerdzb_flash_partitions[] = { ++ { ++ .name = "U-Boot", ++ .offset = ZEFEERDZB_PART0_OF, ++ .size = ZEFEERDZB_PART0_SZ, ++ .mask_flags = MTD_WRITEABLE /* force read-only */ ++ }, ++ { ++ .name = "U-Boot environment #1", ++ .offset = ZEFEERDZB_PART1_OF, ++ .size = ZEFEERDZB_PART1_SZ, ++ }, ++ { ++ .name = "U-Boot environment #2", ++ .offset = ZEFEERDZB_PART2_OF, ++ .size = ZEFEERDZB_PART2_SZ, ++ }, ++ { ++ .name = "Linux kernel", ++ .offset = ZEFEERDZB_PART3_OF, ++ .size = ZEFEERDZB_PART3_SZ, ++ }, ++ { ++ .name = "spare 1", ++ .offset = ZEFEERDZB_PART4_OF, ++ .size = ZEFEERDZB_PART4_SZ, ++ } ++}; ++ ++struct map_info zefeerdzb_flash_map = { ++ .name = "DAVE Srl ZefeerDZB", ++ .size = WINDOW_SIZE, ++ .bankwidth = 2, ++ .phys = WINDOW_ADDR, ++}; ++ ++#define NUM_ZEFEERDZB_FLASH_PARTITIONS \ ++ (sizeof(zefeerdzb_flash_partitions)/sizeof(zefeerdzb_flash_partitions[0])) ++ ++static struct mtd_info *zefeerdzb_mtd; ++ ++int __init init_zefeerdzb_flash(void) ++{ ++ printk(KERN_NOTICE "zefeerdzb: flash mapping: %x at %x\n", ++ WINDOW_SIZE, WINDOW_ADDR); ++ ++ zefeerdzb_flash_map.virt = ++ (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); ++ ++ if (!zefeerdzb_flash_map.virt) { ++ printk("init_zefeerdzb_flash: failed to ioremap\n"); ++ return -EIO; ++ } ++ simple_map_init(&zefeerdzb_flash_map); ++ ++ zefeerdzb_mtd = do_map_probe("cfi_probe", &zefeerdzb_flash_map); ++ ++ if (zefeerdzb_mtd) { ++ zefeerdzb_mtd->owner = THIS_MODULE; ++ return add_mtd_partitions(zefeerdzb_mtd, ++ zefeerdzb_flash_partitions, ++ NUM_ZEFEERDZB_FLASH_PARTITIONS); ++ } ++ ++ return -ENXIO; ++} ++ ++static void __exit cleanup_zefeerdzb_flash(void) ++{ ++ if (zefeerdzb_mtd) { ++ del_mtd_partitions(zefeerdzb_mtd); ++ /* moved iounmap after map_destroy - armin */ ++ map_destroy(zefeerdzb_mtd); ++ iounmap((void *)zefeerdzb_flash_map.virt); ++ } ++} ++ ++module_init(init_zefeerdzb_flash); ++module_exit(cleanup_zefeerdzb_flash); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("DAVE Srl <info@dave-tech.it>"); ++MODULE_DESCRIPTION ++ ("MTD map driver for the DAVE Srl ZefeerDZB processor module"); +diff --git a/drivers/mtd/maps/zefeerdzq.c b/drivers/mtd/maps/zefeerdzq.c +new file mode 100644 +index 0000000..dc0e402 +--- /dev/null ++++ b/drivers/mtd/maps/zefeerdzq.c +@@ -0,0 +1,142 @@ ++/* ++ * $Id: zefeerdzq.c,v 1.8 2004/07/12 21:59:44 dwmw2 Exp $ ++ * ++ * drivers/mtd/maps/zefeerdzq.c ++ * ++ * FLASH map for the DAVE Srl ZefeerDZQ processor module. ++ * ++ * ++ * 2004 (c) DAVE Srl. This file is licensed under ++ * the terms of the GNU General Public License version 2. This program ++ * is licensed "as is" without any warranty of any kind, whether express ++ * or implied. ++ */ ++ ++#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/map.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/io.h> ++ ++#if 0 ++/* Support for ZELK <= 0.9.5 */ ++#define WINDOW_ADDR 0x60000000 ++#else ++#define WINDOW_ADDR 0x00000000 ++#endif ++#define WINDOW_SIZE 0x01000000 ++ ++/* 128 kB U-Boot */ ++#define ZEFEERDZQ_PART0_OF 0 ++#define ZEFEERDZQ_PART0_SZ 0x20000 ++/* 128 kB U-Boot env #1 */ ++#define ZEFEERDZQ_PART1_OF ZEFEERDZQ_PART0_OF + ZEFEERDZQ_PART0_SZ ++#define ZEFEERDZQ_PART1_SZ 0x20000 ++/* 128 kB U-Boot env #2 */ ++#define ZEFEERDZQ_PART2_OF ZEFEERDZQ_PART1_OF + ZEFEERDZQ_PART1_SZ ++#define ZEFEERDZQ_PART2_SZ 0x20000 ++/* Linux kernel */ ++#define ZEFEERDZQ_PART3_OF ZEFEERDZQ_PART2_OF + ZEFEERDZQ_PART2_SZ ++#define ZEFEERDZQ_PART3_SZ (0x200000 - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ) ++/* ramdisk */ ++#define ZEFEERDZQ_PART4_OF ZEFEERDZQ_PART3_OF + ZEFEERDZQ_PART3_SZ ++#define ZEFEERDZQ_PART4_SZ (0x400000 - ZEFEERDZQ_PART3_SZ - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ) ++/* spare */ ++#define ZEFEERDZQ_PART5_OF ZEFEERDZQ_PART4_OF + ZEFEERDZQ_PART4_SZ ++#define ZEFEERDZQ_PART5_SZ (WINDOW_SIZE - ZEFEERDZQ_PART4_SZ - ZEFEERDZQ_PART3_SZ - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ) ++ ++static struct mtd_partition zefeerdzq_flash_partitions[] = { ++ { ++ .name = "U-Boot", ++ .offset = ZEFEERDZQ_PART0_OF, ++ .size = ZEFEERDZQ_PART0_SZ, ++ .mask_flags = MTD_WRITEABLE /* force read-only */ ++ }, ++ { ++ .name = "U-Boot environment #1", ++ .offset = ZEFEERDZQ_PART1_OF, ++ .size = ZEFEERDZQ_PART1_SZ, ++ }, ++ { ++ .name = "U-Boot environment #2", ++ .offset = ZEFEERDZQ_PART2_OF, ++ .size = ZEFEERDZQ_PART2_SZ, ++ }, ++ { ++ .name = "Linux kernel", ++ .offset = ZEFEERDZQ_PART3_OF, ++ .size = ZEFEERDZQ_PART3_SZ, ++ }, ++ { ++ .name = "spare 1", ++ .offset = ZEFEERDZQ_PART4_OF, ++ .size = ZEFEERDZQ_PART4_SZ, ++ }, ++ { ++ .name = "spare 2", ++ .offset = ZEFEERDZQ_PART5_OF, ++ .size = ZEFEERDZQ_PART5_SZ, ++ } ++}; ++ ++struct map_info zefeerdzq_flash_map = { ++ .name = "DAVE Srl ZefeerDZQ", ++ .size = WINDOW_SIZE, ++ .bankwidth = 2, ++ .phys = WINDOW_ADDR, ++}; ++ ++#define NUM_ZEFEERDZQ_FLASH_PARTITIONS \ ++ (sizeof(zefeerdzq_flash_partitions)/sizeof(zefeerdzq_flash_partitions[0])) ++ ++static struct mtd_info *zefeerdzq_mtd; ++ ++int __init init_zefeerdzq_flash(void) ++{ ++ printk(KERN_NOTICE "zefeerdzq: flash mapping: %x at %x\n", ++ WINDOW_SIZE, WINDOW_ADDR); ++ ++ zefeerdzq_flash_map.virt = ++ (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); ++ ++ if (!zefeerdzq_flash_map.virt) { ++ printk("init_zefeerdzq_flash: failed to ioremap\n"); ++ return -EIO; ++ } ++ simple_map_init(&zefeerdzq_flash_map); ++ ++ zefeerdzq_mtd = do_map_probe("cfi_probe", &zefeerdzq_flash_map); ++ ++ if (zefeerdzq_mtd) { ++ zefeerdzq_mtd->owner = THIS_MODULE; ++ return add_mtd_partitions(zefeerdzq_mtd, ++ zefeerdzq_flash_partitions, ++ NUM_ZEFEERDZQ_FLASH_PARTITIONS); ++ } ++ ++ return -ENXIO; ++} ++ ++static void __exit cleanup_zefeerdzq_flash(void) ++{ ++ if (zefeerdzq_mtd) { ++ del_mtd_partitions(zefeerdzq_mtd); ++ /* moved iounmap after map_destroy - armin */ ++ map_destroy(zefeerdzq_mtd); ++ iounmap((void *)zefeerdzq_flash_map.virt); ++ } ++} ++ ++module_init(init_zefeerdzq_flash); ++module_exit(cleanup_zefeerdzq_flash); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("DAVE Srl <info@dave-tech.it>"); ++MODULE_DESCRIPTION ++ ("MTD map driver for the DAVE Srl ZefeerDZQ processor module"); +diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig +index 1fc4c13..8e79d32 100644 +--- a/drivers/mtd/nand/Kconfig ++++ b/drivers/mtd/nand/Kconfig +@@ -109,6 +109,12 @@ config MTD_NAND_S3C2410_HWECC + currently not be able to switch to software, as there is no + implementation for ECC method used by the S3C2410 + ++config MTD_NAND_ZEFEEREVB ++ tristate "NAND Flash device on ZefeerEVB (L/H) board" ++ depends on (MACH_ZEFEERDZA || MACH_ZEFEERDZB || MACH_ZEFEERDZG || MACH_ZEFEERDZN || MACH_ZEFEERDZQ) && MTD_NAND ++ help ++ This enables the NAND flash driver on the ZefeerEVB Board (L or H version). ++ + config MTD_NAND_DISKONCHIP + tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)" + depends on MTD_NAND && EXPERIMENTAL +diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile +index 4174202..bee7760 100644 +--- a/drivers/mtd/nand/Makefile ++++ b/drivers/mtd/nand/Makefile +@@ -18,5 +18,6 @@ obj-$(CONFIG_MTD_NAND_H1900) += h1910.o + obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o + obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o + obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o ++obj-$(CONFIG_MTD_NAND_ZEFEEREVB) += zefeerevb.o + + nand-objs = nand_base.o nand_bbt.o +diff --git a/drivers/mtd/nand/zefeerevb.c b/drivers/mtd/nand/zefeerevb.c +new file mode 100644 +index 0000000..b67e958 +--- /dev/null ++++ b/drivers/mtd/nand/zefeerevb.c +@@ -0,0 +1,280 @@ ++/* ++ * drivers/mtd/nand/zefeerevb.c ++ * ++ * Copyright (C) 2004 DAVE Srl (info@dave-tech.it) ++ * ++ * ++ * ++ * $Id: zefeerevb.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * Overview: ++ * This is a device driver for the NAND flash devices found on the ++ * ZefeerEVB board (Samsung K9F5608U0B 32MB). ++ */ ++ ++#include <linux/init.h> ++#include <linux/slab.h> ++#include <linux/module.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/nand.h> ++#include <linux/mtd/partitions.h> ++#include <asm/arch/regmap.h> ++#include <asm/arch/zefeerevb.h> ++#include <asm/io.h> ++ ++#define USE_READY_BUSY_PIN ++/* see datasheets (tR) */ ++#define NAND_BIG_DELAY_US 25 ++#define NAND_SMALL_DELAY_US 10 ++ ++/* handy sizes */ ++#define SZ_4M 0x00400000 ++#define NAND_SMALL_SIZE 0x02000000 ++#define NAND_EVB_MTD_NAME "zefeerevb-nand" ++ ++/* Macros to perform I/O operations */ ++#define MACRO_NAND_DISABLE_CE(nandptr) do \ ++{ \ ++ writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_nCE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \ ++} while(0) ++ ++#define MACRO_NAND_ENABLE_CE(nandptr) do \ ++{ \ ++ writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_nCE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \ ++} while(0) ++ ++#define MACRO_NAND_CTL_CLRALE(nandptr) do \ ++{ \ ++ writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_ALE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \ ++} while(0) ++ ++#define MACRO_NAND_CTL_SETALE(nandptr) do \ ++{ \ ++ writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_ALE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \ ++} while(0) ++ ++#define MACRO_NAND_CTL_CLRCLE(nandptr) do \ ++{ \ ++ writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_CLE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \ ++} while(0) ++ ++#define MACRO_NAND_CTL_SETCLE(nandptr) do \ ++{ \ ++ writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_CLE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \ ++} while(0) ++ ++#define MACRO_NAND_WAIT_READY(nand) \ ++while ( !(readl((volatile unsigned*)GPIO_PADR) & NAND_EVB_RB_GPIO_PIN); ) ++ ++/* ++ * MTD structure for ZefeerEVB board ++ */ ++static struct mtd_info *zefeerevb_mtd = NULL; ++ ++/* ++ * Module stuff ++ */ ++static int zefeerevb_fio_pbase = ZEFEEREVB_NAND_PADDR; ++ ++#ifdef MODULE ++MODULE_PARM(zefeerevb_fio_pbase, "i"); ++__setup("zefeerevb_fio_pbase=", zefeerevb_fio_pbase); ++#endif ++ ++#ifdef CONFIG_MTD_PARTITIONS ++/* ++ * Define static partitions for flash devices ++ */ ++static struct mtd_partition partition_info_evb[] = { ++ {name:"ZefeerEVB Nand Flash", ++ offset:0, ++ size:32 * 1024 * 1024} ++}; ++ ++#define NUM_PARTITIONS 1 ++ ++extern int parse_cmdline_partitions(struct mtd_info *master, ++ struct mtd_partition **pparts, ++ const char *mtd_id); ++#endif ++ ++static void zefeerevb_hwcontrol(struct mtd_info *mtdinfo, int cmd) ++{ ++ switch (cmd) { ++ ++ case NAND_CTL_SETCLE: ++ MACRO_NAND_CTL_SETCLE((unsigned long)0); ++ break; ++ case NAND_CTL_CLRCLE: ++ MACRO_NAND_CTL_CLRCLE((unsigned long)0); ++ break; ++ case NAND_CTL_SETALE: ++ MACRO_NAND_CTL_SETALE((unsigned long)0); ++ break; ++ case NAND_CTL_CLRALE: ++ MACRO_NAND_CTL_CLRALE((unsigned long)0); ++ break; ++ case NAND_CTL_SETNCE: ++ MACRO_NAND_ENABLE_CE((unsigned long)0); ++ break; ++ case NAND_CTL_CLRNCE: ++ MACRO_NAND_DISABLE_CE((unsigned long)0); ++ break; ++ } ++} ++ ++#ifdef USE_READY_BUSY_PIN ++/* ++ * read device ready pin ++ */ ++static int zefeerevb_device_ready(struct mtd_info *minfo) ++{ ++ return (readl((volatile unsigned *)GPIO_PADR) & ++ NAND_EVB_RB_GPIO_PIN); ++} ++#endif ++ ++#ifdef CONFIG_MTD_PARTITIONS ++const char *part_probes_evb[] = { "cmdlinepart", NULL }; ++#endif ++ ++/* ++ * Main initialization routine ++ */ ++static int __init zefeerevb_init(void) ++{ ++ struct nand_chip *this; ++ const char *part_type = 0; ++ int mtd_parts_nb = 0; ++ struct mtd_partition *mtd_parts = 0; ++ void __iomem *zefeerevb_fio_base; ++ u32 tmp; ++ ++ /* Init I/O pins */ ++ MACRO_NAND_DISABLE_CE(0); ++ MACRO_NAND_CTL_CLRALE(0); ++ MACRO_NAND_CTL_CLRCLE(0); ++ ++ tmp = (u32) readl(GPIO_PADDR); ++ tmp |= ++ (NAND_EVB_nCE_GPIO_PIN | NAND_EVB_CLE_GPIO_PIN | ++ NAND_EVB_ALE_GPIO_PIN); ++#ifdef USE_READY_BUSY_PIN ++ tmp &= ~NAND_EVB_RB_GPIO_PIN; ++#endif ++ writel(tmp, GPIO_PADDR); ++ ++ /* Init I/O pins */ ++ MACRO_NAND_DISABLE_CE(0); ++ MACRO_NAND_CTL_CLRALE(0); ++ MACRO_NAND_CTL_CLRCLE(0); ++ ++ /* Set up chip select */ ++ writel((0 << 30) | (0 << 28) | (0 << 27) | (0 << 26) | (0 << 11) | ++ (1 << 10) | (4 << 5) | (6 << 0), SMCBCR2); ++ ++ /* Allocate memory for MTD device structure and private data */ ++ zefeerevb_mtd = kmalloc(sizeof(struct mtd_info) + ++ sizeof(struct nand_chip), GFP_KERNEL); ++ if (!zefeerevb_mtd) { ++ printk ++ ("Unable to allocate ZefeerEVB NAND MTD device structure.\n"); ++ return -ENOMEM; ++ } ++ ++ /* map physical address */ ++ zefeerevb_fio_base = ++ (void __iomem *)ioremap(zefeerevb_fio_pbase, SZ_4M); ++ if (!zefeerevb_fio_base) { ++ printk("ioremap ZefeerEVB NAND flash failed\n"); ++ kfree(zefeerevb_mtd); ++ return -EIO; ++ } ++ ++ /* Get pointer to private data */ ++ this = (struct nand_chip *)(&zefeerevb_mtd[1]); ++ ++ /* Initialize structures */ ++ memset((char *)zefeerevb_mtd, 0, sizeof(struct mtd_info)); ++ memset((char *)this, 0, sizeof(struct nand_chip)); ++ ++ /* Link the private data with the MTD structure */ ++ zefeerevb_mtd->priv = this; ++ ++ /* insert callbacks */ ++ this->IO_ADDR_R = (void __iomem *)zefeerevb_fio_base; ++ this->IO_ADDR_W = (void __iomem *)zefeerevb_fio_base; ++ this->hwcontrol = zefeerevb_hwcontrol; ++#ifdef USE_READY_BUSY_PIN ++ this->dev_ready = zefeerevb_device_ready; ++#endif ++ this->chip_delay = NAND_SMALL_DELAY_US; ++ ++ /* ECC mode */ ++ this->eccmode = NAND_ECC_SOFT; ++ ++ /* Scan to find existence of the device */ ++ if (nand_scan(zefeerevb_mtd, 1)) { ++ iounmap((void *)zefeerevb_fio_base); ++ kfree(zefeerevb_mtd); ++ return -ENXIO; ++ } ++#ifdef CONFIG_MTD_PARTITIONS ++ zefeerevb_mtd->name = NAND_EVB_MTD_NAME; ++ mtd_parts_nb = ++ parse_mtd_partitions(zefeerevb_mtd, part_probes_evb, &mtd_parts, 0); ++ if (mtd_parts_nb > 0) ++ part_type = "command line"; ++ else ++ mtd_parts_nb = 0; ++#endif ++ if (mtd_parts_nb == 0) { ++#ifdef CONFIG_MTD_PARTITIONS ++ mtd_parts = partition_info_evb; ++ mtd_parts_nb = NUM_PARTITIONS; ++#endif ++ part_type = "static"; ++ } ++ ++ /* Register the partitions */ ++ printk(KERN_NOTICE "Using %s partition definition\n", part_type); ++ add_mtd_partitions(zefeerevb_mtd, mtd_parts, mtd_parts_nb); ++ ++ /* Return happy */ ++ return 0; ++} ++ ++module_init(zefeerevb_init); ++ ++#ifdef MODULE ++/* ++ * Clean up routine ++ */ ++static void __exit zefeerevb_cleanup(void) ++{ ++ struct nand_chip *this; ++ ++ /* Release resources, unregister device(s) */ ++ nand_release(zefeer_mtd); ++ nand_release(zefeerevb_mtd); ++ ++ /* Release iomaps */ ++ this = (struct nand_chip *)&zefeer_mtd[1]; ++ iounmap((void *)this->zefeer_fio_base; ++ this = (struct nand_chip *)&zefeerevb_mtd[1]; ++ iounmap((void *)this->zefeerevb_fio_base; ++ /* Free the MTD device structure */ ++ kfree(zefeer_mtd); ++ kfree(zefeerevb_mtd); ++ } ++ ++ module_exit(zefeerevb_cleanup); ++#endif ++ MODULE_LICENSE("GPL"); ++ MODULE_AUTHOR("DAVE Srl <support-zefeer@dave-tech.it>"); ++ MODULE_DESCRIPTION ++ ("MTD map driver for DAVE Srl ZefeerEVB (L/H) board"); +diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig +index 470364d..12afe1d 100644 +--- a/drivers/net/arm/Kconfig ++++ b/drivers/net/arm/Kconfig +@@ -44,3 +44,13 @@ config ARM_ETHER00 + will generate a suitable hw address based on the board serial + number (MTD support is required for this). Otherwise you will + need to set a suitable hw address using ifconfig. ++ ++config EP93XX_ETHERNET ++ tristate "EP93xx Ethernet support" ++ depends on NET_ETHERNET && ARM && ARCH_EP93XX ++ select CRC32 ++ select MII ++ help ++ This is a driver for the ethernet hardware included in EP93xx CPUs. ++ Say Y if you are building a kernel for EP93xx based devices. ++ +diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile +index b0d7068..c1539da 100644 +--- a/drivers/net/arm/Makefile ++++ b/drivers/net/arm/Makefile +@@ -8,3 +8,4 @@ obj-$(CONFIG_ARM_ETHER00) += ether00.o + obj-$(CONFIG_ARM_ETHERH) += etherh.o + obj-$(CONFIG_ARM_ETHER3) += ether3.o + obj-$(CONFIG_ARM_ETHER1) += ether1.o ++obj-$(CONFIG_EP93XX_ETHERNET) += ep93xx_eth.o +diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c +new file mode 100644 +index 0000000..e314549 +--- /dev/null ++++ b/drivers/net/arm/ep93xx_eth.c +@@ -0,0 +1,1412 @@ ++/* ++ * ep93xx_eth.c ++ * Ethernet Device Driver for Cirrus Logic EP93xx. ++ * ++ * Copyright (C) 2003 by Cirrus Logic www.cirrus.com ++ * This software may be used and distributed according to the terms ++ * of the GNU Public License. ++ * ++ * This driver was written based on skeleton.c by Donald Becker and ++ * smc9194.c by Erik Stahlman. ++ * ++ * Getting a MAC address: ++ * ++ * Former versions of this driver got their MAC from I2C EEPROM or even used ++ * hardcoded ones. Unfortunately I had to remove the board dependant I2C stuff, ++ * and use a random generated MAC instead of the hardcoded one. Good news is ++ * the there is support for setting the MAC from userspace now. (see below) ++ * ++ * first consider some potential problems if you use this random generated MAC: ++ * ++ * you can no longer count on it to be really unique ++ * identifying a particular board over network will be difficult ++ * DHCP servers can no longer use the MAC for assigning static IPs ++ * DHCP servers with long leasetimes quickly run out of leases ++ * ... ++ * ++ * So how can you set a valid MAC from userspace then? ++ * ++ * Let's say you've just bought your OUI from IEEE and it's "aa:bb:cc" ++ * Now you'd like to assign the MAC for your EP93xx board with serial #5 ++ * MAC = OUI<<24 + serial number = aa:bb:cc:00:00:05 ++ * ++ * ifconfig eth0 hw ether aa:bb:cc:00:00:05 # first set the MAC ++ * ifconfig eth0 192.168.1.1 netmask 255.255.255.0 up # then set the IP ++ * ++ * Apart from hardcoding this lines in your startup scripts you could also use ++ * some userspace utility to read (and set) the MAC from eeprom, flash, ... ++ * ++ * History: ++ * 07/19/01 0.1 Sungwook Kim initial release ++ * 10/16/01 0.2 Sungwook Kim add workaround for ignorance of Tx request ++ * while sending frame ++ * add some error stuations handling ++ * ++ * 03/25/03 Melody Lee Modified for EP93xx ++ * ++ * 2004/2005 Michael Burian porting to linux-2.6 ++ * 2005-10-12 Michael Burian fix problems when setting MAC with ifconfig ++ * 2005-10-30 Michael Burian cleanups, ethtool support ++ */ ++ ++/* TODO: ++ * 1. try if it's possible to use skbuff directly for RX/TX (avoid memcpy) ++ * 2. use kzalloc instead of kmalloc+memset ++ */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/types.h> ++#include <linux/fcntl.h> ++#include <linux/interrupt.h> ++#include <linux/ioport.h> ++#include <linux/in.h> ++#include <linux/delay.h> ++#include <linux/slab.h> ++#include <linux/string.h> ++#include <linux/errno.h> ++#include <linux/init.h> ++#include <linux/netdevice.h> ++#include <linux/etherdevice.h> ++#include <linux/skbuff.h> ++#include <linux/dma-mapping.h> ++#include <linux/mii.h> ++#include <linux/crc32.h> ++#include <linux/random.h> ++#include <linux/ethtool.h> ++ ++#include <asm/system.h> ++#include <asm/bitops.h> ++#include <asm/io.h> ++#include <asm/dma.h> ++#include <asm/irq.h> ++#include <asm/arch/hardware.h> ++ ++#include "ep93xx_eth.h" ++ ++#define DRV_NAME "ep93xx_eth" ++#define DRV_VERSION "2.8" ++#define DRV_DATE "2005-11-08" ++ ++static const char *version = DRV_NAME ": version " DRV_VERSION " " DRV_DATE \ ++ " Cirrus Logic\n"; ++ ++/* total number of device instance, 0 means the 1st instance. */ ++static int num_of_instance; ++static struct net_device * ep93xx_etherdev; ++ ++/* ++ * A List of default device port configuration for auto probing. ++ * At this time, the CPU has only one Ethernet device, ++ * but better to support multiple device configuration. ++ * Keep in mind that the array must end in zero. ++ */ ++ ++/* We get the MAC_BASE from include/asm-arm/arch-ep93xx/regmap.h */ ++static struct { ++ unsigned int base_addr; /* base address, (0:end mark) */ ++ int irq; /* IRQ number, (0:auto detect) */ ++} port_list[] __initdata = { ++ { ++ MAC_BASE, 39}, { ++ 0 /* end mark */ , 0} ++}; ++ ++/* ++ * Some definitions belong to the operation of this driver. ++ * You should understand how it affect to driver before any modification. ++ */ ++ ++/* Interrupt Sources in Use */ ++#define DEF_INT_SRC (IntEn_TxSQIE|IntEn_RxEOFIE|IntEn_RxEOBIE|IntEn_RxHDRIE) ++ ++/* ++ * Length of Device Queue in number of entries ++ * (must be less than or equal to 255) ++ */ ++ ++/* length of Rx Descriptor Queue (4 or bigger) Must be power of 2. */ ++#define LQRXD 64 ++#define LQRXS LQRXD /* length of Rx Status Queue */ ++ ++/* length of Tx Descriptor Queue (4 or bigger) Must be power of 2. */ ++#define LQTXD 8 ++#define LQTXS LQTXD /* length of Tx Status Queue */ ++ ++/* Tx Queue fill-up level control */ ++#define LVL_TXSTOP LQTXD - 2 /* level to ask the stack to stop Tx */ ++#define LVL_TXRESUME 2 /* level to ask the stack to resume Tx */ ++ ++/* Rx Buffer length in byte */ ++#define LRXB (1518+2+16) /* length of Rx buf, must be 4-byte aligned */ ++#define LTXB LRXB ++ ++#define EP93XX_DEF_MSG (NETIF_MSG_DRV | \ ++ NETIF_MSG_PROBE | \ ++ NETIF_MSG_LINK | \ ++ NETIF_MSG_RX_ERR | \ ++ NETIF_MSG_TX_ERR | \ ++ NETIF_MSG_HW) ++ ++#define DBG(lvl,msg,args...) do { printk(lvl"%s:%d: %s(): " msg, __FILE__, \ ++ __LINE__, __FUNCTION__, ## args); } while (0) ++ ++/* ++ * Custom Data Structures ++ */ ++ ++/* ++ * the information about the buffer passed to device. ++ * there are matching bufdsc informations ++ * for each Tx/Rx Descriptor Queue entry to trace ++ * the buffer within those queues. ++ */ ++struct bufdsc { ++ /* virtual address representing the buffer passed to device */ ++ void *vaddr; ++ /* free routine */ ++ int (*free_rout) (void *buf); ++}; ++ ++/* device private information */ ++struct ep93xx_priv { ++ /* static device information */ ++ int id; /* device instance ID */ ++ /* pointers to various queues (virtual address) */ ++ struct rx_dsc *rdq; /* Rx Descriptor Queue */ ++ struct rx_sts *rsq; /* Rx Status Queue */ ++ struct tx_dsc *tdq; /* Tx Descriptor Queue */ ++ struct tx_sts *tsq; /* Tx Status Queue */ ++ unsigned char *rxbuf; /* base of Rx Buffer pool */ ++ unsigned char *txbuf; /* base of Tx Buffer pool */ ++ struct bufdsc *rxbd; /* Rx Buffers info */ ++ struct bufdsc *txbd; /* Tx Buffers info */ ++ /* physical addresses of the same queues */ ++ dma_addr_t p_qbase; /* base */ ++ dma_addr_t p_rdq; /* Rx Descriptor Queue */ ++ dma_addr_t p_rsq; /* Rx Status Queue */ ++ dma_addr_t p_tdq; /* Tx Descriptor Queue */ ++ dma_addr_t p_tsq; /* Tx Status Queue */ ++ dma_addr_t p_rxbuf; /* Rx Buffer pool */ ++ dma_addr_t p_txbuf; /* Tx Buffer pool */ ++ /* MII Bus ID of Ethernet PHY */ ++ struct mii_if_info mii; ++ /* lock for mii when using ioctls */ ++ spinlock_t mii_lock; ++ /* dynamic information, subject to clear when device open */ ++ struct net_device_stats stats; /* statistic data */ ++ /* next processing index of device queues */ ++ int idx_rdq; ++ int idx_rsq; ++ int idx_tdqhead; ++ int idx_tdqtail; ++ int idx_tsq; ++ void __iomem *base_addr; /* base address */ ++ u32 msg_enable; ++ int regs_len; ++}; ++ ++/* ++ * Internal Routines ++ */ ++ ++static inline unsigned int next_index(unsigned int idx_cur, unsigned int len) ++{ ++ return (idx_cur + 1) % len; /* next array index */ ++} ++ ++static inline u32 _rdl(struct net_device *dev, u32 reg) ++{ ++ return readl(((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg); ++} ++ ++static inline void _wrl(struct net_device *dev, u32 val, u32 reg) ++{ ++ writel(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg); ++} ++ ++static inline void _wrw(struct net_device *dev, u16 val, u32 reg) ++{ ++ writew(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg); ++} ++ ++static inline void _wrb(struct net_device *dev, u8 val, u32 reg) ++{ ++ writeb(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg); ++} ++ ++/** ++ * wait_on_reg() ++ */ ++static int wait_on_reg(struct net_device *dev, int reg, unsigned long mask, unsigned long expect) ++{ ++ int i, dt; ++ ++ for (i = 0; i < 10000; i++) { ++ dt = _rdl(dev, reg); ++ dt = (dt ^ expect) & mask; ++ if (0 == dt) ++ break; ++ } ++ return dt; ++} ++ ++/** ++ * mdio_write() ++ */ ++static void mdio_write(struct net_device *dev, int idPhy, int reg, int dt) ++{ ++ wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy); ++ _wrl(dev, dt, REG_MIIData); ++ _wrl(dev, MIICmd_OP_WR | ((idPhy & 0x1f) << 5) | ((reg & 0x1f) << 0), REG_MIICmd); ++} ++ ++/** ++ * mdio_read() ++ */ ++static int mdio_read(struct net_device *dev, int idPhy, int reg) ++{ ++ int dt; ++ ++ wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy); ++ _wrl(dev, MIICmd_OP_RD | ((idPhy & 0x1f) << 5) | ((reg & 0x1f) << 0), REG_MIICmd); ++ ++ wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy); ++ dt = _rdl(dev, REG_MIIData); ++ ++ return dt & 0xffff; ++} ++ ++/** ++ * phy_init() ++ */ ++static void phy_init(struct net_device *dev) ++{ ++ ++ u32 oldval; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ oldval = _rdl(dev, REG_SelfCTL); ++ ++ /* Set MDC clock to be divided by 8 and disable PreambleSuppress bit */ ++ _wrl(dev, 0x0e00, REG_SelfCTL); ++ ++ if (mii_link_ok(&(priv->mii))) ++ mii_check_media(&(priv->mii), netif_msg_link(priv), 1); ++ ++ /* restore the old value */ ++ _wrl(dev, oldval, REG_SelfCTL); ++} ++ ++/** ++ * devQue_start() ++ * ++ * make descriptor queues active ++ * allocate queue entries if needed ++ * and set device registers up to make it operational ++ * assume device has been initialized ++ */ ++static int devQue_start(struct net_device *dev) ++{ ++ int err; ++ int i; ++ void *buf; ++ u32 phy_addr; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ /* turn off device bus mastering */ ++ _wrl(dev, BMCtl_RxDis | BMCtl_TxDis | _rdl(dev, REG_BMCtl), REG_BMCtl); ++ err = wait_on_reg(dev, REG_BMSts, BMSts_TxAct, ~BMSts_TxAct); ++ err |= wait_on_reg(dev, REG_BMSts, BMSts_RxAct, ~BMSts_RxAct); ++ if (err && netif_msg_hw(priv)) ++ DBG(KERN_ERR, "%s: BM does not stop\n", dev->name); ++ ++ /* Tx Status Queue */ ++ memset(priv->tsq, 0, sizeof(priv->tsq[0]) * LQTXS); ++ priv->idx_tsq = 0; ++ _wrl(dev, priv->p_tsq, REG_TxSBA); ++ _wrl(dev, priv->p_tsq, REG_TxSCA); ++ _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSBL); ++ _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSCL); ++ ++ /* Tx Descriptor Queue */ ++ memset(priv->tdq, 0, sizeof(priv->tdq[0]) * LQTXD); ++ priv->idx_tdqhead = priv->idx_tdqtail = 0; ++ _wrl(dev, priv->p_tdq, REG_TxDBA); ++ _wrl(dev, priv->p_tdq, REG_TxDCA); ++ _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDBL); ++ _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDCL); ++ ++ /* Rx Status Queue */ ++ memset(priv->rsq, 0, sizeof(priv->rsq[0]) * LQRXS); ++ priv->idx_rsq = 0; ++ _wrl(dev, priv->p_rsq, REG_RxSBA); ++ _wrl(dev, priv->p_rsq, REG_RxSCA); ++ _wrw(dev, sizeof(priv->rsq[0]) * LQRXS, REG_RxSBL); ++ _wrw(dev, sizeof(priv->rsq[0]) * LQRXS, REG_RxSCL); ++ ++ /* Rx Descriptor Queue */ ++ memset(priv->rdq, 0, sizeof(priv->rdq[0]) * LQRXD); ++ phy_addr = priv->p_rxbuf; ++ for (i = 0; i < LQRXD; i++) { ++ priv->rdq[i].bi = i; /* index */ ++ priv->rdq[i].ba = phy_addr; /* physical address */ ++ priv->rdq[i].bl = LRXB; /* length */ ++ phy_addr += LRXB; ++ } ++ priv->idx_rdq = 0; ++ _wrl(dev, priv->p_rdq, REG_RxDBA); ++ _wrl(dev, priv->p_rdq, REG_RxDCA); ++ _wrw(dev, sizeof(priv->rdq[0]) * LQRXD, REG_RxDBL); ++ _wrw(dev, sizeof(priv->rdq[0]) * LQRXD, REG_RxDCL); ++ ++ /* init Rx Buffer Descriptors */ ++ buf = priv->rxbuf; ++ for (i = 0; i < LQRXD; i++) { ++ priv->rxbd[i].vaddr = buf; ++ priv->rxbd[i].free_rout = NULL; ++ buf += LRXB; ++ } ++ ++ /* init Tx Buffer Descriptors */ ++ memset(priv->txbd, 0x0, sizeof(*priv->txbd) * LQTXD); ++ ++ buf = priv->txbuf; ++ for (i = 0; i < LQTXD; i++) { ++ priv->txbd[i].vaddr = buf; ++ priv->txbd[i].free_rout = NULL; ++ buf += LTXB; ++ } ++ ++ /* turn on device bus mastering */ ++ _wrl(dev, BMCtl_TxEn | BMCtl_RxEn | _rdl(dev, REG_BMCtl), REG_BMCtl); ++ err = wait_on_reg(dev, REG_BMSts, BMSts_TxAct | BMSts_TxAct, BMSts_TxAct | BMSts_TxAct); ++ if (err && netif_msg_hw(priv)) ++ DBG(KERN_ERR, "%s: BM does not start\n", dev->name); ++ ++ /* Enqueue whole entries; this must be done after BM activation */ ++ _wrl(dev, LQRXS, REG_RxSEQ); /* Rx Status Queue */ ++ _wrl(dev, LQRXD, REG_RxDEQ); /* Rx Desc. queue */ ++ ++ return 0; ++} ++ ++/** ++ * devQue_init() ++ * init device descriptor queues at system level ++ * device access is not recommended at this point ++ * ++ */ ++static int devQue_init(struct net_device *dev) ++{ ++ void *buf; ++ void *tmp; ++ int size, size2; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ /* verify device Tx/Rx Descriptor/Status Queue data size */ ++ if (8 != sizeof(struct rx_dsc)) { ++ if (netif_msg_probe(priv)) ++ DBG(KERN_ERR, "sizeof rx_dsc != 8 bytes!\n"); ++ return -ENOMEM; ++ } else if (8 != sizeof(struct rx_sts)) { ++ if (netif_msg_probe(priv)) ++ DBG(KERN_ERR, "sizeof rx_sts != 8 bytes!\n"); ++ return -ENOMEM; ++ } else if (8 != sizeof(struct tx_dsc)) { ++ if (netif_msg_probe(priv)) ++ DBG(KERN_ERR, "sizeof tx_dsc != 8 bytes!\n"); ++ return -ENOMEM; ++ } else if (4 != sizeof(struct tx_sts)) { ++ if (netif_msg_probe(priv)) ++ DBG(KERN_ERR, "sizeof tx_sts != 4 bytes!\n"); ++ return -ENOMEM; ++ } ++ ++ /* ++ allocate kernel memory for whole queues ++ best if non-cached memory block due to DMA access by the device ++ if CPU doesn't have bus snooping ++ */ ++ size = sizeof(struct rx_dsc) * (LQRXD + 1) + ++ sizeof(struct rx_sts) * (LQRXS + 1) + ++ sizeof(struct tx_dsc) * (LQTXD + 1) + ++ sizeof(struct tx_sts) * (LQTXS + 1) + sizeof(unsigned long) * 4; ++ ++ buf = tmp = dma_alloc_coherent(NULL, size, &priv->p_qbase, GFP_KERNEL | GFP_DMA); ++ if (!buf) { ++ if (netif_msg_probe(priv)) ++ DBG(KERN_ERR, "no memory for queue\n"); ++ return -ENOMEM; ++ } ++ ++ /* ++ * assign memory to each queue ++ */ ++ priv->rdq = buf; ++ buf = buf + sizeof(struct rx_dsc) * (LQRXD + 1); ++ priv->rsq = buf; ++ buf = buf + sizeof(struct rx_sts) * (LQRXS + 1); ++ priv->tdq = buf; ++ buf = buf + sizeof(struct tx_dsc) * (LQTXD + 1); ++ priv->tsq = buf; ++ buf = buf + sizeof(struct tx_sts) * (LQTXS + 1); ++ ++ /* ++ * store physical address of each queue ++ */ ++ priv->p_rdq = priv->p_qbase; ++ priv->p_rsq = priv->p_rdq + ((u32) priv->rsq - (u32) priv->rdq); ++ priv->p_tdq = priv->p_rdq + ((u32) priv->tdq - (u32) priv->rdq); ++ priv->p_tsq = priv->p_rdq + ((u32) priv->tsq - (u32) priv->rdq); ++ ++ /* ++ * init queue entries ++ */ ++ memset(priv->rdq, 0, sizeof(struct rx_dsc) * LQRXD); ++ memset(priv->rsq, 0, sizeof(struct rx_sts) * LQRXS); ++ memset(priv->tdq, 0, sizeof(struct tx_dsc) * LQTXD); ++ memset(priv->tsq, 0, sizeof(struct tx_sts) * LQTXS); ++ ++ /* Allocate Rx Buffer ++ (We might need to copy from Rx buf to skbuff in whatever case, ++ because device bus master requires 32bit aligned Rx buffer address ++ but Linux network stack requires odd 16bit aligned Rx buf address) */ ++ priv->rxbuf = dma_alloc_coherent(NULL, LRXB * LQRXD, &priv->p_rxbuf, GFP_KERNEL | GFP_DMA); ++ ++ if (!priv->rxbuf) { ++ priv->rxbuf = NULL; ++ if (netif_msg_probe(priv)) ++ DBG(KERN_ERR, "no memory for RxBuf\n"); ++ goto err_free_qbase_1; ++ } ++ ++ /* Allocate Tx Buffer */ ++ priv->txbuf = dma_alloc_coherent(NULL, LTXB * LQTXD, &priv->p_txbuf, GFP_KERNEL | GFP_DMA); ++ ++ if (!priv->txbuf) { ++ priv->txbuf = NULL; ++ if (netif_msg_probe(priv)) ++ DBG(KERN_ERR, "no memory for TxBuf\n"); ++ goto err_free_rxbuf_2; ++ } ++ ++ /* ++ * allocate kernel memory for buffer descriptors ++ */ ++ size2 = sizeof(struct bufdsc) * (LQRXD + LQTXD); ++ buf = kmalloc(size2, GFP_KERNEL); ++ if (!buf) { ++ if (netif_msg_probe(priv)) ++ DBG(KERN_ERR, "no memory for buf desc\n"); ++ goto err_free_txbuf_3; ++ } ++ memset(buf, 0x0, size2); /* clear with 0 */ ++ priv->rxbd = buf; ++ priv->txbd = buf + sizeof(struct bufdsc) * LQRXD; ++ ++ return 0; ++ ++err_free_txbuf_3: ++ dma_free_coherent(NULL, LTXB * LQTXD, priv->txbuf, priv->p_txbuf); ++err_free_rxbuf_2: ++ dma_free_coherent(NULL, LRXB * LQRXD, priv->rxbuf, priv->p_rxbuf); ++err_free_qbase_1: ++ dma_free_coherent(NULL, size, tmp, priv->p_qbase); ++ return -ENOMEM; ++} ++ ++/** ++ * devQue_cleanup() ++ * Release queue, Tx buffers and Rx buffers memory ++ * Only call after unregister_netdev ++ */ ++static void devQue_cleanup(struct net_device *dev) ++{ ++ int size; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ /* descriptor queues size */ ++ size = sizeof(struct rx_dsc) * (LQRXD + 1) + ++ sizeof(struct rx_sts) * (LQRXS + 1) + ++ sizeof(struct tx_dsc) * (LQTXD + 1) + ++ sizeof(struct tx_sts) * (LQTXS + 1) + sizeof(unsigned long) * 4; ++ ++ dma_free_coherent(NULL, size, priv->rdq, priv->p_qbase); ++ dma_free_coherent(NULL, LTXB * LQTXD, priv->txbuf, priv->p_txbuf); ++ dma_free_coherent(NULL, LRXB * LQRXD, priv->rxbuf, priv->p_rxbuf); ++ kfree(priv->rxbd); ++ ++} ++ ++/** ++ * set_multicast_tbl() ++ */ ++static void set_multicast_tbl(struct net_device *dev, u8 *buf) ++{ ++ int i; ++ unsigned char position; ++ struct dev_mc_list *cur_addr; ++ ++ memset(buf, 0x00, 8); ++ ++ cur_addr = dev->mc_list; ++ for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) { ++ ++ if (!cur_addr) ++ break; ++ if (!(*cur_addr->dmi_addr & 1)) ++ continue; /* make sure multicast addr */ ++ position = ether_crc_le(6, cur_addr->dmi_addr) >> 26; ++ buf[position >> 3] |= 1 << (position & 0x07); ++ } ++} ++ ++/** ++ * ind_addr_wr() ++ */ ++static int ind_addr_wr(struct net_device *dev, int afp, char *buf) ++{ ++ u32 rxctl; ++ int i, len; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ afp &= 0x07; ++ if (4 == afp || 5 == afp) { ++ if (netif_msg_hw(priv)) ++ DBG(KERN_ERR, "invalid afp value\n"); ++ return -1; ++ } ++ len = (AFP_AFP_HASH == afp) ? 8 : 6; ++ ++ rxctl = _rdl(dev, REG_RxCTL); /* turn Rx off */ ++ _wrl(dev, ~RxCTL_SRxON & rxctl, REG_RxCTL); ++ _wrl(dev, afp, REG_AFP); /* load new address pattern */ ++ for (i = 0; i < len; i++) ++ _wrb(dev, buf[i], REG_IndAD + i); ++ _wrl(dev, rxctl, REG_RxCTL); /* turn Rx back */ ++ ++ return 0; ++} ++ ++/** ++ * rx_ctl() ++ */ ++static int rx_ctl(struct net_device *dev, int sw) ++{ ++ unsigned long tmp = _rdl(dev, REG_RxCTL); ++ ++ /* ++ * Workaround for MAC lost 60-byte-long frames: ++ * must enable Runt_CRC_Accept bit ++ */ ++ if (sw) ++ _wrl(dev, tmp | RxCTL_SRxON | RxCTL_RCRCA, REG_RxCTL); ++ else ++ _wrl(dev, tmp & ~RxCTL_SRxON, REG_RxCTL); ++ ++ return 0; ++} ++ ++/** ++ * chk_tx_lvl() ++ */ ++static void chk_tx_lvl(struct net_device *dev) ++{ ++ int filled; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ /* check Tx Descriptor Queue fill-up level */ ++ filled = priv->idx_tdqhead - priv->idx_tdqtail; ++ if (filled < 0) ++ filled += LQTXD; ++ ++ if (filled <= (LVL_TXRESUME + 1)) ++ netif_wake_queue(dev); ++} ++ ++/** ++ * cleanup_tx() ++ */ ++static void cleanup_tx(struct net_device *dev) ++{ ++ struct tx_sts *txsts; ++ int idxsts, bi; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ /* ++ * process Tx Status Queue (no need to limit processing of TxStatus ++ * Queue because each queue entry consist of 1 dword) ++ */ ++ while (priv->tsq[priv->idx_tsq].flags & TXSTS_TXFP) { ++ idxsts = priv->idx_tsq; ++ priv->idx_tsq = next_index(priv->idx_tsq, LQTXS); ++ txsts = &priv->tsq[idxsts]; ++ if (!(txsts->flags & TXSTS_TXFP)) { /* empty? */ ++ if (netif_msg_tx_err(priv)) ++ DBG(KERN_ERR, "QueTxSts is empty\n"); ++ return; ++ } ++ txsts->flags &= ~TXSTS_TXFP; /* mark processed */ ++ ++ bi = txsts->bi & TXSTS_BI; /* buffer index */ ++ ++ /* statistics collection */ ++ if (txsts->flags & TXSTS_TXWE) { /* Sent without error */ ++ priv->stats.tx_packets++; ++ priv->stats.tx_bytes += ((struct tx_dsc *)(priv->txbd[bi].vaddr))->bl_af & TXDSC_BL; ++ } else { /* Tx failed due to error */ ++ if (netif_msg_tx_err(priv)) ++ DBG(KERN_ERR, "Tx failed QueTxSts"); ++ priv->stats.tx_errors++; ++ if (txsts->flags & TXSTS_LCRS) ++ priv->stats.tx_carrier_errors++; ++ if (txsts->flags & TXSTS_TXU) ++ priv->stats.tx_fifo_errors++; ++ if (txsts->flags & TXSTS_ECOLL) ++ priv->stats.collisions++; ++ } ++ ++ /* free Tx buffer */ ++ if (priv->txbd[bi].free_rout) { ++ (*priv->txbd[bi].free_rout)(priv->txbd[bi].vaddr); ++ priv->txbd[bi].free_rout = NULL; ++ } ++ ++ /* ahead Tx Descriptor Queue tail index */ ++ priv->idx_tdqtail = next_index(priv->idx_tdqtail, LQTXD); ++ } ++} ++ ++/** ++ * restart_tx() ++ */ ++static int restart_tx(struct net_device *dev) ++{ ++ int i; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ /* disable int */ ++ ++ /* turn off master INT control */ ++ _wrl(dev, _rdl(dev, REG_GIntMsk) & ~GIntMsk_IntEn, REG_GIntMsk); ++ ++ /* stop Tx and disable Tx DMA */ ++ _wrl(dev, _rdl(dev, REG_TxCTL) & ~TxCTL_STxON, REG_TxCTL); ++ _wrl(dev, _rdl(dev, REG_BMCtl) | BMCtl_TxDis, REG_BMCtl); ++ ++ /* reset Tx DMA */ ++ _wrl(dev, BMCtl_TxChR | _rdl(dev, REG_BMCtl), REG_BMCtl); ++ ++ /* release Tx buffers */ ++ for (i = 0; i < LQTXD; i++) { ++ if (priv->txbd[i].free_rout) { ++ priv->txbd[i].free_rout(priv->txbd[i].vaddr); ++ priv->txbd[i].free_rout = NULL; ++ } ++ priv->stats.tx_dropped++; ++ } ++ ++ /* init Tx Queues and flush cache */ ++ memset(priv->tsq, 0, sizeof(priv->tsq[0]) * LQTXS); ++ ++ /* init variables */ ++ priv->idx_tsq = priv->idx_tdqhead = priv->idx_tdqtail = 0; ++ ++ /* init registers */ ++ wait_on_reg(dev, REG_BMSts, BMCtl_TxChR, ~BMCtl_TxChR); ++ _wrl(dev, priv->p_tsq, REG_TxSBA); ++ _wrl(dev, priv->p_tsq, REG_TxSCA); ++ _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSBL); ++ _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSCL); ++ _wrl(dev, priv->p_tdq, REG_TxDBA); ++ _wrl(dev, priv->p_tdq, REG_TxDCA); ++ _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDBL); ++ _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDCL); ++ ++ /* start Tx and enable Tx DMA */ ++ _wrl(dev, _rdl(dev, REG_TxCTL) | TxCTL_STxON, REG_TxCTL); ++ _wrl(dev, _rdl(dev, REG_BMCtl) | BMCtl_TxEn, REG_BMCtl); ++ ++ /* enable int again */ ++ _wrl(dev, _rdl(dev, REG_GIntMsk) | GIntMsk_IntEn, REG_GIntMsk); ++ ++ return 0; ++} ++ ++/** ++ * reset() ++ */ ++static void reset(struct net_device *dev) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ /* soft reset command */ ++ _wrb(dev, SelfCTL_RESET, REG_SelfCTL); ++ if (wait_on_reg(dev, REG_SelfCTL, SelfCTL_RESET, ~SelfCTL_RESET)) ++ if (netif_msg_drv(priv)) ++ DBG(KERN_WARNING, "Soft Reset does not self-clear\n"); ++} ++ ++/** ++ * eth_shutdown()- closes down the Ethernet module ++ * ++ * Make sure to: ++ * 1. disable all interrupt mask ++ * 2. disable Rx ++ * 3. disable Tx ++ * ++ * TODO: ++ * (1) maybe utilize power down mode. ++ * Why not yet? Because while the chip will go into power down mode, ++ * the manual says that it will wake up in response to any I/O requests ++ * in the register space. Empirical results do not show this working. ++ */ ++static int eth_shutdown(struct net_device *dev) ++{ ++ reset(dev); ++ return 0; ++} ++ ++/** ++ * eth_init() - Reset and initialize the device. ++ * ++ * Device should be initialized enough to function in polling mode. ++ * Tx and Rx must be disabled and no INT generation. ++ */ ++static int eth_init(struct net_device *dev) ++{ ++ /* reset device */ ++ reset(dev); ++ ++ /* init PHY */ ++ phy_init(dev); ++ ++ /* init MAC */ ++ ++ /*i Set MDC clock to be divided by 8 and enable PreambleSuppress bit */ ++ _wrl(dev, 0x0f00, REG_SelfCTL); ++ /* mask Interrupt */ ++ _wrl(dev, 0x00, REG_GIntMsk); ++ /* no Rx on at this point */ ++ _wrl(dev, RxCTL_BA | RxCTL_IA0, REG_RxCTL); ++ _wrl(dev, 0x00, REG_TxCTL); ++ _wrl(dev, 0x00, REG_GT); ++ _wrl(dev, 0x00, REG_BMCtl); ++ /* Buffer Threshold */ ++ _wrl(dev, (0x80 << 16) | (0x40 << 0), REG_RxBTH); ++ _wrl(dev, (0x80 << 16) | (0x40 << 0), REG_TxBTH); ++ /* Status Threshold */ ++ _wrl(dev, (4 << 16) | (2 << 0), REG_RxSTH); ++ _wrl(dev, (4 << 16) | (2 << 0), REG_TxSTH); ++ /* Descriptor Threshold */ ++ _wrl(dev, (4 << 16) | (2 << 0), REG_RxDTH); ++ _wrl(dev, (4 << 16) | (2 << 0), REG_TxDTH); ++ /* Max Frame Length & Tx Start Threshold */ ++ _wrl(dev, ((1518 + 1) << 16) | (944 << 0), REG_MaxFL); ++ ++ _rdl(dev, REG_TxCollCnt); /* clear Tx Collision Count */ ++ _rdl(dev, REG_RxMissCnt); /* clear Rx Miss Counter */ ++ _rdl(dev, REG_RxRntCnt); /* clear Rx Runt Counter */ ++ ++ /* clear Pending INT */ ++ _rdl(dev, REG_IntStsC); ++ /* Tx on */ ++ _wrl(dev, TxCTL_STxON | _rdl(dev, REG_TxCTL), REG_TxCTL); ++ ++ /* Set MAC address */ ++ ind_addr_wr(dev, AFP_AFP_IA0, &dev->dev_addr[0]); ++ ++ /* init queue */ ++ devQue_start(dev); ++ ++ return 0; ++} ++ ++/** ++ * rx_isr() - Receive Interrupt Service Routine ++ */ ++static void rx_isr(struct net_device *dev) ++{ ++ struct rx_sts *rxsts; ++ /* index of Rx Status Queue Head from device (next put point) */ ++ int idx_rsqhead; ++ int idxsts; ++ int cnt_sts_processed, cnt_desc_processed; ++ char *dest; ++ struct sk_buff *skb; ++ int len; ++ unsigned int dt; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ /* get Current Rx Status Queue pointer */ ++ dt = _rdl(dev, REG_RxSCA); ++ ++ /* convert to array index */ ++ idx_rsqhead = (dt - priv->p_rsq) / sizeof(priv->rsq[0]); ++ if (!(0 <= idx_rsqhead && idx_rsqhead < LQRXS)) { ++ if (netif_msg_rx_err(priv)) ++ DBG(KERN_ERR, " invalid REG_RxSCA\n"); ++ return; ++ } ++ ++ /* process Rx (limit to idx_rsqhead due to cache) */ ++ cnt_sts_processed = cnt_desc_processed = 0; ++ while (idx_rsqhead != priv->idx_rsq) { ++ idxsts = priv->idx_rsq; ++ priv->idx_rsq = next_index(priv->idx_rsq, LQRXS); ++ rxsts = &priv->rsq[idxsts]; ++ if (!(rxsts->w1 & RXSTS_RFP)) { /* empty? */ ++ if (netif_msg_rx_err(priv)) ++ DBG(KERN_ERR, "QueRxSts empty\n"); ++ return; ++ } ++ rxsts->w1 &= ~RXSTS_RFP; /* mark processed */ ++ ++ cnt_sts_processed++; ++ ++ if (!(rxsts->w1 & RXSTS_EOB)) /* buffer has no data */ ++ continue; ++ ++ if ((rxsts->bi & RXSTS_BI) != priv->idx_rdq) { ++ if (netif_msg_rx_err(priv)) ++ DBG(KERN_ERR, "unmatching idx_rdq\n"); ++ continue; ++ } ++ priv->idx_rdq = next_index(priv->idx_rdq, LQRXD); ++ cnt_desc_processed++; ++ ++ /* received a frame with error */ ++ if (!((rxsts->w1 & RXSTS_EOF) && (rxsts->w1 & RXSTS_RWE))) { ++ if (netif_msg_rx_err(priv)) ++ DBG(KERN_WARNING, "Rx error RxSts\n"); ++ priv->stats.rx_errors++; ++ if (rxsts->w1 & RXSTS_OE) ++ priv->stats.rx_fifo_errors++; ++ if (rxsts->w1 & RXSTS_FE) ++ priv->stats.rx_frame_errors++; ++ if ((rxsts->w1 & RXSTS_RUNT) || (rxsts->w1 & RXSTS_EDATA)) ++ priv->stats.rx_length_errors++; ++ if (rxsts->w1 & RXSTS_CRCE) ++ priv->stats.rx_crc_errors++; ++ continue; ++ } ++ ++ len = rxsts->fl; ++ ++ /* alloc buffer for protocal stack */ ++ skb = dev_alloc_skb(len + 5); ++ if (NULL == skb) { ++ if (netif_msg_rx_err(priv)) ++ DBG(KERN_ERR, "Low Memory, Rx dropped\n"); ++ priv->stats.rx_dropped++; ++ continue; ++ } ++ ++ /* odd 16 bit alignment to make protocal stack happy */ ++ skb_reserve(skb, 2); ++ skb->dev = dev; ++ dest = skb_put(skb, len); ++ memcpy(dest, priv->rxbd[(rxsts->bi & RXSTS_BI)].vaddr, len); ++ skb->protocol = eth_type_trans(skb, dev); ++ /* pass Rx packet to system */ ++ netif_rx(skb); ++ dev->last_rx = jiffies; ++ priv->stats.rx_packets++; ++ priv->stats.rx_bytes += len; ++ if (RXSTS_AM == (rxsts->w1 & RXSTS_AM)) ++ priv->stats.multicast++; ++ } ++ ++ /* enqueue */ ++ _wrl(dev, cnt_sts_processed, REG_RxSEQ); ++ _wrl(dev, cnt_desc_processed, REG_RxDEQ); ++} ++ ++/** ++ * tx_isr() - Transmit Interrupt Service Routine ++ */ ++static int tx_isr(struct net_device *dev) ++{ ++ cleanup_tx(dev); ++ chk_tx_lvl(dev); /* resume Tx if it was stopped */ ++ return 0; ++} ++ ++/** ++ * ep93xx_isr() ++ */ ++static irqreturn_t ep93xx_isr(int irq, void *dev_id, struct pt_regs *pRegs) ++{ ++ struct net_device *dev = dev_id; ++ int lpCnt; ++ u32 intS; ++ ++ lpCnt = 0; ++ do { ++ /* get INT status and then clear */ ++ intS = _rdl(dev, REG_IntStsC); ++ ++ if (!intS) ++ break; /* no INT */ ++ if (IntSts_RxSQ & intS) ++ rx_isr(dev); /* Rx INT */ ++ if (IntSts_TxSQ & intS) ++ tx_isr(dev); /* Tx INT */ ++ } while (lpCnt++ < 64); /* limit loop to serve other interrupts too */ ++ return IRQ_HANDLED; ++} ++ ++/* Exposed Driver Routines to the Outside World */ ++ ++/** ++ * ep93xx_get_stats() ++ */ ++static struct net_device_stats *ep93xx_get_stats(struct net_device *dev) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ return &priv->stats; ++} ++ ++/** ++ * ep93xx_set_multicast_list() ++ */ ++static void ep93xx_set_multicast_list(struct net_device *dev) ++{ ++ u8 tbl[8 + 1]; ++ ++ if (IFF_PROMISC & dev->flags) { ++ _wrl(dev, RxCTL_PA | _rdl(dev, REG_RxCTL), REG_RxCTL); ++ ++ } else if (IFF_ALLMULTI & dev->flags) { /* receive all multicast addr */ ++ _wrl(dev, RxCTL_MA | (~RxCTL_PA & _rdl(dev, REG_RxCTL)), REG_RxCTL); ++ memset(tbl, 0xff, 8); ++ ind_addr_wr(dev, AFP_AFP_HASH, &tbl[0]); ++ ++ } else if (dev->mc_count) { /* set H/W multicasting filter */ ++ _wrl(dev, RxCTL_MA | (~RxCTL_PA & _rdl(dev, REG_RxCTL)), REG_RxCTL); ++ set_multicast_tbl(dev, &tbl[0]); ++ ind_addr_wr(dev, AFP_AFP_HASH, &tbl[0]); ++ ++ } else { /* no multicasting */ ++ _wrl(dev, ~(RxCTL_PA | RxCTL_MA) & _rdl(dev, REG_RxCTL), REG_RxCTL); ++ } ++} ++ ++/** ++ * ep93xx_tx_timeout() ++ */ ++static void ep93xx_tx_timeout(struct net_device *dev) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ /* If we get here, some higher level has decided we are broken. ++ There should really be a "kick me" function call instead. */ ++ if (netif_msg_tx_err(priv)) ++ DBG(KERN_WARNING, "transmit timed out\n"); ++ ++ phy_init(dev); ++ ++ /* kick Tx engine */ ++ restart_tx(dev); ++ ++ /* ask the Network Stack to resume Tx if there is room available */ ++ chk_tx_lvl(dev); ++} ++ ++/** ++ * ep93xx_start_xmit() ++ */ ++static int ep93xx_start_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++/* @swk check H/W defect of Tx Underrun Error caused by certain frame length */ ++ struct tx_dsc *txdsc; ++ int idx_tdqhd; ++ int filled; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ idx_tdqhd = priv->idx_tdqhead; ++ txdsc = &priv->tdq[idx_tdqhd]; ++ ++ /* check Tx Descriptor Queue fill-up level */ ++ filled = idx_tdqhd - priv->idx_tdqtail; ++ if (filled < 0) ++ filled += LQTXD; ++ filled += 1; ++ ++ /* check Queue level */ ++ if (LVL_TXSTOP <= filled) { ++ netif_stop_queue(dev); /* no more Tx allowed */ ++ if (netif_msg_tx_err(priv)) ++ DBG(KERN_INFO, "%s: Tx STOP requested\n", dev->name); ++ if (LVL_TXSTOP < filled) { ++ /* this situation can not be happen */ ++ if (netif_msg_tx_err(priv)) ++ DBG(KERN_ERR, "%s: Tx Request while stopped\n", dev->name); ++ return NETDEV_TX_BUSY; ++ } ++ } ++ ++ /* fill up Tx Descriptor Queue entry */ ++ if (skb->len < ETH_ZLEN) { ++ txdsc->bl_af = ETH_ZLEN & TXDSC_BL; /* also clears AF! */ ++ skb = skb_padto(skb, ETH_ZLEN); ++ if (skb == NULL) ++ return NETDEV_TX_OK; ++ } else { ++ txdsc->bl_af = skb->len & TXDSC_BL; /* also clears AF! */ ++ } ++ txdsc->ba = priv->p_txbuf + (idx_tdqhd * LTXB); ++ txdsc->bi_eof = (idx_tdqhd & TXDSC_BI) | TXDSC_EOF; ++ ++ dev->trans_start = jiffies; ++ ++ /* copy data to Tx buffer */ ++ memcpy(priv->txbd[idx_tdqhd].vaddr, skb->data, skb->len); ++ priv->txbd[idx_tdqhd].free_rout = NULL; ++ ++ /* Free the data buffer passed by upper layer */ ++ dev_kfree_skb_any(skb); ++ ++ /* ahead Tx Desc Queue */ ++ priv->idx_tdqhead = next_index(priv->idx_tdqhead, LQTXD); ++ wmb(); ++ ++ /* Enqueue a Tx Descriptor to the device */ ++ _wrl(dev, 1, REG_TxDEQ); ++ ++ if (netif_msg_tx_queued(priv)) ++ DBG(KERN_DEBUG, "%s: Tx packet queued\n", dev->name); ++ ++ return NETDEV_TX_OK; ++} ++ ++/** ++ * ep93xx_close() ++ * ++ * this makes the board clean up everything that it can ++ * and not talk to the outside world. Caused by ++ *. an 'ifconfig ethX down' ++ */ ++static int ep93xx_close(struct net_device *dev) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ free_irq(dev->irq, dev); ++ ++ netif_stop_queue(dev); ++ eth_shutdown(dev); ++ ++ if (netif_msg_ifdown(priv)) ++ DBG(KERN_INFO, "%s: ep93xx_close()\n", dev->name); ++ ++ return 0; ++} ++ ++/** ++ * ep93xx_open() - Open and Initialize the board ++ * ++ * Set up everything, reset the card, etc .. ++ */ ++static int ep93xx_open(struct net_device *dev) ++{ ++ int status; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ /* clear dynamic device info */ ++ memset(&priv->stats, 0, sizeof(priv->stats)); ++ priv->idx_rdq = 0; ++ priv->idx_rsq = 0; ++ priv->idx_tdqhead = 0; ++ priv->idx_tdqtail = 0; ++ priv->idx_tsq = 0; ++ ++ /* reset/init device */ ++ status = eth_init(dev); ++ if (status != 0) { ++ return -EAGAIN; ++ } ++ ++ /* turn on INT, turn on Rx */ ++ status = request_irq(dev->irq, &ep93xx_isr, 0, DRV_NAME, dev); ++ if (status) { ++ if (netif_msg_ifup(priv)) ++ DBG(KERN_ERR, "%s: unable to get IRQ\n", dev->name); ++ return status; ++ } ++ ++ /* Enable interrupt driven operation. Also turn on Rx but no Tx. */ ++ /* setup Interrupt sources */ ++ _wrl(dev, DEF_INT_SRC, REG_IntEn); ++ /* turn on INT */ ++ _wrl(dev, GIntMsk_IntEn, REG_GIntMsk); ++ /* turn on Rx */ ++ rx_ctl(dev, 1); ++ ++ /* link to upper layer */ ++ netif_start_queue(dev); ++ ++ if (netif_msg_ifup(priv)) ++ DBG(KERN_INFO, "%s: irq=%d\n", dev->name, dev->irq); ++ ++ return 0; ++} ++ ++static int ep93xx_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ int rc; ++ ++ if (!netif_running(dev)) ++ return -EINVAL; ++ ++ spin_lock_irq(&priv->mii_lock); ++ rc = generic_mii_ioctl(&priv->mii, if_mii(rq), cmd, NULL); ++ spin_unlock_irq(&priv->mii_lock); ++ ++ return rc; ++} ++ ++/* ++ * Ethtool support ++ */ ++ ++static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) ++{ ++ strcpy(info->driver, DRV_NAME); ++ strcpy(info->version, DRV_VERSION); ++} ++ ++static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ spin_lock_irq(&priv->mii_lock); ++ mii_ethtool_gset(&priv->mii, cmd); ++ spin_unlock_irq(&priv->mii_lock); ++ return 0; ++} ++ ++static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ int rc; ++ spin_lock_irq(&priv->mii_lock); ++ rc = mii_ethtool_sset(&priv->mii, cmd); ++ spin_unlock_irq(&priv->mii_lock); ++ return rc; ++} ++ ++static int ep93xx_nway_reset(struct net_device *dev) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ return mii_nway_restart(&priv->mii); ++} ++ ++static u32 ep93xx_get_link(struct net_device *dev) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ return mii_link_ok(&priv->mii); ++} ++ ++static u32 ep93xx_get_msglevel(struct net_device *dev) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ return priv->msg_enable; ++} ++ ++static void ep93xx_set_msglevel(struct net_device *dev, u32 datum) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ priv->msg_enable = datum; ++} ++ ++static void ep93xx_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ spin_lock_irq(&priv->mii_lock); ++ memcpy_fromio(regbuf, priv->base_addr, regs->len); ++ spin_unlock_irq(&priv->mii_lock); ++} ++ ++static int ep93xx_get_regs_len(struct net_device *dev) ++{ ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ return priv->regs_len; ++} ++ ++static struct ethtool_ops ep93xx_ethtool_ops = { ++ .get_drvinfo = ep93xx_get_drvinfo, ++ .get_settings = ep93xx_get_settings, ++ .set_settings = ep93xx_set_settings, ++ .get_regs = ep93xx_get_regs, ++ .get_regs_len = ep93xx_get_regs_len, ++ .nway_reset = ep93xx_nway_reset, ++ .get_link = ep93xx_get_link, ++ .get_msglevel = ep93xx_get_msglevel, ++ .set_msglevel = ep93xx_set_msglevel, ++}; ++ ++/** ++ * driver_init() - Logical driver initialization for an individual device ++ * ++ * Minimum device H/W access at this point ++ * ++ * Task: ++ * Initialize the structure if needed ++ * print out my vanity message if not done so already ++ * print out what type of hardware is detected ++ * print out the ethernet address ++ * find the IRQ ++ * set up my private data ++ * configure the dev structure with my subroutines ++ * actually GRAB the irq. ++ * GRAB the region ++ * ++ */ ++static int __init driver_init(struct net_device *dev, u32 baseA, int irq) ++{ ++ int i; ++ struct resource *res; ++ struct sockaddr sa; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ if (0 == num_of_instance) ++ printk("%s", version); ++ ++ /* skip probing for a second one, we _know_ that it does not exist */ ++ if (1 == num_of_instance) ++ return -ENODEV; ++ ++ memset(dev->priv, 0x00, sizeof(struct ep93xx_priv)); ++ ++ /* device instance ID */ ++ priv->id = num_of_instance; ++ ++ /* mii stuff */ ++ spin_lock_init(&priv->mii_lock); ++ priv->mii.dev = dev; ++ priv->mii.mdio_read = mdio_read; ++ priv->mii.mdio_write = mdio_write; ++ priv->mii.phy_id_mask = 0x1f; ++ priv->mii.reg_num_mask = 0x1f; ++ priv->msg_enable = EP93XX_DEF_MSG; ++ priv->regs_len = DEV_REG_SPACE; ++ ++ priv->base_addr = (void *)(baseA); ++ ++ dev->irq = irq; ++ ++ res = request_mem_region(baseA, DEV_REG_SPACE, DRV_NAME); ++ if (res == NULL) { ++ if (netif_msg_probe(priv)) ++ DBG(KERN_ERR, "request_mem_region failed!\n"); ++ goto err_free_priv_1; ++ } ++ ++ dev->open = &ep93xx_open; ++ dev->stop = &ep93xx_close; ++ dev->do_ioctl = &ep93xx_ioctl; ++ dev->hard_start_xmit = &ep93xx_start_xmit; ++ dev->tx_timeout = &ep93xx_tx_timeout; ++ dev->watchdog_timeo = HZ * 5; ++ dev->get_stats = &ep93xx_get_stats; ++ dev->set_multicast_list = &ep93xx_set_multicast_list; ++ dev->ethtool_ops = &ep93xx_ethtool_ops; ++ ++ ether_setup(dev); ++ ++ if (devQue_init(dev)) ++ goto err_free_bd_memregion_irq_2; ++ ++ reset(dev); ++ ++ /* ++ * use a random MAC for now - ++ * don't forget to set a valid MAC later on with ifconfig ++ */ ++ sa.sa_family = AF_INET; ++ random_ether_addr(sa.sa_data); ++ dev->set_mac_address(dev, &sa); ++ ++ if (netif_msg_probe(priv)) { ++ printk(KERN_INFO DRV_NAME ": #%d at 0x%p IRQ:%d\n", priv->id, priv->base_addr, dev->irq); ++ printk(KERN_INFO DRV_NAME ": using random number"); ++ for (i = 0; i < 6; i++) ++ printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]); ++ ++ printk(" as MAC, don't forget to assign a valid MAC later!\n"); ++ } ++ num_of_instance++; ++ return 0; ++ ++err_free_bd_memregion_irq_2: ++ kfree(priv->rxbd); ++ disable_irq(dev->irq); ++ free_irq(dev->irq, dev); ++ release_mem_region((u32)priv->base_addr, DEV_REG_SPACE); ++err_free_priv_1: ++ kfree(dev->priv); ++ return -EAGAIN; ++} ++ ++/** ++ * ep93xx_probe - probe for ep93xx device ++ * ++ * Probe for the one (and only) ethernet device found on ++ * EP93xx SOC CPU. ++ */ ++static int __init ep93xx_probe(void) ++{ ++ int err; ++ struct ep93xx_priv *priv; ++ struct net_device *dev = alloc_etherdev(sizeof(struct ep93xx_priv)); ++ ++ if (!dev) ++ return -ENODEV; ++ ++ priv = netdev_priv(dev); ++ ++ SET_MODULE_OWNER(dev); ++ ++ sprintf(dev->name, "eth0"); ++ ++ priv->base_addr = (void *)(port_list[0].base_addr); ++ ++ dev->irq = port_list[0].irq; ++ ++ err = driver_init(dev, (u32)priv->base_addr, dev->irq); ++ if (err) ++ goto err_free_netdev; ++ ++ err = register_netdev(dev); ++ if (err) ++ goto err_free_memregion_irq_1; ++ ++ ep93xx_etherdev = dev; ++ disable_irq(dev->irq); ++ return 0; ++ ++err_free_memregion_irq_1: ++ kfree(priv->rxbd); ++ disable_irq(dev->irq); ++ free_irq(dev->irq, dev); ++ release_mem_region((u32)priv->base_addr, DEV_REG_SPACE); ++err_free_netdev: ++ free_netdev(dev); ++ return err; ++} ++ ++static void __exit ep93xx_exit(void) ++{ ++ struct net_device *dev = ep93xx_etherdev; ++ struct ep93xx_priv *priv = netdev_priv(dev); ++ ++ if (dev) { ++ unregister_netdev(dev); ++ devQue_cleanup(dev); ++ free_irq(dev->irq, dev); ++ release_mem_region((u32)priv->base_addr, DEV_REG_SPACE); ++ free_netdev(dev); ++ } ++} ++ ++module_init(ep93xx_probe); ++module_exit(ep93xx_exit); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/net/arm/ep93xx_eth.h b/drivers/net/arm/ep93xx_eth.h +new file mode 100644 +index 0000000..1752eaf +--- /dev/null ++++ b/drivers/net/arm/ep93xx_eth.h +@@ -0,0 +1,355 @@ ++/* ++ * ep93xx_eth.h ++ * : header file of Ethernet Device Driver for Cirrus Logic EP93xx. ++ * ++ * Copyright (C) 2003 by Cirrus Logic www.cirrus.com ++ * This software may be used and distributed according to the terms ++ * of the GNU Public License. ++ * ++ * This file contains device related information like register info ++ * and register access method macros for the Ethernet device ++ * embedded within Cirrus Logic's EP93xx SOC chip. ++ * ++ * Information contained in this file was obtained from ++ * the EP9312 Manual Revision 0.12 and 0.14 from Cirrus Logic. ++ * ++ * History ++ * 05/18/01 Sungwook Kim Initial release ++ * 03/25/2003 Melody Modified for EP92xx ++ */ ++ ++#ifndef _EP93xx_ETH_H_ ++#define _EP93xx_ETH_H_ ++ ++/* ++ * Definition of the registers. ++ * For details, refer to the datasheet . ++ * ++ * Basically, most registers are 32 bits width register. ++ * But some are 16 bits and some are 6 or 8 bytes long. ++ */ ++ ++#define REG_RxCTL 0x0000 /*offset to Receiver Control Reg */ ++#define RxCTL_PauseA (1<<20) ++#define RxCTL_RxFCE1 (1<<19) ++#define RxCTL_RxFCE0 (1<<18) ++#define RxCTL_BCRC (1<<17) ++#define RxCTL_SRxON (1<<16) ++#define RxCTL_RCRCA (1<<13) ++#define RxCTL_RA (1<<12) ++#define RxCTL_PA (1<<11) ++#define RxCTL_BA (1<<10) ++#define RxCTL_MA (1<<9) ++#define RxCTL_IAHA (1<<8) ++#define RxCTL_IA3 (1<<3) ++#define RxCTL_IA2 (1<<2) ++#define RxCTL_IA1 (1<<1) ++#define RxCTL_IA0 (1<<0) ++ ++#define REG_TxCTL 0x0004 /*offset to Transmit Control Reg */ ++#define TxCTL_DefDis (1<<7) ++#define TxCTL_MBE (1<<6) ++#define TxCTL_ICRC (1<<5) ++#define TxCTL_TxPD (1<<5) ++#define TxCTL_OColl (1<<3) ++#define TxCTL_SP (1<<2) ++#define TxCTL_PB (1<<1) ++#define TxCTL_STxON (1<<0) ++ ++#define REG_TestCTL 0x0008 /*Test Control Reg, R/W */ ++#define TestCTL_MACF (1<<7) ++#define TestCTL_MFDX (1<<6) ++#define TestCTL_DB (1<<5) ++#define TestCTL_MIIF (1<<4) ++ ++#define REG_MIICmd 0x0010 /*offset to MII Command Reg, R/W */ ++#define MIICmd_OP (0x03<<14) ++#define MIICmd_OP_RD (2<<14) ++#define MIICmd_OP_WR (1<<14) ++#define MIICmd_PHYAD (0x1f<<5) ++#define MIICmd_REGAD (0x1f<<0) ++ ++#define REG_MIIData 0x0014 /*offset to MII Data Reg, R/W */ ++#define MIIData_MIIData (0xffff<<0) ++ ++#define REG_MIISts 0x0018 /*offset to MII Status Reg, R */ ++#define MIISts_Busy (1<<0) ++ ++#define REG_SelfCTL 0x0020 /*offset to Self Control Reg */ ++#define SelfCTL_RWP (1<<7) /*Remote Wake Pin */ ++#define SelfCTL_GPO0 (1<<5) ++#define SelfCTL_PUWE (1<<4) ++#define SelfCTL_PDWE (1<<3) ++#define SelfCTL_MIIL (1<<2) ++#define SelfCTL_RESET (1<<0) ++ ++#define REG_IntEn 0x0024 /*Interrupt Enable Reg, R/W */ ++#define IntEn_RWIE (1<<30) ++#define IntEn_RxMIE (1<<29) ++#define IntEn_RxBIE (1<<28) ++#define IntEn_RxSQIE (1<<27) ++#define IntEn_TxLEIE (1<<26) ++#define IntEn_ECIE (1<<25) ++#define IntEn_TxUHIE (1<<24) ++#define IntEn_MOIE (1<<18) ++#define IntEn_TxCOIE (1<<17) ++#define IntEn_RxROIE (1<<16) ++#define IntEn_MIIIE (1<<12) ++#define IntEn_PHYSIE (1<<11) ++#define IntEn_TIE (1<<10) ++#define IntEn_SWIE (1<<8) ++#define IntEn_TxSQIE (1<<3) ++#define IntEn_RxEOFIE (1<<2) ++#define IntEn_RxEOBIE (1<<1) ++#define IntEn_RxHDRIE (1<<0) ++ ++#define REG_IntStsP 0x0028 /*offset to Interrupt Status Preserve Reg, R/W */ ++#define REG_IntStsC 0x002c /*offset to Interrupt Status Clear Reg, R */ ++#define IntSts_RWI (1<<30) ++#define IntSts_RxMI (1<<29) ++#define IntSts_RxBI (1<<28) ++#define IntSts_RxSQI (1<<27) ++#define IntSts_TxLEI (1<<26) ++#define IntSts_ECI (1<<25) ++#define IntSts_TxUHI (1<<24) ++#define IntSts_MOI (1<<18) ++#define IntSts_TxCOI (1<<17) ++#define IntSts_RxROI (1<<16) ++#define IntSts_MIII (1<<12) ++#define IntSts_PHYSI (1<<11) ++#define IntSts_TI (1<<10) ++#define IntSts_AHBE (1<<9) ++#define IntSts_SWI (1<<8) ++#define IntSts_OTHER (1<<4) ++#define IntSts_TxSQ (1<<3) ++#define IntSts_RxSQ (1<<2) ++ ++#define REG_GT 0x0040 /*offset to General Timer Reg */ ++#define GT_GTC (0xffff<<16) ++#define GT_GTP (0xffff<<0) ++ ++#define REG_FCT 0x0044 /*offset to Flow Control Timer Reg */ ++#define FCT_FCT (0x00ffffff<<0) ++ ++#define REG_FCF 0x0048 /*offset to Flow Control Format Reg */ ++#define FCF_MACCT (0xffff<<16) ++#define FCF_TPT (0xffff<<0) ++ ++#define REG_AFP 0x004c /*offset to Address Filter Pointer Reg */ ++#define AFP_AFP (0x07<<0) /*Address Filter Pointer ++ (bank control for REG_IndAD) */ ++#define AFP_AFP_IA0 0 /*Primary Individual Address (MAC Addr) */ ++#define AFP_AFP_IA1 1 /*Individual Address 1 */ ++#define AFP_AFP_IA2 2 /*Individual Address 2 */ ++#define AFP_AFP_IA3 3 /*Individual Address 3 */ ++#define AFP_AFP_DTxP 6 /*Destination Address of Tx Pause Frame */ ++#define AFP_AFP_HASH 7 /*Hash Table */ ++ ++#define REG_IndAD 0x0050 /*offset to Individual Address Reg, ++ n bytes, R/W */ ++ ++#define REG_GIntSts 0x0060 /*offset to Global Interrupt ++ Status Reg (writing 1 will clear) */ ++#define REG_GIntROS 0x0068 /*offset to Global Interrupt ++ Status Read Only Reg */ ++#define GIntSts_INT (1<<15) /*Global Interrupt Request Status */ ++ ++#define REG_GIntMsk 0x0064 /*offset to Global Interrupt Mask Reg */ ++#define GIntMsk_IntEn (1<<15) /*Global Interrupt Enable */ ++ ++#define REG_GIntFrc 0x006c /*offset to Global Interrupt Force Reg */ ++#define GIntFrc_INT (1<<15) /*Force to set GIntSts */ ++ ++#define REG_TxCollCnt 0x0070 /*Transmit Collision Count Reg, R */ ++#define REG_RxMissCnt 0x0074 /*Receive Miss Count Reg, R */ ++#define REG_RxRntCnt 0x0078 /*Receive Runt Count Reg, R */ ++ ++#define REG_BMCtl 0x0080 /*offset to Bus Master Control Reg, R/W */ ++#define BMCtl_MT (1<<13) ++#define BMCtl_TT (1<<12) ++#define BMCtl_UnH (1<<11) ++#define BMCtl_TxChR (1<<10) ++#define BMCtl_TxDis (1<<9) ++#define BMCtl_TxEn (1<<8) ++#define BMCtl_EH2 (1<<6) ++#define BMCtl_EH1 (1<<5) ++#define BMCtl_EEOB (1<<4) ++#define BMCtl_RxChR (1<<2) ++#define BMCtl_RxDis (1<<1) ++#define BMCtl_RxEn (1<<0) ++ ++#define REG_BMSts 0x0084 /*offset to Bus Master Status Reg, R */ ++#define BMSts_TxAct (1<<7) ++#define BMSts_TP (1<<4) ++#define BMSts_RxAct (1<<3) ++#define BMSts_QID (0x07<<0) ++#define BMSts_QID_RxDt (0<<0) ++#define BMSts_QID_TxDt (1<<0) ++#define BMSts_QID_RxSts (2<<0) ++#define BMSts_QID_TxSts (3<<0) ++#define BMSts_QID_RxDesc (4<<0) ++#define BMSts_QID_TxDesc (5<<0) ++ ++#define REG_RBCA 0x0088 /*offset to Receive Buffer ++ Current Address Reg, R */ ++#define REG_TBCA 0x008c /*offset to Transmit Buffer ++ Current Address Reg, R */ ++ ++#define REG_RxDBA 0x0090 /*offset to Receive Descriptor Queue ++ Base Address Reg, R/W */ ++#define REG_RxDBL 0x0094 /*offset to Receive Descriptor Queue ++ Base Length Reg, R/W, 16bits */ ++#define REG_RxDCL 0x0096 /*offset to Receive Descriptor Queue ++ Current Length Reg, R/W, 16bits */ ++#define REG_RxDCA 0x0098 /*offset to Receive Descriptor Queue ++ Current Address Reg, R/W */ ++ ++#define REG_RxDEQ 0x009c /*offset to Receive Descriptor ++ Enqueue Reg, R/W */ ++#define RxDEQ_RDV (0xffff<<16) /*R 16bit; Receive Descriptor Value */ ++#define RxDEQ_RDI (0xff<<0) /*W 8bit; Receive Descriptor Increment */ ++ ++#define REG_RxSBA 0x00a0 /*offset to Receive Status Queue ++ Base Address Reg, R/W */ ++#define REG_RxSBL 0x00a4 /*offset to Receive Status Queue ++ Base Length Reg, R/W, 16bits */ ++#define REG_RxSCL 0x00a6 /*offset to Receive Status Queue ++ Current Length Reg, R/W, 16bits */ ++#define REG_RxSCA 0x00a8 /*offset to Receive Status Queue ++ Current Address Reg, R/W */ ++ ++#define REG_RxSEQ 0x00ac /*offset to Receive Status Queue ++ Current Address Reg, R/W */ ++#define RxSEQ_RSV (0xffff<<16) ++#define RxSEQ_RSI (0xff<<0) ++ ++#define REG_TxDBA 0x00b0 /*offset to Transmit Descriptor Queue ++ Base Address Reg, R/W */ ++#define REG_TxDBL 0x00b4 /*offset to Transmit Descriptor Queue ++ Base Length Reg, R/W, 16bits */ ++#define REG_TxDCL 0x00b6 /*offset to Transmit Descriptor Queue ++ Current Length Reg, R/W, 16bits */ ++#define REG_TxDCA 0x00b8 /*offset to Transmit Descriptor Queue ++ Current Address Reg, R/W */ ++ ++#define REG_TxDEQ 0x00bc /*offset to Transmit Descriptor Queue ++ Current Address Reg, R/W */ ++#define TxDEQ_TDV (0xffff<<16) ++#define TxDEQ_TDI (0xff<<0) ++ ++#define REG_TxSBA 0x00c0 /*offset to Transmit Status Queue ++ Base Address Reg, R/W */ ++#define REG_TxSBL 0x00c4 /*offset to Transmit Status Queue ++ Base Length Reg, R/W, 16bits */ ++#define REG_TxSCL 0x00c6 /*offset to Transmit Status Queue ++ Current Length Reg, R/W, 16bits */ ++#define REG_TxSCA 0x00c8 /*offset to Transmit Status Queue ++ Current Address Reg, R/W */ ++ ++#define REG_RxBTH 0x00d0 /*offset to Receive Buffer ++ Threshold Reg, R/W */ ++#define RxBTH_RDHT (0x03ff<<16) ++#define RxBTH_RDST (0x03ff<<0) ++ ++#define REG_TxBTH 0x00d4 /*offset to Transmit Buffer ++ Threshold Reg, R/W */ ++#define TxBTH_TDHT (0x03ff<<16) ++#define TxBTH_TDST (0x03ff<<0) ++ ++#define REG_RxSTH 0x00d8 /*offset to Receive Status ++ Threshold Reg, R/W */ ++#define RxSTH_RSHT (0x003f<<16) ++#define RxSTH_RSST (0x003f<<0) ++ ++#define REG_TxSTH 0x00dc /*offset to Transmit Status ++ Threshold Reg, R/W */ ++#define TxSTH_TSHT (0x003f<<16) ++#define TxSTH_TSST (0x003f<<0) ++ ++#define REG_RxDTH 0x00e0 /*offset to Receive Descriptor ++ Threshold Reg, R/W */ ++#define RxDTH_RDHT (0x003f<<16) ++#define RxDTH_RDST (0x003f<<0) ++ ++#define REG_TxDTH 0x00e4 /*offset to Transmit Descriptor ++ Threshold Reg, R/W */ ++#define TxDTH_TDHT (0x003f<<16) ++#define TxDTH_TDST (0x003f<<0) ++ ++#define REG_MaxFL 0x00e8 /*offset to Max Frame Length Reg, R/W */ ++#define MaxFL_MFL (0x07ff<<16) ++#define MaxFL_TST (0x07ff<<0) ++ ++#define REG_RxHL 0x00ec /*offset to Receive Header Length Reg, R/W */ ++#define RxHL_RHL2 (0x07ff<<16) ++#define RxHL_RHL1 (0x03ff<<0) ++ ++#define REG_MACCFG0 0x0100 /*offset to Test Reg #0, R/W */ ++#define MACCFG0_DbgSel (1<<7) ++#define MACCFG0_LCKEN (1<<6) ++#define MACCFG0_LRATE (1<<5) ++#define MACCFG0_RXERR (1<<4) ++#define MACCFG0_BIT33 (1<<2) ++#define MACCFG0_PMEEN (1<<1) ++#define MACCFG0_PMEST (1<<0) ++ ++#define REG_MACCFG1 0x0104 /*offset to Test Reg #1, R/W */ ++#define REG_MACCFG2 0x0108 /*offset to Test Reg #2, R */ ++#define REG_MACCFG3 0x010c /*offset to Test Reg #3, R */ ++ ++/*--------------------------------------------------------------- ++ * Definition of Descriptor/Status Queue Entry ++ *-------------------------------------------------------------*/ ++struct rx_dsc { ++ __be32 ba; ++ __be16 bl; ++ __be16 bi; /* let nsof flag be part of bi */ ++}; ++ ++#define RXSTS_RFP 0x80000000 ++#define RXSTS_RWE 0x40000000 ++#define RXSTS_EOF 0x20000000 ++#define RXSTS_EOB 0x10000000 ++#define RXSTS_AM 0x00C00000 ++#define RXSTS_OE 0x00100000 ++#define RXSTS_FE 0x00080000 ++#define RXSTS_RUNT 0x00040000 ++#define RXSTS_EDATA 0x00020000 ++#define RXSTS_CRCE 0x00010000 ++ ++#define RXSTS_BI 0x7FFF ++struct rx_sts { /* Receive Status Queue Entry */ ++ __be32 w1; ++ __be16 fl; ++ __be16 bi; /* bi and rfp2 */ ++}; ++ ++#define TXDSC_BL 0x0FFF ++#define TXDSC_AF 0x8000 ++#define TXDSC_BI 0x7FFF ++#define TXDSC_EOF 0x8000 ++struct tx_dsc { /* Transmit Descriptor Queue Entry */ ++ __be32 ba; /*b31-0: physical Buffer Address */ ++ __be16 bl_af; /* Buffer Length, Abort Frame */ ++ __be16 bi_eof; /* Buffer Index, End Of Frame */ ++}; ++ ++#define TXSTS_BI 0x7fff ++#define TXSTS_TXFP 0x80 ++#define TXSTS_TXWE 0x40 ++#define TXSTS_LCRS 0x10 ++#define TXSTS_TXU 0x02 ++#define TXSTS_ECOLL 0x01 ++ ++struct tx_sts { ++ __be16 bi; ++ u8 ncoll; ++ u8 flags; ++}; ++ ++/* ++ * Size of device registers occupied in memory/IO address map ++ */ ++#define DEV_REG_SPACE 0x00010000 ++ ++#endif /* _EP93xx_ETH_H_ */ +diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig +index 309eb55..b7e03e3 100644 +--- a/drivers/pcmcia/Kconfig ++++ b/drivers/pcmcia/Kconfig +@@ -198,6 +198,19 @@ config PCMCIA_PXA2XX + help + Say Y here to include support for the PXA2xx PCMCIA controller + ++config PCMCIA_EP93XX ++ tristate "EP93xx support" ++ depends on ARM && ARCH_EP93XX && PCMCIA ++ help ++ Say Y here to include support for the EP93xx PCMCIA controller ++ ++config PCMCIA_ZEFEEREVBH ++ bool "ZefeerEVB-H support" ++ depends on ARM && ARCH_EP93XX && PCMCIA && PCMCIA_EP93XX && MACH_ZEFEERDZQ ++ help ++ Say Y here to include support for the PCMCIA interface on ++ ZefeerEVB-H board ++ + config PCMCIA_PROBE + bool + default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X +diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile +index bcecf51..5878b5a 100644 +--- a/drivers/pcmcia/Makefile ++++ b/drivers/pcmcia/Makefile +@@ -30,6 +30,7 @@ obj-$(CONFIG_HD64465_PCMCIA) += hd6446 + obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o + obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o + obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o pxa2xx_cs.o ++obj-$(CONFIG_PCMCIA_EP93XX) += ep93xx_core.o ep93xx_cs.o + obj-$(CONFIG_M32R_PCC) += m32r_pcc.o + obj-$(CONFIG_M32R_CFC) += m32r_cfc.o + obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o +@@ -39,6 +40,7 @@ obj-$(CONFIG_OMAP_CF) += omap_cf.o + + sa11xx_core-y += soc_common.o sa11xx_base.o + pxa2xx_core-y += soc_common.o pxa2xx_base.o ++ep93xx_core-y += soc_common.o ep93xx_base.o + + au1x00_ss-y += au1000_generic.o + au1x00_ss-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o +@@ -69,3 +71,7 @@ pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa + pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o + pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o + ++ep93xx_cs-$(CONFIG_MACH_ADSSPHERE) += ep93xx_adssphere.o ++ep93xx_cs-$(CONFIG_MACH_EDB9315) += ep93xx_edb9315.o ++ep93xx_cs-$(CONFIG_MACH_DMA03) += ep93xx_edb9315.o ++ep93xx_cs-$(CONFIG_PCMCIA_ZEFEEREVBH) += ep93xx_zefeerevbh.o +diff --git a/drivers/pcmcia/ep93xx_adssphere.c b/drivers/pcmcia/ep93xx_adssphere.c +new file mode 100644 +index 0000000..8e1a181 +--- /dev/null ++++ b/drivers/pcmcia/ep93xx_adssphere.c +@@ -0,0 +1,190 @@ ++/* ++ * linux/drivers/pcmcia/ep93xx_adssphere.c ++ * ++ * Adapted from pxa27x_mainstone.c ++ * ++ * Robert Whaley 2005 rwhaley@applieddata.net ++ * ++ * Adssphere PCMCIA specific routines. ++ * ++ * Created: May 12, 2004 ++ * Author: Nicolas Pitre ++ * Copyright: MontaVista Software Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/errno.h> ++#include <linux/interrupt.h> ++#include <linux/device.h> ++ ++#include <pcmcia/ss.h> ++ ++#include <asm/io.h> ++#include <asm/hardware.h> ++#include <asm/irq.h> ++ ++#include <asm/arch/adssphere.h> ++ ++#include "soc_common.h" ++ ++static struct pcmcia_irqs irqs[] = { ++ { 0, IRQ_GPIO1, "CF CD1" }, ++ { 0, IRQ_GPIO2, "CF CD2" }, ++ { 0, IRQ_GPIO3, "CF STSCHG/BVD1" }, ++ { 0, IRQ_GPIO4, "CF SPKR/BVD2" }, ++}; ++ ++ ++static int adssphere_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ++{ ++ int rtn; ++ ++ if (skt->nr != 0) ++ return -ENXIO; ++ ++ skt->irq = IRQ_GPIO6; ++ ++ rtn = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); ++ ++ /* enable GPIO6 as interrupt */ ++ writel(0x40, GPIO_INTEN); ++ ++ /* enable GPIO1-4 and 6 as interrupt */ ++ /* Note: 1-4 need to be edge triggered, but ++ then the irq vectors need to hit GPIOxEIO ++ which they don't currently do - no big deal ++ since CD and BVD are polled anyway */ ++ /* writel(0x5e, GPIO_INTEN); */ ++ ++ return rtn; ++} ++ ++static void adssphere_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) ++{ ++ soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); ++} ++ ++static void adssphere_pcmcia_socket_state(struct soc_pcmcia_socket *skt, ++ struct pcmcia_state *state) ++{ ++ unsigned long status; ++ ++ status = inl(GPIO_PFDR); ++ ++ state->detect = (status & PCMCIA_DETECT) ? 0 : 1; ++ state->ready = (status & PCMCIA_READY) ? 1 : 0; ++ state->bvd1 = (status & PCMCIA_BVD1) ? 1 : 0; ++ state->bvd2 = (status & PCMCIA_BVD2) ? 1 : 0; ++ state->vs_3v = (status & PCMCIA_VS_3V) ? 0 : 1; ++ state->vs_Xv = (status & PCMCIA_VS_XV) ? 0 : 1; ++ state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1; ++ ++// printk("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state)); ++} ++ ++static int adssphere_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, ++ const socket_state_t *state) ++{ ++ unsigned long clrbits = 0, setbits = 0, cr0; ++ int ret = 0; ++ ++ switch (state->Vcc) { ++ case 0: { ++ clrbits = ADSSPHERE_CR0_CF_33 | ADSSPHERE_CR0_CF_50; ++ setbits = 0; ++ break; ++ } ++ case 33: { ++ clrbits = ADSSPHERE_CR0_CF_50; ++ setbits = ADSSPHERE_CR0_CF_33; ++ break; ++ } ++ case 50: { ++ clrbits = ADSSPHERE_CR0_CF_33; ++ setbits = ADSSPHERE_CR0_CF_50; ++ break; ++ } ++ default: ++ printk(KERN_ERR "%s(): bad Vcc %u\n", ++ __FUNCTION__, state->Vcc); ++ ret = -1; ++ } ++ ++ if (!ret && skt->nr == 0) { ++ cr0 = inl(ADSSPHERE_CR0); ++ cr0 &= ~clrbits; ++ cr0 |= setbits; ++ writel(cr0, ADSSPHERE_CR0); ++ ++ if (state->flags & SS_RESET) { ++ /* see EP93xx User's Guide */ ++ writel(0x15, PCMCIACNT); ++ } else { ++ /* CF mode - BIT1 for PCMCIA mode */ ++ writel(0x11, PCMCIACNT); ++ } ++ } ++ ++ return ret; ++} ++ ++static void adssphere_pcmcia_socket_init(struct soc_pcmcia_socket *skt) ++{ ++} ++ ++static void adssphere_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) ++{ ++} ++ ++static struct pcmcia_low_level adssphere_pcmcia_ops = { ++ .owner = THIS_MODULE, ++ .hw_init = adssphere_pcmcia_hw_init, ++ .hw_shutdown = adssphere_pcmcia_hw_shutdown, ++ .socket_state = adssphere_pcmcia_socket_state, ++ .configure_socket = adssphere_pcmcia_configure_socket, ++ .socket_init = adssphere_pcmcia_socket_init, ++ .socket_suspend = adssphere_pcmcia_socket_suspend, ++ .nr = 1, ++}; ++ ++static struct platform_device *adssphere_pcmcia_device; ++ ++static int __init adssphere_pcmcia_init(void) ++{ ++ int ret; ++ ++ adssphere_pcmcia_device = kmalloc(sizeof(*adssphere_pcmcia_device), GFP_KERNEL); ++ if (!adssphere_pcmcia_device) ++ return -ENOMEM; ++ memset(adssphere_pcmcia_device, 0, sizeof(*adssphere_pcmcia_device)); ++ adssphere_pcmcia_device->name = "ep93xx-pcmcia"; ++ adssphere_pcmcia_device->dev.platform_data = &adssphere_pcmcia_ops; ++ ++ ret = platform_device_register(adssphere_pcmcia_device); ++ if (ret) ++ kfree(adssphere_pcmcia_device); ++ ++ return ret; ++} ++ ++static void __exit adssphere_pcmcia_exit(void) ++{ ++ /* ++ * This call is supposed to free our adssphere_pcmcia_device. ++ * Unfortunately platform_device don't have a free method, and ++ * we can't assume it's free of any reference at this point so we ++ * can't free it either. ++ */ ++ platform_device_unregister(adssphere_pcmcia_device); ++} ++ ++module_init(adssphere_pcmcia_init); ++module_exit(adssphere_pcmcia_exit); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/pcmcia/ep93xx_base.c b/drivers/pcmcia/ep93xx_base.c +new file mode 100644 +index 0000000..2377989 +--- /dev/null ++++ b/drivers/pcmcia/ep93xx_base.c +@@ -0,0 +1,190 @@ ++/*====================================================================== ++ ++ Device driver for the PCMCIA control functionality of EP93xx ++ microprocessors. Derived from pxa2xx_base.c ++ ++ The contents of this file may be used under the ++ terms of the GNU Public License version 2 (the "GPL") ++ ++ (c) Ian Molton (spyro@f2s.com) 2003 ++ (c) Stefan Eletzhofer (stefan.eletzhofer@inquant.de) 2003,4 ++ (c) Robert Whaley (rwhaley@applieddata.net) 2005 ++ ++ derived from sa11xx_base.c ++ ++ Portions created by John G. Dorsey are ++ Copyright (C) 1999 John G. Dorsey. ++ ++ ======================================================================*/ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/config.h> ++#include <linux/ioport.h> ++#include <linux/kernel.h> ++#include <linux/spinlock.h> ++ ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <asm/system.h> ++ ++#include <pcmcia/cs_types.h> ++#include <pcmcia/ss.h> ++#include <pcmcia/bulkmem.h> ++#include <pcmcia/cistpl.h> ++ ++#include "cs_internal.h" ++#include "soc_common.h" ++ ++#define MIN(a,b) ((a)>(b) ? (b) : (a)) ++ ++#define MCXX_SETUP_MAX 0xff ++#define MCXX_ASST_MAX 0xff ++#define MCXX_HOLD_MAX 0x0f ++ ++#define MCXX_SETUP_SHIFT 0 ++#define MCXX_ASST_SHIFT 16 ++#define MCXX_HOLD_SHIFT 8 ++ ++ ++ ++static inline u_int ep93xx_mcxx_hold(u_int pcmcia_cycle_ns, ++ u_int hclk_10khz) ++{ ++ u_int code = pcmcia_cycle_ns * hclk_10khz; ++ return (code / 100000) + ((code % 100000) ? 1 : 0) - 1; ++} ++ ++static inline u_int ep93xx_mcxx_asst(u_int pcmcia_cycle_ns, ++ u_int hclk_10khz) ++{ ++ u_int code = pcmcia_cycle_ns * hclk_10khz; ++ return (code / 100000) + ((code % 100000) ? 1 : 0) - 1; ++} ++ ++static inline u_int ep93xx_mcxx_setup(u_int pcmcia_cycle_ns, ++ u_int hclk_10khz) ++{ ++ u_int code = pcmcia_cycle_ns * hclk_10khz; ++ return (code / 100000) + ((code % 100000) ? 1 : 0) - 1; ++} ++ ++static int ep93xx_pcmcia_set_mcmem( int sock, int speed, int clock ) ++{ ++ writel(PC16BITSWIDE ++ | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT) ++ | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT) ++ | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT), ++ PC1COMMON); ++ ++ return 0; ++} ++ ++static int ep93xx_pcmcia_set_mcio( int sock, int speed, int clock ) ++{ ++ writel(PC16BITSWIDE ++ | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT) ++ | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT) ++ | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT), ++ PC1IO); ++ ++ return 0; ++} ++ ++static int ep93xx_pcmcia_set_mcatt( int sock, int speed, int clock ) ++{ ++ writel(PC16BITSWIDE ++ | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT) ++ | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT) ++ | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT), ++ PC1ATTRIB); ++ ++ return 0; ++} ++ ++static int ep93xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int clk) ++{ ++ struct soc_pcmcia_timing timing; ++ int sock = skt->nr; ++ ++ soc_common_pcmcia_get_timing(skt, &timing); ++ ++ ep93xx_pcmcia_set_mcmem(sock, timing.mem, clk); ++ ep93xx_pcmcia_set_mcatt(sock, timing.attr, clk); ++ ep93xx_pcmcia_set_mcio(sock, timing.io, clk); ++ ++ return 0; ++} ++ ++static int ep93xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt) ++{ ++ unsigned int hclk = 10000; /* for now just hard code hclk to 100Mhz (in 10khz units)*/ ++ return ep93xx_pcmcia_set_mcxx(skt, hclk); ++} ++ ++int ep93xx_drv_pcmcia_probe(struct device *dev) ++{ ++ int ret; ++ struct pcmcia_low_level *ops; ++ int first, nr; ++ ++ if (!dev || !dev->platform_data) ++ return -ENODEV; ++ ++ ops = (struct pcmcia_low_level *)dev->platform_data; ++ first = ops->first; ++ nr = ops->nr; ++ ++ /* Provide our EP93xx specific timing routines. */ ++ ops->set_timing = ep93xx_pcmcia_set_timing; ++ ++ ret = soc_common_drv_pcmcia_probe(dev, ops, first, nr); ++ ++ return ret; ++} ++EXPORT_SYMBOL(ep93xx_drv_pcmcia_probe); ++ ++static int ep93xx_drv_pcmcia_suspend(struct device *dev, u32 state, u32 level) ++{ ++ int ret = 0; ++ if (level == SUSPEND_SAVE_STATE) ++ ret = pcmcia_socket_dev_suspend(dev, state); ++ return ret; ++} ++ ++static int ep93xx_drv_pcmcia_resume(struct device *dev, u32 level) ++{ ++ int ret = 0; ++ if (level == RESUME_RESTORE_STATE) ++ { ++ ret = pcmcia_socket_dev_resume(dev); ++ } ++ return ret; ++} ++ ++static struct device_driver ep93xx_pcmcia_driver = { ++ .probe = ep93xx_drv_pcmcia_probe, ++ .remove = soc_common_drv_pcmcia_remove, ++ .suspend = ep93xx_drv_pcmcia_suspend, ++ .resume = ep93xx_drv_pcmcia_resume, ++ .name = "ep93xx-pcmcia", ++ .bus = &platform_bus_type, ++}; ++ ++static int __init ep93xx_pcmcia_init(void) ++{ ++ return driver_register(&ep93xx_pcmcia_driver); ++} ++ ++static void __exit ep93xx_pcmcia_exit(void) ++{ ++ driver_unregister(&ep93xx_pcmcia_driver); ++} ++ ++module_init(ep93xx_pcmcia_init); ++module_exit(ep93xx_pcmcia_exit); ++ ++MODULE_AUTHOR("Robert Whaley (whaley@applieddata.net)"); ++MODULE_DESCRIPTION("Linux PCMCIA Card Services: EP93xx core socket driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/pcmcia/ep93xx_edb9315.c b/drivers/pcmcia/ep93xx_edb9315.c +new file mode 100644 +index 0000000..519fc8d +--- /dev/null ++++ b/drivers/pcmcia/ep93xx_edb9315.c +@@ -0,0 +1,283 @@ ++/* ++ * linux/drivers/pcmcia/ep93xx_edb9315.c ++ * ++ * Adapted from pxa27x_mainstone.c ++ * ++ * Edb9315 PCMCIA specific routines. ++ * ++ * Created: May 12, 2004 ++ * Author: Nicolas Pitre ++ * Copyright: MontaVista Software Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/errno.h> ++#include <linux/interrupt.h> ++#include <linux/device.h> ++ ++#include <pcmcia/ss.h> ++ ++#include <asm/io.h> ++#include <asm/hardware.h> ++#include <asm/irq.h> ++ ++#include <asm/arch/edb9315.h> ++ ++#include "soc_common.h" ++ ++static struct pcmcia_irqs irqs[] = { ++ { 0, IRQ_GPIO1, "CF CD1" }, ++ { 0, IRQ_GPIO2, "CF CD2" }, ++ { 0, IRQ_GPIO3, "CF STSCHG/BVD1" }, ++ { 0, IRQ_GPIO4, "CF SPKR/BVD2" }, ++}; ++ ++ ++static int edb9315_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ++{ ++ int rtn; ++ ++ if (skt->nr == 0) ++ return -ENXIO; ++ ++ skt->irq = IRQ_GPIO6; ++ ++ rtn = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); ++ ++ /* enable GPIO6 as interrupt */ ++ writel(0x40, GPIO_INTEN); ++ ++ /* enable GPIO1-4 and 6 as interrupt */ ++ /* Note: 1-4 need to be edge triggered, but ++ then the irq vectors need to hit GPIOxEIO ++ which they don't currently do - no big deal ++ since CD and BVD are polled anyway */ ++ /* writel(0x5e, GPIO_INTEN); */ ++ ++ return rtn; ++} ++ ++static void edb9315_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) ++{ ++ soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); ++} ++ ++static void edb9315_pcmcia_socket_state(struct soc_pcmcia_socket *skt, ++ struct pcmcia_state *state) ++{ ++ unsigned long status; ++ ++ status = inl(GPIO_PFDR); ++ ++ state->detect = (status & PCMCIA_DETECT) ? 0 : 1; ++ state->ready = (status & PCMCIA_READY) ? 1 : 0; ++ state->bvd1 = (status & PCMCIA_BVD1) ? 1 : 0; ++ state->bvd2 = (status & PCMCIA_BVD2) ? 1 : 0; ++ state->vs_3v = (status & PCMCIA_VS_3V) ? 0 : 1; ++ state->vs_Xv = (status & PCMCIA_VS_XV) ? 0 : 1; ++ state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1; ++ ++// printk("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state)); ++} ++ ++/* ++ * We bit-bang the pcmcia power controller using this function. ++ */ ++static void ep93xx_bitbang( unsigned long ulNewEEValue ) ++{ ++ unsigned long ulGdata; ++ ++ ulGdata = inl( GPIO_PGDR ); ++ ++ ulGdata &= ~(GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0); ++ ++ ulNewEEValue &= (GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0); ++ ++ ulGdata |= ulNewEEValue; ++ ++ outl( ulGdata, GPIO_PGDR ); ++ ulGdata = inl( GPIO_PGDR ); // read to push write out wrapper ++ ++ // Voltage controller's data sheet says minimum pulse width is ++ // one microsecond. ++ udelay(5); ++} ++ ++static int ++ep93xx_set_voltage( u_short sock, u_char NewVcc ) ++{ ++ struct socket_info_t * skt = &socket_info[sock]; ++ unsigned long ulSwitchSettings, ulDataBit, ulGdirection; ++ int i; ++ ++ if (sock >= EP93XX_MAX_SOCK) ++ return -EINVAL; ++ ++ if( skt->Vcc == NewVcc ){ ++ DEBUG(3, "Power already set to %d\n", NewVcc ); ++ return 0; ++ } ++ ++ ulSwitchSettings = EE_ADDRESS | ENABLE; ++ switch( NewVcc ) ++ { ++ case 0: ++ DEBUG(3, "Configure the socket for 0 Volts\n"); ++ ulSwitchSettings |= AVCC_0V; ++ break; ++ ++ case 50: ++ ulSwitchSettings |= AVCC_5V; ++ DEBUG(3, "Configure the socket for 5 Volts\n"); ++ break; ++ ++ case 33: ++ DEBUG(3, "Configure the socket for 3.3 Volts\n"); ++ ulSwitchSettings |= AVCC_33V; ++ break; ++ ++ default: ++ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__, ++ NewVcc); ++ return -1; ++ } ++ ++ // ++ // Configure the proper GPIO pins as outputs. ++ // ++ ep93xx_bitbang( GPIOA_EECLK | GPIOA_EEDAT ); ++ ++ // ++ // Read modify write the data direction register, set the ++ // proper lines to be outputs. ++ // ++ ulGdirection = inl( GPIO_PGDDR ); ++ ulGdirection |= GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0; ++ outl( ulGdirection, GPIO_PGDDR ); ++ ulGdirection = inl( GPIO_PGDDR ); // read to push write out wrapper ++ ++ // ++ // Clear all except EECLK ++ // Lower the clock. ++ // ++ ep93xx_bitbang( GPIOA_EECLK ); ++ ep93xx_bitbang( 0 ); ++ ++ // ++ // Serial shift the command word out to the voltage controller. ++ // ++ for( i=18 ; i>=0 ; --i ) ++ { ++ if( (ulSwitchSettings >> i) & 0x1 ) ++ ulDataBit = GPIOA_EEDAT; ++ else ++ ulDataBit = 0; ++ ++ // ++ // Put the data on the bus and lower the clock. ++ // Raise the clock to latch the data in. ++ // Lower the clock again. ++ // ++ ep93xx_bitbang( ulDataBit ); ++ ep93xx_bitbang( ulDataBit | GPIOA_EECLK ); ++ ep93xx_bitbang( ulDataBit ); ++ } ++ ++ // ++ // Raise and lower the Latch. ++ // Raise EECLK, delay, raise EEDAT, leave them that way. ++ // ++ ep93xx_bitbang( GPIOA_SLA0 ); ++ ep93xx_bitbang( 0 ); ++ ep93xx_bitbang( GPIOA_EECLK ); ++ ep93xx_bitbang( GPIOA_EECLK | GPIOA_EEDAT ); ++ ++ skt->Vcc = NewVcc; ++ ++ DEBUG(3, "ep93xx_set_voltage - exit\n"); ++ ++ return 0; ++} ++ ++static int edb9315_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, ++ const socket_state_t *state) ++{ ++ unsigned long clrbits = 0, setbits = 0, cr0; ++ int ret = 0; ++ ++ ep93xx_set_voltage(skt->nr, state->Vxx); ++ ++ if (!ret && skt->nr == 0) { ++ ++ if (state->flags & SS_RESET) { ++ /* see EP93xx User's Guide */ ++ writel(0x15, PCMCIACNT); ++ } else { ++ /* CF mode - BIT1 for PCMCIA mode */ ++ writel(0x11, PCMCIACNT); ++ } ++ } ++ ++ return ret; ++} ++ ++static void edb9315_pcmcia_socket_init(struct soc_pcmcia_socket *skt) ++{ ++} ++ ++static void edb9315_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) ++{ ++} ++ ++static struct pcmcia_low_level edb9315_pcmcia_ops = { ++ .owner = THIS_MODULE, ++ .hw_init = edb9315_pcmcia_hw_init, ++ .hw_shutdown = edb9315_pcmcia_hw_shutdown, ++ .socket_state = edb9315_pcmcia_socket_state, ++ .configure_socket = edb9315_pcmcia_configure_socket, ++ .socket_init = edb9315_pcmcia_socket_init, ++ .socket_suspend = edb9315_pcmcia_socket_suspend, ++ .nr = 1, ++}; ++ ++static struct platform_device *edb9315_pcmcia_device; ++ ++static int __init edb9315_pcmcia_init(void) ++{ ++ int ret; ++ ++ edb9315_pcmcia_device = kmalloc(sizeof(*edb9315_pcmcia_device), GFP_KERNEL); ++ if (!edb9315_pcmcia_device) ++ return -ENOMEM; ++ memset(edb9315_pcmcia_device, 0, sizeof(*edb9315_pcmcia_device)); ++ edb9315_pcmcia_device->name = "ep93xx-pcmcia"; ++ edb9315_pcmcia_device->dev.platform_data = &edb9315_pcmcia_ops; ++ ++ ret = platform_device_register(edb9315_pcmcia_device); ++ if (ret) ++ kfree(edb9315_pcmcia_device); ++ ++ return ret; ++} ++ ++static void __exit edb9315_pcmcia_exit(void) ++{ ++ /* ++ * This call is supposed to free our edb9315_pcmcia_device. ++ * Unfortunately platform_device don't have a free method, and ++ * we can't assume it's free of any reference at this point so we ++ * can't free it either. ++ */ ++ platform_device_unregister(edb9315_pcmcia_device); ++} ++ ++module_init(edb9315_pcmcia_init); ++module_exit(edb9315_pcmcia_exit); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/pcmcia/ep93xx_zefeerevbh.c b/drivers/pcmcia/ep93xx_zefeerevbh.c +new file mode 100644 +index 0000000..44d44ed +--- /dev/null ++++ b/drivers/pcmcia/ep93xx_zefeerevbh.c +@@ -0,0 +1,175 @@ ++/* ++ * linux/drivers/pcmcia/ep93xx_zefeerevbh.c ++ * ++ * Adapted from ep93xx_zefeerevbh.c ++ * ++ * ++ * ZefeerEVB-H PCMCIA specific routines. ++ * ++ * Copyright: DAVE Srl <www.dave-tech.it> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/errno.h> ++#include <linux/interrupt.h> ++#include <linux/device.h> ++ ++#include <pcmcia/ss.h> ++ ++#include <asm/io.h> ++#include <asm/hardware.h> ++#include <asm/irq.h> ++ ++#include <asm/arch/zefeerevb.h> ++ ++#include "soc_common.h" ++ ++#if 0 ++#define DPRINTK(fmt, args...) printk( "[%s:] \n" fmt, __FUNCTION__, ## args) ++#else ++#define DPRINTK(fmt, args...) ++#endif ++ ++static struct pcmcia_irqs irqs[] = { ++ { 0, IRQ_GPIO1, "CF CD1" }, ++ { 0, IRQ_GPIO2, "CF CD2" }, ++ { 0, IRQ_GPIO3, "CF STSCHG/BVD1" }, ++ { 0, IRQ_GPIO4, "CF SPKR/BVD2" }, ++}; ++ ++ ++static int zefeerevbh_pcmcia_hw_init(struct soc_pcmcia_socket *skt) ++{ ++ int rtn; ++ unsigned long tmp; ++ ++ if (skt->nr != 0) ++ return -ENXIO; ++ ++ /* Set interrupt lines as input */ ++ tmp = readl(GPIO_PFDDR); ++ tmp = (tmp & (~((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 6)))); ++ writel(tmp, GPIO_PFDDR); ++ ++ skt->irq = IRQ_GPIO6; ++ ++ rtn = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); ++ ++ /* enable GPIO6 as interrupt */ ++ writel(0x40, GPIO_INTEN); ++ ++ /* enable GPIO1-4 and 6 as interrupt */ ++ /* Note: 1-4 need to be edge triggered, but ++ then the irq vectors need to hit GPIOxEIO ++ which they don't currently do - no big deal ++ since CD and BVD are polled anyway */ ++ /* writel(0x5e, GPIO_INTEN); */ ++ ++ return rtn; ++} ++ ++static void zefeerevbh_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) ++{ ++ soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); ++} ++ ++static void zefeerevbh_pcmcia_socket_state(struct soc_pcmcia_socket *skt, ++ struct pcmcia_state *state) ++{ ++ unsigned long status; ++ ++ status = inl(GPIO_PFDR); ++ ++ state->detect = (status & PCMCIA_DETECT) ? 0 : 1; ++ state->ready = (status & PCMCIA_READY) ? 1 : 0; ++ state->bvd1 = (status & PCMCIA_BVD1) ? 1 : 0; ++ state->bvd2 = (status & PCMCIA_BVD2) ? 1 : 0; ++ state->vs_3v = (status & PCMCIA_VS_3V) ? 0 : 1; ++ state->vs_Xv = (status & PCMCIA_VS_XV) ? 0 : 1; ++ state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1; ++ ++ DPRINTK("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state)); ++} ++ ++static int zefeerevbh_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, ++ const socket_state_t *state) ++{ ++ ++ printk(KERN_INFO "[%s]: Vcc = %u, Vpp = %u\n", __FUNCTION__, state->Vcc, state->Vpp); ++ ++ /* By default power handling is managed by external controller automatically */ ++ ++ if (skt->nr == 0) { ++ if (state->flags & SS_RESET) { ++ /* see EP93xx User's Guide */ ++ writel(0x15, PCMCIACNT); ++ } else { ++ /* CF mode - BIT1 for PCMCIA mode */ ++ writel(0x11, PCMCIACNT); ++ } ++ } ++ ++ ++ return 0; ++} ++ ++static void zefeerevbh_pcmcia_socket_init(struct soc_pcmcia_socket *skt) ++{ ++} ++ ++static void zefeerevbh_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) ++{ ++} ++ ++static struct pcmcia_low_level zefeerevbh_pcmcia_ops = { ++ .owner = THIS_MODULE, ++ .hw_init = zefeerevbh_pcmcia_hw_init, ++ .hw_shutdown = zefeerevbh_pcmcia_hw_shutdown, ++ .socket_state = zefeerevbh_pcmcia_socket_state, ++ .configure_socket = zefeerevbh_pcmcia_configure_socket, ++ .socket_init = zefeerevbh_pcmcia_socket_init, ++ .socket_suspend = zefeerevbh_pcmcia_socket_suspend, ++ .nr = 1, ++}; ++ ++static struct platform_device *zefeerevbh_pcmcia_device; ++ ++static int __init zefeerevbh_pcmcia_init(void) ++{ ++ int ret; ++ ++ zefeerevbh_pcmcia_device = kmalloc(sizeof(*zefeerevbh_pcmcia_device), GFP_KERNEL); ++ if (!zefeerevbh_pcmcia_device) ++ return -ENOMEM; ++ memset(zefeerevbh_pcmcia_device, 0, sizeof(*zefeerevbh_pcmcia_device)); ++ zefeerevbh_pcmcia_device->name = "ep93xx-pcmcia"; ++ zefeerevbh_pcmcia_device->dev.platform_data = &zefeerevbh_pcmcia_ops; ++ ++ ret = platform_device_register(zefeerevbh_pcmcia_device); ++ if (ret) ++ kfree(zefeerevbh_pcmcia_device); ++ ++ return ret; ++} ++ ++static void __exit zefeerevbh_pcmcia_exit(void) ++{ ++ /* ++ * This call is supposed to free our zefeerevbh_pcmcia_device. ++ * Unfortunately platform_device don't have a free method, and ++ * we can't assume it's free of any reference at this point so we ++ * can't free it either. ++ */ ++ platform_device_unregister(zefeerevbh_pcmcia_device); ++} ++ ++module_init(zefeerevbh_pcmcia_init); ++module_exit(zefeerevbh_pcmcia_exit); ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig +index 812bae6..15bfa5d 100644 +--- a/drivers/serial/Kconfig ++++ b/drivers/serial/Kconfig +@@ -289,6 +289,25 @@ config SERIAL_CLPS711X_CONSOLE + your boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time.) + ++config SERIAL_EP93XX ++ tristate "EP93XX serial port support" ++ depends on ARM && ARCH_EP93XX ++ select SERIAL_CORE ++ help ++ Support for the serial ports included in the EP93xx CPU SOC. ++ ++config SERIAL_EP93XX_CONSOLE ++ bool "Support for console on EP93XX serial port" ++ depends on SERIAL_EP93XX=y ++ select SERIAL_CORE_CONSOLE ++ help ++ Even if you say Y here, the currently visible virtual console ++ (/dev/tty0) will still be used as the system console by default, but ++ you can alter that using a kernel command line option such as ++ "console=ttyCL1". (Try "man bootparam" or see the documentation of ++ your boot loader (lilo or loadlin) about how to pass options to the ++ kernel at boot time.) ++ + config SERIAL_S3C2410 + tristate "Samsung S3C2410 Serial port support" + depends on ARM && ARCH_S3C2410 +diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile +index d7c7c71..ef074dc 100644 +--- a/drivers/serial/Makefile ++++ b/drivers/serial/Makefile +@@ -26,6 +26,7 @@ obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250 + obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o + obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o + obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o ++obj-$(CONFIG_SERIAL_EP93XX) += ep93xx.o + obj-$(CONFIG_SERIAL_PXA) += pxa.o + obj-$(CONFIG_SERIAL_SA1100) += sa1100.o + obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o +diff --git a/drivers/serial/ep93xx.c b/drivers/serial/ep93xx.c +new file mode 100644 +index 0000000..60f91a6 +--- /dev/null ++++ b/drivers/serial/ep93xx.c +@@ -0,0 +1,863 @@ ++/* ++ * drivers/serial/ep93xx.c ++ * ++ * Driver for EP93xx serial ports ++ * ++ * Based on drivers/serial/amba-pl011.c ++ * ++ * Copyright 1999 ARM Limited ++ * Copyright (C) 2000 Deep Blue Solutions Ltd. ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * ++ * 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 ++ * ++ * $Id: ep93xx.c,v 1.42 2002/07/28 10:03:28 rmk Exp $ ++ * ++ */ ++ ++/* todo: ++ * - correct major/minor numbers ++ * - implement request/release/verify port ++ * - from /dev/ttyAM0, 'stty -F /dev/ttyAM1 57600' not working right. ++ * looks like it changes the divisor, but it gets changed back as ++ * soon as you enter a char on /dev/ttyAM1. ++ * - do not enable modem status ints unless HW is setup ++ * - do not return modem status unless HW is setup ++ * - figure out a nice way to handle CL0 HDLC/modem, CL1 SIR IrDA, ++ * and CL2 HDLC/RS485 ++ * - UART DMA operation? ++ * - handle icount fields rng and buf_overrun? ++ */ ++#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/tty.h> ++#include <linux/device.h> ++#include <linux/sysrq.h> ++#include <linux/console.h> ++#include <linux/serial.h> ++ ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <asm/hardware/amba.h> ++#include <asm/arch/hardware.h> ++#include <asm/arch/clocks.h> ++ ++#if defined(CONFIG_SERIAL_EP93XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) ++#define SUPPORT_SYSRQ ++#endif ++ ++#include <linux/serial_core.h> ++ ++#if defined(CONFIG_ARCH_EP9312) || defined(CONFIG_ARCH_EP9315) ++#define UART_NR 3 ++#else ++#define UART_NR 2 ++#endif ++ ++#define SERIAL_EP93XX_MAJOR 204 ++#define SERIAL_EP93XX_MINOR 16 ++ ++#define ISR_PASS_LIMIT 256 ++ ++#define REG(port,name) ((port)->membase + (name) - EP93XX_APB_BASE - UART1_OFFSET) ++ ++#define UARTDR(port) REG(port,UART1DR) ++#define UARTCR(port) REG(port,UART1CR) ++#define UARTFR(port) REG(port,UART1FR) ++#define UARTRSR(port) REG(port,UART1RSR) ++#define UARTECR(port) REG(port,UART1ECR) ++#define UARTMCR(port) REG(port,UART1MCR) ++#define UARTMSR(port) REG(port,UART1MSR) ++#define UARTIIR(port) REG(port,UART1IIR) ++#define UARTICR(port) REG(port,UART1ICR) ++#define UARTLCH(port) REG(port,UART1CR_H) ++#define UARTLCM(port) REG(port,UART1CR_M) ++#define UARTLCL(port) REG(port,UART1CR_L) ++ ++#define UARTRSR_CREAD 0x100 ++ ++static void enable_clocks(struct uart_port *port) ++{ ++ unsigned int devcfg = readl(SYSCON_DEVCFG); ++ ++ switch (port->line) { ++ case 0: ++ devcfg |= SYSCON_DEVCFG_U1EN; ++ devcfg &= ~SYSCON_DEVCFG_MonG; /* handle this better... */ ++ break; ++ case 1: ++ devcfg |= SYSCON_DEVCFG_U2EN; ++ break; ++ case 2: ++ devcfg |= SYSCON_DEVCFG_U3EN; ++ break; ++ } ++ ++ SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(devcfg)); ++} ++ ++static void disable_clocks(struct uart_port *port) ++{ ++ unsigned int devcfg = readl(SYSCON_DEVCFG); ++ ++ switch (port->line) { ++ case 0: ++ devcfg &= ~SYSCON_DEVCFG_U1EN; ++ break; ++ case 1: ++ devcfg &= ~SYSCON_DEVCFG_U2EN; ++ break; ++ case 2: ++ devcfg &= ~SYSCON_DEVCFG_U3EN; ++ break; ++ } ++ ++ SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(devcfg)); ++} ++ ++static int is_port_enabled(struct uart_port *port) ++{ ++ unsigned int devcfg = readl(SYSCON_DEVCFG); ++ ++ switch (port->line) { ++ case 0: ++ devcfg &= SYSCON_DEVCFG_U1EN; ++ break; ++ case 1: ++ devcfg &= SYSCON_DEVCFG_U2EN; ++ break; ++ case 2: ++ devcfg &= SYSCON_DEVCFG_U3EN; ++ break; ++ } ++ ++ return devcfg ? 1 : 0; ++} ++ ++static void ep93xxuart_stop_tx(struct uart_port *port) ++{ ++ unsigned long cr = readl(UARTCR(port)); ++ cr &= ~UARTCR_TIE; ++ writel(cr, UARTCR(port)); ++} ++ ++static void ep93xxuart_start_tx(struct uart_port *port) ++{ ++ unsigned long cr = readl(UARTCR(port)); ++ cr |= UARTCR_TIE; ++ writel(cr, UARTCR(port)); ++} ++ ++static void ep93xxuart_stop_rx(struct uart_port *port) ++{ ++ unsigned long cr = readl(UARTCR(port)); ++ cr &= ~(UARTCR_RIE | UARTCR_RTIE); ++ writel(cr, UARTCR(port)); ++} ++ ++static void ep93xxuart_enable_ms(struct uart_port *port) ++{ ++ /* fixme: add an ms mask to a wrapper port struct */ ++ if (port->line == 0) { ++ unsigned long cr = readl(UARTCR(port)); ++ cr |= UARTCR_MSIE; ++ writel(cr, UARTCR(port)); ++ } ++} ++ ++#ifdef SUPPORT_SYSRQ ++static void ep93xxuart_rx_chars(struct uart_port *port, struct pt_regs *regs) ++#else ++static void ep93xxuart_rx_chars(struct uart_port *port) ++#endif ++{ ++ struct tty_struct *tty = port->info->tty; ++ unsigned long fifo, chr, stat, flg; ++ unsigned int count = 256; ++ ++ fifo = readl(UARTFR(port)); ++ while (((fifo & UARTFR_RXFE) == 0) && count--) { ++ ++ if (tty->flip.count >= TTY_FLIPBUF_SIZE) { ++ tty->flip.work.func((void *)tty); ++ if (tty->flip.count >= TTY_FLIPBUF_SIZE) { ++ printk(KERN_WARNING "TTY_DONT_FLIP set\n"); ++ return; ++ } ++ } ++ ++ chr = readl(UARTDR(port)); ++ flg = TTY_NORMAL; ++ ++ port->icount.rx++; ++ ++ stat = readl(UARTRSR(port)) | UARTRSR_CREAD; ++ ++ if (stat & (UARTRSR_FE | UARTRSR_PE | UARTRSR_OE | UARTRSR_BE)) { ++ ++ writel(0, UARTECR(port)); ++ ++ if (stat & UARTRSR_BE) { ++ stat &= ~(UARTRSR_PE | UARTRSR_FE); ++ port->icount.brk++; ++ if (uart_handle_break(port)) ++ goto ignore_char; ++ } else if (stat & UARTRSR_PE) { ++ port->icount.parity++; ++ } else if (stat & UARTRSR_FE) { ++ port->icount.frame++; ++ } ++ ++ if (stat & UARTRSR_OE) ++ port->icount.overrun++; ++ ++ stat &= port->read_status_mask; ++ ++ if (stat & UARTRSR_BE) ++ flg = TTY_BREAK; ++ else if (stat & UARTRSR_PE) ++ flg = TTY_PARITY; ++ else if (stat & UARTRSR_FE) ++ flg = TTY_FRAME; ++ } ++ ++ if (uart_handle_sysrq_char(port, chr, regs)) ++ goto ignore_char; ++ ++ if ((stat & port->ignore_status_mask) == 0) { ++ *tty->flip.flag_buf_ptr++ = flg; ++ *tty->flip.char_buf_ptr++ = chr; ++ tty->flip.count++; ++ } ++ ++ if ((stat & UARTRSR_OE) && tty->flip.count < TTY_FLIPBUF_SIZE) { ++ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN; ++ *tty->flip.char_buf_ptr++ = 0; ++ tty->flip.count++; ++ } ++ ++ ignore_char: ++ fifo = readl(UARTFR(port)); ++ } ++ tty_flip_buffer_push(tty); ++} ++ ++static void ep93xxuart_tx_chars(struct uart_port *port) ++{ ++ struct circ_buf *xmit = &port->info->xmit; ++ int count; ++ ++ if (port->x_char) { ++ writel(port->x_char, UARTDR(port)); ++ port->icount.tx++; ++ port->x_char = 0; ++ return; ++ } ++ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { ++ ep93xxuart_stop_tx(port); ++ return; ++ } ++ ++ count = port->fifosize >> 1; ++ do { ++ writel(xmit->buf[xmit->tail], UARTDR(port)); ++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); ++ port->icount.tx++; ++ if (uart_circ_empty(xmit)) ++ break; ++ } while (--count > 0); ++ ++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) ++ uart_write_wakeup(port); ++ ++ if (uart_circ_empty(xmit)) ++ ep93xxuart_stop_tx(port); ++} ++ ++static void ep93xxuart_modem_status(struct uart_port *port) ++{ ++ unsigned int status = readl(UARTFR(port)); ++ ++ writel(0, UARTICR(port)); ++ ++ if (status & UARTMSR_DDCD) ++ uart_handle_dcd_change(port, status & UARTMSR_DCD); ++ ++ if (status & UARTMSR_DDSR) ++ port->icount.dsr++; ++ ++ if (status & UARTMSR_DCTS) ++ uart_handle_cts_change(port, status & UARTMSR_CTS); ++ ++ if (status & (UARTMSR_DDCD | UARTMSR_DDSR | UARTMSR_DCTS)) ++ wake_up_interruptible(&port->info->delta_msr_wait); ++} ++ ++static irqreturn_t ep93xxuart_int(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct uart_port *port = dev_id; ++ unsigned int pass_counter = ISR_PASS_LIMIT; ++ int handled = 0; ++ unsigned long iir; ++ ++ spin_lock(&port->lock); ++ ++ iir = readl(UARTIIR(port)); ++ ++ if (iir) { ++ do { ++ if (iir & (UARTIIR_RIS | UARTIIR_RTIS)) ++#ifdef SUPPORT_SYSRQ ++ ep93xxuart_rx_chars(port, regs); ++#else ++ ep93xxuart_rx_chars(port); ++#endif ++ if (iir & UARTIIR_TIS) ++ ep93xxuart_tx_chars(port); ++ if (iir & UARTIIR_MIS) ++ ep93xxuart_modem_status(port); ++ ++ if (pass_counter-- == 0) ++ break; ++ ++ iir = readl(UARTIIR(port)); ++ ++ } while (iir & ++ (UARTIIR_RIS | UARTIIR_RTIS | UARTIIR_TIS | ++ UARTIIR_MIS)); ++ handled = 1; ++ } ++ ++ spin_unlock(&port->lock); ++ ++ return IRQ_RETVAL(handled); ++} ++ ++static unsigned int ep93xxuart_tx_empty(struct uart_port *port) ++{ ++ unsigned long status = readl(UARTFR(port)); ++ return status & UARTFR_TXFE ? 0 : TIOCSER_TEMT; /* FIXME: klaus used UARTFR_BUSY? */ ++} ++ ++static unsigned int ep93xxuart_get_mctrl(struct uart_port *port) ++{ ++ unsigned int result = 0; ++ ++ /* fixme: use a wrapper struct w/ ms flags */ ++ if (port->line == 0) { ++ unsigned int msr = readl(UARTMSR(port)); ++ if (msr & UARTMSR_CTS) ++ result |= TIOCM_CTS; ++ if (msr & UARTMSR_DSR) ++ result |= TIOCM_DSR; ++ if (msr & UARTMSR_RI) ++ result |= TIOCM_RI; ++ if (msr & UARTMSR_DCD) ++ result |= TIOCM_CAR; ++ } ++ return result; ++} ++ ++static void ep93xxuart_set_mctrl(struct uart_port *port, unsigned int mctrl) ++{ ++ unsigned long mcr; ++ ++ if (port->line == 0) { ++ mcr = readl(UARTMCR(port)); ++ if (mctrl & TIOCM_RTS) ++ mcr |= UARTMCR_RTS; ++ else ++ mcr &= ~UARTMCR_RTS; ++ if (mctrl & TIOCM_DTR) ++ mcr |= UARTMCR_DTR; ++ else ++ mcr &= ~UARTMCR_DTR; ++ if (mctrl & TIOCM_OUT1) ++ mcr |= UARTMCR_OUT1; ++ else ++ mcr &= ~UARTMCR_OUT1; ++ if (mctrl & TIOCM_OUT2) ++ mcr |= UARTMCR_OUT2; ++ else ++ mcr &= ~UARTMCR_OUT2; ++ writel(mcr, UARTMCR(port)); ++ } ++} ++ ++/* FIXME: klaus grabbed the &port->lock spinlock here.. */ ++static void ep93xxuart_break_ctl(struct uart_port *port, int break_state) ++{ ++ unsigned long lch; ++ ++ lch = readl(UARTLCH(port)); ++ if (break_state) ++ lch |= UARTLCR_H_BRK; ++ else ++ lch &= ~UARTLCR_H_BRK; ++ writel(lch, UARTLCH(port)); ++} ++ ++static int ep93xxuart_startup(struct uart_port *port) ++{ ++ unsigned int uartcr; ++ int retval; ++ ++ retval = request_irq(port->irq, ep93xxuart_int, 0, "ep93xxuart", port); ++ if (retval) ++ return retval; ++ ++ enable_clocks(port); ++ ++ uartcr = readl(UARTCR(port)); ++ uartcr |= UARTCR_UARTE | UARTCR_RIE | UARTCR_RTIE; ++ uartcr &= ~0x6; ++ writel(uartcr, UARTCR(port)); ++ ++ return 0; ++} ++ ++static void ep93xxuart_shutdown(struct uart_port *port) ++{ ++ unsigned int uartcr; ++ unsigned int linectl; ++ ++ linectl = readl(UARTLCH(port)); ++ linectl &= ~(UARTLCR_H_FEN | UARTLCR_H_BRK); ++ writel(linectl, UARTLCH(port)); ++ ++ uartcr = readl(UARTCR(port)); ++ uartcr &= ~(UARTCR_UARTE | UARTCR_RIE | UARTCR_RTIE | UARTCR_TIE); ++ writel(uartcr, UARTCR(port)); ++ ++ disable_clocks(port); ++ ++ free_irq(port->irq, port); ++} ++ ++static void ++ep93xxuart_set_termios(struct uart_port *port, struct termios *termios, ++ struct termios *old) ++{ ++ unsigned int baud, quot; ++ unsigned long flags; ++ unsigned long lch; ++ ++ /* wait for fifo to drain.. is this needed? upper level should handle it.. */ ++ if (is_port_enabled(port)) ++ do { ++ flags = readl(UARTFR(port)); ++ } while (flags & UARTFR_BUSY); ++ ++ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); ++ quot = uart_get_divisor(port, baud); ++ ++ switch (termios->c_cflag & CSIZE) { ++ case CS5: ++ lch = UARTLCR_H_WLEN_5_DATA; ++ break; ++ case CS6: ++ lch = UARTLCR_H_WLEN_6_DATA; ++ break; ++ case CS7: ++ lch = UARTLCR_H_WLEN_7_DATA; ++ break; ++ default: ++ lch = UARTLCR_H_WLEN_8_DATA; ++ break; ++ } ++ ++ if (termios->c_cflag & CSTOPB) ++ lch |= UARTLCR_H_STP2; ++ ++ if (termios->c_cflag & PARENB) { ++ lch |= UARTLCR_H_PEN; ++ if (!(termios->c_cflag & PARODD)) ++ lch |= UARTLCR_H_EPS; ++ } ++ ++ if (port->fifosize > 1) ++ lch |= UARTLCR_H_FEN; ++ ++ spin_lock_irqsave(&port->lock, flags); ++ ++ lch |= readl(UARTLCH(port)) & UARTLCR_H_BRK; ++ ++ uart_update_timeout(port, termios->c_cflag, baud); ++ ++ port->read_status_mask = UARTRSR_OE; ++ if (termios->c_iflag & INPCK) ++ port->read_status_mask |= UARTRSR_FE | UARTRSR_PE; ++ if (termios->c_iflag & (BRKINT | PARMRK)) ++ port->read_status_mask |= UARTRSR_BE; ++ ++ port->ignore_status_mask = 0; ++ if (termios->c_iflag & IGNPAR) ++ port->ignore_status_mask |= UARTRSR_FE | UARTRSR_PE; ++ if (termios->c_iflag & IGNBRK) { ++ port->ignore_status_mask |= UARTRSR_BE; ++ if (termios->c_iflag & IGNPAR) ++ port->ignore_status_mask |= UARTRSR_OE; ++ } ++ if ((termios->c_cflag & CREAD) == 0) ++ port->ignore_status_mask |= UARTRSR_CREAD; ++ ++ quot -= 1; ++ ++ writel(quot & 0xff, UARTLCL(port)); ++ writel((quot >> 8) & 0xff, UARTLCM(port)); ++ writel(lch, UARTLCH(port)); ++ ++ spin_unlock_irqrestore(&port->lock, flags); ++} ++ ++static const char *ep93xxuart_type(struct uart_port *port) ++{ ++ return port->type == PORT_EP93XX ? "uart-ep93xx" : NULL; ++} ++ ++static void ep93xxuart_release_port(struct uart_port *port) ++{ ++ /* update when we break up static io_desc maps */ ++} ++ ++static int ep93xxuart_request_port(struct uart_port *port) ++{ ++ /* update when we break up static io_desc maps */ ++ return 0; ++} ++ ++static void ep93xxuart_config_port(struct uart_port *port, int flags) ++{ ++ if (flags & UART_CONFIG_TYPE) ++ if (ep93xxuart_request_port(port) == 0) ++ port->type = PORT_EP93XX; ++ ++ /* FIXME: handle UART_CONFIG_IRQ? */ ++} ++ ++static int ep93xxuart_verify_port(struct uart_port *port, ++ struct serial_struct *ser) ++{ ++ if (ser->type != PORT_UNKNOWN && ser->type != PORT_EP93XX) ++ return -EINVAL; ++ if (ser->irq < 0 || ser->irq >= NR_IRQS) ++ return -EINVAL; ++ if (ser->baud_base < 9600) ++ return -EINVAL; ++ return 0; ++} ++ ++static struct uart_ops ep93xx_pops = { ++ .tx_empty = ep93xxuart_tx_empty, ++ .set_mctrl = ep93xxuart_set_mctrl, ++ .get_mctrl = ep93xxuart_get_mctrl, ++ .stop_tx = ep93xxuart_stop_tx, ++ .start_tx = ep93xxuart_start_tx, ++ .stop_rx = ep93xxuart_stop_rx, ++ .enable_ms = ep93xxuart_enable_ms, ++ .break_ctl = ep93xxuart_break_ctl, ++ .startup = ep93xxuart_startup, ++ .shutdown = ep93xxuart_shutdown, ++ .set_termios = ep93xxuart_set_termios, ++ .type = ep93xxuart_type, ++ .release_port = ep93xxuart_release_port, ++ .request_port = ep93xxuart_request_port, ++ .config_port = ep93xxuart_config_port, ++ .verify_port = ep93xxuart_verify_port, ++}; ++ ++static struct uart_port ep93xx_ports[UART_NR] = { ++ { ++ .membase = (void *)UART1_BASE, ++ .mapbase = UART1_BASE, ++ .iotype = UPIO_MEM, ++ .irq = IRQ_UART1, ++ .uartclk = EP93XX_UART_CLK, ++ .fifosize = 16, ++ .ops = &ep93xx_pops, ++ .flags = UPF_BOOT_AUTOCONF, ++ }, ++ { ++ .membase = (void *)UART2_BASE, ++ .mapbase = UART2_BASE, ++ .iotype = UPIO_MEM, ++ .irq = IRQ_UART2, ++ .uartclk = EP93XX_UART_CLK, ++ .fifosize = 16, ++ .ops = &ep93xx_pops, ++ .line = 1, ++ .flags = UPF_BOOT_AUTOCONF, ++ }, ++#if UART_NR > 2 ++ { ++ .membase = (void *)UART3_BASE, ++ .mapbase = UART3_BASE, ++ .iotype = UPIO_MEM, ++ .irq = IRQ_UART3, ++ .uartclk = EP93XX_UART_CLK, ++ .fifosize = 16, ++ .ops = &ep93xx_pops, ++ .line = 2, ++ .flags = UPF_BOOT_AUTOCONF, ++ } ++#endif ++}; ++ ++#ifdef CONFIG_SERIAL_EP93XX_CONSOLE ++/* ++ * Print a string to the serial port trying not to disturb ++ * any possible real use of the port... ++ * ++ * The console_lock must be held when we get here. ++ * ++ * Note that this is called with interrupts already disabled ++ */ ++static void ++ep93xxuart_console_write(struct console *co, const char *s, unsigned int count) ++{ ++ struct uart_port *port = ep93xx_ports + co->index; ++ unsigned long cr, cr2, fr; ++ int i; ++ ++ /* ++ * Ensure that the port is enabled. ++ */ ++ cr = readl(UARTCR(port)); ++ cr2 = cr & ~(UARTCR_RIE | UARTCR_RTIE | UARTCR_TIE | UARTCR_MSIE); ++ writel((cr2 | UARTCR_UARTE), UARTCR(port)); ++ ++ /* ++ * Now, do each character ++ */ ++ for (i = 0; i < count; i++) { ++ do { ++ fr = readl(UARTFR(port)); ++ } while (fr & UARTFR_TXFF); ++ writel(s[i], UARTDR(port)); ++ if (s[i] == '\n') { ++ do { ++ fr = readl(UARTFR(port)); ++ } while (fr & UARTFR_TXFF); ++ writel('\r', UARTDR(port)); ++ } ++ } ++ ++ /* ++ * Finally, wait for transmitter to become empty ++ * and restore the uart state. ++ */ ++ do { ++ fr = readl(UARTFR(port)); ++ } while ((fr & UARTFR_TXFE) == 0); ++ ++ writel(cr, UARTCR(port)); ++} ++ ++static void __init ++ep93xxuart_console_get_options(struct uart_port *port, int *baud, ++ int *parity, int *bits) ++{ ++ if (readl(UARTCR(port)) & UARTCR_UARTE) { ++ unsigned long lch, quot; ++ ++ lch = readl(UARTLCH(port)); ++ ++ *parity = 'n'; ++ if (lch & UARTLCR_H_PEN) { ++ if (lch & UARTLCR_H_EPS) ++ *parity = 'e'; ++ else ++ *parity = 'o'; ++ } ++ ++ if ((lch & UARTLCR_H_WLEN) == UARTLCR_H_WLEN_7_DATA) ++ *bits = 7; ++ else ++ *bits = 8; ++ ++ quot = ++ ((readl(UARTLCM(port)) & 0xff) << 8) | (readl(UARTLCL(port)) ++ & 0xff); ++ ++ *baud = port->uartclk / (16 * (quot + 1)); ++ } ++} ++ ++static int __init ep93xxuart_console_setup(struct console *co, char *options) ++{ ++ struct uart_port *port; ++ int baud = 57600; ++ int bits = 8; ++ int parity = 'n'; ++ int flow = 'n'; ++ ++ /* ++ * Check whether an invalid uart number has been specified, and ++ * if so, search for the first available port that does have ++ * console support. ++ */ ++ port = uart_get_console(ep93xx_ports, UART_NR, co); ++ ++ /* ++ * Temporary fix. ++ */ ++ spin_lock_init(&port->lock); ++ ++ if (options) ++ uart_parse_options(options, &baud, &parity, &bits, &flow); ++ else ++ ep93xxuart_console_get_options(port, &baud, &parity, &bits); ++ ++ return uart_set_options(port, co, baud, parity, bits, flow); ++} ++ ++extern struct uart_driver ep93xx_reg; ++static struct console ep93xx_console = { ++ .name = "ttyAM", ++ .write = ep93xxuart_console_write, ++ .device = uart_console_device, ++ .setup = ep93xxuart_console_setup, ++ .flags = CON_PRINTBUFFER, ++ .index = -1, ++ .data = &ep93xx_reg, ++}; ++ ++static int __init ep93xxuart_console_init(void) ++{ ++ register_console(&ep93xx_console); ++ return 0; ++} ++ ++console_initcall(ep93xxuart_console_init); ++ ++#define EP93XX_CONSOLE &ep93xx_console ++#else ++#define EP93XX_CONSOLE NULL ++#endif ++ ++static struct uart_driver ep93xx_reg = { ++ .driver_name = "ttyAM", ++ .dev_name = "ttyAM", ++ .major = SERIAL_EP93XX_MAJOR, ++ .minor = SERIAL_EP93XX_MINOR, ++ .nr = UART_NR, ++ .cons = EP93XX_CONSOLE, ++}; ++ ++static int ep93xxuart_probe(struct amba_device *dev, void *id) ++{ ++ int i; ++ ++ for (i = 0; i < UART_NR; i++) { ++ if (ep93xx_ports[i].membase != (void *)dev->res.start) ++ continue; ++ ++ ep93xx_ports[i].dev = &dev->dev; ++ uart_add_one_port(&ep93xx_reg, &ep93xx_ports[i]); ++ amba_set_drvdata(dev, &ep93xx_ports[i]); ++ break; ++ } ++ ++ return 0; ++} ++ ++static int ep93xxuart_remove(struct amba_device *dev) ++{ ++ struct uart_port *p = amba_get_drvdata(dev); ++ ++ if (p) ++ uart_remove_one_port(&ep93xx_reg, p); ++ ++ amba_set_drvdata(dev, NULL); ++ ++ return 0; ++} ++ ++static int ep93xxuart_suspend(struct amba_device *dev, pm_message_t msg) ++{ ++ struct uart_port *p = amba_get_drvdata(dev); ++ ++ if (p) ++ uart_suspend_port(&ep93xx_reg, p); ++ ++ return 0; ++} ++ ++static int ep93xxuart_resume(struct amba_device *dev) ++{ ++ struct uart_port *p = amba_get_drvdata(dev); ++ ++ if (p) ++ uart_resume_port(&ep93xx_reg, p); ++ ++ return 0; ++} ++ ++static struct amba_id ep93xxuart_ids[] __initdata = { ++ { /* UART1 */ ++ .id = 0x808c0000, ++ .mask = 0xffff0000, ++ }, ++ { /* UART2 */ ++ .id = 0x808d0000, ++ .mask = 0xffff0000, ++ }, ++ { /* UART3 */ ++ .id = 0x808e0000, ++ .mask = 0xffff0000, ++ }, ++ {0, 0}, ++}; ++ ++static struct amba_driver ep93xxuart_driver = { ++ .drv = { ++ .name = "uart-ep93xx", ++ }, ++ .id_table = ep93xxuart_ids, ++ .probe = ep93xxuart_probe, ++ .remove = ep93xxuart_remove, ++ .suspend = ep93xxuart_suspend, ++ .resume = ep93xxuart_resume, ++}; ++ ++static int __init ep93xxuart_init(void) ++{ ++ int ret; ++ ++ printk(KERN_INFO "Serial: EP93xx driver $Revision: 1.42 $\n"); ++ ++ ret = uart_register_driver(&ep93xx_reg); ++ if (ret == 0) { ++ ret = amba_driver_register(&ep93xxuart_driver); ++ if (ret) ++ uart_unregister_driver(&ep93xx_reg); ++ } ++ ++ return ret; ++} ++ ++static void __exit ep93xxuart_exit(void) ++{ ++ amba_driver_unregister(&ep93xxuart_driver); ++ uart_unregister_driver(&ep93xx_reg); ++} ++ ++module_init(ep93xxuart_init); ++module_exit(ep93xxuart_exit); ++ ++MODULE_AUTHOR("Ray Lehtiniemi"); ++MODULE_DESCRIPTION("EP93XX generic serial driver $Revision: 1.42 $"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig +index 85dacc9..e57292f 100644 +--- a/drivers/usb/Kconfig ++++ b/drivers/usb/Kconfig +@@ -22,6 +22,7 @@ config USB_ARCH_HAS_OHCI + default y if ARCH_LH7A404 + default y if ARCH_S3C2410 + default y if PXA27x ++ default y if ARCH_EP93XX + # PPC: + default y if STB03xxx + default y if PPC_MPC52xx +diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c +new file mode 100644 +index 0000000..8aec2fb +--- /dev/null ++++ b/drivers/usb/host/ohci-ep93xx.c +@@ -0,0 +1,248 @@ ++/* ++ * OHCI HCD (Host Controller Driver) for USB. ++ * ++ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> ++ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> ++ * (C) Copyright 2002 Hewlett-Packard Company ++ * (C) Copyright 2004 Ray Lehtiniemi ++ * ++ * EP93XX Bus Glue ++ * ++ * Written by Ray Lehtiniemi <rayl@mail.com> ++ * Based on SA-1111 glue. ++ * ++ * This file is licenced under the GPL. ++ */ ++ ++#include <asm/hardware.h> ++#include <asm/hardware/amba.h> ++ ++#ifndef CONFIG_ARCH_EP93XX ++#error "This file is EP93xx bus glue. CONFIG_ARCH_EP93XX must be defined." ++#endif ++ ++extern int usb_disabled(void); ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++static void ep93xx_start_hc(struct amba_device *dev) ++{ ++ unsigned int pwrcnt; ++ ++ printk(KERN_DEBUG __FILE__ ": starting EP93xx OHCI USB Controller\n"); ++ ++ pwrcnt = readl(SYSCON_PWRCNT); ++ pwrcnt |= SYSCON_PWRCNT_USHEN; ++ writel(pwrcnt, SYSCON_PWRCNT); ++} ++ ++static void ep93xx_stop_hc(struct amba_device *dev) ++{ ++ unsigned int pwrcnt; ++ ++ printk(KERN_DEBUG __FILE__ ": stopping EP93xx OHCI USB Controller\n"); ++ ++ pwrcnt = readl(SYSCON_PWRCNT); ++ pwrcnt &= ~SYSCON_PWRCNT_USHEN; ++ writel(pwrcnt, SYSCON_PWRCNT); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++#if 0 ++static void dump_hci_status(struct usb_hcd *hcd, const char *label) ++{ ++ unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS); ++ ++ dbg("%s USB_STATUS = { %s%s%s%s%s}", label, ++ ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""), ++ ((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""), ++ ((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "), ++ ((status & USB_STATUS_NHCIMFCLR) ? "" : "HCIMFCLR "), ++ ((status & USB_STATUS_USBPWRSENSE) ? "USBPWRSENSE " : "")); ++} ++#endif ++ ++/*-------------------------------------------------------------------------*/ ++ ++void usb_hcd_ep93xx_remove(struct usb_hcd *, struct amba_device *); ++ ++/* configure so an HC device and id are always provided */ ++/* always called with process context; sleeping is OK */ ++ ++/** ++ * usb_hcd_ep93xx_probe - initialize ep93xx HCD ++ * Context: !in_interrupt() ++ * ++ * Allocates basic resources for this USB host controller, and ++ * then invokes the start() method for the HCD associated with it ++ * through the hotplug entry's driver_data. ++ * ++ * Store this function in the HCD's struct pci_driver as probe(). ++ */ ++int usb_hcd_ep93xx_probe(const struct hc_driver *driver, ++ struct amba_device *dev) ++{ ++ int retval; ++ struct usb_hcd *hcd; ++ ++ hcd = usb_create_hcd(driver, &dev->dev, "ep93xx"); ++ ++ if (!hcd) ++ return -ENOMEM; ++ ++ hcd->rsrc_start = dev->res.start; ++ hcd->rsrc_len = dev->res.end - dev->res.start + 1; ++ ++ hcd->regs = (void __iomem *)dev->res.start; ++ ++ ep93xx_start_hc(dev); ++ ohci_hcd_init(hcd_to_ohci(hcd)); ++ ++ retval = usb_add_hcd(hcd, dev->irq[0], SA_INTERRUPT); ++ if (retval == 0) ++ return retval; ++ ++ ep93xx_stop_hc(dev); ++ ++ usb_put_hcd(hcd); ++ return retval; ++} ++ ++/* may be called without controller electrically present */ ++/* may be called with controller, bus, and devices active */ ++ ++/** ++ * usb_hcd_ep93xx_remove - shutdown processing for SA-1111-based HCDs ++ * @dev: USB Host Controller being removed ++ * Context: !in_interrupt() ++ * ++ * Reverses the effect of usb_hcd_ep93xx_probe(), first invoking ++ * the HCD's stop() method. It is always called from a thread ++ * context, normally "rmmod", "apmd", or something similar. ++ * ++ */ ++void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, struct amba_device *dev) ++{ ++ usb_remove_hcd(hcd); ++ ep93xx_stop_hc(dev); ++ usb_put_hcd(hcd); ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ int ret; ++ ++ ohci_dbg(ohci, "ohci_ep93xx_start, ohci:%p", ohci); ++ ++ if ((ret = ohci_init(ohci)) < 0) ++ return ret; ++ ++ if ((ret = ohci_run(ohci)) < 0) { ++ err("can't start %s", hcd->self.bus_name); ++ ohci_stop(hcd); ++ return ret; ++ } ++ ++ return 0; ++} ++ ++/*-------------------------------------------------------------------------*/ ++ ++static const struct hc_driver ohci_ep93xx_hc_driver = { ++ .description = hcd_name, ++ .product_desc = "EP93xx OHCI", ++ .hcd_priv_size = sizeof(struct ohci_hcd), ++ ++ /* ++ * generic hardware linkage ++ */ ++ .irq = ohci_irq, ++ .flags = HCD_USB11, ++ ++ /* ++ * basic lifecycle operations ++ */ ++ .start = ohci_ep93xx_start, ++#ifdef CONFIG_PM ++ /* suspend: ohci_ep93xx_suspend, -- tbd */ ++ /* resume: ohci_ep93xx_resume, -- tbd */ ++#endif ++ .stop = ohci_stop, ++ ++ /* ++ * managing i/o requests and associated device resources ++ */ ++ .urb_enqueue = ohci_urb_enqueue, ++ .urb_dequeue = ohci_urb_dequeue, ++ .endpoint_disable = ohci_endpoint_disable, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ohci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ohci_hub_status_data, ++ .hub_control = ohci_hub_control, ++}; ++ ++/*-------------------------------------------------------------------------*/ ++ ++static int ep93xxohci_probe(struct amba_device *dev, void *id) ++{ ++ int ret = -ENODEV; ++ ++ if (usb_disabled()) ++ return -ENODEV; ++ ++ ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, dev); ++ ++ return ret; ++} ++ ++static int ep93xxohci_remove(struct amba_device *dev) ++{ ++ struct usb_hcd *hcd = amba_get_drvdata(dev); ++ ++ usb_hcd_ep93xx_remove(hcd, dev); ++ ++ return 0; ++} ++ ++static struct amba_id ep93xxohci_ids[] __initdata = { ++ { ++ .id = 0x80020000, ++ .mask = 0xffff0000, ++ }, ++ {0, 0}, ++}; ++ ++static struct amba_driver ep93xxohci_driver = { ++ .drv = { ++ .name = "ohci-ep93xx", ++ }, ++ .id_table = ep93xxohci_ids, ++ .probe = ep93xxohci_probe, ++ .remove = ep93xxohci_remove, ++}; ++ ++static int __init ep93xxohci_init(void) ++{ ++ printk(KERN_INFO "USB: EP93xx driver $Revision: 1.42 $\n"); ++ return amba_driver_register(&ep93xxohci_driver); ++} ++ ++static void __exit ep93xxohci_cleanup(void) ++{ ++ amba_driver_unregister(&ep93xxohci_driver); ++} ++ ++module_init(ep93xxohci_init); ++module_exit(ep93xxohci_cleanup); +diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c +index bf1d9ab..bb525a2 100644 +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -909,6 +909,10 @@ MODULE_LICENSE ("GPL"); + #include "ohci-pxa27x.c" + #endif + ++#ifdef CONFIG_ARCH_EP93XX ++#include "ohci-ep93xx.c" ++#endif ++ + #ifdef CONFIG_SOC_AU1X00 + #include "ohci-au1xxx.c" + #endif +@@ -923,6 +927,7 @@ MODULE_LICENSE ("GPL"); + || defined(CONFIG_ARCH_OMAP) \ + || defined (CONFIG_ARCH_LH7A404) \ + || defined (CONFIG_PXA27x) \ ++ || defined (CONFIG_ARCH_EP93XX) \ + || defined (CONFIG_SOC_AU1X00) \ + || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \ + ) +diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig +index cc8e3bf..1d46ab0 100644 +--- a/drivers/video/Kconfig ++++ b/drivers/video/Kconfig +@@ -172,6 +172,122 @@ config FB_CLPS711X + Say Y to enable the Framebuffer driver for the CLPS7111 and + EP7212 processors. + ++config FB_CX25871_I2C ++ tristate "Conexant CX25871 video encoder" ++ depends on I2C && EXPERIMENTAL ++ help ++ ++ ! ! ! B R O K E N B R O K E N B R O K E N ! ! ! ++ ++ If you say yes here you get support for the Conexant CX25871 ++ video encoder. Currently only EP93xx CPUs use this for some ++ NTSC setup. This setup should be done in ep93xxfb.c instead. ++ It is currently hardcoded here in cx25871, which is wrong, as ++ it will happen anytime instead of exactly when it is needed. ++ I've got no NTSC hardware, and no time to test this either. ++ ++ Why I've written it then? Well I had to get I2C working and it ++ helped me on my way there. ++ ++ If nobody cares about NTSC support for EP93xx it will go away soon! ++ ++ Only say Y if you have such a chip and are prepared to fix the remaining ++ stuff yourself. ++ ++ See ep93xxfb.[ch] and cx25871.c for details. ++ ++ This driver can also be built as a module. If so, the module ++ will be called cx25871. ++ ++config FB_EP93XX ++ bool "EP93XX Framebuffer support" ++ depends on FB && ARM && (ARCH_EP9312 || ARCH_EP9315) ++ select FB_CFB_FILLRECT ++ select FB_CFB_COPYAREA ++ select FB_CFB_IMAGEBLIT ++ help ++ Say Y here if you want support for the on EP93XX framebuffer. ++ ++ You can also say M here to compile this as a module. However this ++ is not recommended as loading the module without a display can ++ be a problem. (Make sure you can login without display before you ++ say M or N here). ++ ++ The module will be called ep93xxfb. ++choice ++ prompt "Display Type" ++ depends on FB_EP93XX ++ help ++ Choose the kind of display you want to attach to the EP93XX framebuffer. ++ ++config FB_CRT_EP93XX ++ bool "CRT Display" ++ ++config FB_LCD_EP93XX ++ bool "LCD Display" ++ help ++ Support for the Philips 640x480 Display on the EDB93XX evaluation board. ++ ++config FB_LCD_EP93XX_SHARP ++ bool "LCD Display 320x200 SHARP" ++ help ++ Support for the Sharp LQ057Q3DC02 320x200 Color TFT LCD. ++ ++config FB_LCD_EP93XX_SHARP_LQ64D343 ++ bool "LCD Display 640x480 SHARP" ++ help ++ Support for the Sharp LQ64D343 640x480 Color TFT LCD. ++ ++config FB_CX25871 ++ bool "NTSC Display" ++ select FB_CX25871_I2C ++ ++config FB_LCD_TX09D50VM1CCA ++ bool "LCD Display 240x320 Hitachi TX09D50VM1CCA" ++ help ++ Support for the Hitachi TX09D50VM1CCA 240x320 Color TFT LCD. ++ ++endchoice ++ ++choice ++ prompt "Display Color Depth" ++ depends on FB_EP93XX ++ default FB_EP93XX_8BPP ++ help ++ Choose the default color depth for you EP93xx display. Note that using ++ other than 8BPP depths tends to be slow. ++ ++config FB_EP93XX_8BPP ++ bool "8bpp" ++ help ++ Use 8 bits per pixel (256 color). ++ Benefits: fastest available mode ++ Drawback: few colors available (might do for console work, though) ++ ++config FB_EP93XX_16BPP_565 ++ bool "16bpp_565" ++ help ++ Use 16 bits per pixel. Weighting red:green:blue is 5:6:5 bits. ++ Make sure your Xserver / Framebuffer based applications use exactly this ++ weighting. ++ ++config FB_EP93XX_24BPP ++ bool "24bpp" ++ help ++ Use 24 bits per pixel. Weighting red:green:blue is 8:8:8 bits. Say Y here ++ if you want lots of colors and do not care that much about performance. ++ ++ ++ ++config FB_EP93XX_32BPP ++ bool "32bpp" ++ help ++ Use 32 bits per pixel. Weighting transparent:red:green:blue is 8:8:8:8 bits. ++ Note that transparency is seldom implemented so this one is just slower and ++ consumes more memory than 24BPP. ++endchoice ++ ++ + config FB_SA1100 + bool "SA-1100 LCD support" + depends on (FB = y) && ARM && ARCH_SA1100 +diff --git a/drivers/video/Makefile b/drivers/video/Makefile +index aa434e7..82f680b 100644 +--- a/drivers/video/Makefile ++++ b/drivers/video/Makefile +@@ -99,6 +99,8 @@ obj-$(CONFIG_FB_S3C2410) += s3c2410fb. + obj-$(CONFIG_FB_VESA) += vesafb.o + obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o + obj-$(CONFIG_FB_OF) += offb.o ++obj-$(CONFIG_FB_EP93XX) += ep93xxfb.o ++obj-$(CONFIG_FB_CX25871_I2C) += cx25871.o + + # the test framebuffer is last + obj-$(CONFIG_FB_VIRTUAL) += vfb.o +diff --git a/drivers/video/cx25871.c b/drivers/video/cx25871.c +new file mode 100644 +index 0000000..816cbef +--- /dev/null ++++ b/drivers/video/cx25871.c +@@ -0,0 +1,200 @@ ++/* ++ cx25871.c ++ ++ Driver for the Conexant CX25871 VIDEO ENCODER ++ ++ based on: ds1621.c ++ ++ ++ ++ ++ BIG FAT WARNING: THIS IS EXPERIMENTAL AND UNTESTED CODE ++ ++ ++ ++ ++ ++ ++ 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., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include <linux/config.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/delay.h> ++#include <linux/slab.h> ++#include <linux/i2c.h> ++#include <asm/io.h> ++ ++/* ++ * assign an invalid (local use) id for now ++ * TODO: get an official one! ++ */ ++#define I2C_DRIVERID_EP93XX 0xffff ++ ++/* Addresses to scan */ ++static unsigned short normal_i2c[] = { 0x44, I2C_CLIENT_END }; ++static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; ++ ++I2C_CLIENT_INSMOD; ++ ++static int cx25871_attach_adapter(struct i2c_adapter *adapter); ++static int cx25871_detect(struct i2c_adapter *adapter, int address, int kind); ++static void cx25871_init_client(struct i2c_client *client); ++static int cx25871_detach_client(struct i2c_client *client); ++ ++/* This is the driver that will be inserted */ ++static struct i2c_driver cx25871_driver = { ++ .owner = THIS_MODULE, ++ .name = "cx25871", ++ .id = I2C_DRIVERID_EP93XX, ++ .flags = I2C_DF_NOTIFY, ++ .attach_adapter = cx25871_attach_adapter, ++ .detach_client = cx25871_detach_client, ++}; ++ ++static int cx25871_id = 0; ++ ++/* Cleanup and introduce cx25871 specific data, if necessary */ ++struct cx25871_data { ++ struct i2c_client client; ++ struct semaphore update_lock; ++ char valid; /* !=0 if following fields are valid */ ++ unsigned long last_updated; /* In jiffies */ ++}; ++ ++static int cx25871_read_value(struct i2c_client *client, u8 reg) ++{ ++ return i2c_smbus_read_byte_data(client, reg); ++} ++ ++static int cx25871_write_value(struct i2c_client *client, u8 reg, u16 value) ++{ ++ return i2c_smbus_write_byte_data(client, reg, value); ++} ++ ++static void cx25871_init_client(struct i2c_client *client) ++{ ++ /*FIXME: This should be done in ep93xxfb.c, shouldn't it? */ ++ ++ int _todo__fix_this_ugly_hack_; ++ ++ cx25871_write_value(client, 0xB8, 0); ++ mdelay(1000); ++ /* After auto-configuration, setup pseudo-master mode BUT with EN_BLANKO bit cleared */ ++ cx25871_write_value(client, 0xBA, ++ CX25871_REGxBA_SLAVER | CX25871_REGxBA_DACOFF); ++ cx25871_write_value(client, 0xC6, (CX25871_REGxC6_INMODE_MASK & 0x3)); ++ cx25871_write_value(client, 0xC4, CX25871_REGxC4_EN_OUT); ++ cx25871_write_value(client, 0x32, 0); ++ cx25871_write_value(client, 0xBA, CX25871_REGxBA_SLAVER); ++} ++ ++static int cx25871_attach_adapter(struct i2c_adapter *adapter) ++{ ++ printk("cx25871_attach_adapter\n"); ++ return i2c_probe(adapter, &addr_data, cx25871_detect); ++} ++ ++/* This function is called by i2c_detect */ ++int cx25871_detect(struct i2c_adapter *adapter, int address, int kind) ++{ ++ struct i2c_client *new_client; ++ struct cx25871_data *data; ++ int err = 0; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA ++ | I2C_FUNC_SMBUS_WRITE_BYTE)) ++ goto exit; ++ ++ /* OK. For now, we presume we have a valid client. We now create the ++ client structure, even though we cannot fill it completely yet. ++ But it allows us to access cx25871_{read,write}_value. */ ++ if (!(data = kmalloc(sizeof(struct cx25871_data), GFP_KERNEL))) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ memset(data, 0, sizeof(struct cx25871_data)); ++ ++ new_client = &data->client; ++ i2c_set_clientdata(new_client, data); ++ new_client->addr = address; ++ new_client->adapter = adapter; ++ new_client->driver = &cx25871_driver; ++ new_client->flags = 0; ++ ++ /* Fill in remaining client fields and put it into the global list */ ++ strlcpy(new_client->name, "cx25871", I2C_NAME_SIZE); ++ ++ new_client->id = cx25871_id++; ++ data->valid = 0; ++ init_MUTEX(&data->update_lock); ++ ++ /* Tell the I2C layer a new client has arrived */ ++ if ((err = i2c_attach_client(new_client))) ++ goto exit_free; ++ /* Initialize the EP93XX chip */ ++ cx25871_init_client(new_client); ++ ++/* Register sysfs hooks */ ++#if 0 ++ device_create_file(&new_client->dev, &dev_attr_alarms); ++ device_create_file(&new_client->dev, &dev_attr_temp1_input); ++ device_create_file(&new_client->dev, &dev_attr_temp1_min); ++ device_create_file(&new_client->dev, &dev_attr_temp1_max); ++#endif ++ return 0; ++ ++/* OK, this is not exactly good programming practice, usually. But it is ++ very code-efficient in this case. */ ++ exit_free: ++ kfree(data); ++ exit: ++ return err; ++} ++ ++static int cx25871_detach_client(struct i2c_client *client) ++{ ++ int err; ++ ++ if ((err = i2c_detach_client(client))) { ++ dev_err(&client->dev, "Client deregistration failed, " ++ "client not detached.\n"); ++ return err; ++ } ++ ++ kfree(i2c_get_clientdata(client)); ++ ++ return 0; ++} ++ ++static int __init cx25871_init(void) ++{ ++ printk("cx25871_init\n"); ++ return i2c_add_driver(&cx25871_driver); ++} ++ ++static void __exit cx25871_exit(void) ++{ ++ i2c_del_driver(&cx25871_driver); ++} ++ ++MODULE_DESCRIPTION("Conexant CX25871 video encoder"); ++MODULE_LICENSE("GPL"); ++ ++module_init(cx25871_init); ++module_exit(cx25871_exit); +diff --git a/drivers/video/ep93xxfb.c b/drivers/video/ep93xxfb.c +new file mode 100644 +index 0000000..475943a +--- /dev/null ++++ b/drivers/video/ep93xxfb.c +@@ -0,0 +1,787 @@ ++/****************************************************************************** ++ * ++ * File: linux/drivers/video/ep93xxfb.c ++ * ++ * Purpose: Framebuffer driver for EP9312/EP9315 evaluation board. ++ * ++ * based on: ++ * skeletonfb.c ++ * ep93xxfb.c from Linux 2.4.21-rmk1-cirrus-1-3-0 ++ * ++ *******************************************************************************/ ++#include <linux/config.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/sched.h> ++#include <linux/errno.h> ++#include <linux/delay.h> ++#include <linux/string.h> ++#include <linux/ctype.h> ++#include <linux/mm.h> ++#include <linux/tty.h> ++#include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/fb.h> ++#include <linux/device.h> ++#include <linux/dma-mapping.h> ++ ++#include <asm/hardware.h> ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <asm/mach-types.h> ++#include <asm/uaccess.h> ++#include <asm/pgtable.h> ++ ++#include "ep93xxfb.h" ++ ++/* ++#define DEBUG ++#define USE_PRINTASCII ++*/ ++ ++#ifdef DEBUG ++# if defined(CONFIG_DEBUG_LL) && defined(USE_PRINTASCII) ++extern void printascii(const char *); ++# define DPRINTK(fmt, args...) {char str[256];sprintf(str, "%s: " fmt, __FUNCTION__ , ## args);printascii(str);} ++# else ++# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) ++# endif ++#else ++# define DPRINTK(fmt, args...) ++#endif ++ ++static struct fb_info info; ++static struct fb_fix_screeninfo ep93xxfb_fix; ++static struct fb_var_screeninfo ep93xxfb_var; ++static struct ep93xxfb_par ep93xxfb_par; ++static unsigned int pseudo_palette[MAX_PALETTE_NUM_ENTRIES]; ++ ++int __init ep93xxfb_init(void); ++static int ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green, ++ unsigned blue, unsigned transp, ++ struct fb_info *info); ++static int ep93xxfb_blank(int blank_mode, struct fb_info *info); ++int __init ep93xxfb_init(void); ++static void __exit ep93xxfb_cleanup(void); ++int __init ep93xxfb_setup(char *options); ++ ++static struct fb_ops ep93xxfb_ops = { ++ .owner = THIS_MODULE, ++ .fb_setcolreg = ep93xxfb_setcolreg, ++ .fb_blank = ep93xxfb_blank, ++ .fb_fillrect = cfb_fillrect, ++ .fb_copyarea = cfb_copyarea, ++ .fb_imageblit = cfb_imageblit, ++}; ++ ++/* ++ * ep93xxfb_palette_write: ++ * Encode palette data to 24bit palette format. ++ * Write palette data to the master palette and inactive hw palette ++ * switch palettes. And handle asynchronous palette switches. ++ */ ++static inline void ++ep93xxfb_palette_write(u_int regno, u_int red, u_int green, ++ u_int blue, u_int trans) ++{ ++ unsigned int cont, i, pal; ++ ++ /* Only supports color LUT, not gray LUT ++ * ++ * TBD if not in 4 or 8bpp, then does LUT logic operate? ++ * TBD or do we need to do nothing here? ++ * ++ * LCD: TBD RGB mapping may match spec p193. ++ * ++ * CRT: LUT RGB mapping is really R/G/B from high to low bits ++ * because really determined by wiring to video DAC. ++ * (disregard spec p 193 showing color LUT B/G/R order) ++ * Here are the details: ++ * ++ * Shift mode 1 directs LUT bits 7-2 onto P5-P0, ++ * LUT bits 15-10 onto P11-P6, and LUT bits 23-16 ++ * onto P17-P12. ++ * ++ * Board wired P17-12 to video DAC Red inputs, ++ * P11-P6 wired to video DAC Green inputs, and ++ * P5-P0 wired to video DAC Blue inputs. ++ */ ++ pal = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8); ++ ++ pseudo_palette[regno] = pal; ++ ++ /* Two cases here: ++ * 1. If LUT switch is pending, then write inactive LUT and when ++ * switch happens, this new palette entry will be active. ++ * Race condition here between LUT switch and this write is okay ++ * since we fix it below. ++ * ++ * 2. If LUT switch is not pending, then write here is incomplete ++ * and whole palette will be written below. ++ */ ++ ++ writel(pal, COLOR_LUT + (regno << 2)); ++ ++ cont = readl(LUTCONT); ++ ++ if ((cont & LUTCONT_STAT && cont & LUTCONT_RAM1) || ++ (!(cont & LUTCONT_STAT) && !(cont & LUTCONT_RAM1))) { ++ /* LUT switch is no longer pending ++ * ++ * We do not know if write to LUT above really went ++ * to currently active LUT. So need to make sure that ++ * data gets into inactive LUT and switch LUTs. ++ * ++ * But currently inactive LUT may be out of date ++ * in more entries than just last write. ++ * Need to update currently inactive LUT for all writes ++ * which went to currently active LUT. ++ * Fully update the LUT now, which is a simpler policy ++ * than trying to track writes and do partial update of LUT. ++ * (Worstcase impact: we update palette every frame) ++ */ ++ ++ for (i = 0; i < 256; i++) // Update inactive LUT ++ { ++ writel(pseudo_palette[i], ++ (COLOR_LUT + (i << 2))); ++ } ++ /* Switch active LUTs next frame */ ++ writel(cont ^ LUTCONT_RAM1, LUTCONT); ++ } ++} ++ ++/** ++ * xxxfb_setcolreg - Optional function. Sets a color register. ++ * @regno: Which register in the CLUT we are programming ++ * @red: The red value which can be up to 16 bits wide ++ * @green: The green value which can be up to 16 bits wide ++ * @blue: The blue value which can be up to 16 bits wide. ++ * @transp: If supported the alpha value which can be up to 16 bits wide. ++ * @info: frame buffer info structure ++ * ++ * Set a single color register. The values supplied have a 16 bit ++ * magnitude which needs to be scaled in this function for the hardware. ++ * Things to take into consideration are how many color registers, if ++ * any, are supported with the current color visual. With truecolor mode ++ * no color palettes are supported. Here a psuedo palette is created ++ * which we store the value in pseudo_palette in struct fb_info. For ++ * pseudocolor mode we have a limited color palette. To deal with this ++ * we can program what color is displayed for a particular pixel value. ++ * DirectColor is similar in that we can program each color field. If ++ * we have a static colormap we don't need to implement this function. ++ * ++ * Returns negative errno on error, or zero on success. ++ */ ++static int ++ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, ++ unsigned transp, struct fb_info *info) ++{ ++ if (regno >= MAX_PALETTE_NUM_ENTRIES) /* no. of hw registers */ ++ return 1; ++ /* ++ * Program hardware... do anything you want with transp ++ */ ++ ++ /* grayscale works only partially under directcolor */ ++ if (info->var.grayscale) { ++ /* grayscale = 0.30*R + 0.59*G + 0.11*B */ ++ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; ++ } ++ ++ /* Directcolor: ++ * var->{color}.offset contains start of bitfield ++ * var->{color}.length contains length of bitfield ++ * {hardwarespecific} contains width of DAC ++ * cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset) ++ * RAMDAC[X] is programmed to (red, green, blue) ++ * ++ * Pseudocolor: ++ * uses offset = 0 && length = DAC register width. ++ * var->{color}.offset is 0 ++ * var->{color}.length contains widht of DAC ++ * cmap is not used ++ * DAC[X] is programmed to (red, green, blue) ++ * Truecolor: ++ * does not use RAMDAC (usually has 3 of them). ++ * var->{color}.offset contains start of bitfield ++ * var->{color}.length contains length of bitfield ++ * cmap is programmed to (red << red.offset) | (green << green.offset) | ++ * (blue << blue.offset) | (transp << transp.offset) ++ * RAMDAC does not exist ++ */ ++#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) ++ ++ switch (info->fix.visual) { ++ case FB_VISUAL_PSEUDOCOLOR: ++ /* Feed the dual 256x24 hardware LUT */ ++ ep93xxfb_palette_write(regno, red, green, blue, transp); ++ break; ++ case FB_VISUAL_TRUECOLOR: ++ /* Truecolor has hardware independent palette */ ++ if (regno >= 16) ++ return 1; ++ ++ red = CNVT_TOHW(red, info->var.red.length); ++ green = CNVT_TOHW(green, info->var.green.length); ++ blue = CNVT_TOHW(blue, info->var.blue.length); ++ transp = CNVT_TOHW(transp, info->var.transp.length); ++ ((u32 *) (info->pseudo_palette))[regno] = ++ (red << info->var.red.offset) | ++ (green << info->var.green.offset) | ++ (blue << info->var.blue.offset) | ++ (transp << info->var.transp.offset); ++ break; ++ case FB_VISUAL_DIRECTCOLOR: ++ /* example here assumes 8 bit DAC. Might be different ++ * for your hardware */ ++ red = CNVT_TOHW(red, 8); ++ green = CNVT_TOHW(green, 8); ++ blue = CNVT_TOHW(blue, 8); ++ /* hey, there is bug in transp handling... */ ++ transp = CNVT_TOHW(transp, 8); ++ break; ++ } ++#undef CNVT_TOHW ++ ++ return 0; ++} ++ ++/** ++ * xxxfb_blank - NOT a required function. Blanks the display. ++ * @blank_mode: the blank mode we want. ++ * @info: frame buffer structure that represents a single frame buffer ++ * ++ * Blank the screen if blank_mode != 0, else unblank. Return 0 if ++ * blanking succeeded, != 0 if un-/blanking failed due to e.g. a ++ * video mode which doesn't support it. Implements VESA suspend ++ * and powerdown modes on hardware that supports disabling hsync/vsync: ++ * blank_mode == 2: suspend vsync ++ * blank_mode == 3: suspend hsync ++ * blank_mode == 4: powerdown ++ * ++ * Returns negative errno on error, or zero on success. ++ * ++ */ ++static int ep93xxfb_blank(int blank_mode, struct fb_info *info) ++{ ++#ifdef CONFIG_MACH_ADSSPHERE ++ void adssphere_blank(int blank_mode); ++ ++ adssphere_blank(blank_mode); ++#endif ++ ++ return 1; ++} ++ ++static struct device ep93xxfb_device = { ++ .bus_id = "ep93xxfb", ++ .coherent_dma_mask = 0xffffffff, ++}; ++ ++/* ++ * ep9312fb_map_video_memory(): ++ * Allocates the DRAM memory for the frame buffer. This buffer is ++ * remapped into a non-cached, non-buffered, memory region to ++ * allow palette and pixel writes to occur without flushing the ++ * cache. Once this area is remapped, all virtual memory ++ * access to the video memory should occur at the new region. ++ */ ++static int ++__init ep9312fb_map_video_memory(void) ++{ ++ dma_addr_t handle; ++ ++ ep93xxfb_par.dev = &ep93xxfb_device; ++ ++ ep93xxfb_par.v_screen_base = dma_alloc_writecombine(ep93xxfb_par.dev, ++ FB_MAPPED_MEM_SIZE, ++ &handle, ++ GFP_KERNEL); ++ ++ if (ep93xxfb_par.v_screen_base == NULL) { ++ printk(KERN_ERR "ep93xxfb: unable to allocate screen memory\n"); ++ return -ENOMEM; ++ } ++ ++ info.screen_base = ep93xxfb_par.v_screen_base; ++ info.fix.smem_start = (unsigned int)ep93xxfb_par.p_screen_base = handle; ++ info.fix.smem_len = FB_MAPPED_MEM_SIZE; ++ ++ return 0; ++} ++ ++static int ep93xxfb_probe_configuration(void) ++{ ++ int xres, yres, bpp, pixelmode, total; ++ unsigned char lookup_bpp[] = {-1, -1, 8, -1, 16, -1, 24, 32}; ++ ++ pixelmode = readl(PIXELMODE); ++ ++ bpp = lookup_bpp[PIXELMODE_P_MASK & pixelmode]; ++ ++ if (bpp < 0) return 0; ++ ++ yres = readl(SCRNLINES); ++ ++ if (yres == 0) return 0; ++ ++ xres = (32 * readl(VLINESTEP)) / bpp; ++ ++ if (xres == 0) return 0; ++ ++ info.node = -1; ++ info.flags = FBINFO_FLAG_DEFAULT; ++ ++ info.fix = ep93xxfb_fix; ++ info.var = ep93xxfb_var; ++ info.fbops = &ep93xxfb_ops; ++ info.pseudo_palette = pseudo_palette; ++ ++ info.monspecs = monspecs; ++ ++ strcpy(info.fix.id, "Cirrus EP93xx"); ++ info.fix.type = FB_TYPE_PACKED_PIXELS; ++ info.fix.xpanstep = 0; ++ info.fix.ypanstep = 0; ++ info.fix.ywrapstep = 0; ++ info.fix.accel = FB_ACCEL_NONE; ++ ++ info.var.xres = xres; ++ info.var.yres = yres; ++ info.var.xres_virtual = xres; ++ info.var.yres_virtual = yres; ++ info.var.bits_per_pixel = bpp; ++ info.var.activate = FB_ACTIVATE_NOW; ++ info.var.height = -1; ++ info.var.width = -1; ++ ++ switch (bpp) { ++ case 8: ++ info.var.red.length = 8; ++ info.var.green.length = 8; ++ info.var.blue.length = 8; ++ ++ info.fix.visual = FB_VISUAL_PSEUDOCOLOR; ++ ep93xxfb_par.bits_per_pixel = 8; ++ break; ++ case 16: ++ info.var.red.length = 5; ++ info.var.green.length = 6; ++ info.var.blue.length = 5; ++ info.var.transp.length = 0; ++ info.var.red.offset = 11; ++ info.var.green.offset = 5; ++ info.var.blue.offset = 0; ++ info.var.transp.offset = 0; ++ ++ info.fix.visual = FB_VISUAL_TRUECOLOR; ++ info.pseudo_palette = ep93xxfb_par.palette; ++ ++ ep93xxfb_par.bits_per_pixel = 16; ++ break; ++ case 24: ++ info.var.red.length = 8; ++ info.var.blue.length = 8; ++ info.var.green.length = 8; ++ info.var.transp.length = 0; ++ info.var.red.offset = 16; ++ info.var.green.offset = 8; ++ info.var.blue.offset = 0; ++ info.var.transp.offset = 0; ++ ++ info.fix.visual = FB_VISUAL_TRUECOLOR; ++ ++ ep93xxfb_par.bits_per_pixel = 24; ++ break; ++ case 32: ++ info.var.red.length = 8; ++ info.var.blue.length = 8; ++ info.var.green.length = 8; ++ info.var.transp.length = 0; ++ info.var.red.offset = 16; ++ info.var.green.offset = 8; ++ info.var.blue.offset = 0; ++ info.var.transp.offset = 0; ++ ++ info.fix.visual = FB_VISUAL_TRUECOLOR; ++ ++ ep93xxfb_par.bits_per_pixel = 32; ++ break; ++ } ++ ++ total = readl(HCLKSTOTAL); ++ info.var.hsync_len = (0x7ff & readl(HSYNCSTRTSTOP)) - ((0x07ff0000 & readl(HSYNCSTRTSTOP)) >> 16); ++ info.var.right_margin = ((0x07ff0000 & readl(HSYNCSTRTSTOP)) >> 16) - (0x7ff & readl(HACTIVESTRTSTOP)); ++ info.var.left_margin = total - info.var.hsync_len - info.var.right_margin - xres + 1; ++ ++ total = readl(VLINESTOTAL); ++ info.var.vsync_len = (0x7ff & readl(VSYNCSTRTSTOP)) - ((0x07ff0000 & readl(VSYNCSTRTSTOP)) >> 16); ++ info.var.upper_margin = total - (0x7ff & readl(VSYNCSTRTSTOP)); ++ info.var.lower_margin = ((0x07ff0000 & readl(VSYNCSTRTSTOP)) >> 16) - yres + 1; ++ ++ info.var.sync = 0; ++ ++ info.var.vmode = FB_VMODE_NONINTERLACED; ++ ++ info.fix.line_length = info.var.xres_virtual * info.var.bits_per_pixel / 8; // stride in bytes ++ ++ info.par = &TimingValues[NULL_MODE]; ++ ++ ep93xxfb_par.screen_size = FB_MAX_MEM_SIZE; ++ ep93xxfb_par.palette_size = MAX_PALETTE_NUM_ENTRIES; ++ ep93xxfb_par.montype = 1; //TBD why not 0 since single entry? ++ ep93xxfb_par.currcon = 0; //TBD is this right? ++ ++ return 1; ++} ++ ++static void ++__init ep93xxfb_init_fbinfo(void) ++{ ++ info.node = -1; ++ info.flags = FBINFO_FLAG_DEFAULT; ++ ++ info.fix = ep93xxfb_fix; ++ info.var = ep93xxfb_var; ++ info.fbops = &ep93xxfb_ops; ++ info.pseudo_palette = pseudo_palette; ++ info.par = &ep93xxfb_par; ++ ++ info.monspecs = monspecs; ++ ++ strcpy(info.fix.id, "Cirrus EP93xx"); ++ info.fix.type = FB_TYPE_PACKED_PIXELS; ++ info.fix.visual = FB_VISUAL_PSEUDOCOLOR; ++ info.fix.xpanstep = 0; ++ info.fix.ypanstep = 0; ++ info.fix.ywrapstep = 0; ++ info.fix.accel = FB_ACCEL_NONE; ++ ++ info.var.xres = TimingValues[DEFAULT_MODE].HRes; ++ info.var.yres = TimingValues[DEFAULT_MODE].VRes; ++ info.var.xres_virtual = TimingValues[DEFAULT_MODE].HRes; ++ info.var.yres_virtual = TimingValues[DEFAULT_MODE].VRes; ++ info.var.bits_per_pixel = 32; ++ info.var.red.length = 8; ++ info.var.green.length = 8; ++ info.var.blue.length = 8; ++ info.var.activate = FB_ACTIVATE_NOW; ++ info.var.height = -1; ++ info.var.width = -1; ++ info.var.vmode = FB_VMODE_NONINTERLACED; ++ ++ /* ++ * setup initial parameters ++ */ ++ info.var.xres = TimingValues[DEFAULT_MODE].HRes; ++ info.var.yres = TimingValues[DEFAULT_MODE].VRes; ++ ++#ifdef CONFIG_FB_EP93XX_8BPP ++ DPRINTK("Default framebuffer is 8bpp."); ++ info.var.bits_per_pixel = 8; ++ ++ info.var.red.length = 8; ++ info.var.green.length = 8; ++ info.var.blue.length = 8; ++ ++ info.fix.visual = FB_VISUAL_PSEUDOCOLOR; ++ ep93xxfb_par.bits_per_pixel = 8; ++#endif /* CONFIG_FB_EP93XX_8BPP */ ++#ifdef CONFIG_FB_EP93XX_16BPP_565 ++ DPRINTK("Default framebuffer is 16bpp 565."); ++ info.var.bits_per_pixel = 16; ++ ++ info.var.red.length = 5; ++ info.var.green.length = 6; ++ info.var.blue.length = 5; ++ info.var.transp.length = 0; ++ info.var.red.offset = 11; ++ info.var.green.offset = 5; ++ info.var.blue.offset = 0; ++ info.var.transp.offset = 0; ++ info.fix.visual = FB_VISUAL_TRUECOLOR; ++ info.pseudo_palette = ep93xxfb_par.palette; ++ ++ ep93xxfb_par.bits_per_pixel = 16; ++#endif /* CONFIG_FB_EP93XX_16BPP */ ++#ifdef CONFIG_FB_EP93XX_24BPP ++ DPRINTK("Default framebuffer is 24bpp."); ++ info.var.bits_per_pixel = 24; ++ ++ info.var.red.length = 8; ++ info.var.blue.length = 8; ++ info.var.green.length = 8; ++ info.var.transp.length = 0; ++ info.var.red.offset = 16; ++ info.var.green.offset = 8; ++ info.var.blue.offset = 0; ++ info.var.transp.offset = 0; ++ info.fix.visual = FB_VISUAL_TRUECOLOR; ++ ++ ep93xxfb_par.bits_per_pixel = 24; ++#endif /* CONFIG_FB_EP93XX_24BPP */ ++#ifdef CONFIG_FB_EP93XX_32BPP ++ DPRINTK("Default framebuffer is 32bpp."); ++ info.var.bits_per_pixel = 32; ++ ++ info.var.red.length = 8; ++ info.var.blue.length = 8; ++ info.var.green.length = 8; ++ info.var.transp.length = 0; ++ info.var.red.offset = 16; ++ info.var.green.offset = 8; ++ info.var.blue.offset = 0; ++ info.var.transp.offset = 0; ++ info.fix.visual = FB_VISUAL_TRUECOLOR; ++ ++ ep93xxfb_par.bits_per_pixel = 32; ++#endif /* CONFIG_FB_EP93XX_32BPP */ ++ ++ info.var.activate = FB_ACTIVATE_NOW; ++ info.var.height = -1; /*TBD unknown */ ++ info.var.width = -1; /*TBD unknown */ ++ ++ info.var.left_margin = TimingValues[DEFAULT_MODE].HFrontPorch; ++ info.var.right_margin = TimingValues[DEFAULT_MODE].HBackPorch; ++ info.var.upper_margin = TimingValues[DEFAULT_MODE].VFrontPorch; ++ info.var.lower_margin = TimingValues[DEFAULT_MODE].VBackPorch; ++ info.var.hsync_len = TimingValues[DEFAULT_MODE].HSyncWidth; ++ info.var.vsync_len = TimingValues[DEFAULT_MODE].VSyncWidth; ++ info.var.sync = 0; ++ info.var.vmode = FB_VMODE_NONINTERLACED; ++ ++ info.fix.line_length = info.var.xres_virtual * info.var.bits_per_pixel / 8; /* stride in bytes */ ++ ++ info.par = &TimingValues[DEFAULT_MODE]; ++ ++ ep93xxfb_par.screen_size = FB_MAX_MEM_SIZE; ++ ep93xxfb_par.palette_size = MAX_PALETTE_NUM_ENTRIES; ++ ep93xxfb_par.montype = 1; /*TBD why not 0 since single entry? */ ++ ep93xxfb_par.currcon = 0; /*TBD is this right? */ ++} ++ ++static int ++ep93xxfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) ++{ ++ u_long flags, ulVIDEOATTRIBS; ++ unsigned int total, uiDevCfg, uiBMAR; ++#ifdef CONFIG_FB_LCD_EP93XX ++ unsigned int uiPADDR, uiPADR; ++#endif ++ struct DisplayTimingValues *pTimingValues; ++ ++ switch (var->bits_per_pixel) { ++ case 4: ++ ep93xxfb_par.visual = FB_VISUAL_PSEUDOCOLOR; ++ ep93xxfb_par.palette_size = 16; ++ break; ++ case 8: ++ ep93xxfb_par.visual = FB_VISUAL_PSEUDOCOLOR; ++ ep93xxfb_par.palette_size = 256; ++ break; ++ case 16: ++ ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR; ++ ep93xxfb_par.palette_size = 16; ++ break; ++ case 24: ++ ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR; ++ ep93xxfb_par.palette_size = 16; ++ break; ++ case 32: ++ ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR; ++ ep93xxfb_par.palette_size = 16; ++ break; ++ default: ++ printk("ERROR! Bad bpp %d\n", var->bits_per_pixel); ++ return -EINVAL; ++ } ++ ++ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST) ++ return 0; ++ else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) && ++ ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN)) ++ return -EINVAL; ++ ++ pTimingValues = (struct DisplayTimingValues *)info->par; ++ ++ /* Disable interrupts and save status */ ++ local_irq_save(flags); ++ ++ printk("Configuring %dx%dx%dbpp\n", var->xres, var->yres, ++ var->bits_per_pixel); ++ ++ /* Disable the video and outputs while changing the video mode. */ ++ writel(0, VIDEOATTRIBS); ++ if (pTimingValues->RasterConfigure) { ++ pTimingValues->RasterConfigure((struct DisplayTimingValues *)info->par); /*pTimingValues); */ ++ } else { ++ total = var->vsync_len + var->upper_margin + var->yres + ++ var->lower_margin - 1; ++ ++ RasterSetLocked(VLINESTOTAL, total); ++ ++ RasterSetLocked(VSYNCSTRTSTOP, total - var->lower_margin + ++ ((total - ++ (var->lower_margin + var->vsync_len)) << 16)); ++ ++ RasterSetLocked(VACTIVESTRTSTOP, var->yres + (total << 16)); ++ ++ /* Reverse start/stop since N_VBLANK output ++ * unblanked same as active ++ */ ++ RasterSetLocked(VBLANKSTRTSTOP, var->yres + (total << 16)); ++ ++ RasterSetLocked(VCLKSTRTSTOP, total + (total << 16)); ++ ++ /* Now configure the Horizontal timings. */ ++ total = var->hsync_len + var->left_margin + var->xres + ++ var->right_margin - 1; ++ ++ RasterSetLocked(HCLKSTOTAL, total); ++ ++ RasterSetLocked(HSYNCSTRTSTOP, total + ++ ((total - var->hsync_len) << 16)); ++ ++ RasterSetLocked(HACTIVESTRTSTOP, total - var->hsync_len - ++ var->left_margin + ++ ((var->right_margin - 1) << 16)); ++ ++ RasterSetLocked(HBLANKSTRTSTOP, total - var->hsync_len - ++ var->left_margin + ++ ((var->right_margin - 1) << 16)); ++ ++ RasterSetLocked(HCLKSTRTSTOP, total + (total << 16)); ++ ++ RasterSetLocked(LINECARRY, 0); ++ ++ RasterSetLocked(VIDEOATTRIBS, ++ VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_SYNCEN | ++ VIDEOATTRIBS_DATAEN); ++ } ++ ++ /* Configure the Frame Buffer size. */ ++ writel((unsigned int)ep93xxfb_par.p_screen_base, VIDSCRNPAGE); ++ writel(var->yres, SCRNLINES); ++ ++ /* Set up the Line size. */ ++ total = var->xres * var->bits_per_pixel / 32; ++ writel((total - 1), LINELENGTH); ++ writel(total, VLINESTEP); ++ ++ switch (var->bits_per_pixel) { ++ case 8: ++ writel((0x8 | PIXELMODE_P_8BPP | PIXELMODE_C_LUT), PIXELMODE); ++ break; ++ case 16: ++ writel(0x8 | PIXELMODE_P_16BPP | ++ ((PIXELMODE_C_565) << (PIXELMODE_C_SHIFT)), PIXELMODE); ++ break; ++ case 24: ++ writel(0x8 | PIXELMODE_P_24BPP | ++ ((PIXELMODE_C_888) << (PIXELMODE_C_SHIFT)), PIXELMODE); ++ break; ++ case 32: ++ writel(0x8 | PIXELMODE_P_32BPP | ++ ((PIXELMODE_C_888) << (PIXELMODE_C_SHIFT)), PIXELMODE); ++ break; ++ default: ++ printk("ERROR! Bad bpp %d\n", var->bits_per_pixel); ++ return -EINVAL; ++ } ++ ++ uiDevCfg = readl(SYSCON_DEVCFG); ++ SysconSetLocked(SYSCON_DEVCFG, ++ ep93xx_SYSCON_DEVCFG(uiDevCfg | SYSCON_DEVCFG_RasOnP3)); ++ ++ if (pTimingValues->VDiv) ++ SysconSetLocked(SYSCON_VIDDIV, pTimingValues->VDiv); ++ ++ uiBMAR = readl(SYSCON_BMAR); ++ writel((uiBMAR | 1), SYSCON_BMAR); ++ ++ ulVIDEOATTRIBS = readl(VIDEOATTRIBS); ++ RasterSetLocked(VIDEOATTRIBS, ulVIDEOATTRIBS | VIDEOATTRIBS_EN | ++#if (defined(CONFIG_MACH_ZEFEERDZG) || defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ)) ++ (1 << VIDEOATTRIBS_SDSEL_SHIFT)); ++#else ++ (3 << VIDEOATTRIBS_SDSEL_SHIFT)); ++#endif ++ ++ ++#ifdef CONFIG_FB_LCD_EP93XX ++ uiPADDR = readl(GPIO_PADDR) | 0x2; ++ writel(uiPADDR, GPIO_PADDR); ++ ++ uiPADR = readl(GPIO_PADR) | 0x2; ++ writel(uiPADR, GPIO_PADR); ++#endif ++ ++ local_irq_restore(flags); ++ return 0; ++} ++ ++int __init ep93xxfb_init(void) ++{ ++ char *option = NULL; ++ DPRINTK("ep93xxfb_init(void)\n"); ++ ++ /* ++ * For kernel boot options (in 'video=xxxfb:<options>' format) ++ */ ++ ++ fb_get_options("ep93xxfb", &option); ++ ep93xxfb_setup(option); ++ ++ /* init all the important stuff in info */ ++ if (!ep93xxfb_probe_configuration()) ++ ep93xxfb_init_fbinfo(); ++ ++ /* Allocate and map framebuffer memory in system DRAM */ ++ if (ep9312fb_map_video_memory() != 0) ++ return -ENOMEM; ++ ++ /* This has to been done !!! */ ++ fb_alloc_cmap(&info.cmap, MAX_PALETTE_NUM_ENTRIES, 0); ++ ++ /* hard code, since we don't support modedb & friends yet */ ++ ep93xxfb_set_var(&info.var, -1, &info); ++ ++ if (register_framebuffer(&info) < 0) ++ return -EINVAL; ++ ++ ep93xxfb_blank(FB_BLANK_UNBLANK, &info); ++ ++ printk(KERN_INFO "fb%d: %s frame buffer device\n", info.node, ++ info.fix.id); ++ ++ printk(KERN_INFO ++ "ep93xxfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", ++ info.fix.smem_start, info.screen_base, info.fix.smem_len / 1024); ++ printk(KERN_INFO ++ "ep93xxfb: mode is %dx%dx%d, linelength=%d, pages=%d\n", ++ ep93xxfb_var.xres, ep93xxfb_var.yres, ++ ep93xxfb_var.bits_per_pixel, info.fix.line_length, ++ screen_info.pages); ++ ++ return 0; ++} ++ ++static void __exit ep93xxfb_cleanup(void) ++{ ++ DPRINTK("ep93xxfb_cleanup(void)\n"); ++ unregister_framebuffer(&info); ++} ++ ++int __init ep93xxfb_setup(char *options) ++{ ++ DPRINTK("ep93xxfb_setup(char *options=\"%s\")\n", options); ++ /* TODO: Parse user speficied options (`video=ep93xxfb:') */ ++ return 0; ++} ++ ++module_init(ep93xxfb_init); ++module_exit(ep93xxfb_cleanup); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Michael Burian"); +diff --git a/drivers/video/ep93xxfb.h b/drivers/video/ep93xxfb.h +new file mode 100644 +index 0000000..dec4857 +--- /dev/null ++++ b/drivers/video/ep93xxfb.h +@@ -0,0 +1,287 @@ ++/* ++ * ep93xxfb.h Cirrus Logic EP93xx Framebuffer header ++ */ ++ ++/* ++ * TODO: ++ * Still lot's of messy stuff here that belongs elsewhere. ++ * ++ * I'd say that each display / display family get an own header file ++ * maybe even the whole ep93xx stuff should get an own directory, just like ati ++ * It also could not hurt to test the NTSC stuff, which already was split into cx25871.c ++ * but not tested to work so far. ++ * ++ * Display initialisation should become human readable, it should be changed ++ * to reflect what's going on in hardware. ++ * ++ * This means we should say which PLL, prescaler, divider, ... is used instead ++ * of just saying VDIV = 0x0000c207, same goes for all the other hardcoded values. ++ * ++ * How will we handle higher clocked EP93xx once they are available? ++ * ++ */ ++ ++#define RasterSetLocked(registername,value) \ ++ { \ ++ writel( 0xAA, REALITI_SWLOCK ); \ ++ writel( value, registername); \ ++ } ++ ++static void InitializeCX25871For640x480NTSC(void); ++ ++struct ep93xxfb_par { ++ struct device *dev; ++ dma_addr_t p_screen_base; ++ unsigned char *v_screen_base; ++ unsigned long screen_size; ++ unsigned int palette_size; ++ unsigned int xres; ++ unsigned int yres; ++ unsigned int bits_per_pixel; ++ signed int montype; ++ unsigned int currcon; ++ unsigned int visual; ++ u16 palette[16]; /* Funky 16 table lookup used by "optional" Parameter. */ ++}; ++ ++#define MAX_PALETTE_NUM_ENTRIES 256 ++#define MAX_CRT_XRES 640 ++#define MAX_CRT_YRES 480 ++#define MAX_BPP 32 ++#define FB_MAX_MEM_SIZE ((MAX_CRT_XRES * MAX_CRT_YRES * MAX_BPP)/8) ++#define FB_MAPPED_MEM_SIZE (PAGE_ALIGN(FB_MAX_MEM_SIZE + PAGE_SIZE)) ++ ++#define EP93XX_NAME "EP93XX" ++#define NR_MONTYPES 1 ++ ++/* Fake monspecs to fill in fbinfo structure */ ++static struct fb_monspecs monspecs __initdata = { ++ {30000, 70000, 50, 65, 0} /* Generic */ ++}; ++ ++#if defined (CONFIG_FB_LCD_EP93XX) ++#define DEFAULT_MODE 1 ++#elif defined (CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343) ++#define DEFAULT_MODE 2 ++#elif defined (CONFIG_FB_CX25871) ++#define DEFAULT_MODE 3 ++#elif defined (CONFIG_FB_CRT_EP93XX) ++#define DEFAULT_MODE 0 ++#elif defined (CONFIG_FB_LCD_EP93XX_SHARP) ++#define DEFAULT_MODE 5 ++#define CONFIG_FB_LCD_EP93XX 1 /*hack!!! FIXME: put whole display support into different files */ ++#elif defined (CONFIG_FB_LCD_TX09D50VM1CCA) ++#define DEFAULT_MODE 6 ++#else ++#error What Display Setting was that!!! ++#endif ++ ++struct DisplayTimingValues { ++ const char *Name; ++ unsigned long DisplayID; ++ int (*RasterConfigure) (struct DisplayTimingValues * pTimingValues); ++ unsigned short Refresh; ++ unsigned long VDiv; ++ ++ unsigned short HRes; ++ unsigned short HFrontPorch; ++ unsigned short HBackPorch; ++ unsigned short HSyncWidth; ++ unsigned short HTotalClocks; ++ ++ unsigned short VRes; ++ unsigned short VFrontPorch; ++ unsigned short VBackPorch; ++ unsigned short VSyncWidth; ++ unsigned short VTotalClocks; ++}; ++ ++typedef int (*fRasterConfigure) (struct DisplayTimingValues *); ++ ++enum DisplayType { ++ CRT_GENERIC, ++ Philips_LB064V02A1, ++ CX25871, ++ Sharp ++}; ++ ++static int Conexant_CX25871(struct DisplayTimingValues *pTimingValues); ++static int NecLCD(struct DisplayTimingValues *pTimingValues); ++ ++#define TIMING_VALUES(NAME, DISPID, FUNC, REFRESH, VDIV, \ ++ HRES, HFP, HBP, HSYNC, VRES, VFP, VBP, VSYNC) \ ++{ \ ++ Name:NAME, \ ++ DISPID, FUNC, REFRESH, VDIV, \ ++ HRES, HFP, HBP, HSYNC, (HRES + HFP + HBP + HSYNC), \ ++ VRES, VFP, VBP, VSYNC, (VRES + VFP + VBP + VSYNC) \ ++} ++ ++/* TODO: ++ * ++ * This is a big, confusing mess right now. ++ * We really should see if we can do it like Documentation/fb/modedb.txt ++ * suggests. ++ * ++ * Fix it, probably by moving this into ep93xx_modes.c or something like that ++ */ ++ ++static struct DisplayTimingValues TimingValues[] = { ++ /* 640x480 Progressive Scan */ ++ TIMING_VALUES("CRT_GENERIC", CRT_GENERIC, ++ (fRasterConfigure) NULL, ++ 60, 0x0000c108, 640, 16, 48, 96, 480, 11, 31, 2), ++ /* 640x480 Progressive Scan Philips LB064V02A1 on EDB9312 Board. */ ++ ++ /* Display can handle clocks from 22MHz(VDIV=0xc107)-28Mhz(VDIV=0xc106) */ ++ TIMING_VALUES("Philips LB064V02A1", Philips_LB064V02A1, ++ 0, ++ 68, 0x0000c106, 640, 16, 48, 96, 480, 11, 31, 2), ++ /*fast refresh rate (26.7MHz) */ ++ /*68, 0x0000c106, 640, 16, 48, 96, 480, 11, 31, 2), */ ++ /*original setting (slowest refresh) (22.8MHz) */ ++ /*68, 0x0000c107, 640, 16, 48, 96, 480, 11, 31, 2), */ ++ ++ /* Sharp LQ64D343 LCD Panel */ ++ TIMING_VALUES("Sharp LQ64d343", CRT_GENERIC, ++ (fRasterConfigure) NULL, ++ 60, 0x0000c205, 640, 32, 32, 96, 480, 34, 34, 4), ++ /* NEC LCD Panel */ ++ TIMING_VALUES("NEC", CRT_GENERIC, ++ NecLCD, ++ 60, 0x0000c204, 640, 32, 32, 96, 480, 34, 34, 4), ++ /* 640x480 NTSC Support for Conexant CX25871 */ ++ TIMING_VALUES("Conexant CX25871", CX25871, ++ Conexant_CX25871, ++ 60, 0x0000c317, 640, 0, 0, 0, 480, 0, 0, 0), ++ /* 320x240 Sharp LCD Panel */ ++ TIMING_VALUES("Sharp LQ057Q3DC02", CRT_GENERIC, ++ (fRasterConfigure) NULL, ++ 0, 0x0000c108, 320, 32, 32, 96, 240, 3, 3, 4), ++ /* ++ 240x320 Hitachi ++ ++ Max pixel clock freq = 1/83ns ~= 12.048 MHz (VDiv = 0x0000c10a) ++ Typ pixel clock freq = 5.33 MHz (VDiv = 0x0000c125) ++ */ ++ TIMING_VALUES("Hitachi TX09D50VM1CCA", CRT_GENERIC, ++ (fRasterConfigure)NULL, ++ 0, 0x0000c125, 240, 16/*HFP*/, 12/*HBP*/, 5/*HSYNC*/, 320, 3/*VFP*/, 3/*VBP*/, 1/*VSYNC*/), ++ /* NULL */ ++ TIMING_VALUES("Unknown", CRT_GENERIC, ++ (fRasterConfigure) NULL, ++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ++ ++}; ++ ++#define NUM_TIMING_VALUES (sizeof(TimingValues)/sizeof(struct DisplayTimingValues)) ++ ++#define NULL_MODE (NUM_TIMING_VALUES-1) ++ ++#define EE_DELAY_USEC 100 ++#define EE_READ_TIMEOUT 100 ++#define CX25871_DEV_ADDRESS 0x88 ++#define CX25871_REGx32_AUTO_CHK 0x80 ++#define CX25871_REGx32_DRVS_MASK 0x60 ++#define CX25871_REGx32_DRVS_SHIFT 5 ++#define CX25871_REGx32_SETUP_HOLD 0x10 ++#define CX25871_REGx32_INMODE_ 0x08 ++#define CX25871_REGx32_DATDLY_RE 0x04 ++#define CX25871_REGx32_OFFSET_RGB 0x02 ++#define CX25871_REGx32_CSC_SEL 0x01 ++ ++/* Register 0xBA */ ++#define CX25871_REGxBA_SRESET 0x80 ++#define CX25871_REGxBA_CHECK_STAT 0x40 ++#define CX25871_REGxBA_SLAVER 0x20 ++#define CX25871_REGxBA_DACOFF 0x10 ++#define CX25871_REGxBA_DACDISD 0x08 ++#define CX25871_REGxBA_DACDISC 0x04 ++#define CX25871_REGxBA_DACDISB 0x02 ++#define CX25871_REGxBA_DACDISA 0x01 ++ ++/* Register 0xC4 */ ++#define CX25871_REGxC4_ESTATUS_MASK 0xC0 ++#define CX25871_REGxC4_ESTATUS_SHIFT 6 ++#define CX25871_REGxC4_ECCF2 0x20 ++#define CX25871_REGxC4_ECCF1 0x10 ++#define CX25871_REGxC4_ECCGATE 0x08 ++#define CX25871_REGxC4_ECBAR 0x04 ++#define CX25871_REGxC4_DCHROMA 0x02 ++#define CX25871_REGxC4_EN_OUT 0x01 ++ ++/* Register 0xC6 */ ++#define CX25871_REGxC6_EN_BLANKO 0x80 ++#define CX25871_REGxC6_EN_DOT 0x40 ++#define CX25871_REGxC6_FIELDI 0x20 ++#define CX25871_REGxC6_VSYNCI 0x10 ++#define CX25871_REGxC6_HSYNCI 0x08 ++#define CX25871_REGxC6_INMODE_MASK 0x07 ++#define CX25871_REGxC6_INMODE_SHIFT 0 ++ ++#define GPIOG_EEDAT 2 ++#define GPIOG_EECLK 1 ++ ++static int Conexant_CX25871(struct DisplayTimingValues *pTimingValues) ++{ ++ unsigned int uiTemp; ++ InitializeCX25871For640x480NTSC(); ++ ++ RasterSetLocked(VIDEOATTRIBS, 0); ++ uiTemp = readl(SYSCON_DEVCFG); ++ SysconSetLocked(SYSCON_DEVCFG, (uiTemp | SYSCON_DEVCFG_EXVC)); ++ ++ RasterSetLocked(VLINESTOTAL, 0x0257); ++ RasterSetLocked(VSYNCSTRTSTOP, 0x01FF022C); /* was 024c */ ++ RasterSetLocked(VBLANKSTRTSTOP, 0x000001E0); ++ RasterSetLocked(VACTIVESTRTSTOP, 0x000001E0); ++ RasterSetLocked(VCLKSTRTSTOP, 0x07FF01E0); ++ ++ RasterSetLocked(HCLKSTOTAL, 0x30F); ++ RasterSetLocked(HSYNCSTRTSTOP, 0x02c0030F); ++ RasterSetLocked(HBLANKSTRTSTOP, 0x00000280); ++ RasterSetLocked(HACTIVESTRTSTOP, 0x00000280); ++ RasterSetLocked(HCLKSTRTSTOP, 0x07ff0280); ++ ++ RasterSetLocked(LINECARRY, 0); ++ ++ RasterSetLocked(VIDEOATTRIBS, ++ VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN); ++ ++ return 0; ++} ++ ++static int NecLCD(struct DisplayTimingValues *pTimingValues) ++{ ++ RasterSetLocked(VIDEOATTRIBS, 0); ++ ++ RasterSetLocked(VLINESTOTAL, 0x020c); ++ RasterSetLocked(VSYNCSTRTSTOP, 0x01fe0200); /* was 024c */ ++ RasterSetLocked(VBLANKSTRTSTOP, 0x0000000); ++ RasterSetLocked(VACTIVESTRTSTOP, 0x020c01df); ++ RasterSetLocked(VCLKSTRTSTOP, 0x020c020c); ++ ++ RasterSetLocked(HCLKSTOTAL, 0x323); ++ RasterSetLocked(HSYNCSTRTSTOP, 0x02c00321); ++ RasterSetLocked(HBLANKSTRTSTOP, 0x00000); ++ RasterSetLocked(HACTIVESTRTSTOP, 0x00100290); ++ RasterSetLocked(HCLKSTRTSTOP, 0x03230323); ++ ++ RasterSetLocked(LINECARRY, 0); ++ ++ RasterSetLocked(VIDEOATTRIBS, VIDEOATTRIBS_INVCLK | ++ VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_SYNCEN | ++ VIDEOATTRIBS_DATAEN); ++ ++ return 0; ++} ++ ++void InitializeCX25871For640x480NTSC(void) ++{ ++/* ++ * If you need this see cx25871.[ch] and grep for "should be done". ++ * see if you can find a suitable and less messy way to do i2c stuff ++ * also see our patch against 2.6.11.7-ep93xx ++ */ ++ printk("ERROR: InitializeCX25871For640x480NTSC unimplemented!\n"); ++} +diff --git a/include/asm-arm/arch-ep93xx/adssphere.h b/include/asm-arm/arch-ep93xx/adssphere.h +new file mode 100644 +index 0000000..97874c1 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/adssphere.h +@@ -0,0 +1,55 @@ ++/* ++ * linux/include/asm-arm/arch-ep93xx/adssphere.h ++ * ++ * Copyright (C) 2005 Robert Whaley <rwhaley@applieddata.net> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef ASM_ARCH_ADSSPHERE_H ++#define ASM_ARCH_ADSSPHERE_H ++ ++#define ADSSPHERE_BASE_VIRT 0xe2000000 ++#define ADSSPHERE_BASE_PHYS 0xf0000000 ++ ++#define ADSSPHERE_CR0 (ADSSPHERE_BASE_VIRT+0x00) ++#define ADSSPHERE_CR1 (ADSSPHERE_BASE_VIRT+0x04) ++#define ADSSPHERE_SR (ADSSPHERE_BASE_VIRT+0x08) ++#define ADSSPHERE_CAN_ADDR (ADSSPHERE_BASE_VIRT+0x0c) ++#define ADSSPHERE_CAN_DATA (ADSSPHERE_BASE_VIRT+0x10) ++#define ADSSPHERE_FW_FW_NUM (ADSSPHERE_BASE_VIRT+0x14) ++#define ADSSPHERE_FW_FW_REV (ADSSPHERE_BASE_VIRT+0x18) ++#define ADSSPHERE_FW_BD_REV (ADSSPHERE_BASE_VIRT+0x1c) ++ ++#define ADSSPHERE_CR0_CF_33 0x01 ++#define ADSSPHERE_CR0_CF_50 0x02 ++#define ADSSPHERE_CR0_COMEN 0x04 ++#define ADSSPHERE_CR0_IRDA 0x08 ++#define ADSSPHERE_CR0_USB 0x10 ++#define ADSSPHERE_CR0_PWSAV 0x20 ++ ++#define ADSSPHERE_CR1_PNL_ON 0x01 ++#define ADSSPHERE_CR1_PNL_EN 0x04 ++#define ADSSPHERE_CR1_BL_ON 0x08 ++#define ADSSPHERE_CR1_AMP_ON 0x10 ++#define ADSSPHERE_CR1_CDC_ON 0x20 ++#define ADSSPHERE_CR1_BTL_ON 0x40 ++ ++#define ADSSPHERE_SR1_SW0 0x01 ++#define ADSSPHERE_SR1_SW1 0x02 ++#define ADSSPHERE_SR1_SW2 0x04 ++#define ADSSPHERE_SR1_SW3 0x08 ++#define ADSSPHERE_SR1_HP 0x10 ++ ++#endif /* ASM_ARCH_ADSSPHERE_H */ +diff --git a/include/asm-arm/arch-ep93xx/clocks.h b/include/asm-arm/arch-ep93xx/clocks.h +new file mode 100644 +index 0000000..acc8023 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/clocks.h +@@ -0,0 +1,160 @@ ++/* ++ * ++ * Filename: clocks.h ++ * ++ * Description: Header file for the clocks. ++ * ++ * Copyright(c) Cirrus Logic Corporation 2003, All Rights Reserved ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License 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 <asm/hardware.h> ++#ifndef _H_CLOCKS ++#define _H_CLOCKS ++ ++/* ++ * How this file works: ++ * Choose your FCLOCK value this causes FDIV, HDIV, PDIV values to be set ++ * ++ * The Real FDIV, HDIV, and PDIV are set according to the following table. ++ * Processor runs at (PLL1 speed/PLL Divide specified by FDIV) ++ * AHB runs at (PLL1 speed/PLL Divide specified by HDIV) ++ * APB runs at AHB/(2^PDIV) ++ * ------------------------------------------------------------------ ++ * HDIV PLL Divide FDIV PLL Divide ++ * 0 1 0 1 ++ * 1 2 1 2 ++ * 2 4 2 4 ++ * 3 5 3 8 ++ * 4 6 4 16 ++ * 5 8 ++ * 6 16 ++ * 7 32 ++ * ++ */ ++ ++/* there is some confusion here about MACH vs. ARCH. clean it up ++ once we get a nice clock management system going */ ++#ifdef CONFIG_ARCH_EP9301 ++#define FCLOCK 166 ++#define EP93XX_UART_CLK 14745600 ++#endif ++ ++#ifdef CONFIG_MACH_EDB9302 ++#define FCLOCK 200 ++#define EP93XX_UART_CLK 14745600 ++#endif ++ ++#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_ADSSPHERE) ++#define FCLOCK 200 ++#define EP93XX_UART_CLK 14745600 ++#endif ++ ++#if defined(CONFIG_MACH_DMA03) ++#define FCLOCK 200 ++#define EP93XX_UART_CLK 14745600 ++#endif ++ ++#ifdef CONFIG_MACH_ACC ++#define EP93XX_UART_CLK 24576000 ++#endif ++ ++#if defined(CONFIG_MACH_ZEFEERDZA) ++#define FCLOCK 166 ++#define EP93XX_UART_CLK 14745600 ++#endif ++ ++#if defined(CONFIG_MACH_ZEFEERDZB) || defined(CONFIG_MACH_ZEFEERDZG) || \ ++ defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ) ++#define FCLOCK 200 ++#define EP93XX_UART_CLK 14745600 ++#endif ++ ++/* ++ * PLL1 Clock =442 Mhz ++ * ++ * FClock = 221 Mhz ++ * HCLock = 73 Mhz ++ * PClock = 46 Mhz ++ */ ++#if (FCLOCK == 221) ++#define FDIV 1 ++#define HDIV 5 ++#define PDIV 1 ++#define PRE_CLKSET1_VALUE 0x0080b3b6 ++#define PLL1_CLOCK 442368000 ++#endif /* (FCLOCK == 221) */ ++ ++/* ++ * PLL1 Clock =400 Mhz ++ * ++ * FClock = 200 Mhz ++ * HCLock = 100 Mhz ++ * PClock = 50 Mhz ++ * ++ */ ++#if (FCLOCK == 200) ++#define FDIV 1 ++#define HDIV 2 ++#define PDIV 1 ++#define PRE_CLKSET1_VALUE 0x0080a3d7 ++#define PLL1_CLOCK 399974400 ++#endif /* (FCLOCK == 200) */ ++ ++/* ++ * PLL1 Clock =368 Mhz ++ * ++ * FClock = 184 Mhz ++ * HCLock = 73 Mhz ++ * PClock = 46 Mhz ++ * ++ */ ++#if (FCLOCK == 183) ++#define FDIV 1 ++#define HDIV 4 ++#define PDIV 1 ++#define PRE_CLKSET1_VALUE 0x0080ab15 ++#define PLL1_CLOCK 368640000 ++#endif /* (FCLOCK == 183) */ ++ ++/* ++ * PLL1 Clock =332 Mhz ++ * ++ * FClock = 166 Mhz ++ * HCLock = 66 Mhz ++ * PClock = 33 Mhz ++ * ++ */ ++#if (FCLOCK == 166) ++#define FDIV 1 ++#define HDIV 3 ++#define PDIV 1 ++#define PRE_CLKSET1_VALUE 0x0080fa5a ++#define PLL1_CLOCK 332049067 ++#endif /* (FCLOCK == 166) */ ++ ++#define CLKSET1_VALUE ( PRE_CLKSET1_VALUE | \ ++ ( PDIV << SYSCON_CLKSET1_PCLK_DIV_SHIFT ) | \ ++ ( HDIV << SYSCON_CLKSET1_HCLK_DIV_SHIFT ) | \ ++ ( FDIV << SYSCON_CLKSET1_FCLK_DIV_SHIFT ) ) ++ ++/* ++ * Value for the PLL 2 register. ++ */ ++#define CLKSET2_VALUE 0x300dc317 ++#define PLL2_CLOCK 192000000 ++ ++#endif /* _H_CLOCKS */ +diff --git a/include/asm-arm/arch-ep93xx/crunch.h b/include/asm-arm/arch-ep93xx/crunch.h +new file mode 100644 +index 0000000..db9fb2e +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/crunch.h +@@ -0,0 +1,48 @@ ++#ifndef __asm_crunch_h__ ++#define __asm_crunch_h__ ++ ++#define CRUNCH_INIT 0x00900000 ++#define CRUNCH_IRQ 58 ++ ++#ifndef __ASSEMBLY__ ++ ++/* enable the MaverickCrunch clock */ ++static inline void crunch_enable(void) ++{ ++ int tmp, aa = 0xAA; ++ int *lock = (int *)0xe09300c0; ++ int *syscfg = (int *)0xe0930080; ++ ++ asm volatile ("str %3, [%1]\n\t" ++ "ldr %0, [%2]\n\t" ++ "orr %0, %0, #(1 << 23)\n\t" ++ "str %0, [%2]":"=r" (tmp) ++ :"r"(lock), "r"(syscfg), "r"(aa) ++ :"memory"); ++} ++ ++/* disable the MaverickCrunch clock */ ++static inline void crunch_disable(void) ++{ ++ int tmp, aa = 0xAA; ++ int *lock = (int *)0xe09300c0; ++ int *syscfg = (int *)0xe0930080; ++ ++ asm volatile ("str %3, [%1]\n\t" ++ "ldr %0, [%2]\n\t" ++ "bic %0, %0, #(1 << 23)\n\t" ++ "str %0, [%2]":"=r" (tmp) ++ :"r"(lock), "r"(syscfg), "r"(aa) ++ :"memory"); ++} ++ ++unsigned int read_dspsc_low(void); ++unsigned int read_dspsc_high(void); ++void write_dspsc(unsigned int); ++void save_fpu(struct task_struct *); ++void restore_fpu(struct task_struct *); ++int setup_crunch(void); ++void crunch_init(void); ++#endif ++ ++#endif /* __asm_crunch_h__ */ +diff --git a/include/asm-arm/arch-ep93xx/cx25871.h b/include/asm-arm/arch-ep93xx/cx25871.h +new file mode 100644 +index 0000000..9d68ed9 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/cx25871.h +@@ -0,0 +1,69 @@ ++/* ++ * Filename: cx25871.h ++ * ++ * Description: Regisister Definitions and function prototypes for ++ * CX25871 NTSC/PAL encoder. ++ * ++ * Copyright(c) Cirrus Logic Corporation 2003, All Rights Reserved ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef _H_CX25871 ++#define _H_CX25871 ++ ++/* CS25871 Device Address. */ ++#define CX25871_DEV_ADDRESS 0x88 ++ ++/* Register 0x32 */ ++#define CX25871_REGx32_AUTO_CHK 0x80 ++#define CX25871_REGx32_DRVS_MASK 0x60 ++#define CX25871_REGx32_DRVS_SHIFT 5 ++#define CX25871_REGx32_SETUP_HOLD 0x10 ++#define CX25871_REGx32_INMODE_ 0x08 ++#define CX25871_REGx32_DATDLY_RE 0x04 ++#define CX25871_REGx32_OFFSET_RGB 0x02 ++#define CX25871_REGx32_CSC_SEL 0x01 ++ ++/* Register 0xBA */ ++#define CX25871_REGxBA_SRESET 0x80 ++#define CX25871_REGxBA_CHECK_STAT 0x40 ++#define CX25871_REGxBA_SLAVER 0x20 ++#define CX25871_REGxBA_DACOFF 0x10 ++#define CX25871_REGxBA_DACDISD 0x08 ++#define CX25871_REGxBA_DACDISC 0x04 ++#define CX25871_REGxBA_DACDISB 0x02 ++#define CX25871_REGxBA_DACDISA 0x01 ++ ++/* Register 0xC4 */ ++#define CX25871_REGxC4_ESTATUS_MASK 0xC0 ++#define CX25871_REGxC4_ESTATUS_SHIFT 6 ++#define CX25871_REGxC4_ECCF2 0x20 ++#define CX25871_REGxC4_ECCF1 0x10 ++#define CX25871_REGxC4_ECCGATE 0x08 ++#define CX25871_REGxC4_ECBAR 0x04 ++#define CX25871_REGxC4_DCHROMA 0x02 ++#define CX25871_REGxC4_EN_OUT 0x01 ++ ++/* Register 0xC6 */ ++#define CX25871_REGxC6_EN_BLANKO 0x80 ++#define CX25871_REGxC6_EN_DOT 0x40 ++#define CX25871_REGxC6_FIELDI 0x20 ++#define CX25871_REGxC6_VSYNCI 0x10 ++#define CX25871_REGxC6_HSYNCI 0x08 ++#define CX25871_REGxC6_INMODE_MASK 0x07 ++#define CX25871_REGxC6_INMODE_SHIFT 0 ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/debug-macro.S b/include/asm-arm/arch-ep93xx/debug-macro.S +new file mode 100644 +index 0000000..3d97614 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/debug-macro.S +@@ -0,0 +1,56 @@ ++/* linux/include/asm-arm/arch-ep93xx/debug-macro.S ++ * ++ * Debugging macro include header ++ * ++ * Copyright (C) 1994-1999 Russell King ++ * Moved from linux/arch/arm/kernel/debug.S by Ray Lehtiniemi ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++*/ ++ ++ .macro addruart,rx ++ mrc p15, 0, \rx, c1, c0 ++ tst \rx, #1 @ MMU enabled? ++ ldreq \rx, =IO_BASE_PHYS @ System peripherals (phys address) ++ ldrne \rx, =IO_BASE_VIRT @ System peripherals (virt address) ++ orr \rx,\rx,#0x008c0000 @ Advance to UART1Base ++ ++ @ We probe for the active serial port here. ++ @ We assume r1 can be clobbered. ++ ++ @ see if UART1 is active ++ ldr r1, [\rx, #0x14] @UART1Ctrl ++ tst r1, #1 ++ ++ @ if UART1 is inactive advance to UART2 ++ addeq \rx, \rx, #0x00010000 ++ ldreq r1, [\rx, #0x14] @UART2Ctrl ++ tsteq r1, #1 ++ ++ @ if UART2 is inactive advance to UART3 ++ addeq \rx, \rx, #0x00010000 ++ ldreq r1, [\rx, #0x14] @UART3Ctrl ++ tsteq r1, #1 ++ ++ @ if all ports are inactive, then there is nothing we can do ++ moveq pc, lr ++ .endm ++ ++ .macro senduart,rd,rx ++ strb \rd, [\rx] @ UARTxData ++ .endm ++ ++ .macro waituart,rd,rx ++1001: ldr \rd, [\rx, #0x18] @ UARTxFlag ++ tst \rd, #0x20 @ TXFF = 0 when ok to transmit ++ bne 1001b ++ .endm ++ ++ .macro busyuart,rd,rx ++1001: ldr \rd, [\rx, #0x18] @ UARTxFlag ++ tst \rd, #0x08 @ BUSY = 1 while transmitting ++ bne 1001b ++ .endm +diff --git a/include/asm-arm/arch-ep93xx/dma.h b/include/asm-arm/arch-ep93xx/dma.h +new file mode 100644 +index 0000000..d3b6493 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/dma.h +@@ -0,0 +1,233 @@ ++/***************************************************************************** ++ * linux/include/asm-arm/arch-ep93xx/dma.h ++ * ++ * Copyright (C) 2003 Cirrus Logic ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ ****************************************************************************/ ++#ifndef __ASM_ARCH_DMA_H ++#define __ASM_ARCH_DMA_H ++ ++#define MAX_DMA_ADDRESS 0xffffffff ++ ++/* ++ * Not using the regular generic DMA interface for ep93xx. ++ */ ++#define MAX_DMA_CHANNELS 0 ++ ++/* ++ * The ep93xx dma controller has 5 memory to peripheral (TX) channels, 5 ++ * peripheral to memory (RX) channels and 2 memory to memory channels. ++ */ ++#define MAX_EP93XX_DMA_M2P_CHANNELS 10 ++#define MAX_EP93XX_DMA_M2M_CHANNELS 2 ++ ++/* ++ * The generic arm linux api does not support the ep93xx dma model, therefore ++ * we use a set of dma support functions written specifically for this dma ++ * controller. ++ */ ++#define MAX_EP93XX_DMA_CHANNELS (MAX_EP93XX_DMA_M2P_CHANNELS + MAX_EP93XX_DMA_M2M_CHANNELS) ++ ++/***************************************************************************** ++ * ++ * Max DMA buffer size ++ * ++ ****************************************************************************/ ++#define DMA_MAX_BUFFER_BYTES 0xFFFF ++ ++/***************************************************************************** ++ * ++ * typedefs ++ * ++ ****************************************************************************/ ++ ++/***************************************************************************** ++ * ++ * All devices which can use a DMA channel ++ * ++ * NOTE: There exist two types of DMA channels, those that transfer ++ * between an internal peripheral and memory (M2P/P2M), and ++ * those that transfer between an external peripheral and memory (M2M). ++ * This becomes a bit confusing when you take into account the fact ++ * that the M2M channels can also transfer between two specific ++ * internal peripherals and memory. ++ * The first 20 enumerated devices use the first type of channel (M2P/ ++ * P2M). The last six enumerations are specific to the M2M channels. ++ * ++ ****************************************************************************/ ++typedef enum { ++ /* ++ * Hardware device options for the 10 M2P/P2M DMA channels. ++ */ ++ DMATx_I2S1 = 0x00000000, /* TX peripheral ports can be allocated an */ ++ DMATx_I2S2 = 0x00000001, /* even numbered DMA channel. */ ++ DMATx_AAC1 = 0x00000002, ++ DMATx_AAC2 = 0x00000003, ++ DMATx_AAC3 = 0x00000004, ++ DMATx_I2S3 = 0x00000005, ++ DMATx_UART1 = 0x00000006, ++ DMATx_UART2 = 0x00000007, ++ DMATx_UART3 = 0x00000008, ++ DMATx_IRDA = 0x00000009, ++ DMARx_I2S1 = 0x0000000A, /* RX perhipheral ports can be allocated an */ ++ DMARx_I2S2 = 0x0000000B, /* odd numbered DMA channel. */ ++ DMARx_AAC1 = 0x0000000C, ++ DMARx_AAC2 = 0x0000000D, ++ DMARx_AAC3 = 0x0000000E, ++ DMARx_I2S3 = 0x0000000F, ++ DMARx_UART1 = 0x00000010, ++ DMARx_UART2 = 0x00000011, ++ DMARx_UART3 = 0x00000012, ++ DMARx_IRDA = 0x00000013, ++ ++ /* ++ * Device options for the 2 M2M DMA channels ++ */ ++ DMA_MEMORY = 0x00000014, ++ DMA_IDE = 0x00000015, ++ DMARx_SSP = 0x00000016, ++ DMATx_SSP = 0x00000017, ++ DMATx_EXT_DREQ = 0x00000018, ++ DMARx_EXT_DREQ = 0x00000019, ++ UNDEF = 0x0000001A ++} ep93xx_dma_dev_t; ++ ++/***************************************************************************** ++ * ++ * Enumerated type used as a parameter for a callback function. ++ * Indicates the type of interrupt. ++ * ++ ****************************************************************************/ ++typedef enum { ++ /* ++ * Common interrupts ++ */ ++ STALL, ++ NFB, ++ ++ /* ++ * Specific to M2P channels ++ */ ++ CHERROR, ++ ++ /* ++ * Specific to M2M channels ++ */ ++ DONE, ++ UNDEF_INT ++} ep93xx_dma_int_t; ++ ++/***************************************************************************** ++ * ++ * Init flag bit defintions for M2P/P2M flags. ++ * ++ ****************************************************************************/ ++ ++/* ++ * Channel error interrupt enable. ++ */ ++#define CHANNEL_ERROR_INT_ENABLE 0x00000001 ++/* ++ * Determines how the channel state machine behaves in the NEXT state and ++ * in receipt of a peripheral error. ++ * 0 -> NEXT -> ON (ignore the peripheral error.) ++ * 1 -> NEXT -> STALL (effectively disable the channel.) ++ */ ++#define EP93XX_DMA_ABORT 0x00000002 ++/* ++ * Ignore channel error interrupt. ++ */ ++#define IGNORE_CHANNEL_ERROR 0x00000004 ++ ++/***************************************************************************** ++ * ++ * Init flag bit defintions for M2M flags. ++ * ++ ****************************************************************************/ ++ ++/* ++ * Destination address hold. This should be set for IDE write transfers ++ */ ++#define DESTINATION_HOLD 0x0000001 ++/* ++ * Source Address hold. This should be set for IDE read transfers ++ */ ++#define SOURCE_HOLD 0x0000002 ++/* ++ * Transfer mode. ++ * 00 - s/w initiated M2M transfer ++ * 01 - h/w initiated external peripheral transfer - memory to external ++ * peripheral/IDE/SSP. ++ * 10 - h/w initiated external peripheral transfer - external ++ * peripheral/IDE/SSP to memory. ++ * 11 - not used. ++ */ ++#define TRANSFER_MODE_MASK 0x000000C ++#define TRANSFER_MODE_SHIFT 2 ++#define TRANSFER_MODE_SW 0x0000000 ++#define TRANSFER_MODE_HW_M2P 0x0000004 ++#define TRANSFER_MODE_HW_P2M 0x0000008 ++/* ++ * Peripheral wait states count. Latency in HCLK cycles needed by the ++ * peripheral to de-assert its request line once the transfer is ++ * finished. ++ * ++ * IDE Operation Wait States ++ * -------------- ------------ ++ * IDE MDMA read 0 ++ * IDE MDMA write 0 ++ * IDE UDMA read 1 ++ * IDE UDMA write 2 ++ */ ++#define WAIT_STATES_MASK 0x00007F0 ++#define WAIT_STATES_SHIFT 4 ++#define WS_IDE_MDMA_READ_WRITE 0 ++#define WS_IDE_UDMA_READ 1 ++#define WS_IDE_UDMA_WRITE 2 ++ ++/***************************************************************************** ++ * ++ * Type definition for the callback function ++ * ++ ****************************************************************************/ ++typedef void (*dma_callback) (ep93xx_dma_int_t dma_int, ++ ep93xx_dma_dev_t device, unsigned int user_data); ++ ++/***************************************************************************** ++ * ++ * API function prototypes ++ * ++ ****************************************************************************/ ++extern int ep93xx_dma_request(int *handle, const char *device_id, ++ ep93xx_dma_dev_t device); ++extern int ep93xx_dma_free(int handle); ++extern int ep93xx_dma_config(int handle, unsigned int flags_m2p, ++ unsigned int flags_m2m, ++ dma_callback callback, unsigned int user_data); ++extern int ep93xx_dma_add_buffer(int handle, unsigned int source, ++ unsigned int dest, unsigned int size, ++ unsigned int last, unsigned int buf_id); ++extern int ep93xx_dma_remove_buffer(int handle, unsigned int *buf_id); ++extern int ep93xx_dma_start(int handle, unsigned int channels, ++ unsigned int *handles); ++extern int ep93xx_dma_pause(int handle, unsigned int channels, ++ unsigned int *handles); ++extern int ep93xx_dma_flush(int handle); ++extern int ep93xx_dma_queue_full(int handle); ++extern int ep93xx_dma_get_position(int handle, unsigned int * buf_id, ++ unsigned int * total, unsigned int * current_frac); ++#endif /* _ASM_ARCH_DMA_H */ +diff --git a/include/asm-arm/arch-ep93xx/entry-macro.S b/include/asm-arm/arch-ep93xx/entry-macro.S +new file mode 100644 +index 0000000..cab811e +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/entry-macro.S +@@ -0,0 +1,39 @@ ++/* ++ * include/asm-arm/arch-ep93xx/entry-macro.S ++ * ++ * Low-level IRQ helper macros for EP93XX-based platforms ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++ .macro disable_fiq ++ .endm ++ ++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ++ ldr \irqstat, =VIC0IRQSTATUS ++ ldr \irqstat, [\irqstat, #0] @ get masked status ++ ++ mov \irqnr, #0 ++1001: tst \irqstat, #1 ++ bne 1003f ++ add \irqnr, \irqnr, #1 ++ mov \irqstat, \irqstat, lsr #1 ++ cmp \irqnr, #32 ++ bcc 1001b ++ /* EQ will be set if we reach 32 */ ++ ++ ldr \irqstat, =VIC1IRQSTATUS ++ ldr \irqstat, [\irqstat, #0] @ get masked status ++ ++1002: tst \irqstat, #1 ++ bne 1003f ++ add \irqnr, \irqnr, #1 ++ mov \irqstat, \irqstat, lsr #1 ++ cmp \irqnr, #64 ++ bcc 1002b ++ /* EQ will be set if we reach 64 */ ++ ++1003: ++ .endm +diff --git a/include/asm-arm/arch-ep93xx/hardware.h b/include/asm-arm/arch-ep93xx/hardware.h +new file mode 100644 +index 0000000..f390858 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/hardware.h +@@ -0,0 +1,60 @@ ++/* ++ * File: linux/include/asm-arm/arch-ep93xx/hardware.h ++ * ++ * Copyright (C) 2003 Cirrus Logic, Inc ++ * ++ * Copyright (C) 1999 ARM Limited. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef __ASM_ARCH_HARDWARE_H ++#define __ASM_ARCH_HARDWARE_H ++ ++#include <asm/arch/clocks.h> ++#include <asm/arch/memory.h> ++#include <asm/arch/regmap.h> ++ ++/* ++ * When adding your regs-*.h file here, please be careful to not have any ++ * macros being doubly defined. You may need to comment out a section of ++ * regmap.h to prevent that. ++ */ ++#include <asm/arch/regs_ac97.h> ++#include <asm/arch/regs_dma.h> ++#include <asm/arch/regs_gpio.h> ++#include <asm/arch/regs_ide.h> ++#include <asm/arch/regs_i2s.h> ++#include <asm/arch/regs_irda.h> ++#include <asm/arch/regs_pcmcia.h> ++#include <asm/arch/regs_raster.h> ++#include <asm/arch/regs_spi.h> ++#include <asm/arch/regs_syscon.h> ++#include <asm/arch/regs_touch.h> ++#include <asm/arch/regs_uart.h> ++ ++#include <asm/arch/regs_hardcode.h> ++ ++#include <asm/arch/cx25871.h> ++ ++/* ++ * Here's a safe way for calculating jiffies that won't break if the ++ * value of HZ changes. ++ */ ++#ifndef MSECS_TO_JIFFIES ++#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000) ++#endif ++ ++#endif /* __ASM_ARCH_HARDWARE_H */ +diff --git a/include/asm-arm/arch-ep93xx/ide.h b/include/asm-arm/arch-ep93xx/ide.h +new file mode 100644 +index 0000000..7eb7faa +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/ide.h +@@ -0,0 +1,235 @@ ++/***************************************************************************** ++ * linux/include/asm-arm/arch-ep93xx/ide.h ++ * ++ * IDE definitions for the EP93XX architecture ++ * ++ * ++ * Copyright (c) 2003 Cirrus Logic, Inc., All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ ****************************************************************************/ ++#ifndef ASM_ARCH_IDE_H ++#define ASM_ARCH_IDE_H ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <asm/hardware.h> ++#include <asm/scatterlist.h> ++ ++/* ++ * Maximum number of IDE interfaces for this architecture is 1. ++ */ ++#ifdef CONFIG_BLK_DEV_EP93XX ++#undef MAX_HWIFS ++#define MAX_HWIFS 1 ++#endif ++/* ++ * Default PIO mode used for setting up DMA commands ++ */ ++#define DEFAULT_PIO_MODE 4 ++ ++/* ++ * ATA Command Register addresses. ++ */ ++ ++#define DATAREGISTER 0x00 ++#define ERRORREGISTER 0x01 ++#define FEATURESREGISTER 0x01 ++#define SECTORCOUNTREGISTER 0x02 ++#define SECTORNUMBERREGISTER 0x03 ++#define CYLINDERLOWREGISTER 0x04 ++#define CYLINDERHIGHREGISTER 0x05 ++#define DEVICEHEADREGISTER 0x06 ++#define COMMANDREGISTER 0x07 ++#define STATUSREGISTER 0x07 ++ ++/* ++ * ATA Control Register addresses. ++ */ ++#define DEVICECONTROLREGISTER 0x06 ++#define ALTERNATESTATUSREGISTER 0x06 ++ ++/* ++ * ATA Register Bit Masks ++ */ ++#define ATASRST 0x04 ++#define ATAnIEN 0x02 ++#define ATADEV 0x10 ++#define ATAABRT 0x04 ++#define ATABSY 0x80 ++#define ATADRDY 0x40 ++#define ATADRQ 0x08 ++#define ATAERR 0x01 ++#define ATADEVFAULT 0x20 ++#define ATAWRITEFAULT 0x20 ++#define ATASERVICE 0x10 ++#define ATACORRECTED 0x04 ++#define ATAINDEX 0x02 ++ ++#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX ++ ++#define EP93XX_DMA_TODEVICE 1 ++#define EP93XX_DMA_FROMDEVICE 2 ++ ++/**************************************************************************** ++ * ++ * Map a set of buffers described by scatterlist in streaming ++ * mode for DMA. This is the scather-gather version of the ++ * above pci_map_single interface. Here the scatter gather list ++ * elements are each tagged with the appropriate dma address ++ * and length. They are obtained via sg_dma_{address,length}(SG). ++ * ++ * NOTE: An implementation may be able to use a smaller number of ++ * DMA address/length pairs than there are SG table elements. ++ * (for example via virtual mapping capabilities) ++ * The routine returns the number of addr/length pairs actually ++ * used, at most nents. ++ * ++ * Device ownership issues as mentioned above for pci_map_single are ++ * the same here. ++ * ++ ****************************************************************************/ ++static inline int ++ep93xx_map_sg(struct scatterlist *sg, unsigned int entries, ++ unsigned int direction) ++{ ++ unsigned int loop; ++ ++ for (loop = 0; loop < entries; loop++, sg++) { ++ consistent_sync(sg->__address, sg->length, direction); ++ sg->dma_address = virt_to_bus(sg->__address); ++ } ++ ++ return entries; ++} ++ ++#endif /* CONFIG_BLK_DEV_IDEDMA_EP93XX */ ++ ++/***************************************************************************** ++ * ++ * Set up a hw structure for a specified data port, control port and IRQ. ++ * This should follow whatever the default interface uses. ++ * ++ ****************************************************************************/ ++static __inline__ void ++old_ide_init_hwif_ports(hw_regs_t * hw, int data_port, int ctrl_port, int *irq) ++{ ++ unsigned long reg; ++ int i; ++ printk("ide_init_hwif_ports\n"); ++ printk("ide_init_hwif_ports(hw=%p data_port=%08x, ctrl_port=%08x \n", ++ hw, data_port, ctrl_port); ++ ++ /* ++ * Set up the IDE interface for PIO transfers, using the default PIO ++ * mode. ++ */ ++ ep93xx_ide_regs->IDECFG.Field.PIO = 1; ++ ep93xx_ide_regs->IDECFG.Field.MODE = DEFAULT_PIO_MODE; ++ ep93xx_ide_regs->IDECFG.Field.WST = 0; ++ ++ /* ++ * Enable the IDE interface. ++ */ ++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 1; ++ ++ /* ++ * Set up the ide device command register offsets in the io_port array. ++ * This offset includes the register offset and the bit settings for ++ * CS0n and CS1n. ++ */ ++ reg = (unsigned long)data_port; ++ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { ++ hw->io_ports[i] = (reg << 2) + 2; ++ reg += 1; ++ ++ printk(" io_ports: %08lx\n", hw->io_ports[i]); ++ } ++ ++ /* ++ * Set up the register offset for the device control registers. ++ * This offset includes the register offset and the bit settings for ++ * CS0n and CS1n. ++ */ ++ reg = (unsigned long)ctrl_port; ++ hw->io_ports[IDE_CONTROL_OFFSET] = (reg << 2) + 1; ++ printk("-io_ports: %08lx\n", hw->io_ports[IDE_CONTROL_OFFSET]); ++ ++ if (irq) ++ *irq = 0; ++ ++} ++ ++extern void ep93xx_ide_init(struct hwif_s *hwif); ++ ++/***************************************************************************** ++ * ++ * This registers the standard ports for this architecture with the IDE ++ * driver. ++ * ++ ****************************************************************************/ ++static __inline__ void old_ide_init_default_hwifs(void) ++{ ++ hw_regs_t hw; ++ ++ struct hwif_s *hwif; ++ unsigned int uiTemp; ++ ++ /* ++ * Make sure the GPIO on IDE bits in the DEVCFG register are not set. ++ */ ++ uiTemp = ++ readl(SYSCON_DEVCFG) & ~(SYSCON_DEVCFG_EonIDE | ++ SYSCON_DEVCFG_GonIDE | ++ SYSCON_DEVCFG_HonIDE); ++ ++ SysconSetLocked(SYSCON_DEVCFG, uiTemp); ++ ++ /* ++ * Initialize the IDE interface ++ */ ++ old_ide_init_hwif_ports(&hw, DATAREGISTER, DEVICECONTROLREGISTER, NULL); ++ ++ /* ++ * Get the interrupt. ++ */ ++ hw.irq = IRQ_EIDE; ++ ++ /* ++ * This is the dma channel number assigned to this IDE interface. Until ++ * dma is enabled for this interface, we set it to NO_DMA. ++ */ ++ hw.dma = NO_DMA; ++ ++ /* ++ * Kernels > 2.6.15-rcX crash when leaving this uninitialized ++ */ ++ hw.dev = NULL; ++ ++ /* ++ * Register the IDE interface, an ide_hwif_t pointer is passed in, ++ * which will get filled in with the hwif pointer for this interface. ++ */ ++ ide_register_hw(&hw, &hwif); ++ ++ /* ++ * Set up a pointer to the ep93xx ideproc function. ++ */ ++ ep93xx_ide_init(hwif); ++ ++ printk ++ ("Cirrus Logic EP93XX IDE initialization - driver version 1.0, 5/21/03. \n"); ++} ++#endif /* ASM_ARCH_IDE_H */ +diff --git a/include/asm-arm/arch-ep93xx/io.h b/include/asm-arm/arch-ep93xx/io.h +new file mode 100644 +index 0000000..7e2e087 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/io.h +@@ -0,0 +1,29 @@ ++/* ++ * File: linux/include/asm-arm/arch-ep93xx/io.h ++ * ++ * Copyright (C) 1999 ARM Limited ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef __ASM_ARM_ARCH_IO_H ++#define __ASM_ARM_ARCH_IO_H ++ ++#define IO_SPACE_LIMIT 0xffffffff ++ ++#define __io(a) ((void __iomem *)(a)) ++#define __mem_pci(a) (a) ++#define __mem_isa(a) (a) ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h +new file mode 100644 +index 0000000..7a58d27 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/irqs.h +@@ -0,0 +1,150 @@ ++/* ++ * File: linux/include/asm-arm/arch-ep93xx/irqs.h ++ * ++ * 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 ++ */ ++ ++/* ++ * Linux IRQ interrupts definitions here. ++ * TBD not worth the effort to put duplicate bit defines in platform.h ++ * ++ * Current IRQ implementation ++ * ++ * 1. Current implementation does not support vectored ++ * interrupts. support for this feature may be ++ * added later. ++ * 2. FIQs are ignored. None are assigned. ++ * 3. All interrupts are assigned to IRQs. ++ * 5. IRQ numbers are same as interrupt bit numbers. ++ * ++ */ ++ ++/* First two interrupt bit assignments are unused. */ ++#define IRQ_RFU0 0 ++#define IRQ_RFU1 1 ++ ++#define IRQ_COMMRX 2 ++#define IRQ_COMMTX 3 ++ ++/* Renamed TCXOI to TIMERX for consistency */ ++#define IRQ_TIMER1 4 ++#define IRQ_TIMER2 5 ++ ++#define IRQ_AAC 6 ++ ++#define IRQ_DMAM2P0 7 ++#define IRQ_DMAM2P1 8 ++#define IRQ_DMAM2P2 9 ++#define IRQ_DMAM2P3 10 ++#define IRQ_DMAM2P4 11 ++#define IRQ_DMAM2P5 12 ++#define IRQ_DMAM2P6 13 ++#define IRQ_DMAM2P7 14 ++#define IRQ_DMAM2P8 15 ++#define IRQ_DMAM2P9 16 ++ ++#define IRQ_DMAM2M0 17 ++#define IRQ_DMAM2M1 18 ++ ++#define IRQ_GPIO0 19 ++#define IRQ_GPIO1 20 ++#define IRQ_GPIO2 21 ++#define IRQ_GPIO3 22 ++ ++#define IRQ_UARTRX1 23 ++#define IRQ_UARTTX1 24 ++#define IRQ_UARTRX2 25 ++#define IRQ_UARTTX2 26 ++#define IRQ_UARTRX3 27 ++#define IRQ_UARTTX3 28 ++ ++#define IRQ_KEY 29 ++#define IRQ_TOUCH 30 ++#define IRQ_GRAPHICS 31 ++ ++/* TODO - this was IRQ_INTX, may need to make changes in code */ ++#define IRQ_EXT0 32 ++#define IRQ_EXT1 33 ++#define IRQ_EXT2 34 ++ ++#define IRQ_64HZ 35 ++#define IRQ_WEINT 36 ++#define IRQ_RTC 37 ++ ++#define IRQ_IRDA 38 ++#define IRQ_MAC 39 ++ ++#define IRQ_EXT3 40 ++#define IRQ_EIDE IRQ_EXT3 ++ ++#define IRQ_PROG 41 ++#define IRQ_1HZ 42 ++#define IRQ_VSYNC 43 ++#define IRQ_VIDEOFIFO 44 ++ ++#define IRQ_SSPRX 45 ++#define IRQ_SSPTX 46 ++ ++#define IRQ_GPIO4 47 ++ ++#define IRQ_GPIO5 48 ++#define IRQ_GPIO6 49 ++#define IRQ_GPIO7 50 ++ ++#define IRQ_TIMER3 51 ++ ++#define IRQ_UART1 52 ++#define IRQ_SSP 53 ++ ++#define IRQ_UART2 54 ++#define IRQ_UART3 55 ++ ++#define IRQ_USH 56 ++#define IRQ_PME 57 ++#define IRQ_DSP 58 ++#define IRQ_GPIO 59 ++ ++#define IRQ_RFU60 60 ++#define IRQ_RFU61 61 ++#define IRQ_RFU62 62 ++#define IRQ_RFU63 63 ++ ++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ ++#define IRQ_TO_BIT(irq) (1 << ((irq - NR_GLBL_IRQS) % 16)) ++ ++#define NR_GLBL_IRQS 64 ++ ++#define GPIO_IRQ0 64 ++#define GPIO_IRQ1 65 ++#define GPIO_IRQ2 66 ++#define GPIO_IRQ3 67 ++#define GPIO_IRQ4 68 ++#define GPIO_IRQ5 69 ++#define GPIO_IRQ6 70 ++#define GPIO_IRQ7 71 ++#define GPIO_IRQ8 72 ++#define GPIO_IRQ9 73 ++#define GPIO_IRQ10 74 ++#define GPIO_IRQ11 75 ++#define GPIO_IRQ12 76 ++#define GPIO_IRQ13 77 ++#define GPIO_IRQ14 78 ++#define GPIO_IRQ15 79 ++ ++#define IRQ_CHAINED_GPIO(x) (NR_GLBL_IRQS + x) ++#define NR_IRQS IRQ_CHAINED_GPIO(16) /* with GPIO IRQs EP9315 has 80 IRQs */ ++#else ++#define NR_IRQS 64 /* without GPIO IRQs EP9315 has 64 IRQs */ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/keyboard.h b/include/asm-arm/arch-ep93xx/keyboard.h +new file mode 100644 +index 0000000..685ff17 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/keyboard.h +@@ -0,0 +1,54 @@ ++/* ++ * linux/include/asm-arm/arch-integrator/keyboard.h ++ * ++ * Copyright (C) 2000-2001 Deep Blue Solutions Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * 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 ++ * ++ * Keyboard driver definitions for the Integrator architecture ++ */ ++#include <asm/irq.h> ++ ++/* Scancode mapping is as follows: ++ * ++ * Scancode = keycode if key down event ++ * Scancode = keycode|KBUP if key up event ++ * ++ * Valid keycodes are 1..0x7F and are defined by the table ++ * in keymap_dave.map. Keycode 0 is reserved to mean invalid. ++ * ++ * Keycodes are computed from scanned key matrix as follows: ++ */ ++ ++#define KEYCODE( row, col) ( ((row)<<4) + (col) + 1) ++#define KBUP 0x80 ++#define NR_SCANCODES 128 /*TBD used? */ ++ ++#ifdef CONFIG_EP93XX_KBD_SCANNED ++void __init ep93xx_scan_kbd_hw_init(void); ++#define kbd_init_hw() ep93xx_scan_kbd_hw_init() ++#elif defined CONFIG_EP93XX_KBD_SPI ++void __init EP93XXSpiKbdInit(void); ++#define kbd_init_hw() EP93XXSpiKbdInit() ++#elif defined CONFIG_EP93XX_KBD_USB ++void __init EP93XXUSBKbdInit(void); ++#define kbd_init_hw() EP93XXUSBKbdInit() ++#endif ++ ++#ifdef kbd_sysrq_xlate ++#undef kbd_sysrq_xlate ++#define kbd_sysrq_xlate (1) ++#endif ++#define kbd_disable_irq() disable_irq( IRQ_KEY) ++#define kbd_enable_irq() enable_irq( IRQ_KEY) +diff --git a/include/asm-arm/arch-ep93xx/mach-edb9302.h b/include/asm-arm/arch-ep93xx/mach-edb9302.h +new file mode 100644 +index 0000000..829883a +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/mach-edb9302.h +@@ -0,0 +1,20 @@ ++/* ++ * linux/include/asm-arm/arch-ep93xx/mach-edb9302.h ++ * ++ * Copyright 2004 Ray Lehtiniemi ++ * Copyright 2004 Siconix, 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. ++ */ ++#ifndef __ASM_ARCH_MACHEDB9302_H ++#define __ASM_ARCH_MACHEDB9302_H ++ ++#include <asm/arch/ssp2.h> ++ ++extern struct ep93xx_ssp_slave ep93xx_ssp_flash; ++extern struct ep93xx_ssp_slave ep93xx_ssp_codec; ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/mach-ttml.h b/include/asm-arm/arch-ep93xx/mach-ttml.h +new file mode 100644 +index 0000000..665873d +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/mach-ttml.h +@@ -0,0 +1,23 @@ ++/* ++ * linux/include/asm-arm/arch-ep93xx/mach-ttml.h ++ * ++ * Copyright 2004 Ray Lehtiniemi ++ * Copyright 2004 Siconix, 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. ++ */ ++#ifndef __ASM_ARCH_MACHTTML_H ++#define __ASM_ARCH_MACHTTML_H ++ ++#include <asm/arch/ssp2.h> ++ ++extern struct ep93xx_ssp_slave ep93xx_ssp_micro; ++extern struct ep93xx_ssp_slave ep93xx_ssp_expansion; ++ ++extern int ssp_do_ttml(struct ep93xx_ssp_slave *s, void *tx, int tlen, void *rx, ++ int rlen); ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/memory.h b/include/asm-arm/arch-ep93xx/memory.h +new file mode 100644 +index 0000000..57e266e +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/memory.h +@@ -0,0 +1,256 @@ ++/* ++ * linux/include/asm-arm/arch-ep93xx/memory.h ++ * ++ * ****************************************************** ++ * * CONFUSED? Read Documentation/IO-mapping.txt * ++ * ****************************************************** ++ * ++ * ++ * Copyright (C) 1999 ARM Limited ++ * Copyright (C) 2002-2003 Cirrus Logic Corp. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef __ASM_ARCH_MMU_H ++#define __ASM_ARCH_MMU_H ++ ++/* ++ * For EP93xx, SDRAM can be discontiguous, in a set number of blocks ++ * of equal size and (usually) equal spacing. The 9301 spacing isn't equal. ++ * ++ * SDRAM_START is the physical address of the start of SDRAM. ++ * SDRAM_NUMBER_OF_BLOCKS = # of blocks of SDRAM. ++ * Each block is of size SDRAM_BLOCK_SIZE and starts at a boundary ++ * of SDRAM_BLOCK_START_BOUNDARY. ++ * ++ * So memory blocks are at: ++ * SDRAM_START ++ * SDRAM_START + SDRAM_BLOCK_START_BOUNDARY ++ * SDRAM_START + (SDRAM_BLOCK_START_BOUNDARY * 2) ++ * SDRAM_START + (SDRAM_BLOCK_START_BOUNDARY * 3) ++ * so on ++ */ ++ ++#ifndef CONFIG_DISCONTIGMEM ++ ++/* ++ * Single 32Meg block of physical memory physically located at 0 . ++ */ ++#define SDRAM_START 0x00000000 ++#define SDRAM_NUMBER_OF_BLOCKS 1 ++#define SDRAM_BLOCK_SIZE 0x02000000 ++#define SDRAM_BLOCK_START_BOUNDARY 0x00000000 ++ ++#else /* CONFIG_DISCONTIGMEM */ ++ ++#if defined(CONFIG_MACH_EDB9301) ++/* ++ * 4 8Meg blocks at 0x0n000000, n={0145} ++ */ ++#define SDRAM_START 0x00000000 ++#define SDRAM_NUMBER_OF_BLOCKS 4 ++#define SDRAM_BLOCK_SIZE 0x00800000 ++#define SDRAM_BLOCK_START_BOUNDARY 0x01000000 ++#endif ++ ++#if defined(CONFIG_MACH_TTML) ++#define SDRAM_START 0x00000000 ++#define SDRAM_NUMBER_OF_BLOCKS 1 ++#define SDRAM_BLOCK_SIZE 0x02000000 ++#define SDRAM_BLOCK_START_BOUNDARY 0x02000000 ++#endif ++ ++#if defined(CONFIG_MACH_EDB9302) ++/* ++ * 4 8Meg blocks at 0x0n000000, n={0145} ++ */ ++#define SDRAM_START 0x00000000 ++#define SDRAM_NUMBER_OF_BLOCKS 4 ++#define SDRAM_BLOCK_SIZE 0x00800000 ++#define SDRAM_BLOCK_START_BOUNDARY 0x01000000 ++#endif ++ ++#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_ADSSPHERE) ++/* ++ * 2 32Meg blocks that are located physically at 0 and 64Meg. ++ */ ++#define SDRAM_START 0x00000000 ++#define SDRAM_NUMBER_OF_BLOCKS 2 ++#define SDRAM_BLOCK_SIZE 0x02000000 ++#define SDRAM_BLOCK_START_BOUNDARY 0x04000000 ++#endif ++ ++#if defined(CONFIG_MACH_DMA03) ++/* ++ * 2 32Meg blocks that are located physically at 0 and 64Meg. ++ */ ++#define SDRAM_START 0x00000000 ++#define SDRAM_NUMBER_OF_BLOCKS 2 ++#define SDRAM_BLOCK_SIZE 0x02000000 ++#define SDRAM_BLOCK_START_BOUNDARY 0x04000000 ++#endif ++ ++#if defined(CONFIG_MACH_ACC) ++/* ++ * 8 8Meg blocks that are located physically at 0xC0000000 ++ * total 64Meg. ++ */ ++#define SDRAM_START 0xC0000000 ++#define SDRAM_NUMBER_OF_BLOCKS 8 ++#define SDRAM_BLOCK_SIZE 0x00800000 ++#define SDRAM_BLOCK_START_BOUNDARY 0x01000000 ++#endif ++ ++#if defined(CONFIG_MACH_ZEFEERDZB) ++/* ++ * 2 8Meg blocks ++ */ ++#define SDRAM_START 0xD0000000 ++#define SDRAM_NUMBER_OF_BLOCKS 2 ++#define SDRAM_BLOCK_SIZE 0x00800000 ++#define SDRAM_BLOCK_START_BOUNDARY 0x01000000 ++#endif ++ ++#if defined(CONFIG_MACH_ZEFEERDZQ) ++/* ++ * 2 32Meg blocks ++ */ ++#define SDRAM_START 0xD0000000 ++#define SDRAM_NUMBER_OF_BLOCKS 2 ++#define SDRAM_BLOCK_SIZE 0x02000000 ++#define SDRAM_BLOCK_START_BOUNDARY 0x04000000 ++#endif ++ ++/* ++ * Here we are assuming EP93xx is configured to have two 32MB SDRAM ++ * areas with 32MB of empty space between them. So use 24 for the node ++ * max shift to get 64MB node sizes. ++ */ ++#define NODE_MAX_MEM_SHIFT 26 ++#define NODE_MAX_MEM_SIZE (1<<NODE_MAX_MEM_SHIFT) ++ ++#endif /* CONFIG_DISCONTIGMEM */ ++ ++/* ++ * MEM_SIZE and PHYS_OFFSET are used to set size of SDRAM for ++ * initial page table in arch/arm/kernel/setup.c ++ * For ep93xx, PHYS_OFFSET is set to be SDRAM_START. ++ */ ++#define MEM_SIZE (SDRAM_BLOCK_SIZE) ++ ++/* ++ * If memory is not discontiguous, this is #defined in ++ * arch/arm/mm/init.c to be 1. ++ */ ++#ifdef CONFIG_DISCONTIGMEM ++#define NR_NODES (SDRAM_NUMBER_OF_BLOCKS) ++#endif ++ ++/* ++ * Where to load the ramdisk (virtual address, not physical) and how ++ * big to make it. (used in arch/arm/kernel/setup.c ++ * In both cases, when redboot loads the ramdisk image to 0x01000000, ++ * the processor will find it because the linux map is funny. ++ */ ++#ifdef CONFIG_ARCH_EP9301 ++#define RAMDISK_START_VIRT (0xC4000000) ++#else ++#define RAMDISK_START_VIRT (0xC1000000) ++#endif ++ ++/* ++ * The ramdisk size comes from a make menuconfig option. ++ */ ++#define RAMDISK_SIZE ((CONFIG_BLK_DEV_RAM_SIZE)<<10) ++ ++/* ++ * Task size: 2GB (from 0 to base of IO in virtual space) ++ */ ++#define TASK_SIZE UL(0x7f000000) ++ ++/* ++ * This decides where the kernel will search for a free chunk of vm ++ * space during mmap's. ++ */ ++#define TASK_UNMAPPED_BASE (0x40000000) ++ ++/* ++ * Page offset: 3GB (start of kernel memory in virtual space) ++ * Phys offset: 0 (start of kernel memory in physical space) ++ */ ++#define PAGE_OFFSET UL(0xC0000000) ++#define PHYS_OFFSET (SDRAM_START) ++ ++/* ++ * We take advantage of the fact that physical and virtual address can be the ++ * same. The NUMA code is handling the large holes that might exist between ++ * all memory banks. ++ */ ++#define __virt_to_phys__is_a_macro ++#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET) ++ ++#define __phys_to_virt__is_a_macro ++#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_OFFSET) ++ ++/* ++ * Virtual view <-> DMA view memory address translations ++ * virt_to_bus: Used to translate the virtual address to an ++ * address suitable to be passed to set_dma_addr ++ * bus_to_virt: Used to convert an address for DMA operations ++ * to an address that the kernel can use. ++ */ ++#define __virt_to_bus__is_a_macro ++#define __virt_to_bus(x) __virt_to_phys(x) ++ ++#define __bus_to_virt__is_a_macro ++#define __bus_to_virt(x) __phys_to_virt(x) ++ ++/* ++ * Note that this file is included by include/asm-arm/memory.h so ++ * the macros in this file have to play nice with those. ++ */ ++#ifdef CONFIG_DISCONTIGMEM ++ ++/* ++ * Given a kernel address, find the home node of the underlying memory. ++ */ ++#define KVADDR_TO_NID(addr) \ ++ (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT) ++ ++/* ++ * Given a page frame number, convert it to a node id. ++ */ ++#define PFN_TO_NID(pfn) \ ++ (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT)) ++ ++/* ++ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory ++ * and returns the mem_map of that node. ++ */ ++#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr))) ++ ++#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn)) ++ ++/* ++ * Given a kaddr, LOCAL_MAR_NR finds the owning node of the memory ++ * and returns the index corresponding to the appropriate page in the ++ * node's mem_map. ++ */ ++#define LOCAL_MAP_NR(kaddr) \ ++ (((unsigned long)(kaddr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT) ++ ++#endif /* CONFIG_DISCONTIGMEM */ ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/param.h b/include/asm-arm/arch-ep93xx/param.h +new file mode 100644 +index 0000000..525face +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/param.h +@@ -0,0 +1,21 @@ ++/* ++ * linux/include/asm-arm/arch-integrator/param.h ++ * ++ * Copyright (C) 1999 ARM Limited ++ * ++ * 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 ++ */ ++ ++/* #define HZ 100 */ +diff --git a/include/asm-arm/arch-ep93xx/platform.h b/include/asm-arm/arch-ep93xx/platform.h +new file mode 100644 +index 0000000..d92833d +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/platform.h +@@ -0,0 +1,43 @@ ++/* ++ * linux/include/asm-arm/arch-ep93xx/platform.h ++ * ++ * Copyright (C) 2002-2003 Cirrus Logic, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef ASM_ARCH_PLATFORM_H ++#define ASM_ARCH_PLATFORM_H ++ ++/* ++ * Timer definitions ++ * ++ * Use timers 1, 2, and 3. Do not use timer 4. ++ * Timers run at 508 kHz. ++ */ ++ ++/* ++ * These are useconds NOT ticks. ++ */ ++#define mSEC_1 1000 ++#define mSEC_5 (mSEC_1 * 5) ++#define mSEC_10 (mSEC_1 * 10) ++#define mSEC_25 (mSEC_1 * 25) ++#define SEC_1 (mSEC_1 * 1000) ++ ++#ifndef __ASSEMBLY__ ++extern struct sys_timer ep93xx_timer; ++#endif ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/regmap.h b/include/asm-arm/arch-ep93xx/regmap.h +new file mode 100644 +index 0000000..7b3eeac +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regmap.h +@@ -0,0 +1,1125 @@ ++/* ++ * File: linux/include/asm-arm/arch-ep93xx/regmap.h ++ * ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * Copyright (C) 2003 Cirrus Logic, Inc ++ * Copyright (C) 1999 ARM Limited. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef __ASM_ARCH_REGMAP_H ++#define __ASM_ARCH_REGMAP_H ++ ++/* ++ * Here's the rules: ++ * - EP93xx register addresses in regmap.h are physical addresses. ++ * ++ * - io_p2v translates a physical address to a virtual one for the ++ * EP93xx's register space only. Don't use it for actual memory. ++ * ++ */ ++ ++#define IO_BASE_VIRT 0xE0000000 /* Virtual address of IO */ ++#define IO_BASE_PHYS 0x80000000 /* Physical address of IO */ ++ ++/* ++ * The HW_REG macro assumes that the param is a virtual address ++ */ ++#define HW_REG(reg) ((unsigned int volatile *)reg) ++ ++/* ++ * Macro to get at IO space when running virtually. ++ * (Translates a physical address to a virtual address) ++ * First cast the pa to an unsigned int in case we are using this ++ * on a macro that is already cast as a pointer. ++ */ ++ ++#define io_p2v(x) ((x) - (IO_BASE_PHYS - IO_BASE_VIRT)) ++#define io_v2p(x) ((x) - (IO_BASE_VIRT - IO_BASE_PHYS)) ++ ++/******************************************************************/ ++/* EP93xx Memory Map and Register list */ ++/******************************************************************/ ++/* */ ++/* 0000_0000 - 0000_ffff: Internal ROM/nSDCE3/nCS0 */ ++/* 0001_0000 - 0fff_ffff: nSDCE3/nCS0 */ ++/* 1000_0000 - 1fff_ffff: nCS1 */ ++/* 2000_0000 - 2fff_ffff: nCS2 */ ++/* 3000_0000 - 3fff_ffff: nCS3 */ ++/* 4000_0000 - 4fff_ffff: Reserved */ ++/* 5000_0000 - 5fff_ffff: Reserved */ ++/* 6000_0000 - 6fff_ffff: nCS6 */ ++/* 7000_0000 - 7fff_ffff: nCS7 */ ++/* 8000_0000 - 800f_ffff: AHB Registers */ ++/* 8010_0000 - 807f_ffff: Reserved */ ++/* 8080_0000 - 8fff_ffff: APB Registers */ ++/* 9000_0000 - bfff_ffff: Not Used */ ++/* c000_0000 - cfff_ffff: nSDCE0 */ ++/* d000_0000 - dfff_ffff: nSDCE1 */ ++/* e000_0000 - efff_ffff: nSDCE2 */ ++/* f000_0000 - ffff_ffff: nCS0/nSDCE3 */ ++/* */ ++/******************************************************************/ ++ ++/******************************************************************/ ++/* EP93xx AHB Blocks */ ++/******************************************************************/ ++/* */ ++/* Start End Usage */ ++/* 8000_0000 8000_FFFF: DMA */ ++/* 8001_0000 8001_FFFF: Ethernet MAC */ ++/* 8002_0000 8002_FFFF: USB Host */ ++/* 8003_0000 8003_FFFF: Raster */ ++/* 8004_0000 8004_FFFF: Reserved */ ++/* 8005_0000 8005_FFFF: Reserved */ ++/* 8006_0000 8006_FFFF: SDRAM */ ++/* 8007_0000 8007_FFFF: Reserved */ ++/* 8008_0000 8008_FFFF: SMC */ ++/* 8009_0000 8009_FFFF: Boot ROM physical address */ ++/* 800A_0000 800A_FFFF: IDE */ ++/* 800B_0000 800B_FFFF: VIC1 */ ++/* 800C_0000 800C_FFFF: VIC2 */ ++/* 800D_0000 800F_FFFF: Reserved */ ++/* */ ++/******************************************************************/ ++ ++#define EP93XX_AHB_BASE (IO_BASE_VIRT) ++ ++/* 8000_0000 - 8000_ffff: DMA */ ++#define DMA_OFFSET 0x000000 ++#define DMA_BASE (EP93XX_AHB_BASE|DMA_OFFSET) ++#define DMAMP_TX_0_CONTROL (DMA_BASE+0x0000) ++#define DMAMP_TX_0_INTERRUPT (DMA_BASE+0x0004) ++#define DMAMP_TX_0_PPALLOC (DMA_BASE+0x0008) ++#define DMAMP_TX_0_STATUS (DMA_BASE+0x000C) ++#define DMAMP_TX_0_REMAIN (DMA_BASE+0x0014) ++#define DMAMP_TX_0_MAXCNT0 (DMA_BASE+0x0020) ++#define DMAMP_TX_0_BASE0 (DMA_BASE+0x0024) ++#define DMAMP_TX_0_CURRENT0 (DMA_BASE+0x0028) ++#define DMAMP_TX_0_MAXCNT1 (DMA_BASE+0x0030) ++#define DMAMP_TX_0_BASE1 (DMA_BASE+0x0034) ++#define DMAMP_TX_0_CURRENT1 (DMA_BASE+0x0038) ++ ++#define DMAMP_RX_1_CONTROL (DMA_BASE+0x0040) ++#define DMAMP_RX_1_INTERRUPT (DMA_BASE+0x0044) ++#define DMAMP_RX_1_PPALLOC (DMA_BASE+0x0048) ++#define DMAMP_RX_1_STATUS (DMA_BASE+0x004C) ++#define DMAMP_RX_1_REMAIN (DMA_BASE+0x0054) ++#define DMAMP_RX_1_MAXCNT0 (DMA_BASE+0x0060) ++#define DMAMP_RX_1_BASE0 (DMA_BASE+0x0064) ++#define DMAMP_RX_1_CURRENT0 (DMA_BASE+0x0068) ++#define DMAMP_RX_1_MAXCNT1 (DMA_BASE+0x0070) ++#define DMAMP_RX_1_BASE1 (DMA_BASE+0x0074) ++#define DMAMP_RX_1_CURRENT1 (DMA_BASE+0x0078) ++ ++#define DMAMP_TX_2_CONTROL (DMA_BASE+0x0080) ++#define DMAMP_TX_2_INTERRUPT (DMA_BASE+0x0084) ++#define DMAMP_TX_2_PPALLOC (DMA_BASE+0x0088) ++#define DMAMP_TX_2_STATUS (DMA_BASE+0x008C) ++#define DMAMP_TX_2_REMAIN (DMA_BASE+0x0094) ++#define DMAMP_TX_2_MAXCNT0 (DMA_BASE+0x00A0) ++#define DMAMP_TX_2_BASE0 (DMA_BASE+0x00A4) ++#define DMAMP_TX_2_CURRENT0 (DMA_BASE+0x00A8) ++#define DMAMP_TX_2_MAXCNT1 (DMA_BASE+0x00B0) ++#define DMAMP_TX_2_BASE1 (DMA_BASE+0x00B4) ++#define DMAMP_TX_2_CURRENT1 (DMA_BASE+0x00B8) ++ ++#define DMAMP_RX_3_CONTROL (DMA_BASE+0x00C0) ++#define DMAMP_RX_3_INTERRUPT (DMA_BASE+0x00C4) ++#define DMAMP_RX_3_PPALLOC (DMA_BASE+0x00C8) ++#define DMAMP_RX_3_STATUS (DMA_BASE+0x00CC) ++#define DMAMP_RX_3_REMAIN (DMA_BASE+0x00D4) ++#define DMAMP_RX_3_MAXCNT0 (DMA_BASE+0x00E0) ++#define DMAMP_RX_3_BASE0 (DMA_BASE+0x00E4) ++#define DMAMP_RX_3_CURRENT0 (DMA_BASE+0x00E8) ++#define DMAMP_RX_3_MAXCNT1 (DMA_BASE+0x00F0) ++#define DMAMP_RX_3_BASE1 (DMA_BASE+0x00F4) ++#define DMAMP_RX_3_CURRENT1 (DMA_BASE+0x00F8) ++ ++#define DMAMM_0_CONTROL (DMA_BASE+0x0100) ++#define DMAMM_0_INTERRUPT (DMA_BASE+0x0104) ++#define DMAMM_0_STATUS (DMA_BASE+0x010C) ++#define DMAMM_0_BCR0 (DMA_BASE+0x0110) ++#define DMAMM_0_BCR1 (DMA_BASE+0x0114) ++#define DMAMM_0_SAR_BASE0 (DMA_BASE+0x0118) ++#define DMAMM_0_SAR_BASE1 (DMA_BASE+0x011C) ++#define DMAMM_0_SAR_CURRENT0 (DMA_BASE+0x0124) ++#define DMAMM_0_SAR_CURRENT1 (DMA_BASE+0x0128) ++#define DMAMM_0_DAR_BASE0 (DMA_BASE+0x012C) ++#define DMAMM_0_DAR_BASE1 (DMA_BASE+0x0130) ++#define DMAMM_0_DAR_CURRENT0 (DMA_BASE+0x0134) ++#define DMAMM_0_DAR_CURRENT1 (DMA_BASE+0x013C) ++ ++#define DMAMM_1_CONTROL (DMA_BASE+0x0140) ++#define DMAMM_1_INTERRUPT (DMA_BASE+0x0144) ++#define DMAMM_1_STATUS (DMA_BASE+0x014C) ++#define DMAMM_1_BCR0 (DMA_BASE+0x0150) ++#define DMAMM_1_BCR1 (DMA_BASE+0x0154) ++#define DMAMM_1_SAR_BASE0 (DMA_BASE+0x0158) ++#define DMAMM_1_SAR_BASE1 (DMA_BASE+0x015C) ++#define DMAMM_1_SAR_CURRENT0 (DMA_BASE+0x0164) ++#define DMAMM_1_SAR_CURRENT1 (DMA_BASE+0x0168) ++#define DMAMM_1_DAR_BASE0 (DMA_BASE+0x016C) ++#define DMAMM_1_DAR_BASE1 (DMA_BASE+0x0170) ++#define DMAMM_1_DAR_CURRENT0 (DMA_BASE+0x0174) ++#define DMAMM_1_DAR_CURRENT1 (DMA_BASE+0x017C) ++ ++#define DMAMP_RX_5_CONTROL (DMA_BASE+0x0200) ++#define DMAMP_RX_5_INTERRUPT (DMA_BASE+0x0204) ++#define DMAMP_RX_5_PPALLOC (DMA_BASE+0x0208) ++#define DMAMP_RX_5_STATUS (DMA_BASE+0x020C) ++#define DMAMP_RX_5_REMAIN (DMA_BASE+0x0214) ++#define DMAMP_RX_5_MAXCNT0 (DMA_BASE+0x0220) ++#define DMAMP_RX_5_BASE0 (DMA_BASE+0x0224) ++#define DMAMP_RX_5_CURRENT0 (DMA_BASE+0x0228) ++#define DMAMP_RX_5_MAXCNT1 (DMA_BASE+0x0230) ++#define DMAMP_RX_5_BASE1 (DMA_BASE+0x0234) ++#define DMAMP_RX_5_CURRENT1 (DMA_BASE+0x0238) ++ ++#define DMAMP_TX_4_CONTROL (DMA_BASE+0x0240) ++#define DMAMP_TX_4_INTERRUPT (DMA_BASE+0x0244) ++#define DMAMP_TX_4_PPALLOC (DMA_BASE+0x0248) ++#define DMAMP_TX_4_STATUS (DMA_BASE+0x024C) ++#define DMAMP_TX_4_REMAIN (DMA_BASE+0x0254) ++#define DMAMP_TX_4_MAXCNT0 (DMA_BASE+0x0260) ++#define DMAMP_TX_4_BASE0 (DMA_BASE+0x0264) ++#define DMAMP_TX_4_CURRENT0 (DMA_BASE+0x0268) ++#define DMAMP_TX_4_MAXCNT1 (DMA_BASE+0x0270) ++#define DMAMP_TX_4_BASE1 (DMA_BASE+0x0274) ++#define DMAMP_TX_4_CURRENT1 (DMA_BASE+0x0278) ++ ++#define DMAMP_RX_7_CONTROL (DMA_BASE+0x0280) ++#define DMAMP_RX_7_INTERRUPT (DMA_BASE+0x0284) ++#define DMAMP_RX_7_PPALLOC (DMA_BASE+0x0288) ++#define DMAMP_RX_7_STATUS (DMA_BASE+0x028C) ++#define DMAMP_RX_7_REMAIN (DMA_BASE+0x0294) ++#define DMAMP_RX_7_MAXCNT0 (DMA_BASE+0x02A0) ++#define DMAMP_RX_7_BASE0 (DMA_BASE+0x02A4) ++#define DMAMP_RX_7_CURRENT0 (DMA_BASE+0x02A8) ++#define DMAMP_RX_7_MAXCNT1 (DMA_BASE+0x02B0) ++#define DMAMP_RX_7_BASE1 (DMA_BASE+0x02B4) ++#define DMAMP_RX_7_CURRENT1 (DMA_BASE+0x02B8) ++ ++#define DMAMP_TX_6_CONTROL (DMA_BASE+0x02C0) ++#define DMAMP_TX_6_INTERRUPT (DMA_BASE+0x02C4) ++#define DMAMP_TX_6_PPALLOC (DMA_BASE+0x02C8) ++#define DMAMP_TX_6_STATUS (DMA_BASE+0x02CC) ++#define DMAMP_TX_6_REMAIN (DMA_BASE+0x02D4) ++#define DMAMP_TX_6_MAXCNT0 (DMA_BASE+0x02E0) ++#define DMAMP_TX_6_BASE0 (DMA_BASE+0x02E4) ++#define DMAMP_TX_6_CURRENT0 (DMA_BASE+0x02E8) ++#define DMAMP_TX_6_MAXCNT1 (DMA_BASE+0x02F0) ++#define DMAMP_TX_6_BASE1 (DMA_BASE+0x02F4) ++#define DMAMP_TX_6_CURRENT1 (DMA_BASE+0x02F8) ++ ++#define DMAMP_RX_9_CONTROL (DMA_BASE+0x0300) ++#define DMAMP_RX_9_INTERRUPT (DMA_BASE+0x0304) ++#define DMAMP_RX_9_PPALLOC (DMA_BASE+0x0308) ++#define DMAMP_RX_9_STATUS (DMA_BASE+0x030C) ++#define DMAMP_RX_9_REMAIN (DMA_BASE+0x0314) ++#define DMAMP_RX_9_MAXCNT0 (DMA_BASE+0x0320) ++#define DMAMP_RX_9_BASE0 (DMA_BASE+0x0324) ++#define DMAMP_RX_9_CURRENT0 (DMA_BASE+0x0328) ++#define DMAMP_RX_9_MAXCNT1 (DMA_BASE+0x0330) ++#define DMAMP_RX_9_BASE1 (DMA_BASE+0x0334) ++#define DMAMP_RX_9_CURRENT1 (DMA_BASE+0x0338) ++ ++#define DMAMP_TX_8_CONTROL (DMA_BASE+0x0340) ++#define DMAMP_TX_8_INTERRUPT (DMA_BASE+0x0344) ++#define DMAMP_TX_8_PPALLOC (DMA_BASE+0x0348) ++#define DMAMP_TX_8_STATUS (DMA_BASE+0x034C) ++#define DMAMP_TX_8_REMAIN (DMA_BASE+0x0354) ++#define DMAMP_TX_8_MAXCNT0 (DMA_BASE+0x0360) ++#define DMAMP_TX_8_BASE0 (DMA_BASE+0x0364) ++#define DMAMP_TX_8_CURRENT0 (DMA_BASE+0x0368) ++#define DMAMP_TX_8_MAXCNT1 (DMA_BASE+0x0370) ++#define DMAMP_TX_8_BASE1 (DMA_BASE+0x0374) ++#define DMAMP_TX_8_CURRENT1 (DMA_BASE+0x0378) ++ ++#define DMA_ARBITRATION (DMA_BASE+0x0380) ++#define DMA_INTERRUPT (DMA_BASE+0x03C0) ++ ++/* ++ * DMA Register Base addresses and Offsets ++ */ ++#define DMA_M2P_TX_0_BASE DMAMP_TX_0_CONTROL ++#define DMA_M2P_RX_1_BASE DMAMP_RX_1_CONTROL ++#define DMA_M2P_TX_2_BASE DMAMP_TX_2_CONTROL ++#define DMA_M2P_RX_3_BASE DMAMP_RX_3_CONTROL ++#define DMA_M2M_0_BASE DMAMM_0_CONTROL ++#define DMA_M2M_1_BASE DMAMM_1_CONTROL ++#define DMA_M2P_RX_5_BASE DMAMP_RX_5_CONTROL ++#define DMA_M2P_TX_4_BASE DMAMP_TX_4_CONTROL ++#define DMA_M2P_RX_7_BASE DMAMP_RX_7_CONTROL ++#define DMA_M2P_TX_6_BASE DMAMP_TX_6_CONTROL ++#define DMA_M2P_RX_9_BASE DMAMP_RX_9_CONTROL ++#define DMA_M2P_TX_8_BASE DMAMP_TX_8_CONTROL ++ ++#define M2P_OFFSET_CONTROL 0x0000 ++#define M2P_OFFSET_INTERRUPT 0x0004 ++#define M2P_OFFSET_PPALLOC 0x0008 ++#define M2P_OFFSET_STATUS 0x000C ++#define M2P_OFFSET_REMAIN 0x0014 ++#define M2P_OFFSET_MAXCNT0 0x0020 ++#define M2P_OFFSET_BASE0 0x0024 ++#define M2P_OFFSET_CURRENT0 0x0028 ++#define M2P_OFFSET_MAXCNT1 0x0030 ++#define M2P_OFFSET_BASE1 0x0034 ++#define M2P_OFFSET_CURRENT1 0x0038 ++ ++#define M2M_OFFSET_CONTROL 0x0000 ++#define M2M_OFFSET_INTERRUPT 0x0004 ++#define M2M_OFFSET_STATUS 0x000C ++#define M2M_OFFSET_BCR0 0x0010 ++#define M2M_OFFSET_BCR1 0x0014 ++#define M2M_OFFSET_SAR_BASE0 0x0018 ++#define M2M_OFFSET_SAR_BASE1 0x001C ++#define M2M_OFFSET_SAR_CURRENT0 0x0024 ++#define M2M_OFFSET_SAR_CURRENT1 0x0028 ++#define M2M_OFFSET_DAR_BASE0 0x002C ++#define M2M_OFFSET_DAR_BASE1 0x0030 ++#define M2M_OFFSET_DAR_CURRENT0 0x0034 ++#define M2M_OFFSET_DAR_CURRENT1 0x003C ++ ++/*----------------------------------------------------------------*/ ++/* 8001_0000 - 8001_ffff: Ether MAC */ ++/*----------------------------------------------------------------*/ ++#define MAC_OFFSET 0x010000 ++#define MAC_BASE (EP93XX_AHB_BASE|MAC_OFFSET) ++ ++#define MAC_RXCTL (MAC_BASE+0x00) ++#define MAC_TXCTL (MAC_BASE+0x04) ++#define MAC_TESTCTL (MAC_BASE+0x08) ++#define MAC_MIICMD (MAC_BASE+0x10) ++#define MAC_MIIDATA (MAC_BASE+0x14) ++#define MAC_MIISTS (MAC_BASE+0x18) ++#define MAC_SELFCTL (MAC_BASE+0x20) ++#define MAC_INTEN (MAC_BASE+0x24) ++#define MAC_INTSTSP (MAC_BASE+0x28) ++#define MAC_INTSTSC (MAC_BASE+0x2C) ++#define MAC_DIAGAD (MAC_BASE+0x38) ++#define MAC_DIAGDATA (MAC_BASE+0x3C) ++#define MAC_GT (MAC_BASE+0x40) ++#define MAC_FCT (MAC_BASE+0x44) ++#define MAC_FCF (MAC_BASE+0x48) ++#define MAC_AFP (MAC_BASE+0x4C) ++#define MAC_HASHTBL (MAC_BASE+0x50) ++#define MAC_INDAD (MAC_BASE+0x50) ++#define MAC_INDAD_UPPER (MAC_BASE+0x54) ++#define MAC_GIINTSTS (MAC_BASE+0x60) ++#define MAC_GIINTMSK (MAC_BASE+0x64) ++#define MAC_GIINTROSTS (MAC_BASE+0x68) ++#define MAC_GIINTFRC (MAC_BASE+0x6C) ++#define MAC_TXCOLLCNT (MAC_BASE+0x70) ++#define MAC_RXMISSCNT (MAC_BASE+0x74) ++#define MAC_RXRUNTCNT (MAC_BASE+0x78) ++#define MAC_BMCTL (MAC_BASE+0x80) ++#define MAC_BMSTS (MAC_BASE+0x84) ++#define MAC_RXBCA (MAC_BASE+0x88) ++#define MAC_RXDQBADD (MAC_BASE+0x90) ++#define MAC_RXDQBLEN (UINT16*)(MAC_BASE+0x94) ++#define MAC_RXDQCURLEN (UINT16*)(MAC_BASE+0x96) ++#define MAC_RXDCURADD (MAC_BASE+0x98) ++#define MAC_RXDENQ (MAC_BASE+0x9C) ++#define MAC_RXSTSQBADD (MAC_BASE+0xA0) ++#define MAC_RXSTSQBLEN (UINT16*)(MAC_BASE+0xA4) ++#define MAC_RXSTSQCURLEN (UINT16*)(MAC_BASE+0xA6) ++#define MAC_RXSTSQCURADD (MAC_BASE+0xA8) ++#define MAC_RXSTSENQ (MAC_BASE+0xAC) ++#define MAC_TXDQBADD (MAC_BASE+0xB0) ++#define MAC_TXDQBLEN (MAC_BASE+0xB4) ++#define MAC_TXDQCURLEN (MAC_BASE+0xB6) ++#define MAC_TXDQCURADD (MAC_BASE+0xB8) ++#define MAC_TXDENQ (MAC_BASE+0xBC) ++#define MAC_TXSTSQBADD (MAC_BASE+0xC0) ++#define MAC_TXSTSQBLEN (MAC_BASE+0xC4) ++#define MAC_TXSTSQCURLEN (MAC_BASE+0xC6) ++#define MAC_TXSTSQCURADD (MAC_BASE+0xC8) ++#define MAC_RXBUFTHRSHLD (MAC_BASE+0xD0) ++#define MAC_TXBUFTHRSHLD (MAC_BASE+0xD4) ++#define MAC_RXSTSTHRSHLD (MAC_BASE+0xD8) ++#define MAC_TXSTSTHRSHLD (MAC_BASE+0xDC) ++#define MAC_RXDTHRSHLD (MAC_BASE+0xE0) ++#define MAC_TXDTHRSHLD (MAC_BASE+0xE4) ++#define MAC_MAXFRMLEN (MAC_BASE+0xE8) ++#define MAC_RXHDRLEN (MAC_BASE+0xEC) ++ ++#define MAC_FIFO (MAC_BASE+0x4000) ++#define MAC_FIFO_LEN 0xc000 ++ ++/*----------------------------------------------------------------*/ ++/* 8002_0000 - 8002_ffff: USB */ ++/*----------------------------------------------------------------*/ ++#define USB_OFFSET 0x020000 ++#define USB_BASE (EP93XX_AHB_BASE|USB_OFFSET) ++ ++#define HCREVISION (USB_BASE+0x00) ++#define HCCONTROL (USB_BASE+0x04) ++#define HCCOMMANDSTATUS (USB_BASE+0x08) ++#define HCINTERRUPTSTATUS (USB_BASE+0x0C) ++#define HCINTERRUPTENABLE (USB_BASE+0x10) ++#define HCINTERRUPTDISABLE (USB_BASE+0x14) ++#define HCHCCA (USB_BASE+0x18) ++#define HCPERIODCURRENTED (USB_BASE+0x1C) ++#define HCCONTROLHEADED (USB_BASE+0x20) ++#define HCCONTROLCURRENTED (USB_BASE+0x24) ++#define HCBULKHEADED (USB_BASE+0x28) ++#define HCBULKCURRENTED (USB_BASE+0x2C) ++#define HCDONEHEAD (USB_BASE+0x30) ++#define HCFMINTERVAL (USB_BASE+0x34) ++#define HCFMREMAINING (USB_BASE+0x38) ++#define HCFMNUMBER (USB_BASE+0x3C) ++#define HCPERIODICSTART (USB_BASE+0x40) ++#define HCLSTHRESHOLD (USB_BASE+0x44) ++#define HCRHDESCRIPTORA (USB_BASE+0x48) ++#define HCRHDESCRIPTORB (USB_BASE+0x4C) ++#define HCRHSTATUS (USB_BASE+0x50) ++#define HCRHPORTSTATUS0 (USB_BASE+0x54) ++#define HCRHPORTSTATUS1 (USB_BASE+0x58) /* not in 9301 */ ++#define HCRHPORTSTATUS2 (USB_BASE+0x5C) ++ ++/* additional non-OHCI registers for controlling the AHB-HCI interface */ ++#define USBCTRL (USB_BASE+0x80) ++#define USBHCISTS (USB_BASE+0x84) ++ ++/* 8003_0000 - 8003_ffff: Raster */ ++#define RASTER_OFFSET 0x030000 ++#define RASTER_BASE (EP93XX_AHB_BASE|RASTER_OFFSET) ++#define VLINESTOTAL (RASTER_BASE+0x00) ++#define VSYNCSTRTSTOP (RASTER_BASE+0x04) ++#define VACTIVESTRTSTOP (RASTER_BASE+0x08) ++#define VCLKSTRTSTOP (RASTER_BASE+0x0C) ++#define HCLKSTOTAL (RASTER_BASE+0x10) ++#define HSYNCSTRTSTOP (RASTER_BASE+0x14) ++#define HACTIVESTRTSTOP (RASTER_BASE+0x18) ++#define HCLKSTRTSTOP (RASTER_BASE+0x1C) ++#define BRIGHTNESS (RASTER_BASE+0x20) ++#define VIDEOATTRIBS (RASTER_BASE+0x24) ++#define VIDSCRNPAGE (RASTER_BASE+0x28) ++#define VIDSCRNHPG (RASTER_BASE+0x2C) ++#define SCRNLINES (RASTER_BASE+0x30) ++#define LINELENGTH (RASTER_BASE+0x34) ++#define VLINESTEP (RASTER_BASE+0x38) ++#define LINECARRY (RASTER_BASE+0x3C) ++#define BLINKRATE (RASTER_BASE+0x40) ++#define BLINKMASK (RASTER_BASE+0x44) ++#define BLINKPATTRN (RASTER_BASE+0x48) ++#define PATTRNMASK (RASTER_BASE+0x4C) ++#define BG_OFFSET (RASTER_BASE+0x50) ++#define PIXELMODE (RASTER_BASE+0x54) ++#define PARLLIFOUT (RASTER_BASE+0x58) ++#define PARLLIFIN (RASTER_BASE+0x5C) ++#define CURSOR_ADR_START (RASTER_BASE+0x60) ++#define CURSOR_ADR_RESET (RASTER_BASE+0x64) ++#define CURSORSIZE (RASTER_BASE+0x68) ++#define CURSORCOLOR1 (RASTER_BASE+0x6C) ++#define CURSORCOLOR2 (RASTER_BASE+0x70) ++#define CURSORXYLOC (RASTER_BASE+0x74) ++#define CURSOR_DHSCAN_LH_YLOC (RASTER_BASE+0x78) ++#define REALITI_SWLOCK (RASTER_BASE+0x7C) ++#define GS_LUT (RASTER_BASE+0x80) ++#define REALITI_TCR (RASTER_BASE+0x100) ++#define REALITI_TISRA (RASTER_BASE+0x104) ++#define REALITI_TISRB (RASTER_BASE+0x108) ++#define CURSOR_TISR (RASTER_BASE+0x10C) ++#define REALITI_TOCRA (RASTER_BASE+0x110) ++#define REALITI_TOCRB (RASTER_BASE+0x114) ++#define FIFO_TOCRA (RASTER_BASE+0x118) ++#define FIFO_TOCRB (RASTER_BASE+0x11C) ++#define BLINK_TISR (RASTER_BASE+0x120) ++#define DAC_TISRA (RASTER_BASE+0x124) ++#define DAC_TISRB (RASTER_BASE+0x128) ++#define SHIFT_TISR (RASTER_BASE+0x12C) ++#define DACMUX_TOCRA (RASTER_BASE+0x130) ++#define DACMUX_TOCRB (RASTER_BASE+0x134) ++#define PELMUX_TOCR (RASTER_BASE+0x138) ++#define VIDEO_TOCRA (RASTER_BASE+0x13C) ++#define VIDEO_TOCRB (RASTER_BASE+0x140) ++#define YCRCB_TOCR (RASTER_BASE+0x144) ++#define CURSOR_TOCR (RASTER_BASE+0x148) ++#define VIDEO_TOCRC (RASTER_BASE+0x14C) ++#define SHIFT_TOCR (RASTER_BASE+0x150) ++#define BLINK_TOCR (RASTER_BASE+0x154) ++#define REALITI_TCER (RASTER_BASE+0x180) ++#define SIGVAL (RASTER_BASE+0x200) ++#define SIGCTL (RASTER_BASE+0x204) ++#define VSIGSTRTSTOP (RASTER_BASE+0x208) ++#define HSIGSTRTSTOP (RASTER_BASE+0x20C) ++#define SIGCLR (RASTER_BASE+0x210) ++#define ACRATE (RASTER_BASE+0x214) ++#define LUTCONT (RASTER_BASE+0x218) ++#define VBLANKSTRTSTOP (RASTER_BASE+0x228) ++#define HBLANKSTRTSTOP (RASTER_BASE+0x22C) ++#define LUT (RASTER_BASE+0x400) ++#define CURSORBLINK1 (RASTER_BASE+0x21C) ++#define CURSORBLINK2 (RASTER_BASE+0x220) ++#define CURSORBLINK (RASTER_BASE+0x224) ++#define EOLOFFSET (RASTER_BASE+0x230) ++#define FIFOLEVEL (RASTER_BASE+0x234) ++#define GS_LUT2 (RASTER_BASE+0x280) ++#define GS_LUT3 (RASTER_BASE+0x300) ++#define COLOR_LUT (RASTER_BASE+0x400) ++ ++/* 8006_0000 - 8006_ffff: SDRAM */ ++#define SDRAM_OFFSET 0x060000 ++#define SDRAM_BASE (EP93XX_AHB_BASE|SDRAM_OFFSET) ++#define SDRAMGLOBALCFG (SDRAM_BASE+0x04) ++#define SDRAMREFRESHTIME (SDRAM_BASE+0x08) /* Refresh Timer */ ++#define SDRAMBOOTSTATUS (SDRAM_BASE+0x0C) ++#define SDRAMCFG0 (SDRAM_BASE+0x10) /* Configuration Register 0 (nSDCS0) */ ++#define SDRAMCFG1 (SDRAM_BASE+0x14) /* Configuration Register 1 (nSDCS1) */ ++#define SDRAMCFG2 (SDRAM_BASE+0x18) /* Configuration Register 2 (nSDCS2) */ ++#define SDRAMCFG3 (SDRAM_BASE+0x1C) /* Configuration Register 3 (nSDCS3) */ ++ ++/* 8008_0000 - 8008_ffff: SMC */ ++#define SMC_OFFSET 0x080000 ++#define SMC_BASE (EP93XX_AHB_BASE|SMC_OFFSET) ++#define SMCBCR0 (SMC_BASE+0x00) /* 0x8008.0000 Bank config register 0 */ ++#define SMCBCR1 (SMC_BASE+0x04) /* 0x8008.0004 Bank config register 1 */ ++#define SMCBCR2 (SMC_BASE+0x08) /* 0x8008.0008 Bank config register 2 */ ++#define SMCBCR3 (SMC_BASE+0x0C) /* 0x8008.000C Bank config register 3 */ ++#define SMCBCR6 (SMC_BASE+0x18) /* 0x8008.0018 Bank config register 6 */ ++#define SMCBCR7 (SMC_BASE+0x1C) /* 0x8008.001C Bank config register 7 */ ++#define PC1ATTRIB (SMC_BASE+0x20) /* 0x8008.0020 PC1 Attribute Register */ ++#define PC1COMMON (SMC_BASE+0x24) /* 0x8008.0024 PC1 Common Register */ ++#define PC1IO (SMC_BASE+0x28) /* 0x8008.0028 PC1 IO Register */ ++#define PC2ATTRIB (SMC_BASE+0x30) /* 0x8008.0030 PC2 Attribute Register */ ++#define PC2COMMON (SMC_BASE+0x34) /* 0x8008.0034 PC2 Common Register */ ++#define PC2IO (SMC_BASE+0x38) /* 0x8008.0038 PC2 IO Register */ ++#define PCMCIACNT (SMC_BASE+0x40) /* 0x8008.0040 PCMCIA control register */ ++ ++/* 8009_0000 - 8009_ffff: Boot ROM */ ++#define BOOT_OFFSET 0x090000 ++#define BOOT_BASE (EP93XX_AHB_BASE|BOOT_OFFSET) ++ ++/* 800A_0000 - 800A_ffff: IDE Interface */ ++#define IDE_OFFSET 0x0a0000 ++#define IDE_BASE (EP93XX_AHB_BASE|IDE_OFFSET) ++/*#define IDECR (IDE_BASE+0x00) ++ *#define IDECFG (IDE_BASE+0x04) ++ *#define IDEMDMAOP (IDE_BASE+0x08) ++ *#define IDEUDMAOP (IDE_BASE+0x0C) ++ *#define IDEDATAOUT (IDE_BASE+0x10) ++ *#define IDEDATAIN (IDE_BASE+0x14) ++ *#define IDEMDMADATAOUT (IDE_BASE+0x18) ++ *#define IDEMDMADATAIN (IDE_BASE+0x1C) ++ *#define IDEUDMADATAOUT (IDE_BASE+0x20) ++ *#define IDEUDMADATAIN (IDE_BASE+0x24) ++ *#define IDEUDMASTATUS (IDE_BASE+0x28) ++ *#define IDEUDMADEBUG (IDE_BASE+0x2C) ++ *#define IDEUDMAWFST (IDE_BASE+0x30) ++ *#define IDEUDMARFST (IDE_BASE+0x34) ++ */ ++ ++/* 800B_0000 - 800B_FFFF: VIC 0 */ ++#define VIC0_OFFSET 0x0B0000 ++#define VIC0_BASE (EP93XX_AHB_BASE|VIC0_OFFSET) ++#define VIC0 (VIC0_BASE+0x000) ++#define VIC0IRQSTATUS (VIC0_BASE+0x000) /* R IRQ status register */ ++#define VIC0FIQSTATUS (VIC0_BASE+0x004) /* R FIQ status register */ ++#define VIC0RAWINTR (VIC0_BASE+0x008) /* R Raw interrupt status register */ ++#define VIC0INTSELECT (VIC0_BASE+0x00C) /* R/W Interrupt select register */ ++#define VIC0INTENABLE (VIC0_BASE+0x010) /* R/W Interrupt enable register */ ++#define VIC0INTENCLEAR (VIC0_BASE+0x014) /* W Interrupt enable clear register */ ++#define VIC0SOFTINT (VIC0_BASE+0x018) /* R/W Software interrupt register */ ++#define VIC0SOFTINTCLEAR (VIC0_BASE+0x01C) /* R/W Software interrupt clear register */ ++#define VIC0PROTECTION (VIC0_BASE+0x020) /* R/W Protection enable register */ ++#define VIC0VECTADDR (VIC0_BASE+0x030) /* R/W Vector address register */ ++#define VIC0DEFVECTADDR (VIC0_BASE+0x034) /* R/W Default vector address register */ ++#define VIC0VECTADDR00 (VIC0_BASE+0x100) /* R/W Vector address 00 register */ ++#define VIC0VECTADDR01 (VIC0_BASE+0x104) /* R/W Vector address 01 register */ ++#define VIC0VECTADDR02 (VIC0_BASE+0x108) /* R/W Vector address 02 register */ ++#define VIC0VECTADDR03 (VIC0_BASE+0x10C) /* R/W Vector address 03 register */ ++#define VIC0VECTADDR04 (VIC0_BASE+0x110) /* R/W Vector address 04 register */ ++#define VIC0VECTADDR05 (VIC0_BASE+0x114) /* R/W Vector address 05 register */ ++#define VIC0VECTADDR06 (VIC0_BASE+0x118) /* R/W Vector address 06 register */ ++#define VIC0VECTADDR07 (VIC0_BASE+0x11C) /* R/W Vector address 07 register */ ++#define VIC0VECTADDR08 (VIC0_BASE+0x120) /* R/W Vector address 08 register */ ++#define VIC0VECTADDR09 (VIC0_BASE+0x124) /* R/W Vector address 09 register */ ++#define VIC0VECTADDR10 (VIC0_BASE+0x128) /* R/W Vector address 10 register */ ++#define VIC0VECTADDR11 (VIC0_BASE+0x12C) /* R/W Vector address 11 register */ ++#define VIC0VECTADDR12 (VIC0_BASE+0x130) /* R/W Vector address 12 register */ ++#define VIC0VECTADDR13 (VIC0_BASE+0x134) /* R/W Vector address 13 register */ ++#define VIC0VECTADDR14 (VIC0_BASE+0x138) /* R/W Vector address 14 register */ ++#define VIC0VECTADDR15 (VIC0_BASE+0x13C) /* R/W Vector address 15 register */ ++#define VIC0VECTCNTL00 (VIC0_BASE+0x200) /* R/W Vector control 00 register */ ++#define VIC0VECTCNTL01 (VIC0_BASE+0x204) /* R/W Vector control 01 register */ ++#define VIC0VECTCNTL02 (VIC0_BASE+0x208) /* R/W Vector control 02 register */ ++#define VIC0VECTCNTL03 (VIC0_BASE+0x20C) /* R/W Vector control 03 register */ ++#define VIC0VECTCNTL04 (VIC0_BASE+0x210) /* R/W Vector control 04 register */ ++#define VIC0VECTCNTL05 (VIC0_BASE+0x214) /* R/W Vector control 05 register */ ++#define VIC0VECTCNTL06 (VIC0_BASE+0x218) /* R/W Vector control 06 register */ ++#define VIC0VECTCNTL07 (VIC0_BASE+0x21C) /* R/W Vector control 07 register */ ++#define VIC0VECTCNTL08 (VIC0_BASE+0x220) /* R/W Vector control 08 register */ ++#define VIC0VECTCNTL09 (VIC0_BASE+0x224) /* R/W Vector control 09 register */ ++#define VIC0VECTCNTL10 (VIC0_BASE+0x228) /* R/W Vector control 10 register */ ++#define VIC0VECTCNTL11 (VIC0_BASE+0x22C) /* R/W Vector control 11 register */ ++#define VIC0VECTCNTL12 (VIC0_BASE+0x230) /* R/W Vector control 12 register */ ++#define VIC0VECTCNTL13 (VIC0_BASE+0x234) /* R/W Vector control 13 register */ ++#define VIC0VECTCNTL14 (VIC0_BASE+0x238) /* R/W Vector control 14 register */ ++#define VIC0VECTCNTL15 (VIC0_BASE+0x23C) /* R/W Vector control 15 register */ ++#define VIC0ITCR (VIC0_BASE+0x300) /* R/W Test control register */ ++#define VIC0ITIP1 (VIC0_BASE+0x304) /* R Test input register (nVICIRQIN/nVICFIQIN) */ ++#define VIC0ITIP2 (VIC0_BASE+0x308) /* R Test input register (VICVECTADDRIN) */ ++#define VIC0ITOP1 (VIC0_BASE+0x30C) /* R Test output register (nVICIRQ/nVICFIQ) */ ++#define VIC0ITOP2 (VIC0_BASE+0x310) /* R Test output register (VICVECTADDROUT) */ ++#define VIC0PERIPHID0 (VIC0_BASE+0xFE0) /* R Peripheral ID register bits 7:0 */ ++#define VIC0PERIPHID1 (VIC0_BASE+0xFE4) /* R Peripheral ID register bits 15:8 */ ++#define VIC0PERIPHID2 (VIC0_BASE+0xFE8) /* R Peripheral ID register bits 23:16 */ ++#define VIC0PERIPHID3 (VIC0_BASE+0xFEC) /* R Peripheral ID register bits 31:24 */ ++ ++/* 800C_0000 - 800C_FFFF: VIC 1 */ ++#define VIC1_OFFSET 0x0C0000 ++#define VIC1_BASE (EP93XX_AHB_BASE|VIC1_OFFSET) ++#define VIC1 (VIC1_BASE+0x000) ++#define VIC1IRQSTATUS (VIC1_BASE+0x000) /* R IRQ status register */ ++#define VIC1FIQSTATUS (VIC1_BASE+0x004) /* R FIQ status register */ ++#define VIC1RAWINTR (VIC1_BASE+0x008) /* R Raw interrupt status register */ ++#define VIC1INTSELECT (VIC1_BASE+0x00C) /* R/W Interrupt select register */ ++#define VIC1INTENABLE (VIC1_BASE+0x010) /* R/W Interrupt enable register */ ++#define VIC1INTENCLEAR (VIC1_BASE+0x014) /* W Interrupt enable clear register */ ++#define VIC1SOFTINT (VIC1_BASE+0x018) /* R/W Software interrupt register */ ++#define VIC1SOFTINTCLEAR (VIC1_BASE+0x01C) /* R/W Software interrupt clear register */ ++#define VIC1PROTECTION (VIC1_BASE+0x020) /* R/W Protection enable register */ ++#define VIC1VECTADDR (VIC1_BASE+0x030) /* R/W Vector address register */ ++#define VIC1DEFVECTADDR (VIC1_BASE+0x034) /* R/W Default vector address register */ ++#define VIC1VECTADDR00 (VIC1_BASE+0x100) /* R/W Vector address 00 register */ ++#define VIC1VECTADDR01 (VIC1_BASE+0x104) /* R/W Vector address 01 register */ ++#define VIC1VECTADDR02 (VIC1_BASE+0x108) /* R/W Vector address 02 register */ ++#define VIC1VECTADDR03 (VIC1_BASE+0x10C) /* R/W Vector address 03 register */ ++#define VIC1VECTADDR04 (VIC1_BASE+0x110) /* R/W Vector address 04 register */ ++#define VIC1VECTADDR05 (VIC1_BASE+0x114) /* R/W Vector address 05 register */ ++#define VIC1VECTADDR06 (VIC1_BASE+0x118) /* R/W Vector address 06 register */ ++#define VIC1VECTADDR07 (VIC1_BASE+0x11C) /* R/W Vector address 07 register */ ++#define VIC1VECTADDR08 (VIC1_BASE+0x120) /* R/W Vector address 08 register */ ++#define VIC1VECTADDR09 (VIC1_BASE+0x124) /* R/W Vector address 09 register */ ++#define VIC1VECTADDR10 (VIC1_BASE+0x128) /* R/W Vector address 10 register */ ++#define VIC1VECTADDR11 (VIC1_BASE+0x12C) /* R/W Vector address 11 register */ ++#define VIC1VECTADDR12 (VIC1_BASE+0x130) /* R/W Vector address 12 register */ ++#define VIC1VECTADDR13 (VIC1_BASE+0x134) /* R/W Vector address 13 register */ ++#define VIC1VECTADDR14 (VIC1_BASE+0x138) /* R/W Vector address 14 register */ ++#define VIC1VECTADDR15 (VIC1_BASE+0x13C) /* R/W Vector address 15 register */ ++#define VIC1VECTCNTL00 (VIC1_BASE+0x200) /* R/W Vector control 00 register */ ++#define VIC1VECTCNTL01 (VIC1_BASE+0x204) /* R/W Vector control 01 register */ ++#define VIC1VECTCNTL02 (VIC1_BASE+0x208) /* R/W Vector control 02 register */ ++#define VIC1VECTCNTL03 (VIC1_BASE+0x20C) /* R/W Vector control 03 register */ ++#define VIC1VECTCNTL04 (VIC1_BASE+0x210) /* R/W Vector control 04 register */ ++#define VIC1VECTCNTL05 (VIC1_BASE+0x214) /* R/W Vector control 05 register */ ++#define VIC1VECTCNTL06 (VIC1_BASE+0x218) /* R/W Vector control 06 register */ ++#define VIC1VECTCNTL07 (VIC1_BASE+0x21C) /* R/W Vector control 07 register */ ++#define VIC1VECTCNTL08 (VIC1_BASE+0x220) /* R/W Vector control 08 register */ ++#define VIC1VECTCNTL09 (VIC1_BASE+0x224) /* R/W Vector control 09 register */ ++#define VIC1VECTCNTL10 (VIC1_BASE+0x228) /* R/W Vector control 10 register */ ++#define VIC1VECTCNTL11 (VIC1_BASE+0x22C) /* R/W Vector control 11 register */ ++#define VIC1VECTCNTL12 (VIC1_BASE+0x230) /* R/W Vector control 12 register */ ++#define VIC1VECTCNTL13 (VIC1_BASE+0x234) /* R/W Vector control 13 register */ ++#define VIC1VECTCNTL14 (VIC1_BASE+0x238) /* R/W Vector control 14 register */ ++#define VIC1VECTCNTL15 (VIC1_BASE+0x23C) /* R/W Vector control 15 register */ ++#define VIC1ITCR (VIC1_BASE+0x300) /* R/W Test control register */ ++#define VIC1ITIP1 (VIC1_BASE+0x304) /* R Test input register (nVICIRQIN/nVICFIQIN) */ ++#define VIC1ITIP2 (VIC1_BASE+0x308) /* R Test input register (VICVECTADDRIN) */ ++#define VIC1ITOP1 (VIC1_BASE+0x30C) /* R Test output register (nVICIRQ/nVICFIQ) */ ++#define VIC1ITOP2 (VIC1_BASE+0x310) /* R Test output register (VICVECTADDROUT) */ ++#define VIC1PERIPHID0 (VIC1_BASE+0xFE0) /* R Peripheral ID register bits 7:0 */ ++#define VIC1PERIPHID1 (VIC1_BASE+0xFE4) /* R Peripheral ID register bits 15:8 */ ++#define VIC1PERIPHID2 (VIC1_BASE+0xFE8) /* R Peripheral ID register bits 23:16 */ ++#define VIC1PERIPHID3 (VIC1_BASE+0xFEC) /* R Peripheral ID register bits 31:24 */ ++ ++/******************************************************************/ ++/* EP93xx APB Blocks */ ++/******************************************************************/ ++/* */ ++/* Start End Usage */ ++/* 8080_0000 8080_FFFF: Reserved */ ++/* 8081_0000 8081_FFFF: Timer */ ++/* 8082_0000 8082_FFFF: I2S */ ++/* 8083_0000 8083_FFFF: Security */ ++/* 8084_0000 8084_FFFF: GPIO */ ++/* 8085_0000 8085_FFFF: Reserved */ ++/* 8086_0000 8086_FFFF: Reserved */ ++/* 8087_0000 8087_FFFF: Reserved */ ++/* 8088_0000 8088_FFFF: AC97 */ ++/* 8089_0000 8089_FFFF: Reserved */ ++/* 808A_0000 808A_FFFF: SPI */ ++/* 808B_0000 808B_FFFF: IrDA */ ++/* 808C_0000 808C_FFFF: UART1 */ ++/* 808D_0000 808D_FFFF: UART2 */ ++/* 808E_0000 808E_FFFF: UART3 */ ++/* 808F_0000 808F_FFFF: Key Matrix */ ++/* 8090_0000 8090_FFFF: Touch Screen */ ++/* 8091_0000 8091_FFFF: PWM */ ++/* 8092_0000 8092_FFFF: Real Time Clock */ ++/* 8093_0000 8093_FFFF: Syscon */ ++/* 8094_0000 8094_FFFF: Watchdog */ ++/* 8095_0000 8FFF_FFFF: Reserved */ ++/* */ ++/******************************************************************/ ++ ++#define EP93XX_APB_BASE (IO_BASE_VIRT | 0x00800000) ++ ++/*----------------------------------------------------------------*/ ++/* 8081_0000 - 8081_ffff: Timers */ ++/*----------------------------------------------------------------*/ ++ ++#define TIMERS_OFFSET 0x010000 ++#define TIMERS_BASE (EP93XX_APB_BASE|TIMERS_OFFSET) ++ ++#define TIMER1LOAD (TIMERS_BASE+0x00) ++#define TIMER1VALUE (TIMERS_BASE+0x04) /* RO */ ++#define TIMER1CONTROL (TIMERS_BASE+0x08) ++#define TIMER1CLEAR (TIMERS_BASE+0x0C) /* WO */ ++ ++#define TIMER2LOAD (TIMERS_BASE+0x20) ++#define TIMER2VALUE (TIMERS_BASE+0x24) /* RO */ ++#define TIMER2CONTROL (TIMERS_BASE+0x28) ++#define TIMER2CLEAR (TIMERS_BASE+0x2C) /* WO */ ++ ++#define TIMER3LOAD (TIMERS_BASE+0x80) ++#define TIMER3VALUE (TIMERS_BASE+0x84) /* RO */ ++#define TIMER3CONTROL (TIMERS_BASE+0x88) ++#define TIMER3CLEAR (TIMERS_BASE+0x8C) /* WO */ ++ ++#define TIMER4VALUELOW (TIMERS_BASE+0x60) ++#define TIMER4VALUEHIGH (TIMERS_BASE+0x64) ++ ++/* 8082_0000 - 8082_ffff: I2S */ ++#define I2S_OFFSET 0x020000 ++#define I2S_BASE (EP93XX_APB_BASE|I2S_OFFSET) ++ ++#define I2STxClkCfg (I2S_BASE+0x00) /* 8082.0000 R/W Transmitter clock config register */ ++#define I2SRxClkCfg (I2S_BASE+0x04) /* 8082.0004 R/W Receiver clock config register */ ++#define I2SGlSts (I2S_BASE+0x08) /* 8082.0008 R/W SAI Global Status register. */ ++#define I2SGlCtrl (I2S_BASE+0x0C) /* 8082.000C R/W SAI Global Control register */ ++ ++#define I2STX0Lft (I2S_BASE+0x10) /* 8082.0010 R/W Left TX data reg for channel 0 */ ++#define I2STX0Rt (I2S_BASE+0x14) /* 8082.0014 R/W Right TX data reg for channel 0 */ ++#define I2STX1Lft (I2S_BASE+0x18) /* 8082.0018 R/W Left TX data reg for channel 1 */ ++#define I2STX1Rt (I2S_BASE+0x1C) /* 8082.001C R/W Right TX data reg for channel 1 */ ++#define I2STX2Lft (I2S_BASE+0x20) /* 8082.0020 R/W Left TX data reg for channel 2 */ ++#define I2STX2Rt (I2S_BASE+0x24) /* 8082.0024 R/W Right TX data reg for channel 2 */ ++ ++#define I2STXLinCtrlData (I2S_BASE+0x28) /* 8082.0028 R/W TX Line Control data register */ ++#define I2STXCtrl (I2S_BASE+0x2C) /* 8082.002C R/W TX Control register */ ++#define I2STXWrdLen (I2S_BASE+0x30) /* 8082.0030 R/W TX Word Length */ ++#define I2STX0En (I2S_BASE+0x34) /* 8082.0034 R/W TX0 Channel Enable */ ++#define I2STX1En (I2S_BASE+0x38) /* 8082.0038 R/W TX1 Channel Enable */ ++#define I2STX2En (I2S_BASE+0x3C) /* 8082.003C R/W TX2 Channel Enable */ ++ ++#define I2SRX0Lft (I2S_BASE+0x40) /* 8082.0040 R Left RX data reg for channel 0 */ ++#define I2SRX0Rt (I2S_BASE+0x44) /* 8082.0044 R Right RX data reg for channel 0 */ ++#define I2SRX1Lft (I2S_BASE+0x48) /* 8082.0048 R Left RX data reg for channel 1 */ ++#define I2SRX1Rt (I2S_BASE+0x4C) /* 8082.004c R Right RX data reg for channel 1 */ ++#define I2SRX2Lft (I2S_BASE+0x50) /* 8082.0050 R Left RX data reg for channel 2 */ ++#define I2SRX2Rt (I2S_BASE+0x54) /* 8082.0054 R Right RX data reg for channel 2 */ ++ ++#define I2SRXLinCtrlData (I2S_BASE+0x58) /* 8082.0058 R/W RX Line Control data register */ ++#define I2SRXCtrl (I2S_BASE+0x5C) /* 8082.005C R/W RX Control register */ ++#define I2SRXWrdLen (I2S_BASE+0x60) /* 8082.0060 R/W RX Word Length */ ++#define I2SRX0En (I2S_BASE+0x64) /* 8082.0064 R/W RX0 Channel Enable */ ++#define I2SRX1En (I2S_BASE+0x68) /* 8082.0068 R/W RX1 Channel Enable */ ++#define I2SRX2En (I2S_BASE+0x6C) /* 8082.006C R/W RX2 Channel Enable */ ++ ++/* 8083_0000 - 8083_ffff: Security Block */ ++#define SECURITY_OFFSET 0x030000 ++#define SECURITY_BASE (EP93XX_APB_BASE|SECURITY_OFFSET) ++#define SECFLG (SECURITY_BASE+0x2400) ++#define SECEN (SECURITY_BASE+0x2410) ++#define UNIQID (SECURITY_BASE+0x2440) ++#define UNIQCHK (SECURITY_BASE+0x2450) ++#define UNIQVAL (SECURITY_BASE+0x2460) ++#define CLINBOOT (SECURITY_BASE+0x2480) ++#define CLINVADDR (SECURITY_BASE+0x2484) ++#define CLSETSKRNL (SECURITY_BASE+0x2488) ++#define CLSKRNL (SECURITY_BASE+0x248C) ++#define ITTMP (SECURITY_BASE+0x2490) ++#define ETBL1 (SECURITY_BASE+0x24A0) ++#define ETCL1 (SECURITY_BASE+0x24A4) ++#define ETAPL1 (SECURITY_BASE+0x24A8) ++#define ETSPTREG1 (SECURITY_BASE+0x24B0) ++#define ETSPTREG2 (SECURITY_BASE+0x24B4) ++#define ETSPTREG3 (SECURITY_BASE+0x24B8) ++ ++#define SECID1 (SECURITY_BASE+0x2500) ++#define SECID2 (SECURITY_BASE+0x2504) ++#define SECCHK1 (SECURITY_BASE+0x2520) ++#define SECCHK2 (SECURITY_BASE+0x2524) ++#define SECVAL1 (SECURITY_BASE+0x2540) ++#define SECVAL2 (SECURITY_BASE+0x2544) ++ ++#define UNIQID2 (SECURITY_BASE+0x2700) ++#define UNIQID3 (SECURITY_BASE+0x2704) ++#define UNIQID4 (SECURITY_BASE+0x2708) ++#define UNIQID5 (SECURITY_BASE+0x270C) ++#define UNIQCHK2 (SECURITY_BASE+0x2710) ++#define USRFLG (SECURITY_BASE+0x2714) /* llandre tells me this is also a CPU model flag */ ++#define UNIQVAL2 (SECURITY_BASE+0x2720) ++#define UNIQVAL3 (SECURITY_BASE+0x2724) ++#define UNIQVAL4 (SECURITY_BASE+0x2728) ++#define TESTVAL (SECURITY_BASE+0x2744) ++#define TESTCHK (SECURITY_BASE+0x2754) ++#define ACHK1 (SECURITY_BASE+0x27A0) ++#define ACHK2 (SECURITY_BASE+0x27A4) ++#define PROCRESET (SECURITY_BASE+0x27A8) ++#define TESTIDR (SECURITY_BASE+0x27AC) ++#define AVAL1 (SECURITY_BASE+0x27B0) ++#define AVAL2 (SECURITY_BASE+0x27B4) ++#define AID1 (SECURITY_BASE+0x27C4) ++#define AID2 (SECURITY_BASE+0x27C8) ++#define ADYNREMAP (SECURITY_BASE+0x27D0) ++#define ALTTMP (SECURITY_BASE+0x27D4) ++#define PROCSIGN (SECURITY_BASE+0x27F0) ++ ++#define ECLIDX (SECURITY_BASE+0x2800) ++#define ECLINE0 (SECURITY_BASE+0x2810) ++#define ECLINE1 (SECURITY_BASE+0x2814) ++#define ECLINE2 (SECURITY_BASE+0x2818) ++#define ECLINE3 (SECURITY_BASE+0x281C) ++#define ECLINE4 (SECURITY_BASE+0x2820) ++#define ECLINE5 (SECURITY_BASE+0x2824) ++#define ECLINE6 (SECURITY_BASE+0x2828) ++#define ECLINE7 (SECURITY_BASE+0x282C) ++#define ETWIDX1 (SECURITY_BASE+0x2840) ++#define ETWL1 (SECURITY_BASE+0x2844) ++#define ETWIDX2 (SECURITY_BASE+0x2848) ++#define ETWL2 (SECURITY_BASE+0x284C) ++ ++#define ETSPT10 (SECURITY_BASE+0x4000) ++#define ETSPT11 (SECURITY_BASE+0x4004) ++#define ETSPT12 (SECURITY_BASE+0x4008) ++#define ETSPT13 (SECURITY_BASE+0x400C) ++ ++#define ETSPT2000 (SECURITY_BASE+0x6000) ++#define ETSPT2020 (SECURITY_BASE+0x6020) ++#define ETSPT2024 (SECURITY_BASE+0x6024) ++ ++/* 8084_0000 - 8084_ffff: GPIO */ ++#define GPIO_OFFSET 0x040000 ++#define GPIO_BASE (EP93XX_APB_BASE|GPIO_OFFSET) ++#define GPIO_PADR (GPIO_BASE+0x00) ++#define GPIO_PBDR (GPIO_BASE+0x04) ++#define GPIO_PCDR (GPIO_BASE+0x08) ++ ++/* For support EP9301 - EP9302 arch */ ++ ++#if !defined(CONFIG_ARCH_EP9301) && !defined (CONFIG_ARCH_EP9302) ++#define GPIO_PDDR (GPIO_BASE+0x0C) ++#endif ++ ++#define GPIO_PADDR (GPIO_BASE+0x10) ++#define GPIO_PBDDR (GPIO_BASE+0x14) ++#define GPIO_PCDDR (GPIO_BASE+0x18) ++ ++/* For support EP9301 - EP9302 arch */ ++ ++#if !defined(CONFIG_ARCH_EP9301) && !defined (CONFIG_ARCH_EP9302) ++#define GPIO_PDDDR (GPIO_BASE+0x1C) ++#endif ++ ++#define GPIO_PEDR (GPIO_BASE+0x20) ++#define GPIO_PEDDR (GPIO_BASE+0x24) ++#define GPIO_PFDR (GPIO_BASE+0x30) ++#define GPIO_PFDDR (GPIO_BASE+0x34) ++#define GPIO_PGDR (GPIO_BASE+0x38) ++#define GPIO_PGDDR (GPIO_BASE+0x3C) ++#define GPIO_PHDR (GPIO_BASE+0x40) ++#define GPIO_PHDDR (GPIO_BASE+0x44) ++#define GPIO_INTTYPE1 (GPIO_BASE+0x4C) ++#define GPIO_INTTYPE2 (GPIO_BASE+0x50) ++#define GPIO_FEOI (GPIO_BASE+0x54) /* WRITE ONLY - READ UNDEFINED */ ++#define GPIO_INTEN (GPIO_BASE+0x58) ++#define GPIO_INTSTATUS (GPIO_BASE+0x5C) ++#define GPIO_RAWINTSTASUS (GPIO_BASE+0x60) ++#define GPIO_FDB (GPIO_BASE+0x64) ++#define GPIO_PAPINDR (GPIO_BASE+0x68) ++#define GPIO_PBPINDR (GPIO_BASE+0x6C) ++#define GPIO_PCPINDR (GPIO_BASE+0x70) ++#define GPIO_PDPINDR (GPIO_BASE+0x74) ++#define GPIO_PEPINDR (GPIO_BASE+0x78) ++#define GPIO_PFPINDR (GPIO_BASE+0x7C) ++#define GPIO_PGPINDR (GPIO_BASE+0x80) ++#define GPIO_PHPINDR (GPIO_BASE+0x84) ++#define GPIO_AINTTYPE1 (GPIO_BASE+0x90) ++#define GPIO_AINTTYPE2 (GPIO_BASE+0x94) ++#define GPIO_AEOI (GPIO_BASE+0x98) /* WRITE ONLY - READ UNDEFINED */ ++#define GPIO_AINTEN (GPIO_BASE+0x9C) ++#define GPIO_INTSTATUSA (GPIO_BASE+0xA0) ++#define GPIO_RAWINTSTSTISA (GPIO_BASE+0xA4) ++#define GPIO_ADB (GPIO_BASE+0xA8) ++#define GPIO_BINTTYPE1 (GPIO_BASE+0xAC) ++#define GPIO_BINTTYPE2 (GPIO_BASE+0xB0) ++#define GPIO_BEOI (GPIO_BASE+0xB4) /* WRITE ONLY - READ UNDEFINED */ ++#define GPIO_BINTEN (GPIO_BASE+0xB8) ++#define GPIO_INTSTATUSB (GPIO_BASE+0xBC) ++#define GPIO_RAWINTSTSTISB (GPIO_BASE+0xC0) ++#define GPIO_BDB (GPIO_BASE+0xC4) ++#define GPIO_EEDRIVE (GPIO_BASE+0xC8) ++/*#define Reserved (GPIO_BASE+0xCC) */ ++#define GPIO_TCR (GPIO_BASE+0xD0) /* Test Registers */ ++#define GPIO_TISRA (GPIO_BASE+0xD4) /* Test Registers */ ++#define GPIO_TISRB (GPIO_BASE+0xD8) /* Test Registers */ ++#define GPIO_TISRC (GPIO_BASE+0xDC) /* Test Registers */ ++#define GPIO_TISRD (GPIO_BASE+0xE0) /* Test Registers */ ++#define GPIO_TISRE (GPIO_BASE+0xE4) /* Test Registers */ ++#define GPIO_TISRF (GPIO_BASE+0xE8) /* Test Registers */ ++#define GPIO_TISRG (GPIO_BASE+0xEC) /* Test Registers */ ++#define GPIO_TISRH (GPIO_BASE+0xF0) /* Test Registers */ ++#define GPIO_TCER (GPIO_BASE+0xF4) /* Test Registers */ ++ ++/* 8088_0000 - 8088_ffff: Ac97 Controller (AAC) */ ++#define AC97_OFFSET 0x080000 ++#define AC97_BASE (EP93XX_APB_BASE|AC97_OFFSET) ++#define AC97DR1 (AC97_BASE+0x00) /* 8088.0000 R/W Data read or written from/to FIFO1 */ ++#define AC97RXCR1 (AC97_BASE+0x04) /* 8088.0004 R/W Control register for receive */ ++#define AC97TXCR1 (AC97_BASE+0x08) /* 8088.0008 R/W Control register for transmit */ ++#define AC97SR1 (AC97_BASE+0x0C) /* 8088.000C R Status register */ ++#define AC97RISR1 (AC97_BASE+0x10) /* 8088.0010 R Raw interrupt status register */ ++#define AC97ISR1 (AC97_BASE+0x14) /* 8088.0014 R Interrupt Status */ ++#define AC97IE1 (AC97_BASE+0x18) /* 8088.0018 R/W Interrupt Enable */ ++#define AC97DR2 (AC97_BASE+0x20) /* 8088.0020 R/W Data read or written from/to FIFO2 */ ++#define AC97RXCR2 (AC97_BASE+0x24) /* 8088.0024 R/W Control register for receive */ ++#define AC97TXCR2 (AC97_BASE+0x28) /* 8088.0028 R/W Control register for transmit */ ++#define AC97SR2 (AC97_BASE+0x2C) /* 8088.002C R Status register */ ++#define AC97RISR2 (AC97_BASE+0x30) /* 8088.0030 R Raw interrupt status register */ ++#define AC97ISR2 (AC97_BASE+0x34) /* 8088.0034 R Interrupt Status */ ++#define AC97IE2 (AC97_BASE+0x38) /* 8088.0038 R/W Interrupt Enable */ ++#define AC97DR3 (AC97_BASE+0x40) /* 8088.0040 R/W Data read or written from/to FIFO3. */ ++#define AC97RXCR3 (AC97_BASE+0x44) /* 8088.0044 R/W Control register for receive */ ++#define AC97TXCR3 (AC97_BASE+0x48) /* 8088.0048 R/W Control register for transmit */ ++#define AC97SR3 (AC97_BASE+0x4C) /* 8088.004C R Status register */ ++#define AC97RISR3 (AC97_BASE+0x50) /* 8088.0050 R Raw interrupt status register */ ++#define AC97ISR3 (AC97_BASE+0x54) /* 8088.0054 R Interrupt Status */ ++#define AC97IE3 (AC97_BASE+0x58) /* 8088.0058 R/W Interrupt Enable */ ++#define AC97DR4 (AC97_BASE+0x60) /* 8088.0060 R/W Data read or written from/to FIFO4. */ ++#define AC97RXCR4 (AC97_BASE+0x64) /* 8088.0064 R/W Control register for receive */ ++#define AC97TXCR4 (AC97_BASE+0x68) /* 8088.0068 R/W Control register for transmit */ ++#define AC97SR4 (AC97_BASE+0x6C) /* 8088.006C R Status register */ ++#define AC97RISR4 (AC97_BASE+0x70) /* 8088.0070 R Raw interrupt status register */ ++#define AC97ISR4 (AC97_BASE+0x74) /* 8088.0074 R Interrupt Status */ ++#define AC97IE4 (AC97_BASE+0x78) /* 8088.0078 R/W Interrupt Enable */ ++#define AC97S1DATA (AC97_BASE+0x80) /* 8088.0080 R/W Data received/transmitted on SLOT1 */ ++#define AC97S2DATA (AC97_BASE+0x84) /* 8088.0084 R/W Data received/transmitted on SLOT2 */ ++#define AC97S12DATA (AC97_BASE+0x88) /* 8088.0088 R/W Data received/transmitted on SLOT12 */ ++#define AC97RGIS (AC97_BASE+0x8C) /* 8088.008C R/W Raw Global interrupt status register */ ++#define AC97GIS (AC97_BASE+0x90) /* 8088.0090 R Global interrupt status register */ ++#define AC97IM (AC97_BASE+0x94) /* 8088.0094 R/W Interrupt mask register */ ++#define AC97EOI (AC97_BASE+0x98) /* 8088.0098 W Interrupt clear register */ ++#define AC97GCR (AC97_BASE+0x9C) /* 8088.009C R/W Main Control register */ ++#define AC97RESET (AC97_BASE+0xA0) /* 8088.00A0 R/W RESET control register. */ ++#define AC97SYNC (AC97_BASE+0xA4) /* 8088.00A4 R/W SYNC control register. */ ++#define AC97GCIS (AC97_BASE+0xA8) /* 8088.00A8 R Global chan FIFO int status register */ ++ ++/* 808A_0000 - 808A_ffff: SSP */ ++#define SSP_OFFSET 0x0A0000 ++#define SSP_BASE (EP93XX_APB_BASE|SSP_OFFSET) ++#define SSPCR0 (SSP_BASE+0x00) ++#define SSPCR1 (SSP_BASE+0x04) ++#define SSPDR (SSP_BASE+0x08) ++#define SSPSR (SSP_BASE+0x0c) ++#define SSPCPSR (SSP_BASE+0x10) ++#define SSPIIR (SSP_BASE+0x14) ++#define SSPICR (SSP_BASE+0x14) ++ ++/* 808B_0000 - 808B_ffff: IrDA */ ++#define IRDA_OFFSET 0x0B0000 ++#define IRDA_BASE (EP93XX_APB_BASE|IRDA_OFFSET) ++#define IrEnable (IRDA_BASE+0x00) ++#define IrCtrl (IRDA_BASE+0x04) ++#define IrAdrMatchVal (IRDA_BASE+0x08) ++#define IrFlag (IRDA_BASE+0x0C) ++#define IrData (IRDA_BASE+0x10) ++#define IrDataTail1 (IRDA_BASE+0x14) ++#define IrDataTail2 (IRDA_BASE+0x18) ++#define IrDataTail3 (IRDA_BASE+0x1c) ++#define IrRIB (IRDA_BASE+0x20) ++#define IrTR0 (IRDA_BASE+0x24) ++#define IrDMACR (IRDA_BASE+0x28) ++#define SIRTR0 (IRDA_BASE+0x30) ++#define MISR (IRDA_BASE+0x80) ++#define MIMR (IRDA_BASE+0x84) ++#define MIIR (IRDA_BASE+0x88) ++#define FISR (IRDA_BASE+0x180) ++#define FIMR (IRDA_BASE+0x184) ++#define FIIR (IRDA_BASE+0x188) ++ ++/* 808C_0000 - 808C_ffff: UART1 */ ++#define UART1_OFFSET 0x0C0000 ++#define UART1_BASE (EP93XX_APB_BASE|UART1_OFFSET) ++#define UART1DR (UART1_BASE+0x000) ++#define UART1RSR (UART1_BASE+0x004) ++#define UART1ECR (UART1_BASE+0x004) ++#define UART1CR_H (UART1_BASE+0x008) ++#define UART1CR_M (UART1_BASE+0x00C) ++#define UART1CR_L (UART1_BASE+0x010) ++#define UART1CR (UART1_BASE+0x014) ++#define UART1FR (UART1_BASE+0x018) ++#define UART1IIR (UART1_BASE+0x01C) ++#define UART1ICR (UART1_BASE+0x01C) ++#define UART1ILPR (UART1_BASE+0x020) ++#define UART1DMACR (UART1_BASE+0x028) ++#define UART1TMR (UART1_BASE+0x084) ++#define UART1MCR (UART1_BASE+0x100) ++#define UART1MSR (UART1_BASE+0x104) ++#define UART1TCR (UART1_BASE+0x108) ++#define UART1TISR (UART1_BASE+0x10C) ++#define UART1TOCR (UART1_BASE+0x110) ++#define HDLC1CR (UART1_BASE+0x20c) ++#define HDLC1AMV (UART1_BASE+0x210) ++#define HDLC1AMSK (UART1_BASE+0x214) ++#define HDLC1RIB (UART1_BASE+0x218) ++#define HDLC1SR (UART1_BASE+0x21c) ++ ++/* 808d_0000 - 808d_ffff: UART2 */ ++#define UART2_OFFSET 0x0D0000 ++#define UART2_BASE (EP93XX_APB_BASE|UART2_OFFSET) ++#define UART2DR (UART2_BASE+0x00) ++#define UART2RSR (UART2_BASE+0x04) /* Read */ ++#define UART2ECR (UART2_BASE+0x04) /* Write */ ++#define UART2CR_H (UART2_BASE+0x08) ++#define UART2CR_M (UART2_BASE+0x0C) ++#define UART2CR_L (UART2_BASE+0x10) ++#define UART2CR (UART2_BASE+0x14) ++#define UART2FR (UART2_BASE+0x18) ++#define UART2IIR (UART2_BASE+0x1C) /* Read */ ++#define UART2ICR (UART2_BASE+0x1C) /* Write */ ++#define UART2ILPR (UART2_BASE+0x20) ++#define UART2DMACR (UART2_BASE+0x28) ++#define UART2TMR (UART2_BASE+0x84) ++ ++/* 808e_0000 - 808e_ffff: UART3 */ ++#define UART3_OFFSET 0x0E0000 ++#define UART3_BASE (EP93XX_APB_BASE|UART3_OFFSET) ++#define UART3DR (UART3_BASE+0x00) ++#define UART3RSR (UART3_BASE+0x04) /* Read */ ++#define UART3ECR (UART3_BASE+0x04) /* Write */ ++#define UART3CR_H (UART3_BASE+0x08) ++#define UART3CR_M (UART3_BASE+0x0C) ++#define UART3CR_L (UART3_BASE+0x10) ++#define UART3CR (UART3_BASE+0x14) ++#define UART3FR (UART3_BASE+0x18) ++#define UART3IIR (UART3_BASE+0x1C) /* Read */ ++#define UART3ICR (UART3_BASE+0x1C) /* Write */ ++#define UART3ILPR (UART3_BASE+0x20) ++#define UART3DMACR (UART3_BASE+0x28) ++#define UART3TCR (UART3_BASE+0x80) ++#define UART3TISR (UART3_BASE+0x88) ++#define UART3TOCR (UART3_BASE+0x8C) ++#define UART3TMR (UART3_BASE+0x84) ++#define UART3MCR (UART3_BASE+0x100) /* Modem Control Reg */ ++#define UART3MSR (UART3_BASE+0x104) /* Modem Status Reg */ ++#define UART3HDLCCR (UART3_BASE+0x20C) /* HDLC Registers */ ++#define UART3HDLCAMV (UART3_BASE+0x210) /* HDLC Registers */ ++#define UART3HDLCAMSK (UART3_BASE+0x214) /* HDLC Registers */ ++#define UART3HDLCCRIB (UART3_BASE+0x218) /* HDLC Registers */ ++#define UART3HDLCSR (UART3_BASE+0x21C) /* HDLC Registers */ ++ ++/* 808f_0000 - 808f_ffff: KEY Matrix */ ++#define KEY_OFFSET 0x0F0000 ++#define KEY_BASE (EP93XX_APB_BASE|KEY_OFFSET) ++#define SCANINIT (KEY_BASE+0x00) ++#define KEY_DIAG (KEY_BASE+0x04) ++#define KEY_REG (KEY_BASE+0x08) ++#define KEY_TCR (KEY_BASE+0x10) ++#define KEY_TISR (KEY_BASE+0x14) ++#define KEY_TOCR (KEY_BASE+0x18) ++ ++/* 8090_0000 - 8090_ffff: Analog Resistive Touchscreen */ ++#define TOUCH_OFFSET 0x100000 ++#define TOUCH_BASE (EP93XX_APB_BASE|TOUCH_OFFSET) ++#define TSSetup (TOUCH_BASE+0x00) /* R/W touchscreen controller setup control register. */ ++#define TSXYMaxMin (TOUCH_BASE+0x04) /* R/W touchscreen controller max/min register. */ ++#define TSXYResult (TOUCH_BASE+0x08) /* R touchscreen controller result register. */ ++#define TSDischarge (TOUCH_BASE+0x0C) /* LOCKED R/W touchscreen Switch Matrix control register. */ ++#define TSXSample (TOUCH_BASE+0x10) /* LOCKED R/W touchscreen Switch Matrix control register. */ ++#define TSYSample (TOUCH_BASE+0x14) /* LOCKED R/W touchscreen Switch Matrix control register. */ ++#define TSDirect (TOUCH_BASE+0x18) /* LOCKED R/W touchscreen Switch Matrix control register. */ ++#define TSDetect (TOUCH_BASE+0x1C) /* LOCKED R/W touchscreen Switch Matrix control register. */ ++#define TSSWLock (TOUCH_BASE+0x20) /* NA R/W touchscreen software lock register. */ ++#define TSSetup2 (TOUCH_BASE+0x24) /* R/W touchscreen setup control register #2. */ ++ ++/* 8091_0000 - 8091_ffff: PWM */ ++#define PWM_OFFSET 0x110000 ++#define PWM_BASE (EP93XX_APB_BASE|PWM_OFFSET) ++#define PWM0_TC (PWM_BASE+0x00) /* 80910000 R/W PWM_0 Terminal Count */ ++#define PWM0_DC (PWM_BASE+0x04) /* 80910004 R/W PWM_0 Duty Cycle */ ++#define PWM0_EN (PWM_BASE+0x08) /* 80910008 R/W PWM_0 Enable */ ++#define PWM0_INV (PWM_BASE+0x0C) /* 8091000C R/W PWM_0 Invert */ ++#define PWM0_SYNC (PWM_BASE+0x10) /* 80910010 R/W PWM_0 Synchronous */ ++#define PWM1_TC (PWM_BASE+0x20) /* 80910020 R/W PWM_1 Terminal Count */ ++#define PWM1_DC (PWM_BASE+0x24) /* 80910024 R/W PWM_1 Duty Cycle */ ++#define PWM1_EN (PWM_BASE+0x28) /* 80910028 R/W PWM_1 Enable */ ++#define PWM1_INV (PWM_BASE+0x2C) /* 8091002C R/W PWM_1 Invert */ ++#define PWM1_SYNC (PWM_BASE+0x30) /* 80910030 R/W PWM_1 Synchronous */ ++ ++/* 8092_0000 - 8092_ffff: RTC */ ++#define RTC_OFFSET 0x120000 ++#define RTC_BASE (EP93XX_APB_BASE|RTC_OFFSET) ++#define RTCDR (RTC_BASE+0x00) ++#define RTCMR (RTC_BASE+0x04) ++#define RTCSTAT (RTC_BASE+0x08) /* Read */ ++#define RTCEOI (RTC_BASE+0x08) /* Write */ ++#define RTCLR (RTC_BASE+0x0C) ++#define RTCCR (RTC_BASE+0x10) ++#define RTCSCOMP (RTC_BASE+0x108) ++ ++/* 8093_0000 - 8093_ffff: CSC/Syscon PLL, clock control, & misc. stuff */ ++#define SYSCON_OFFSET 0x130000 ++#define SYSCON_BASE (EP93XX_APB_BASE|SYSCON_OFFSET) ++#define SYSCON_PWRSR (SYSCON_BASE+0x0000) ++#define SYSCON_PWRCNT (SYSCON_BASE+0x0004) ++#define SYSCON_HALT (SYSCON_BASE+0x0008) ++#define SYSCON_STBY (SYSCON_BASE+0x000c) ++#define SYSCON_BLEOI (SYSCON_BASE+0x0010) ++#define SYSCON_MCEOI (SYSCON_BASE+0x0014) ++#define SYSCON_TEOI (SYSCON_BASE+0x0018) ++#define SYSCON_STFCLR (SYSCON_BASE+0x001c) ++#define SYSCON_CLKSET1 (SYSCON_BASE+0x0020) ++#define SYSCON_CLKSET2 (SYSCON_BASE+0x0024) ++#define SYSCON_RESV00 (SYSCON_BASE+0x0028) ++#define SYSCON_RESV01 (SYSCON_BASE+0x002c) ++#define SYSCON_RESV02 (SYSCON_BASE+0x0030) ++#define SYSCON_RESV03 (SYSCON_BASE+0x0034) ++#define SYSCON_RESV04 (SYSCON_BASE+0x0038) ++#define SYSCON_RESV05 (SYSCON_BASE+0x003c) ++#define SYSCON_SCRREG0 (SYSCON_BASE+0x0040) ++#define SYSCON_SCRREG1 (SYSCON_BASE+0x0044) ++#define SYSCON_CLKTEST (SYSCON_BASE+0x0048) ++#define SYSCON_USBRESET (SYSCON_BASE+0x004c) ++#define SYSCON_APBWAIT (SYSCON_BASE+0x0050) ++#define SYSCON_BMAR (SYSCON_BASE+0x0054) ++#define SYSCON_BOOTCLR (SYSCON_BASE+0x0058) ++#define SYSCON_DEVCFG (SYSCON_BASE+0x0080) ++#define SYSCON_VIDDIV (SYSCON_BASE+0x0084) ++#define SYSCON_MIRDIV (SYSCON_BASE+0x0088) ++#define SYSCON_I2SDIV (SYSCON_BASE+0x008C) ++#define SYSCON_KTDIV (SYSCON_BASE+0x0090) ++#define SYSCON_CHIPID (SYSCON_BASE+0x0094) ++#define SYSCON_TSTCR (SYSCON_BASE+0x0098) ++#define SYSCON_SYSCFG (SYSCON_BASE+0x009C) ++#define SYSCON_SWLOCK (SYSCON_BASE+0x00C0) ++ ++#define SYSCON_DEVCFG_KEYS 0x00000002 ++#define SYSCON_DEVCFG_RasOnP3 0x00000010 ++#define SYSCON_DEVCFG_GONK 0x08000000 ++ ++#define SYSCON_KTDIV_KEN 0x00008000 ++ ++/* 8094_0000 - 8094_ffff: Watchdog */ ++#define WATCHDOG_OFFSET 0x140000 ++#define WATCHDOG_BASE (EP93XX_APB_BASE|WATCHDOG_OFFSET) ++#define WATCHDOG (WATCHDOG_BASE+0x00) ++#define WDSTATUS (WATCHDOG_BASE+0x04) ++ ++#endif /* __ASM_ARCH_HARDWARE_H */ +diff --git a/include/asm-arm/arch-ep93xx/regs_ac97.h b/include/asm-arm/arch-ep93xx/regs_ac97.h +new file mode 100644 +index 0000000..efe0015 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_ac97.h +@@ -0,0 +1,168 @@ ++/*============================================================================= ++ * FILE: regs_ac97.h ++ * ++ * DESCRIPTION: Ac'97 Register Definition ++ * ++ * Copyright Cirrus Logic, 2001-2003 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ *============================================================================= ++ */ ++#ifndef _REGS_AC97_H_ ++#define _REGS_AC97_H_ ++ ++/* Bit definitionses */ ++#define AC97ISR_RIS 8 ++#define AC97ISR_TIS 4 ++#define AC97ISR_RTIS 2 ++#define AC97ISR_TCIS 1 ++ ++#define AC97RGIS_SLOT1TXCOMPLETE 0x01 ++#define AC97RGIS_SLOT2RXVALID 0x02 ++#define AC97RGIS_GPIOTXCOMPLETE 0x04 ++#define AC97RGIS_GPIOINTRX 0x08 ++#define AC97RGIS_RWIS 0x10 ++#define AC97RGIS_CODECREADY 0x20 ++#define AC97RGIS_SLOT2TXCOMPLETE 0x40 ++ ++#define AC97SR_RXFE 0x0001 ++#define AC97SR_TXFE 0x0002 ++#define AC97SR_RXFF 0x0004 ++#define AC97SR_TXFF 0x0008 ++#define AC97SR_TXBUSY 0x0010 ++#define AC97SR_RXOE 0x0020 ++#define AC97SR_TXUE 0x0040 ++ ++#define AC97GSR_IFE 0x1 ++#define AC97GSR_LOOP 0x2 ++#define AC97GSR_OVERRIDECODECREADY 0x4 ++ ++#define AC97RESET_TIMEDRESET 0x1 ++#define AC97RESET_FORCEDRESET 0x2 ++#define AC97RESET_EFORCER 0x4 ++ ++#define AC97RXCR_REN 0x1 ++ ++#define AC97TXCR_TEN 0x1 ++ ++/* ++ * The Ac97 Codec registers, accessable through the Ac-link. ++ * These are not controller registers and are not memory mapped. ++ * Includes registers specific to CS4202 (Beavis). ++ */ ++#define AC97_REG_OFFSET_MASK 0x0000007E ++ ++#define AC97_00_RESET 0x00000000 ++#define AC97_02_MASTER_VOL 0x00000002 ++#define AC97_04_HEADPHONE_VOL 0x00000004 ++#define AC97_06_MONO_VOL 0x00000006 ++#define AC97_08_TONE 0x00000008 ++#define AC97_0A_PC_BEEP_VOL 0x0000000A ++#define AC97_0C_PHONE_VOL 0x0000000C ++#define AC97_0E_MIC_VOL 0x0000000E ++#define AC97_10_LINE_IN_VOL 0x00000010 ++#define AC97_12_CD_VOL 0x00000012 ++#define AC97_14_VIDEO_VOL 0x00000014 ++#define AC97_16_AUX_VOL 0x00000016 ++#define AC97_18_PCM_OUT_VOL 0x00000018 ++#define AC97_1A_RECORD_SELECT 0x0000001A ++#define AC97_1C_RECORD_GAIN 0x0000001C ++#define AC97_1E_RESERVED_1E 0x0000001E ++#define AC97_20_GENERAL_PURPOSE 0x00000020 ++#define AC97_22_3D_CONTROL 0x00000022 ++#define AC97_24_MODEM_RATE 0x00000024 ++#define AC97_26_POWERDOWN 0x00000026 ++#define AC97_28_EXT_AUDIO_ID 0x00000028 ++#define AC97_2A_EXT_AUDIO_POWER 0x0000002A ++#define AC97_2C_PCM_FRONT_DAC_RATE 0x0000002C ++#define AC97_2E_PCM_SURR_DAC_RATE 0x0000002E ++#define AC97_30_PCM_LFE_DAC_RATE 0x00000030 ++#define AC97_32_PCM_LR_ADC_RATE 0x00000032 ++#define AC97_34_MIC_ADC_RATE 0x00000034 ++#define AC97_36_6CH_VOL_C_LFE 0x00000036 ++#define AC97_38_6CH_VOL_SURROUND 0x00000038 ++#define AC97_3A_SPDIF_CONTROL 0x0000003A ++#define AC97_3C_EXT_MODEM_ID 0x0000003C ++#define AC97_3E_EXT_MODEM_POWER 0x0000003E ++#define AC97_40_LINE1_CODEC_RATE 0x00000040 ++#define AC97_42_LINE2_CODEC_RATE 0x00000042 ++#define AC97_44_HANDSET_CODEC_RATE 0x00000044 ++#define AC97_46_LINE1_CODEC_LEVEL 0x00000046 ++#define AC97_48_LINE2_CODEC_LEVEL 0x00000048 ++#define AC97_4A_HANDSET_CODEC_LEVEL 0x0000004A ++#define AC97_4C_GPIO_PIN_CONFIG 0x0000004C ++#define AC97_4E_GPIO_PIN_TYPE 0x0000004E ++#define AC97_50_GPIO_PIN_STICKY 0x00000050 ++#define AC97_52_GPIO_PIN_WAKEUP 0x00000052 ++#define AC97_54_GPIO_PIN_STATUS 0x00000054 ++#define AC97_56_RESERVED 0x00000056 ++#define AC97_58_RESERVED 0x00000058 ++#define AC97_5A_CRYSTAL_REV_N_FAB_ID 0x0000005A ++#define AC97_5C_TEST_AND_MISC_CTRL 0x0000005C ++#define AC97_5E_AC_MODE 0x0000005E ++#define AC97_60_MISC_CRYSTAL_CONTROL 0x00000060 ++#define AC97_62_VENDOR_RESERVED 0x00000062 ++#define AC97_64_DAC_SRC_PHASE_INCR 0x00000064 ++#define AC97_66_ADC_SRC_PHASE_INCR 0x00000066 ++#define AC97_68_RESERVED_68 0x00000068 ++#define AC97_6A_SERIAL_PORT_CONTROL 0x0000006A ++#define AC97_6C_VENDOR_RESERVED 0x0000006C ++#define AC97_6E_VENDOR_RESERVED 0x0000006E ++#define AC97_70_BDI_CONFIG 0x00000070 ++#define AC97_72_BDI_WAKEUP 0x00000072 ++#define AC97_74_VENDOR_RESERVED 0x00000074 ++#define AC97_76_CAL_ADDRESS 0x00000076 ++#define AC97_78_CAL_DATA 0x00000078 ++#define AC97_7A_VENDOR_RESERVED 0x0000007A ++#define AC97_7C_VENDOR_ID1 0x0000007C ++#define AC97_7E_VENDOR_ID2 0x0000007E ++ ++#ifndef __ASSEMBLY__ ++ ++/* enum type for use with reg AC97_RECORD_SELECT */ ++enum Ac97RecordSources { ++ RECORD_MIC = 0x0000, ++ RECORD_CD = 0x0101, ++ RECORD_VIDEO_IN = 0x0202, ++ RECORD_AUX_IN = 0x0303, ++ RECORD_LINE_IN = 0x0404, ++ RECORD_STEREO_MIX = 0x0505, ++ RECORD_MONO_MIX = 0x0606, ++ RECORD_PHONE_IN = 0x0707 ++}; ++ ++#endif /* __ASSEMBLY__ */ ++ ++/* ++ * Sample rates supported directly in AC97_PCM_FRONT_DAC_RATE and ++ * AC97_PCM_LR_ADC_RATE. ++ */ ++#define Ac97_Fs_8000 0x1f40 ++#define Ac97_Fs_11025 0x2b11 ++#define Ac97_Fs_16000 0x3e80 ++#define Ac97_Fs_22050 0x5622 ++#define Ac97_Fs_32000 0x7d00 ++#define Ac97_Fs_44100 0xac44 ++#define Ac97_Fs_48000 0xbb80 ++ ++/* ++ * RSIZE and TSIZE in AC97RXCR and AC97TXCR ++ */ ++#define Ac97_SIZE_20 2 ++#define Ac97_SIZE_18 1 ++#define Ac97_SIZE_16 0 ++#define Ac97_SIZE_12 3 ++ ++#endif /* _REGS_AC97_H_ */ +diff --git a/include/asm-arm/arch-ep93xx/regs_dma.h b/include/asm-arm/arch-ep93xx/regs_dma.h +new file mode 100644 +index 0000000..926965d +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_dma.h +@@ -0,0 +1,269 @@ ++/***************************************************************************** ++ * ++ * linux/include/asm-arm/arch-ep93xx/regs_dma.h ++ * ++ * Register definitions for the ep93xx dma channel registers. ++ * ++ * Copyright (C) 2003 Cirrus Logic ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ ****************************************************************************/ ++#ifndef _REGS_DMA_H_ ++#define _REGS_DMA_H_ ++ ++/***************************************************************************** ++ * 0x8000.0000 -> 0x8000.003C M2P Channel 0 Registers (Tx) ++ * 0x8000.0040 -> 0x8000.007C M2P Channel 1 Registers (Rx) ++ * 0x8000.0080 -> 0x8000.00BC M2P Channel 2 Registers (Tx) ++ * 0x8000.00C0 -> 0x8000.00FC M2P Channel 3 Registers (Rx) ++ * 0x8000.0100 -> 0x8000.013C M2M Channel 0 Registers ++ * 0x8000.0140 -> 0x8000.017C M2M Channel 1 Registers ++ * 0x8000.0180 -> 0x8000.01BC Not Used ++ * 0x8000.01C0 -> 0x8000.01FC Not Used ++ * 0x8000.0200 -> 0x8000.023C M2P Channel 5 Registers (Rx) ++ * 0x8000.0240 -> 0x8000.027C M2P Channel 4 Registers (Tx) ++ * 0x8000.0280 -> 0x8000.02BC M2P Channel 7 Registers (Rx) ++ * 0x8000.02C0 -> 0x8000.02FC M2P Channel 6 Registers (Tx) ++ * 0x8000.0300 -> 0x8000.033C M2P Channel 9 Registers (Rx) ++ * 0x8000.0340 -> 0x8000.037C M2P Channel 8 Registers (Tx) ++ * 0x8000.0380 DMA Channel Arbitration register ++ * 0x8000.03C0 DMA Global Interrupt register ++ * 0x8000.03C4 -> 0x8000.03FC Not Used ++ * ++ * ++ * Internal M2P/P2M Channel Register Map ++ * ++ * Offset Name Access Bits Reset Value ++ * 0x00 CONTROL R/W 6 0 ++ * 0x04 INTERRUPT R/W TC* 3 0 ++ * 0x08 PPALLOC R/W 4 channel dependant ++ * (see reg description) ++ * 0x0C STATUS RO 8 0 ++ * 0x10 reserved ++ * 0x14 REMAIN RO 16 0 ++ * 0X18 Reserved ++ * 0X1C Reserved ++ * 0x20 MAXCNT0 R/W 16 0 ++ * 0x24 BASE0 R/W 32 0 ++ * 0x28 CURRENT0 RO 32 0 ++ * 0x2C Reserved ++ * 0x30 MAXCNT1 R/W 16 0 ++ * 0x34 BASE1 R/W 32 0 ++ * 0X38 CURRENT1 RO 32 0 ++ * 0X3C Reserved ++ * ++ * M2M Channel Register Map ++ * Offset Name Access Bits Reset Value ++ * ++ * 0x00 CONTROL R/W 22 0 ++ * 0x04 INTERRUPT R/W TC* 3 0 ++ * 0x08 Reserved ++ * 0x0C STATUS R/W TC* 14 0 ++ * 0x10 BCR0 R/W 16 0 ++ * 0x14 BCR1 R/W 16 0 ++ * 0x18 SAR_BASE0 R/W 32 0 ++ * 0x1C SAR_BASE1 R/W 32 0 ++ * 0x20 Reserved ++ * 0x24 SAR_CURRENT0 RO 32 0 ++ * 0x28 SAR_CURRENT1 RO 32 0 ++ * 0x2C DAR_BASE0 R/W 32 0 ++ * 0x30 DAR_BASE1 R/W 32 0 ++ * 0x34 DAR_CURRENT0 RO 32 0 ++ * 0X38 Reserved ++ * 0X3C DAR_CURRENT1 RO 32 0 ++ * * Write this location once to clear the bit (see ++ * Interrupt/Status register description for which bits ++ * this rule applies to). ++ * ++ ****************************************************************************/ ++ ++#ifndef __ASSEMBLY__ ++/* ++ * DMA Register Base addresses ++ */ ++static unsigned int const DMAM2PChannelBase[10] = { ++ DMA_M2P_TX_0_BASE, ++ DMA_M2P_RX_1_BASE, ++ DMA_M2P_TX_2_BASE, ++ DMA_M2P_RX_3_BASE, ++ DMA_M2P_TX_4_BASE, ++ DMA_M2P_RX_5_BASE, ++ DMA_M2P_TX_6_BASE, ++ DMA_M2P_RX_7_BASE, ++ DMA_M2P_TX_8_BASE, ++ DMA_M2P_RX_9_BASE ++}; ++ ++static unsigned int const DMAM2MChannelBase[2] = { ++ DMA_M2M_0_BASE, ++ DMA_M2M_1_BASE ++}; ++ ++#endif /* __ASSEMBLY__ */ ++ ++/*----------------------------------------------------------------------------------*/ ++/* M2P Registers */ ++/*----------------------------------------------------------------------------------*/ ++/* ++ * M2P CONTROL register bit defines ++ */ ++#define CONTROL_M2P_STALLINTEN 0x00000001 /* Enables the STALL interrupt */ ++#define CONTROL_M2P_NFBINTEN 0x00000002 /* Enables the NFB interrupt */ ++#define CONTROL_M2P_CHERRORINTEN 0x00000008 /* Enables the ChError interrupt */ ++#define CONTROL_M2P_ENABLE 0x00000010 /* Enables the channel */ ++#define CONTROL_M2P_ABRT 0x00000020 /* Determines how DMA behaves in */ ++ /* NEXT state with peripheral */ ++ /* error */ ++ /* 0: NEXT -> ON, ignore error */ ++ /* 1: NEXT -> STALL, disable ch. */ ++#define CONTROL_M2P_ICE 0x00000040 /* Ignore Channel Error */ ++ ++/* ++ * M2P INTERRUPT register bit defines ++ */ ++#define INTERRUPT_M2P_STALLINT 0x00000001 /* Indicates channel stalled. */ ++#define INTERRUPT_M2P_NFBINT 0x00000002 /* Indicates channel is hungry. */ ++#define INTERRUPT_M2P_CHERRORINT 0x00000008 /* Peripheral detects error */ ++ ++/* ++ * STATUS register bit defines ++ */ ++#define STATUS_M2P_STALL 0x00000001 /* A '1' indicates channel is */ ++ /* stalled */ ++#define STATUS_M2P_NFB 0x00000002 /* A '1' indicates channel has moved */ ++ /* from NEXT state to ON state, but */ ++ /* waiting for next buffer to be */ ++ /* programmed. */ ++#define STATUS_M2P_CHERROR 0x00000008 /* Enables the ChError interrupt */ ++#define STATUS_M2P_CURRENT_MASK 0x00000030 /* Current state of the FSM */ ++#define STATUS_M2P_CURRENT_SHIFT 4 ++#define STATUS_M2P_NEXTBUFFER 0x00000040 /* Informs the int handler after an */ ++ /* NFB int which pair of maxcnt and */ ++ /* base regs to update. */ ++#define STATUS_M2P_BYTES_MASK 0x0000f800 /* number of valid DMA data */ ++#define STATUS_M2P_BYTES_SHIFT 7 /* currently in */ ++ /* packer/unpacker */ ++ ++#define STATUS_M2P_DMA_NO_BUF 0x00000000 ++#define STATUS_M2P_DMA_BUF_ON 0x00000010 ++#define STATUS_M2P_DMA_BUF_NEXT 0x00000020 ++ ++/* ++ * Register masks to mask off reserved bits after reading register. ++ */ ++#define M2P_MASK_PPALLOC 0x0000000f ++#define M2P_MASK_REMAIN 0x0000ffff ++#define M2P_MASK_MAXCNT0 0x0000ffff ++#define M2P_MASK_BASE0 0xffffffff ++#define M2P_MASK_CURRENT0 0xffffffff ++#define M2P_MASK_MAXCNT1 0x0000ffff ++#define M2P_MASK_BASE1 0xffffffff ++#define M2P_MASK_CURRENT1 0xffffffff ++ ++/*----------------------------------------------------------------------------------*/ ++/* M2M Registers */ ++/*----------------------------------------------------------------------------------*/ ++ ++#define CONTROL_M2M_STALLINTEN 0x00000001 /* Enables the STALL interrupt */ ++#define CONTROL_M2M_SCT 0x00000002 /* Source Copy Transfer. Setup a */ ++ /* block transfer from 1 memory source */ ++ /* location. */ ++#define CONTROL_M2M_DONEINTEN 0x00000004 /* Enables the DONE interrupt which */ ++ /* indicates if the xfer completed */ ++ /* successfully */ ++#define CONTROL_M2M_ENABLE 0x00000008 /* Enables the channel */ ++#define CONTROL_M2M_START 0x00000010 /* Initiates the xfer. 'software trigger' */ ++#define CONTROL_M2M_BWC_MASK 0x000001e0 /* Bandwidth control. Indicate number of */ ++#define CONTROL_M2M_BWC_SHIFT 5 /* bytes in a transfer. */ ++#define CONTROL_M2M_PW_MASK 0x00000600 /* Peripheral width. Used for xfers */ ++#define CONTROL_M2M_PW_SHIFT 9 /* between memory and external peripheral. */ ++ /* 00: byte, 01: halfword, 10: word. */ ++#define CONTROL_M2M_DAH 0x00000800 /* Destination Address Hold */ ++#define CONTROL_M2M_SAH 0x00001000 /* Source Address Hold */ ++#define CONTROL_M2M_TM_MASK 0x00006000 /* Transfer Mode. 00: sw triggered, */ ++#define CONTROL_M2M_TM_SHIFT 13 /* 01: hw initiated M2P, 01: hw initiated P2M */ ++#define CONTROL_M2M_ETDP_MASK 0x00018000 /* End-of-Transfer/Terminal Count pin */ ++#define CONTROL_M2M_ETDP_SHIFT 15 /* direction and polarity. */ ++#define CONTROL_M2M_DACKP 0x00020000 /* DMA acknowledge pin polarity */ ++ ++#define CONTROL_M2M_DREQP_MASK 0x00180000 /* DMA request pin polarity. must be set */ ++#define CONTROL_M2M_DREQP_SHIFT 19 /* before enable bit. */ ++#define CONTROL_M2M_NFBINTEN 0x00200000 /* Enables generation of the NFB interrupt. */ ++#define CONTROL_M2M_RSS_MASK 0x00c00000 /* Request source selection: */ ++#define CONTROL_M2M_RSS_SHIFT 22 /* 000 - External DReq[0] */ ++ /* 001 - External DReq[1] */ ++ /* 01X - Internal SSPRx */ ++ /* 10X - Internal SSPTx */ ++ /* 11X - Internal IDE */ ++#define CONTROL_M2M_NO_HDSK 0x01000000 /* No handshake. When set the peripheral doesn't */ ++ /* require the regular handshake protocal. Must */ ++ /* be set for SSP and IDE operations, optional */ ++ /* for external peripherals. */ ++#define CONTROL_M2M_PWSC_MASK 0xfe000000 /* Peripheral wait states count. Gives the latency */ ++#define CONTROL_M2M_PWSC_SHIFT 25 /* (in PCLK cycles) needed by the peripheral to */ ++ /* deassert its' request once the M2M xfer w/ DMA */ ++ /* is complete. */ ++ ++/* ++ * M2M INTERRUPT register bit defines ++ */ ++#define INTERRUPT_M2M_STALLINT 0x00000001 /* Stall interrupt indicates channel stalled. */ ++#define INTERRUPT_M2M_DONEINT 0x00000002 /* Transaction done. */ ++#define INTERRUPT_M2M_NFBINT 0x00000004 /* Next frame buffer interrupt indicates */ ++ /* channel requires a new buffer */ ++ ++/* ++ * M2M STATUS register bit defines ++ */ ++#define STATUS_M2M_STALL 0x00000001 /* A '1' indicates channel is stalled */ ++#define STATUS_M2M_CURRENTSTATE_MASK 0x0000003e /* Indicates state of M2M Channel control */ ++#define STATUS_M2M_CURRENTSTATE_SHIFT 1 /* FSM (0-2): */ ++ /* 000 - IDLE, 001 - STALL, 010 - MEM_RD, */ ++ /* 011 - MEM_WR, 100 - BWC_WAIT */ ++ /* and M2M buffer FSM (3-2): */ ++ /* 00 - NO_BUF, 01 - BUF_ON, 10 - BUF_NEXT */ ++#define STATUS_M2M_DONE 0x00000040 /* Transfer completed successfully if 1. */ ++#define STATUS_M2M_TCS_MASK 0x00000180 /* Terminal Count status. Indicates whether or */ ++#define STATUS_M2M_TCS_SHIFT 7 /* or not the actual byte count reached */ ++ /* programmed limit for buffer descriptor */ ++#define STATUS_M2M_EOTS_MASK 0x00000600 /* End-of-Transfer status for buffer */ ++#define STATUS_M2M_EOTS_SHIFT 9 ++#define STATUS_M2M_NFB 0x00000800 /* A '1' indicates channel has moved */ ++ /* from NEXT state to ON state, but the next */ ++ /* byte count reg for next buffer has not been */ ++ /* programmed yet. */ ++#define STATUS_M2M_NB 0x00001000 /* NextBuffer status. Informs NFB service */ ++ /* routine, after NFB int, which pair of buffer */ ++ /* descriptor registers is free to update. */ ++#define STATUS_M2M_DREQS 0x00002000 /* DREQ status. Reflects the status of the */ ++ /* synchronized external peripherals DMA */ ++ /* request signal. */ ++ ++/* ++ * Register masks to mask off reserved bits after reading register. ++ */ ++#define M2M_MASK_BCR0 0x0000ffff ++#define M2M_MASK_BCR1 0x0000ffff ++#define M2M_MASK_SAR_BASE0 0xffffffff ++#define M2M_MASK_SAR_BASE1 0xffffffff ++#define M2M_MASK_SAR_CURRENT0 0xffffffff ++#define M2M_MASK_SAR_CURRENT1 0xffffffff ++#define M2M_MASK_DAR_BASE0 0xffffffff ++#define M2M_MASK_DAR_BASE1 0xffffffff ++#define M2M_MASK_DAR_CURRENT0 0xffffffff ++#define M2M_MASK_DAR_CURRENT1 0xffffffff ++ ++#endif /* _REGS_DMA_H_ */ +diff --git a/include/asm-arm/arch-ep93xx/regs_gpio.h b/include/asm-arm/arch-ep93xx/regs_gpio.h +new file mode 100644 +index 0000000..12397be +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_gpio.h +@@ -0,0 +1,31 @@ ++/*======================================================================= ++ * ++ * FILE: regs_gpio.h ++ * ++ * DESCRIPTION: GPIO Register Definition ++ * ++ * Copyright Cirrus Logic, 2001-2003 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ *======================================================================= ++ */ ++#ifndef _REGS_GPIO_H_ ++#define _REGS_GPIO_H_ ++ ++/* ++ * This file intentionally blank. ++ */ ++ ++#endif /* _REGS_GPIO_H_ */ +diff --git a/include/asm-arm/arch-ep93xx/regs_hardcode.h b/include/asm-arm/arch-ep93xx/regs_hardcode.h +new file mode 100644 +index 0000000..ecbc512 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_hardcode.h +@@ -0,0 +1,110 @@ ++/* ++ * File: linux/include/asm-arm/arch-ep93xx/regs_hardcode.h ++ * ++ * Handle 'Must-be-zero' and 'Must-be-one' values for various ++ * registers on different flavours of the EP93xx family. ++ * ++ * Copyright (C) 2004 Ray Lehtiniemi ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef __ASM_ARCH_HARDCODE_H ++#define __ASM_ARCH_HARDCODE_H ++ ++#if defined(CONFIG_ARCH_EP9301) ++#define ep93xx_SYSCON_DEVCFG(v) (((v) & ~0x0460c220) | 0x08000d00) ++#define ep93xx_VIC0INTSELECT(v) (((v) & ~0xf8080000) | 0x00000000) ++#define ep93xx_VIC1INTSELECT(v) (((v) & ~0x06879a04) | 0x00000000) ++#define ep93xx_VIC0INTENABLE(v) (((v) & ~0xf8080000) | 0x00000000) ++#define ep93xx_VIC1INTENABLE(v) (((v) & ~0x06879a04) | 0x00000000) ++#define ep93xx_VIC0INTENCLEAR(v) (((v) & ~0xf8080000) | 0x00000000) ++#define ep93xx_VIC1INTENCLEAR(v) (((v) & ~0x06879a04) | 0x00000000) ++#define ep93xx_MAC_RXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_RXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_RXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_UART1MCR(v) (((v) & ~0x000000e0) | 0x00000000) ++#define ep93xx_UART2TMR(v) (((v) & ~0x000000fd) | 0x00000000) ++#define ep93xx_IrCtrl(v) (((v) & ~0x00000001) | 0x00000000) ++#define ep93xx_RTCSCOMP(v) (((v) & ~0x00200000) | 0x00000000) ++ ++/* cut'n'paste from 9301, verify this section... */ ++#elif defined(CONFIG_ARCH_EP9302) ++#define ep93xx_SYSCON_DEVCFG(v) (((v) & ~0x0460c220) | 0x08000d00) ++#define ep93xx_VIC0INTSELECT(v) (((v) & ~0xf8080000) | 0x00000000) ++#define ep93xx_VIC1INTSELECT(v) (((v) & ~0x06879a04) | 0x00000000) ++#define ep93xx_VIC0INTENABLE(v) (((v) & ~0xf8080000) | 0x00000000) ++#define ep93xx_VIC1INTENABLE(v) (((v) & ~0x06879a04) | 0x00000000) ++#define ep93xx_VIC0INTENCLEAR(v) (((v) & ~0xf8080000) | 0x00000000) ++#define ep93xx_VIC1INTENCLEAR(v) (((v) & ~0x06879a04) | 0x00000000) ++#define ep93xx_MAC_RXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_RXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_RXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_UART1MCR(v) (((v) & ~0x000000e0) | 0x00000000) ++#define ep93xx_UART2TMR(v) (((v) & ~0x000000fd) | 0x00000000) ++#define ep93xx_IrCtrl(v) (((v) & ~0x00000001) | 0x00000000) ++#define ep93xx_RTCSCOMP(v) (((v) & ~0x00200000) | 0x00000000) ++ ++#elif defined(CONFIG_ARCH_EP9312) ++#define ep93xx_SYSCON_DEVCFG(v) (((v) & ~0x00000020) | 0x00000000) ++#define ep93xx_VIC0INTSELECT(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_VIC1INTSELECT(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_VIC0INTENABLE(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_VIC1INTENABLE(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_VIC0INTENCLEAR(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_VIC1INTENCLEAR(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_PIXELMODE(v) (((v) & ~0x00010000) | 0x00000000) ++#define ep93xx_MAC_RXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_RXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_RXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_UART1MCR(v) (((v) & ~0x000000e0) | 0x00000000) ++#define ep93xx_UART2TMR(v) (((v) & ~0x000000fd) | 0x00000000) ++#define ep93xx_UART3MCR(v) (((v) & ~0x000000e0) | 0x00000000) ++#define ep93xx_IrCtrl(v) (((v) & ~0x00000001) | 0x00000000) ++#define ep93xx_RTCSCOMP(v) (((v) & ~0x00200000) | 0x00000000) ++ ++#elif defined(CONFIG_ARCH_EP9315) ++#define ep93xx_SYSCON_DEVCFG(v) (((v) & ~0x00000020) | 0x00000000) ++#define ep93xx_VIC0INTSELECT(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_VIC1INTSELECT(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_VIC0INTENABLE(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_VIC1INTENABLE(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_VIC0INTENCLEAR(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_VIC1INTENCLEAR(v) (((v) & ~0x00000000) | 0x00000000) ++#define ep93xx_PIXELMODE(v) (((v) & ~0x00010000) | 0x00000000) ++#define ep93xx_MAC_RXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_RXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_RXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_MAC_TXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000) ++#define ep93xx_UART1MCR(v) (((v) & ~0x000000e0) | 0x00000000) ++#define ep93xx_UART2TMR(v) (((v) & ~0x000000fd) | 0x00000000) ++#define ep93xx_UART3MCR(v) (((v) & ~0x000000e0) | 0x00000000) ++#define ep93xx_IrCtrl(v) (((v) & ~0x00000001) | 0x00000000) ++#define ep93xx_RTCSCOMP(v) (((v) & ~0x00200000) | 0x00000000) ++ ++#endif ++ ++#endif /* __ASM_ARCH_HARDWARE_H */ +diff --git a/include/asm-arm/arch-ep93xx/regs_i2s.h b/include/asm-arm/arch-ep93xx/regs_i2s.h +new file mode 100644 +index 0000000..2ca60df +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_i2s.h +@@ -0,0 +1,91 @@ ++/*============================================================================= ++ * ++ * FILE: reg_i2s.h ++ * ++ * DESCRIPTION: ep93xx I2S Register Definition ++ * ++ * Copyright Cirrus Logic, 2001-2003 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ *============================================================================= ++ */ ++#ifndef _REG_I2S_H_ ++#define _REG_I2S_H_ ++ ++/* I2STXClkCfg bits */ ++#define i2s_txcc_trls 0x00000001 ++#define i2s_txcc_tckp 0x00000002 ++#define i2s_txcc_trel 0x00000004 ++#define i2s_txcc_mstr 0x00000008 ++#define i2s_txcc_nbcg 0x00000010 ++ ++#define i2s_txcc_bcr_32x 0x00000020 ++#define i2s_txcc_bcr_64x 0x00000040 ++#define i2s_txcc_bcr_128x 0x00000060 ++ ++/* I2SRxClkCfg bits */ ++#define i2s_rxcc_rrls 0x00000001 ++#define i2s_rxcc_rckp 0x00000002 ++#define i2s_rxcc_rrel 0x00000004 ++#define i2s_rxcc_mstr 0x00000008 ++#define i2s_rxcc_nbcg 0x00000010 ++ ++#define i2s_rxcc_bcr_32x 0x00000020 ++#define i2s_rxcc_bcr_64x 0x00000040 ++#define i2s_rxcc_bcr_128x 0x00000060 ++ ++/* I2SGlSts bits */ ++#define TX0_UNDERFLOW 0x00000001 ++#define TX1_UNDERFLOW 0x00000002 ++#define TX2_UNDERFLOW 0x00000004 ++ ++#define RX0_OVERFLOW 0x00000008 ++#define RX1_OVERFLOW 0x00000010 ++#define RX2_OVERFLOW 0x00000020 ++ ++#define TX0_OVERFLOW 0x00000040 ++#define TX1_OVERFLOW 0x00000080 ++#define TX2_OVERFLOW 0x00000100 ++ ++#define RX0_UNDERFLOW 0x00000200 ++#define RX1_UNDERFLOW 0x00000400 ++#define RX2_UNDERFLOW 0x00000800 ++ ++#define TX0_FIFO_FULL 0x00001000 ++#define TX0_FIFO_EMPTY 0x00002000 ++#define TX0_FIFO_HALF_EMPTY 0x00004000 ++ ++#define RX0_FIFO_FULL 0x00008000 ++#define RX0_FIFO_EMPTY 0x00010000 ++#define RX0_FIFO_HALF_FULL 0x00020000 ++ ++#define TX1_FIFO_FULL 0x00040000 ++#define TX1_FIFO_EMPTY 0x00080000 ++#define TX1_FIFO_HALF_EMPTY 0x00100000 ++ ++#define RX1_FIFO_FULL 0x00200000 ++#define RX1_FIFO_EMPTY 0x00400000 ++#define RX1_FIFO_HALF_FULL 0x00800000 ++ ++#define TX2_FIFO_FULL 0x01000000 ++#define TX2_FIFO_EMPTY 0x02000000 ++#define TX2_FIFO_HALF_EMPTY 0x04000000 ++ ++#define RX2_FIFO_FULL 0x08000000 ++#define RX2_FIFO_EMPTY 0x10000000 ++#define RX2_FIFO_HALF_FULL 0x20000000 ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/regs_ide.h b/include/asm-arm/arch-ep93xx/regs_ide.h +new file mode 100644 +index 0000000..762ebfd +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_ide.h +@@ -0,0 +1,250 @@ ++/***************************************************************************** ++ * ++ * linux/include/asm-arm/arch-ep93xx/regs_ide.h ++ * ++ * Register definitions for the ep93xx ide registers. ++ * ++ * Copyright (C) 2003 Cirrus Logic ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++ * ++ ****************************************************************************/ ++#ifndef _REGS_IDE_H_ ++#define _REGS_IDE_H_ ++ ++#ifndef __ASSEMBLY__ ++ ++/***************************************************************************** ++ * ++ * IDE register definitions ++ * ++ ****************************************************************************/ ++typedef struct _ide_regs_s { ++ union { ++ unsigned int Value; ++ } IDECR; /* 00 */ ++ ++ union { ++ struct { ++ unsigned int IDEEN:1; /* IDE master enable */ ++ unsigned int PIO:1; /* Polled IO operation selection */ ++ unsigned int MDMA:1; /* Multiword DMA operation selection */ ++ unsigned int UDMA:1; /* Ultra DMA operation selection */ ++ unsigned int MODE:4; /* Speed mode number (0 - 4 for PIO, */ ++ /* 0 - 2 for MDMA, 0 - 4 for UDMA) */ ++ unsigned int WST:2; /* Wait State for Turn. Number of */ ++ /* HCLK cycles to hold the data bus */ ++ /* after */ ++ /* PIO write operation */ ++ unsigned int RAZ:22; /* read only always zero */ ++ } Field; ++ unsigned int Value; ++ } IDECFG; /* 04 */ ++ ++ union { ++ struct { ++ unsigned int MEN:1; /* Enable Multiword DMA operation. */ ++ /* 1 - start mdma, 0 - terminate */ ++ /* mdma operation by host. */ ++ unsigned int RWOP:1; /* Read or write operation selection: */ ++ /* 0 = read, 1 = write. */ ++ unsigned int RAZ:30; /* read only always zero */ ++ } Field; ++ unsigned int Value; ++ } IDEMDMAOP; /* 08 */ ++ ++ union { ++ struct { ++ unsigned int UEN:1; /* Enable Ultra DMA operation */ ++ /* 1 - start udma, 0 - terminate */ ++ /* udma operation by host. */ ++ unsigned int RWOP:1; /* Read or write operation selection: */ ++ /* 0 = read, 1 = write. */ ++ unsigned int RAZ:30; /* read only always zero */ ++ } Field; ++ unsigned int Value; ++ } IDEUDMAOP; /* 0C */ ++ ++ union { ++ unsigned int Value; ++ } IDEDATAOUT; /* 10 */ ++ ++ union { ++ unsigned int Value; ++ } IDEDATAIN; /* 14 */ ++ ++ union { ++ struct { ++ unsigned int IDEDD:32; /* IDE output data in the output buffer */ ++ /* in MDMA mode. This register should */ ++ /* only be written to by the DMA engine. */ ++ } Field; ++ unsigned int Value; ++ } IDEMDMADATAOUT; /* 18 */ ++ ++ union { ++ struct { ++ unsigned int IDEDD:32; /* IDE input data in the input buffer */ ++ /* in MDMA mode. */ ++ } Field; ++ unsigned int Value; ++ } IDEMDMADATAIN; /* 1C */ ++ ++ union { ++ struct { ++ unsigned int IDEDD:32; /* IDE output data at the tail of the */ ++ /* output buffer in UDMA mode. */ ++ } Field; ++ unsigned int Value; ++ } IDEUDMADATAOUT; /* 20 */ ++ ++ union { ++ struct { ++ unsigned int IDEDD:32; /* IDE input data at teh head of the */ ++ /* input buffer in UDMA mode. */ ++ } Field; ++ unsigned int Value; ++ } IDEUDMADATAIN; /* 24 */ ++ ++ union { ++ struct { ++ unsigned int CS0n:1; /* Chip select pin 0 status. Should */ ++ /* be driven to 1 (deasserted) in UDMA */ ++ unsigned int CS1n:1; /* Chip select pin 1 status. Should */ ++ /* be driven to 1 (deasserted) in UDMA */ ++ unsigned int DA:3; /* Device address status, should be */ ++ /* driven to 0 (deasserted) in UDMA */ ++ unsigned int HSHD:1; /* HSTROBE (during data out) status, */ ++ /* HDMARDYn (during data in) status, */ ++ /* driven by UDMA state machine. */ ++ unsigned int STOP:1; /* STOP (during data out) status, driven */ ++ /* by UDMA state machine. */ ++ unsigned int DM:1; /* DMACKn status, driven by UDMA state */ ++ /* machine. */ ++ unsigned int DDOE:1; /* DD bus output enable as controlled */ ++ /* by UDMA state machine. */ ++ unsigned int DMARQ:1; /* Synchronized version of DMARQ input */ ++ /* from device. */ ++ unsigned int DSDD:1; /* DSTROBE (during data in) and DDMARDYn */ ++ /* (during data out) status from device. */ ++ unsigned int RAZ1:5; /* reserved, always zero */ ++ unsigned int DMAIDE:1; /* DMA request signal from UDMA state */ ++ /* machine. */ ++ unsigned int INTIDE:1; /* INT line generated by UDMA state */ ++ /* machine. */ ++ unsigned int SBUSY:1; /* UDMA state machine busy, not in idle */ ++ /* state. */ ++ unsigned int RAZ2:5; /* Reserved, always zero. */ ++ unsigned int NDO:1; /* Error for data out not completed */ ++ unsigned int NDI:1; /* Error for data in not completed */ ++ unsigned int N4X:1; /* Error for data transferred not */ ++ /* multiples of 4 32 bit words. */ ++ unsigned int RAZ3:5; /* Reserved, always zero */ ++ } Field; ++ unsigned int Value; ++ } IDEUDMASTATUS; /* 28 */ ++ ++ union { ++ struct { ++ unsigned int RWOE:1; /* Reset UDMA write data out error. */ ++ unsigned int RWPTR:1; /* Reset UDMA write buffer ptr to 0. */ ++ unsigned int RWDR:1; /* Reset UDMA write DMA request. */ ++ unsigned int RROE:1; /* Reset UDMA read data in error. */ ++ unsigned int RRPTR:1; /* Reset UDMA read buffer ptr to 0. */ ++ unsigned int RRDR:1; /* Reset UDMA read DMA request. */ ++ unsigned int RAZ:26; /* reserved, always zero */ ++ } Field; ++ unsigned int Value; ++ } IDEUDMADEBUG; /* 2C */ ++ ++ union { ++ struct { ++ unsigned int HPTR:4; /* Head pointer in the write buffer */ ++ unsigned int TPTR:4; /* Tail pointer in the write buffer */ ++ unsigned int EMPTY:1; /* Write buffer empty status */ ++ unsigned int HOM:1; /* Half or more entries in write buffer */ ++ /* filled status */ ++ unsigned int NFULL:1; /* Write buffer near full status */ ++ unsigned int FULL:1; /* Write buffer full status */ ++ unsigned int RAZ:4; /* Reserved, always zero */ ++ unsigned int CRC:16; /* CRC result for data operation */ ++ /* TODO: is there a CRC? */ ++ } Field; ++ unsigned int Value; ++ } IDEUDMAWFST; /* 30 */ ++ ++ union { ++ struct { ++ unsigned int HPTR:4; /* Head pointer in the read buffer */ ++ unsigned int TPTR:4; /* Tail pointer in the read buffer */ ++ unsigned int EMPTY:1; /* Read buffer empty status */ ++ unsigned int HOM:1; /* Half or more entries in read buffer */ ++ /* filled status */ ++ unsigned int NFULL:1; /* Read buffer near full status */ ++ unsigned int FULL:1; /* Read buffer full status */ ++ unsigned int RAZ:4; /* Reserved, always zero */ ++ unsigned int CRC:16; /* CRC result for data operation */ ++ /* TODO: is there a CRC? */ ++ } Field; ++ unsigned int Value; ++ } IDEUDMARFST; /* 34 */ ++ ++} IDEREGISTERS; ++ ++/***************************************************************************** ++ * ++ * Global Register Anchor Definitions (these address values will change) ++ * ++ ****************************************************************************/ ++#ifdef CONFIG_BLK_DEV_EP93XX ++static volatile IDEREGISTERS *const ep93xx_ide_regs = ++ (IDEREGISTERS *) (IDE_BASE); ++#endif ++ ++#endif /* Not __ASSEMBLY__ */ ++ ++#define IDECtrl HW_REG(io_p2v(0x800a0000)) ++#define IDECfg HW_REG(io_p2v(0x800a0004)) ++#define IDEMDMAOp HW_REG(io_p2v(0x800a0008)) ++#define IDEUDMAOp HW_REG(io_p2v(0x800a000c)) ++#define IDEDataOut HW_REG(io_p2v(0x800a0010)) ++#define IDEDataIn HW_REG(io_p2v(0x800a0014)) ++#define IDEMDMADataOut HW_REG(io_p2v(0x800a0018)) ++#define IDEMDMADataIn HW_REG(io_p2v(0x800a001c)) ++#define IDEUDMADataOut HW_REG(io_p2v(0x800a0020)) ++#define IDEUDMADataIn HW_REG(io_p2v(0x800a0024)) ++#define IDEUDMASts HW_REG(io_p2v(0x800a0028)) ++#define IDEUDMADebug HW_REG(io_p2v(0x800a002c)) ++#define IDEUDMAWrBufSts HW_REG(io_p2v(0x800a0030)) ++#define IDEUDMARdBufSts HW_REG(io_p2v(0x800a0034)) ++ ++/***************************************************************************** ++ * ++ * Bit definitions for use with assembly code for the ide control register. ++ * ++ ****************************************************************************/ ++#define IDECtrl_CS0n 0x00000001 ++#define IDECtrl_CS1n 0x00000002 ++#define IDECtrl_DA_MASK 0x0000001c ++#define IDECtrl_DA_SHIFT 2 ++#define IDECtrl_DIORn 0x00000020 ++#define IDECtrl_DIOWn 0x00000040 ++#define IDECtrl_DASPn 0x00000080 ++#define IDECtrl_DMARQ 0x00000100 ++#define IDECtrl_INTRQ 0x00000200 ++#define IDECtrl_IORDY 0x00000400 ++ ++#endif /* _REGS_IDE_H_ */ +diff --git a/include/asm-arm/arch-ep93xx/regs_irda.h b/include/asm-arm/arch-ep93xx/regs_irda.h +new file mode 100644 +index 0000000..77edafa +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_irda.h +@@ -0,0 +1,24 @@ ++/*======================================================================= ++ * ++ * FILE: regs_irda.h ++ * ++ * DESCRIPTION: IrDA Register Definition ++ * ++ * Copyright Cirrus Logic, 2001-2003 ++ * ++ *======================================================================= ++ */ ++#ifndef _REGS_IRDA_H_ ++#define _REGS_IRDA_H_ ++ ++/* Bit definitions */ ++ ++#define IrEnable_EN_NONE 0x00 ++#define IrEnable_EN_SIR 0x01 ++#define IrEnable_EN_MIR 0x02 ++#define IrEnable_EN_FIR 0x03 ++#define IrEnable_LBM 0x04 ++#define IrEnable_MD 0x08 ++#define IrEnable_FD 0x10 ++ ++#endif /* _REGS_IRDA_H_ */ +diff --git a/include/asm-arm/arch-ep93xx/regs_pcmcia.h b/include/asm-arm/arch-ep93xx/regs_pcmcia.h +new file mode 100644 +index 0000000..6f731e7 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_pcmcia.h +@@ -0,0 +1,72 @@ ++/* ++ * linux/include/asm-arm/arch-ep93xx/regs-pcmcia.h ++ * ++ * Derived from: ++ * linux/include/asm-arm/arch-pxa/pxa-regs.h ++ * ++ * Author: Nicolas Pitre ++ * Created: Jun 15, 2001 ++ * Copyright: MontaVista Software Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++/* ++ * Personal Computer Memory Card International Association (PCMCIA) sockets ++ * (from pxa-regs.h for compatibility) ++ */ ++#ifndef _REGS_PCMCIA_H_ ++#define _REGS_PCMCIA_H_ ++ ++#define PCMCIAPrtSp 0x04000000 /* PCMCIA Partition Space [byte] */ ++#define PCMCIASp (4*PCMCIAPrtSp) /* PCMCIA Space [byte] */ ++#define PCMCIAIOSp PCMCIAPrtSp /* PCMCIA I/O Space [byte] */ ++#define PCMCIAAttrSp PCMCIAPrtSp /* PCMCIA Attribute Space [byte] */ ++#define PCMCIAMemSp PCMCIAPrtSp /* PCMCIA Memory Space [byte] */ ++ ++#define PCMCIA0Sp PCMCIASp /* PCMCIA 0 Space [byte] */ ++#define PCMCIA0IOSp PCMCIAIOSp /* PCMCIA 0 I/O Space [byte] */ ++#define PCMCIA0AttrSp PCMCIAAttrSp /* PCMCIA 0 Attribute Space [byte] */ ++#define PCMCIA0MemSp PCMCIAMemSp /* PCMCIA 0 Memory Space [byte] */ ++ ++#define PCMCIA1Sp PCMCIASp /* PCMCIA 1 Space [byte] */ ++#define PCMCIA1IOSp PCMCIAIOSp /* PCMCIA 1 I/O Space [byte] */ ++#define PCMCIA1AttrSp PCMCIAAttrSp /* PCMCIA 1 Attribute Space [byte] */ ++#define PCMCIA1MemSp PCMCIAMemSp /* PCMCIA 1 Memory Space [byte] */ ++ ++ ++#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \ ++ (0x40000000 + (Nb)*PCMCIASp) ++#define _PCMCIAIO(Nb) _PCMCIA (Nb) /* PCMCIA I/O [0..1] */ ++#define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \ ++ (_PCMCIA (Nb) + 2*PCMCIAPrtSp) ++#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \ ++ (_PCMCIA (Nb) + 3*PCMCIAPrtSp) ++ ++#define _PCMCIA0 _PCMCIA (0) /* PCMCIA 0 */ ++#define _PCMCIA0IO _PCMCIAIO (0) /* PCMCIA 0 I/O */ ++#define _PCMCIA0Attr _PCMCIAAttr (0) /* PCMCIA 0 Attribute */ ++#define _PCMCIA0Mem _PCMCIAMem (0) /* PCMCIA 0 Memory */ ++ ++#define _PCMCIA1 _PCMCIA (1) /* PCMCIA 1 */ ++#define _PCMCIA1IO _PCMCIAIO (1) /* PCMCIA 1 I/O */ ++#define _PCMCIA1Attr _PCMCIAAttr (1) /* PCMCIA 1 Attribute */ ++#define _PCMCIA1Mem _PCMCIAMem (1) /* PCMCIA 1 Memory */ ++ ++#define PCATTRIB(sock) ((sock ==0) ? (PC1ATTRIB) : (PC2ATTRIB)) ++#define PCCOMMON(sock) ((sock ==0) ? (PC1COMMON) : (PC2COMMON)) ++#define PCIO(sock) ((sock ==0) ? (PC1IO) : (PC2IO)) ++ ++#define PC16BITSWIDE 0x80000000 ++ ++#define PCMCIA_WRPROT 0x01 ++#define PCMCIA_DETECT 0x06 ++#define PCMCIA_BVD1 0x08 ++#define PCMCIA_BVD2 0x10 ++#define PCMCIA_VS_3V 0x20 ++#define PCMCIA_READY 0x40 ++#define PCMCIA_VS_XV 0x80 ++ ++#endif /* _REGS_PCMCIA_H_ */ +diff --git a/include/asm-arm/arch-ep93xx/regs_raster.h b/include/asm-arm/arch-ep93xx/regs_raster.h +new file mode 100644 +index 0000000..bfab3ed +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_raster.h +@@ -0,0 +1,279 @@ ++/*============================================================================= ++ * ++ * FILE: regs_raster.h ++ * ++ * DESCRIPTION: ep93xx Raster Engine Register Definition ++ * ++ * Copyright Cirrus Logic, 2001-2003 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ *============================================================================= ++ */ ++#ifndef _REGS_RASTER_H_ ++#define _REGS_RASTER_H_ ++ ++/* VLINESTOTAL Register Definitions */ ++#define VLINESTOTAL_MASK 0x000007ff ++ ++/* VSYNCSTRTSTOP Register Definitions */ ++#define VSYNCSTRTSTOP_STRT_MASK 0x07ff0000 ++#define VSYNCSTRTSTOP_STRT_SHIFT 0 ++#define VSYNCSTRTSTOP_STOP_MASK 0x000007ff ++#define VSYNCSTRTSTOP_STOP_SHIFT 16 ++ ++/* VACTIVESTRTSTOP Register Definitions */ ++#define VACTIVESTRTSTOP_STRT_MASK 0x07ff0000 ++#define VACTIVESTRTSTOP_STRT_SHIFT 0 ++#define VACTIVESTRTSTOP_STOP_MASK 0x000007ff ++#define VACTIVESTRTSTOP_STOP_SHIFT 16 ++ ++/* VCLKSTRTSTOP Register Definitions */ ++#define VCLKSTRTSTOP_STRT_MASK 0x07ff0000 ++#define VCLKSTRTSTOP_STRT_SHIFT 0 ++#define VCLKSTRTSTOP_STOP_MASK 0x000007ff ++#define VCLKSTRTSTOP_STOP_SHIFT 16 ++ ++/* VBLANKSTRTSTOP Register Definitions */ ++#define VBLANKSTRTSTOP_STRT_MASK 0x07ff0000 ++#define VBLANKSTRTSTOP_STRT_SHIFT 0 ++#define VBLANKSTRTSTOP_STOP_MASK 0x000007ff ++#define VBLANKSTRTSTOP_STOP_SHIFT 16 ++ ++/* HSYNCSTRTSTOP Register Definitions */ ++#define HSYNCSTRTSTOP_STRT_MASK 0x07ff0000 ++#define HSYNCSTRTSTOP_STRT_SHIFT 0 ++#define HSYNCSTRTSTOP_STOP_MASK 0x000007ff ++#define HSYNCSTRTSTOP_STOP_SHIFT 16 ++ ++/* HACTIVESTRTSTOP Register Definitions */ ++#define HACTIVESTRTSTOP_STRT_MASK 0x07ff0000 ++#define HACTIVESTRTSTOP_STRT_SHIFT 0 ++#define HACTIVESTRTSTOP_STOP_MASK 0x000007ff ++#define HACTIVESTRTSTOP_STOP_SHIFT 16 ++ ++/* HCLKSTRTSTOP Register Definitions */ ++#define HCLKSTRTSTOP_STRT_MASK 0x07ff0000 ++#define HCLKSTRTSTOP_STRT_SHIFT 0 ++#define HCLKSTRTSTOP_STOP_MASK 0x000007ff ++#define HCLKSTRTSTOP_STOP_SHIFT 16 ++ ++/* BRIGHTNESS Register Definitions */ ++#define BRIGHTNESS_MASK 0x0000ffff ++#define BRIGHTNESS_CNT_MASK 0x000000ff ++#define BRIGHTNESS_CNT_SHIFT 0 ++#define BRIGHTNESS_CMP_MASK 0x0000ff00 ++#define BRIGHTNESS_CMP_SHIFT 8 ++ ++/* VIDEOATTRIBS Register Definitions */ ++#define VIDEOATTRIBS_MASK 0x001fffff ++#define VIDEOATTRIBS_EN 0x00000001 ++#define VIDEOATTRIBS_PCLKEN 0x00000002 ++#define VIDEOATTRIBS_SYNCEN 0x00000004 ++#define VIDEOATTRIBS_DATAEN 0x00000008 ++#define VIDEOATTRIBS_CSYNC 0x00000010 ++#define VIDEOATTRIBS_VCPOL 0x00000020 ++#define VIDEOATTRIBS_HSPOL 0x00000040 ++#define VIDEOATTRIBS_BLKPOL 0x00000080 ++#define VIDEOATTRIBS_INVCLK 0x00000100 ++#define VIDEOATTRIBS_ACEN 0x00000200 ++#define VIDEOATTRIBS_LCDEN 0x00000400 ++#define VIDEOATTRIBS_RGBEN 0x00000800 ++#define VIDEOATTRIBS_CCIREN 0x00001000 ++#define VIDEOATTRIBS_PIFEN 0x00002000 ++#define VIDEOATTRIBS_INTEN 0x00004000 ++#define VIDEOATTRIBS_INT 0x00008000 ++#define VIDEOATTRIBS_INTRLC 0x00010000 ++#define VIDEOATTRIBS_EQUSER 0x00020000 ++#define VIDEOATTRIBS_DHORZ 0x00040000 ++#define VIDEOATTRIBS_DVERT 0x00080000 ++#define VIDEOATTRIBS_BKPXD 0x00100000 ++ ++#define VIDEOATTRIBS_SDSEL_MASK 0x00600000 ++#define VIDEOATTRIBS_SDSEL_SHIFT 21 ++ ++/* HBLANKSTRTSTOP Register Definitions */ ++#define HBLANKSTRTSTOP_STRT_MASK 0x07ff0000 ++#define HBLANKSTRTSTOP_STRT_SHIFT 0 ++#define HBLANKSTRTSTOP_STOP_MASK 0x000007ff ++#define HBLANKSTRTSTOP_STOP_SHIFT 16 ++ ++/* LINECARRY Register Definitions */ ++#define LINECARRY_LCARY_MASK 0x000007ff ++#define LINECARRY_LCARY_SHIFT 0 ++ ++/* BLINKRATE Register Definitons */ ++#define BLINKRATE_MASK 0x000000ff ++ ++/* BLINKMASK Register Definitons */ ++#define BLINKMASK_MASK 0x00ffffff ++ ++/* VIDSCRNPAGE Register Definitons */ ++#define VIDSCRNPAGE_PAGE_MASK 0x0ffffffc ++ ++/* VIDSCRNHPG Register Definitons */ ++#define VIDSCRNHPG_MASK 0x0ffffffc ++ ++/* SCRNLINES Register Definitons */ ++#define SCRNLINES_MASK 0x000007ff ++ ++/* LINELENGTH Register Definitons */ ++#define LINELENGTH_MASK 0x000007ff ++ ++/* VLINESTEP Register Definitons */ ++#define VLINESTEP_MASK 0x00000fff ++ ++/* REALITI_SWLOCK Register Definitons */ ++#define REALITI_SWLOCK_MASK_WR 0xff ++#define REALITI_SWLOCK_MASK_R 0x1 ++#define REALITI_SWLOCK_VALUE 0xaa ++ ++/* LUTCONT Register Definitions */ ++#define LUTCONT_MASK 0x00000003 ++#define LUTCONT_SWTCH 0x00000001 ++#define LUTCONT_STAT 0x00000002 ++#define LUTCONT_RAM0 0 ++#define LUTCONT_RAM1 1 ++ ++/* CURSORBLINK1 Register Definitions */ ++#define CURSORBLINK1_MASK 0x00ffffff ++/* CURSORBLINK2 Register Definitions */ ++#define CURSORBLINK2_MASK 0x00ffffff ++ ++/* CURSORBLINK Register Definitions */ ++#define CURSORBLINK_MASK 0x000001ff ++#define CURSORBLINK_RATE_MASK 0x000000ff ++#define CURSORBLINK_RATE_SHIFT 0 ++#define CURSORBLINK_EN 0x00000100 ++ ++/* BLINKPATRN Register Definitions */ ++#define BLINKPATRN_MASK 0x00ffffff ++ ++/* PATRNMASK Register Definitions */ ++#define PATRNMASK_MASK 0x00ffffff ++ ++/* BG_OFFSET Register Definitions */ ++#define BG_OFFSET_MASK 0x00ffffff ++ ++/* PIXELMODE Register Definitions */ ++#define PIXELMODE_P_MASK 0x00000007 ++#define PIXELMODE_P_MUX_DISABLE 0x00000000 ++#define PIXELMODE_P_4BPP 0x00000001 ++#define PIXELMODE_P_8BPP 0x00000002 ++#define PIXELMODE_P_16BPP 0x00000004 ++#define PIXELMODE_P_24BPP 0x00000006 ++#define PIXELMODE_P_32BPP 0x00000007 ++#define PIXELMODE_P_SHIFT 0 ++ ++#define PIXELMODE_S_MASK 0x00000038 ++#define PIXELMODE_S_SHIFT 3 ++#define PIXELMODE_S_1PPC 0x0 ++#define PIXELMODE_S_1PPCMAPPED 0x1 ++#define PIXELMODE_S_2PPC 0x2 ++#define PIXELMODE_S_4PPC 0x3 ++#define PIXELMODE_S_8PPC 0x4 ++#define PIXELMODE_S_223PPC 0x5 ++#define PIXELMODE_S_DS223PPC 0x6 ++#define PIXELMODE_S_UNDEF 0x7 ++ ++#define PIXELMODE_M_MASK 0x000003c0 ++#define PIXELMODE_M_SHIFT 6 ++#define PIXELMODE_M_NOBLINK 0 ++#define PIXELMODE_M_ANDBLINK 1 ++#define PIXELMODE_M_ORBLINK 2 ++#define PIXELMODE_M_XORBLINK 3 ++#define PIXELMODE_M_BGBLINK 4 ++#define PIXELMODE_M_OFFSINGBLINK 5 ++#define PIXELMODE_M_OFF888BLINK 6 ++#define PIXELMODE_M_DIMBLINK 0xc ++#define PIXELMODE_M_BRTBLINK 0xd ++#define PIXELMODE_M_DIM888BLINK 0xe ++#define PIXELMODE_M_BRT888BLINK 0xf ++ ++#define PIXELMODE_C_MASK 0x00003c00 ++#define PIXELMODE_C_SHIFT 10 ++#define PIXELMODE_C_LUT 0 ++#define PIXELMODE_C_888 4 ++#define PIXELMODE_C_565 5 ++#define PIXELMODE_C_555 6 ++#define PIXELMODE_C_GSLUT 8 ++ ++#define PIXELMODE_DSCAN 0x00004000 ++#define PIXELMODE_TRBSW 0x00008000 ++#define PIXELMODE_P13951 0x00010000 ++ ++/*PARLLIFOUT Register Defintions */ ++#define PARLLIFOUT_DAT_MASK 0x0000000f ++#define PARLLIFOUT_DAT_SHIFT 0 ++#define PARLLIFOUT_RD 0x00000010 ++ ++/*PARLLIFIN Register Defintions */ ++#define PARLLIFIN_DAT_MASK 0x0000000f ++#define PARLLIFIN_DAT_SHIFT 0 ++#define PARLLIFIN_CNT_MASK 0x000f0000 ++#define PARLLIFIN_CNT_SHIFT 16 ++#define PARLLIFIN_ESTRT_MASK 0x00f00000 ++#define PARLLIFIN_ESTRT_SHIFT 20 ++ ++/* CURSORADRSTART Register Defintions */ ++#define CURSOR_ADR_START_MASK 0xfffffffc ++ ++/* CURSORADRSTART Register Defintions */ ++#define CURSOR_ADR_RESET_MASK 0xfffffffc ++ ++/* CURSORCOLOR1 Register Definitions */ ++#define CURSORCOLOR1_MASK 0x00ffffff ++/* CURSORCOLOR2 Register Definitions */ ++#define CURSORCOLOR2_MASK 0x00ffffff ++ ++/* CURSORXYLOC Register Definitions */ ++#define CURSORXYLOC_MASK 0x07ff87ff ++#define CURSORXYLOC_XLOC_MASK 0x000007ff ++#define CURSORXYLOC_XLOC_SHIFT 0 ++#define CURSORXYLOC_CEN 0x00008000 ++#define CURSORXYLOC_YLOC_MASK 0x07ff0000 ++#define CURSORXYLOC_YLOC_SHIFT 16 ++ ++/* CURSOR_DSCAN_LH_YLOC Register Definitions */ ++#define CURSOR_DSCAN_LH_YLOC_MASK 0x000087ff ++ ++#define CURSOR_DSCAN_LH_YLOC_YLOC_MASK 0x000007ff ++#define CURSOR_DSCAN_LH_YLOC_YLOC_SHIFT 0 ++#define CURSOR_DSCAN_LH_YLOC_CLHEN 0x00008000 ++ ++/* CURSORSIZE Register Definitions */ ++#define CURSORSIZE_MASK 0x0000ffff ++ ++#define CURSORSIZE_CWID_MASK 0x00000003 ++#define CURSORSIZE_CWID_SHIFT 0 ++#define CURSORSIZE_CWID_1_WORD 0 ++#define CURSORSIZE_CWID_2_WORD 1 ++#define CURSORSIZE_CWID_3_WORD 2 ++#define CURSORSIZE_CWID_4_WORD 3 ++ ++#define CURSORSIZE_CLINS_MASK 0x000000fc ++#define CURSORSIZE_CLINS_SHIFT 2 ++ ++#define CURSORSIZE_CSTEP_MASK 0x00000300 ++#define CURSORSIZE_CSTEP_SHIFT 8 ++#define CURSORSIZE_CSTEP_1_WORD 0 ++#define CURSORSIZE_CSTEP_2_WORD 1 ++#define CURSORSIZE_CSTEP_3_WORD 2 ++#define CURSORSIZE_CSTEP_4_WORD 3 ++ ++#define CURSORSIZE_DLNS_MASK 0x0000fc00 ++#define CURSORSIZE_DLNS_SHIFT 10 ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/regs_spi.h b/include/asm-arm/arch-ep93xx/regs_spi.h +new file mode 100644 +index 0000000..a51d3dc +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_spi.h +@@ -0,0 +1,76 @@ ++/*======================================================================= ++ * ++ * FILE: regs_spi.h ++ * ++ * DESCRIPTION: SSP Register Definition ++ * ++ * Copyright Cirrus Logic, 2001-2003 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ *======================================================================= ++ */ ++ ++#ifndef _REGS_SSP_H_ ++#define _REGS_SSP_H_ ++ ++/* Bits in SSPCR0 */ ++#define SSPCR0_DSS_MASK 0x0000000f ++#define SSPCR0_DSS_4BIT 0x00000003 ++#define SSPCR0_DSS_5BIT 0x00000004 ++#define SSPCR0_DSS_6BIT 0x00000005 ++#define SSPCR0_DSS_7BIT 0x00000006 ++#define SSPCR0_DSS_8BIT 0x00000007 ++#define SSPCR0_DSS_9BIT 0x00000008 ++#define SSPCR0_DSS_10BIT 0x00000009 ++#define SSPCR0_DSS_11BIT 0x0000000a ++#define SSPCR0_DSS_12BIT 0x0000000b ++#define SSPCR0_DSS_13BIT 0x0000000c ++#define SSPCR0_DSS_14BIT 0x0000000d ++#define SSPCR0_DSS_15BIT 0x0000000e ++#define SSPCR0_DSS_16BIT 0x0000000f ++ ++/* Bits in SSPCR1 */ ++#define SSPC1_RIE 0x00000001 ++#define SSPC1_TIE 0x00000002 ++#define SSPC1_RORIE 0x00000004 ++#define SSPC1_LBM 0x00000008 ++#define SSPC1_SSE 0x00000010 ++#define SSPC1_MS 0x00000020 ++#define SSPC1_SOD 0x00000040 ++ ++#define SSPCR0_DSS_SHIFT 0 ++#define SSPCR0_FRF_MASK 0x00000030 ++#define SSPCR0_FRF_SHIFT 4 ++#define SSPCR0_FRF_MOTOROLA (0 << SSPCR0_FRF_SHIFT) ++#define SSPCR0_FRF_TI (1 << SSPCR0_FRF_SHIFT) ++#define SSPCR0_FRF_NI (2 << SSPCR0_FRF_SHIFT) ++#define SSPCR0_SPO 0x00000040 ++#define SSPCR0_SPH 0x00000080 ++#define SSPCR0_SCR_MASK 0x0000ff00 ++#define SSPCR0_SCR_SHIFT 8 ++ ++/* Bits in SSPSR */ ++#define SSPSR_TFE 0x00000001 /* TX FIFO is empty */ ++#define SSPSR_TNF 0x00000002 /* TX FIFO is not full */ ++#define SSPSR_RNE 0x00000004 /* RX FIFO is not empty */ ++#define SSPSR_RFF 0x00000008 /* RX FIFO is full */ ++#define SSPSR_BSY 0x00000010 /* SSP is busy */ ++ ++/* Bits in SSPIIR */ ++#define SSPIIR_RIS 0x00000001 /* RX FIFO IRQ status */ ++#define SSPIIR_TIS 0x00000002 /* TX FIFO is not full */ ++#define SSPIIR_RORIS 0x00000004 /* RX FIFO is full */ ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/regs_syscon.h b/include/asm-arm/arch-ep93xx/regs_syscon.h +new file mode 100644 +index 0000000..271cfcd +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_syscon.h +@@ -0,0 +1,257 @@ ++/*============================================================================= ++ * ++ * FILE: reg_syscon.h ++ * ++ * DESCRIPTION: ep93xx Syscon Register Definition ++ * ++ * Copyright Cirrus Logic, 2001-2003 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ * ++ *============================================================================= ++ */ ++#ifndef _REGS_SYSCON_H_ ++#define _REGS_SYSCON_H_ ++ ++#ifndef __ASSEMBLY__ ++ ++#define SysconSetLocked(registername,value) \ ++ { \ ++ writel( 0xAA, SYSCON_SWLOCK); \ ++ writel( value, registername); \ ++ } ++ ++#endif /* Not __ASSEMBLY__ */ ++ ++/* SYSCON_CLKSET1 */ ++#define SYSCON_CLKSET1_PLL1_X2IPD_SHIFT 0 ++#define SYSCON_CLKSET1_PLL1_X2IPD_MASK 0x0000001f ++#define SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT 5 ++#define SYSCON_CLKSET1_PLL1_X2FBD2_MASK 0x000007e0 ++#define SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT 11 ++#define SYSCON_CLKSET1_PLL1_X1FBD1_MASK 0x0000f800 ++#define SYSCON_CLKSET1_PLL1_PS_SHIFT 16 ++#define SYSCON_CLKSET1_PLL1_PS_MASK 0x00030000 ++#define SYSCON_CLKSET1_PCLKDIV_SHIFT 18 ++#define SYSCON_CLKSET1_PCLKDIV_MASK 0x000c0000 ++#define SYSCON_CLKSET1_HCLKDIV_SHIFT 20 ++#define SYSCON_CLKSET1_HCLKDIV_MASK 0x00700000 ++#define SYSCON_CLKSET1_nBYP1 0x00800000 ++#define SYSCON_CLKSET1_SMCROM 0x01000000 ++#define SYSCON_CLKSET1_FCLKDIV_SHIFT 25 ++#define SYSCON_CLKSET1_FCLKDIV_MASK 0x0e000000 ++ ++#define SYSCON_CLKSET1_HSEL 0x00000001 ++#define SYSCON_CLKSET1_PLL1_EXCLKSEL 0x00000002 ++ ++#define SYSCON_CLKSET1_PLL1_P_MASK 0x0000007C ++#define SYSCON_CLKSET1_PLL1_P_SHIFT 2 ++ ++#define SYSCON_CLKSET1_PLL1_M1_MASK 0x00000780 ++#define SYSCON_CLKSET1_PLL1_M1_SHIFT 7 ++#define SYSCON_CLKSET1_PLL1_M2_MASK 0x0000F800 ++#define SYSCON_CLKSET1_PLL1_M2_SHIFT 11 ++#define SYSCON_CLKSET1_PLL1_PS_MASK 0x00030000 ++#define SYSCON_CLKSET1_PLL1_PS_SHIFT 16 ++#define SYSCON_CLKSET1_PCLK_DIV_MASK 0x000C0000 ++#define SYSCON_CLKSET1_PCLK_DIV_SHIFT 18 ++#define SYSCON_CLKSET1_HCLK_DIV_MASK 0x00700000 ++#define SYSCON_CLKSET1_HCLK_DIV_SHIFT 20 ++#define SYSCON_CLKSET1_SMCROM 0x01000000 ++#define SYSCON_CLKSET1_FCLK_DIV_MASK 0x0E000000 ++#define SYSCON_CLKSET1_FCLK_DIV_SHIFT 25 ++ ++#define SYSCON_CLKSET2_PLL2_EN 0x00000001 ++#define SYSCON_CLKSET2_PLL2EXCLKSEL 0x00000002 ++#define SYSCON_CLKSET2_PLL2_P_MASK 0x0000007C ++#define SYSCON_CLKSET2_PLL2_P_SHIFT 2 ++#define SYSCON_CLKSET2_PLL2_M2_MASK 0x00000F80 ++#define SYSCON_CLKSET2_PLL2_M2_SHIFT 7 ++#define SYSCON_CLKSET2_PLL2_M1_MASK 0x0001F000 ++#define SYSCON_CLKSET2_PLL2_M1 12 ++#define SYSCON_CLKSET2_PLL2_PS_MASK 0x000C0000 ++#define SYSCON_CLKSET2_PLL2_PS_SHIFT 18 ++#define SYSCON_CLKSET2_USBDIV_MASK 0xF0000000 ++#define SYSCON_CLKSET2_USBDIV_SHIFT 28 ++ ++/* DEV_CFG Register Defines */ ++#define SYSCON_DEVCFG_SHena 0x00000001 ++#define SYSCON_DEVCFG_KEYS 0x00000002 ++#define SYSCON_DEVCFG_ADCPD 0x00000004 ++#define SYSCON_DEVCFG_RAS 0x00000008 ++#define SYSCON_DEVCFG_RASonP3 0x00000010 ++#define SYSCON_DEVCFG_TTIC 0x00000020 ++#define SYSCON_DEVCFG_I2SonAC97 0x00000040 ++#define SYSCON_DEVCFG_I2SonSSP 0x00000080 ++#define SYSCON_DEVCFG_EonIDE 0x00000100 ++#define SYSCON_DEVCFG_PonG 0x00000200 ++#define SYSCON_DEVCFG_GonIDE 0x00000400 ++#define SYSCON_DEVCFG_HonIDE 0x00000800 ++#define SYSCON_DEVCFG_HC1CEN 0x00001000 ++#define SYSCON_DEVCFG_HC1IN 0x00002000 ++#define SYSCON_DEVCFG_HC3CEN 0x00004000 ++#define SYSCON_DEVCFG_HC3IN 0x00008000 ++#define SYSCON_DEVCFG_ADCEN 0x00010000 ++#define SYSCON_DEVCFG_TIN 0x00020000 ++#define SYSCON_DEVCFG_U1EN 0x00040000 ++#define SYSCON_DEVCFG_EXVC 0x00080000 ++#define SYSCON_DEVCFG_U2EN 0x00100000 ++#define SYSCON_DEVCFG_A1onG 0x00200000 ++#define SYSCON_DEVCFG_A2onG 0x00400000 ++#define SYSCON_DEVCFG_CPENA 0x00800000 ++#define SYSCON_DEVCFG_U3EN 0x01000000 ++#define SYSCON_DEVCFG_MonG 0x02000000 ++#define SYSCON_DEVCFG_TonG 0x04000000 ++#define SYSCON_DEVCFG_GonK 0x08000000 ++#define SYSCON_DEVCFG_IonU2 0x10000000 ++#define SYSCON_DEVCFG_D0onG 0x20000000 ++#define SYSCON_DEVCFG_D1onG 0x40000000 ++#define SYSCON_DEVCFG_SWRST 0x80000000 ++ ++/* VIDDIV Register Defines */ ++#define SYSCON_VIDDIV_VDIV_MASK 0x0000007f ++#define SYSCON_VIDDIV_VDIV_SHIFT 0 ++#define SYSCON_VIDDIV_PDIV_MASK 0x00000300 ++#define SYSCON_VIDDIV_PDIV_SHIFT 8 ++#define SYSCON_VIDDIV_PSEL 0x00002000 ++#define SYSCON_VIDDIV_ESEL 0x00004000 ++#define SYSCON_VIDDIV_VENA 0x00008000 ++ ++/* MIRDIV Register Defines */ ++#define SYSCON_MIRDIV_MDIV_MASK 0x0000003f ++#define SYSCON_MIRDIV_MDIV_SHIFT 0 ++#define SYSCON_MIRDIV_PDIV_MASK 0x00000300 ++#define SYSCON_MIRDIV_PDIV_SHIFT 8 ++#define SYSCON_MIRDIV_PSEL 0x00002000 ++#define SYSCON_MIRDIV_ESEL 0x00004000 ++#define SYSCON_MIRDIV_MENA 0x00008000 ++ ++/* I2SDIV Register Defines */ ++#define SYSCON_I2SDIV_MDIV_MASK 0x0000007f ++#define SYSCON_I2SDIV_MDIV_SHIFT 0 ++#define SYSCON_I2SDIV_PDIV_MASK 0x00000300 ++#define SYSCON_I2SDIV_PDIV_SHIFT 8 ++#define SYSCON_I2SDIV_PSEL 0x00002000 ++#define SYSCON_I2SDIV_ESEL 0x00004000 ++#define SYSCON_I2SDIV_MENA 0x00008000 ++#define SYSCON_I2SDIV_SDIV 0x00010000 ++#define SYSCON_I2SDIV_LRDIV_MASK 0x00060000 ++#define SYSCON_I2SDIV_LRDIV_SHIFT 17 ++#define SYSCON_I2SDIV_SPOL 0x00080000 ++#define SYSCON_I2SDIV_DROP 0x00100000 ++#define SYSCON_I2SDIV_ORIDE 0x20000000 ++#define SYSCON_I2SDIV_SLAVE 0x40000000 ++#define SYSCON_I2SDIV_SENA 0x80000000 ++ ++#define SYSCON_I2SDIV_PDIV_OFF 0x00000000 ++#define SYSCON_I2SDIV_PDIV_2 0x00000100 ++#define SYSCON_I2SDIV_PDIV_25 0x00000200 ++#define SYSCON_I2SDIV_PDIV_3 0x00000300 ++ ++#define SYSCON_I2SDIV_LRDIV_32 0x00000000 ++#define SYSCON_I2SDIV_LRDIV_64 0x00020000 ++#define SYSCON_I2SDIV_LRDIV_128 0x00040000 ++ ++/* KTDIV Register Defines */ ++#define SYSCON_KTDIV_KDIV 0x00000001 ++#define SYSCON_KTDIV_KEN 0x00008000 ++#define SYSCON_KTDIV_ADIV 0x00010000 ++#define SYSCON_KTDIV_TSEN 0x80000000 ++ ++/* CHIPID Register Defines */ ++#define SYSCON_CHIPID_ID_MASK 0x0000ffff ++#define SYSCON_CHIPID_ID_SHIFT 0 ++#define SYSCON_CHIPID_PKID 0x00010000 ++#define SYSCON_CHIPID_BND 0x00040000 ++#define SYSCON_CHIPID_FAB_MASK 0x0e000000 ++#define SYSCON_CHIPID_FAB_SHIFT 25 ++#define SYSCON_CHIPID_REV_MASK 0xf0000000 ++#define SYSCON_CHIPID_REV_SHIFT 28 ++ ++/* TESTCR Register Defines */ ++#define SYSCON_TESTCR_TMODE_MASK 0x000000ff ++#define SYSCON_TESTCR_TMODE_SHIFT 0 ++#define SYSCON_TESTCR_BONDO 0x00000100 ++#define SYSCON_TESTCR_PACKO 0x00000800 ++#define SYSCON_TESTCR_ETOM 0x00002000 ++#define SYSCON_TESTCR_TOM 0x00004000 ++#define SYSCON_TESTCR_OVR 0x00008000 ++#define SYSCON_TESTCR_TonIDE 0x00010000 ++#define SYSCON_TESTCR_RonG 0x00020000 ++ ++/* SYSCFG Register Defines */ ++#define SYSCON_SYSCFG_LCSn1 0x00000001 ++#define SYSCON_SYSCFG_LCSn2 0x00000002 ++#define SYSCON_SYSCFG_LCSn3 0x00000004 ++#define SYSCON_SYSCFG_LEECK 0x00000008 ++#define SYSCON_SYSCFG_LEEDA 0x00000010 ++#define SYSCON_SYSCFG_LASDO 0x00000020 ++#define SYSCON_SYSCFG_LCSn6 0x00000040 ++#define SYSCON_SYSCFG_LCSn7 0x00000080 ++#define SYSCON_SYSCFG_SBOOT 0x00000100 ++#define SYSCON_SYSCFG_FAB_MASK 0x0e000000 ++#define SYSCON_SYSCFG_FAB_SHIFT 25 ++#define SYSCON_SYSCFG_REV_MASK 0xf0000000 ++#define SYSCON_SYSCFG_REV_SHIFT 28 ++ ++/* PWRSR Register Defines */ ++#define SYSCON_PWRSR_CHIPMAN_MASK 0xFF000000 ++#define SYSCON_PWRSR_CHIPMAN_SHIFT 24 ++#define SYSCON_PWRSR_CHIPID_MASK 0x00FF0000 ++#define SYSCON_PWRSR_CHIPID_SHIFT 16 ++#define SYSCON_PWRSR_WDTFLG 0x00008000 ++#define SYSCON_PWRSR_CLDFLG 0x00002000 ++#define SYSCON_PWRSR_TEST_RESET 0x00001000 ++#define SYSCON_PWRSR_RSTFLG 0x00000800 ++#define SYSCON_PWRSR_SWRESET 0x00000400 ++#define SYSCON_PWRSR_PLL2_LOCKREG 0x00000200 ++#define SYSCON_PWRSR_PLL2_LOCK 0x00000100 ++#define SYSCON_PWRSR_PLL1_LOCKREG 0x00000080 ++#define SYSCON_PWRSR_PLL1_LOCK 0x00000040 ++#define SYSCON_PWRSR_RTCDIV 0x0000003F ++ ++/* PWRCNT Register Defines */ ++#define SYSCON_PWRCNT_FIREN 0x80000000 ++#define SYSCON_PWRCNT_UARTBAUD 0x20000000 ++#define SYSCON_PWRCNT_USHEN 0x10000000 ++#define SYSCON_PWRCNT_DMA_M2MCH1 0x08000000 ++#define SYSCON_PWRCNT_DMA_M2MCH0 0x04000000 ++#define SYSCON_PWRCNT_DMA_M2PCH8 0x02000000 ++#define SYSCON_PWRCNT_DMA_M2PCH9 0x01000000 ++#define SYSCON_PWRCNT_DMA_M2PCH6 0x00800000 ++#define SYSCON_PWRCNT_DMA_M2PCH7 0x00400000 ++#define SYSCON_PWRCNT_DMA_M2PCH4 0x00200000 ++#define SYSCON_PWRCNT_DMA_M2PCH5 0x00100000 ++#define SYSCON_PWRCNT_DMA_M2PCH2 0x00080000 ++#define SYSCON_PWRCNT_DMA_M2PCH3 0x00040000 ++#define SYSCON_PWRCNT_DMA_M2PCH0 0x00020000 ++#define SYSCON_PWRCNT_DMA_M2PCH1 0x00010000 ++ ++/* BMAR Register Defines */ ++#define BMAR_PRIORD_00 0x00000000 ++#define BMAR_PRIORD_01 0x00000001 ++#define BMAR_PRIORD_02 0x00000002 ++#define BMAR_PRIORD_03 0x00000003 ++#define BMAR_PRI_CORE 0x00000008 ++#define BMAR_DMA_ENIRQ 0x00000010 ++#define BMAR_DMA_ENFIQ 0x00000020 ++#define BMAR_USB_ENIRQ 0x00000040 ++#define BMAR_USB_ENFIQ 0x00000080 ++#define BMAR_MAC_ENIRQ 0x00000100 ++#define BMAR_MAC_ENFIQ 0x00000200 ++#define BMAR_GRAPHICS_ENIRQ 0x00000400 ++#define BMAR_GRAPHICS_ENFIQ 0x00000800 ++ ++#endif /* _REGS_SYSCON_H_ */ +diff --git a/include/asm-arm/arch-ep93xx/regs_touch.h b/include/asm-arm/arch-ep93xx/regs_touch.h +new file mode 100644 +index 0000000..aad8a99 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_touch.h +@@ -0,0 +1,94 @@ ++/*============================================================================= ++ * ++ * FILE: regs_touch.h ++ * ++ * DESCRIPTION: Analog Touchscreen Register Definition ++ * ++ * Copyright Cirrus Logic, 2001-2003 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ *============================================================================= ++ */ ++#ifndef _REGS_TOUCH_H_ ++#define _REGS_TOUCH_H_ ++ ++/* ++ *----------------------------------------------------------------------------- ++ * Individual bit #defines ++ *----------------------------------------------------------------------------- ++ */ ++#define TSSETUP_SDLY_MASK 0x000003FF ++#define TSSETUP_SDLY_SHIFT 0 ++#define TSSETUP_NSMP_4 0x00000000 ++#define TSSETUP_NSMP_8 0x00000400 ++#define TSSETUP_NSMP_16 0x00000800 ++#define TSSETUP_NSMP_32 0x00000C00 ++#define TSSETUP_NSMP_MASK 0x00000C00 ++#define TSSETUP_DEV_4 0x00000000 ++#define TSSETUP_DEV_8 0x00001000 ++#define TSSETUP_DEV_12 0x00002000 ++#define TSSETUP_DEV_16 0x00003000 ++#define TSSETUP_DEV_24 0x00004000 ++#define TSSETUP_DEV_32 0x00005000 ++#define TSSETUP_DEV_64 0x00006000 ++#define TSSETUP_DEV_128 0x00007000 ++#define TSSETUP_ENABLE 0x00008000 ++#define TSSETUP_DLY_MASK 0x03FF0000 ++#define TSSETUP_DLY_SHIFT 16 ++#define TSSETUP_TDTCT 0x80000000 ++ ++#define TSMAXMIN_XMIN_MASK 0x000000FF ++#define TSMAXMIN_XMIN_SHIFT 0 ++#define TSMAXMIN_YMIN_MASK 0x0000FF00 ++#define TSMAXMIN_YMIN_SHIFT 8 ++#define TSMAXMIN_XMAX_MASK 0x00FF0000 ++#define TSMAXMIN_XMAX_SHIFT 16 ++#define TSMAXMIN_YMAX_MASK 0xFF000000 ++#define TSMAXMIN_YMAX_SHIFT 24 ++ ++#define TSXYRESULT_X_MASK 0x00000FFF ++#define TSXYRESULT_X_SHIFT 0 ++#define TSXYRESULT_AD_MASK 0x0000FFFF ++#define TSXYRESULT_AD_SHIFT 0 ++#define TSXYRESULT_Y_MASK 0x0FFF0000 ++#define TSXYRESULT_Y_SHIFT 16 ++#define TSXYRESULT_SDR 0x80000000 ++ ++#define TSX_SAMPLE_MASK 0x00003FFF ++#define TSX_SAMPLE_SHIFT 0x00 ++#define TSY_SAMPLE_MASK 0x3FFF0000 ++#define TSY_SAMPLE_SHIFT 0x10 ++ ++#define TSSETUP2_TINT 0x00000001 ++#define TSSETUP2_NICOR 0x00000002 ++#define TSSETUP2_PINT 0x00000004 ++#define TSSETUP2_PENSTS 0x00000008 ++#define TSSETUP2_PINTEN 0x00000010 ++#define TSSETUP2_DEVINT 0x00000020 ++#define TSSETUP2_DINTEN 0x00000040 ++#define TSSETUP2_DTMEN 0x00000080 ++#define TSSETUP2_DISDEV 0x00000100 ++#define TSSETUP2_NSIGND 0x00000200 ++#define TSSETUP2_S28EN 0x00000400 ++#define TSSETUP2_RINTEN 0x00000800 ++ ++#define TSXYRESULT_SDR 0x80000000 ++ ++/* ++ *----------------------------------------------------------------------------- ++ *----------------------------------------------------------------------------- ++ */ ++ ++#endif /* _REGS_TOUCH_H_ */ +diff --git a/include/asm-arm/arch-ep93xx/regs_uart.h b/include/asm-arm/arch-ep93xx/regs_uart.h +new file mode 100644 +index 0000000..cfadf4a +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/regs_uart.h +@@ -0,0 +1,84 @@ ++/* ++ * File: linux/include/asm-arm/arch-ep93xx/regs_uart.h ++ * ++ * Copyright (C) 2003 Cirrus Logic, Inc ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#ifndef _REGS_UART_H_ ++#define _REGS_UART_H_ ++ ++/* Bits in UARTRSR */ ++#define UARTRSR_FE 0x00000001 /* Framing error */ ++#define UARTRSR_PE 0x00000002 /* Parity error */ ++#define UARTRSR_BE 0x00000004 /* Break error */ ++#define UARTRSR_OE 0x00000008 /* Overrun error */ ++ ++/* Bits in UARTCR - UART1CR, UART2CR, or UART3CR */ ++#define UARTLCR_H_BRK 0x00000001 ++#define UARTLCR_H_PEN 0x00000002 ++#define UARTLCR_H_EPS 0x00000004 ++#define UARTLCR_H_STP2 0x00000008 ++#define UARTLCR_H_FEN 0x00000010 ++#define UARTLCR_H_WLEN 0x00000060 ++#define UARTLCR_H_WLEN_8_DATA 0x00000060 ++#define UARTLCR_H_WLEN_7_DATA 0x00000040 ++#define UARTLCR_H_WLEN_6_DATA 0x00000020 ++#define UARTLCR_H_WLEN_5_DATA 0x00000000 ++ ++/* Bits in UARTFR - UART1FR, UART2FR, or UART3FR */ ++#define UARTFR_RSR_ERRORS 0x0000000F ++#define UARTFR_CTS 0x00000001 ++#define UARTFR_DSR 0x00000002 ++#define UARTFR_DCD 0x00000004 ++#define UARTFR_BUSY 0x00000008 ++#define UARTFR_RXFE 0x00000010 ++#define UARTFR_TXFF 0x00000020 ++#define UARTFR_RXFF 0x00000040 ++#define UARTFR_TXFE 0x00000080 ++ ++/* Bits in UARTIIR */ ++#define UARTIIR_MIS 0x00000001 ++#define UARTIIR_RIS 0x00000002 ++#define UARTIIR_TIS 0x00000004 ++#define UARTIIR_RTIS 0x00000008 ++ ++/* Bits in UARTCR */ ++#define UARTCR_UARTE 0x00000001 ++#define UARTCR_MSIE 0x00000008 ++#define UARTCR_RIE 0x00000010 ++#define UARTCR_TIE 0x00000020 ++#define UARTCR_RTIE 0x00000040 ++#define UARTCR_LBE 0x00000080 ++ ++/* Bits in UARTMCR */ ++#define UARTMCR_DTR 0x00000001 ++#define UARTMCR_RTS 0x00000002 ++#define UARTMCR_OUT1 0x00000004 ++#define UARTMCR_OUT2 0x00000008 ++#define UARTMCR_LOOP 0x00000010 ++ ++/* Bits in UARTMSR */ ++#define UARTMSR_DCTS 0x00000001 ++#define UARTMSR_DDSR 0x00000002 ++#define UARTMSR_TERI 0x00000004 ++#define UARTMSR_DDCD 0x00000008 ++#define UARTMSR_CTS 0x00000010 ++#define UARTMSR_DSR 0x00000020 ++#define UARTMSR_RI 0x00000040 ++#define UARTMSR_DCD 0x00000080 ++ ++#endif /* _REGS_UART_H_ */ +diff --git a/include/asm-arm/arch-ep93xx/serial.h b/include/asm-arm/arch-ep93xx/serial.h +new file mode 100644 +index 0000000..06ab737 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/serial.h +@@ -0,0 +1,49 @@ ++/* ++ * linux/include/asm-arm/arch-integrator/serial.h ++ * ++ * Copyright (C) 1999 ARM Limited ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef __ASM_ARCH_SERIAL_H ++#define __ASM_ARCH_SERIAL_H ++ ++#include <asm/arch/platform.h> ++#include <asm/irq.h> ++ ++/* ++ * This assumes you have a 1.8432 MHz clock for your UART. ++ * ++ * It'd be nice if someone built a serial card with a 24.576 MHz ++ * clock, since the 16550A is capable of handling a top speed of 1.5 ++ * megabits/second; but this requires the faster clock. ++ */ ++#define BASE_BAUD (1843200 / 16) ++ ++#define _SER_IRQ0 IRQ_UARTINT0 ++#define _SER_IRQ1 IRQ_UARTINT1 ++ ++#define RS_TABLE_SIZE 2 ++ ++#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) ++ ++ /* UART CLK PORT IRQ FLAGS */ ++#define STD_SERIAL_PORT_DEFNS \ ++ { 0, BASE_BAUD, 0x3F8, _SER_IRQ0, STD_COM_FLAGS }, /* ttyS0 */ \ ++ { 0, BASE_BAUD, 0x2F8, _SER_IRQ1, STD_COM_FLAGS }, /* ttyS1 */ ++ ++#define EXTRA_SERIAL_PORT_DEFNS ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/ssp-cirrus.h b/include/asm-arm/arch-ep93xx/ssp-cirrus.h +new file mode 100644 +index 0000000..e29dc9d +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/ssp-cirrus.h +@@ -0,0 +1,30 @@ ++/* ++ * ++ * FILE: ssp.h ++ * ++ * DESCRIPTION: SSP Interface Driver Module implementation ++ * ++ * Copyright Cirrus Logic Corporation, 2001-2003. All rights reserved ++ * ++ */ ++#ifndef _SSP_DRV_H_ ++#define _SSP_DRV_H_ ++ ++enum SSPDeviceType { ++ PS2_KEYBOARD = 0, ++ I2S_CODEC = 1, ++ SERIAL_FLASH = 2 ++}; ++ ++typedef void (*SSPDataCallback) (unsigned int Data); ++ ++typedef struct _SSP_DRIVER_API { ++ int (*Open) (enum SSPDeviceType Device, SSPDataCallback Callback); ++ int (*Read) (int Handle, unsigned int Addr, unsigned int *pValue); ++ int (*Write) (int Handle, unsigned int Addr, unsigned int Value); ++ int (*Close) (int Handle); ++} SSP_DRIVER_API; ++ ++extern SSP_DRIVER_API *SSPDriver; ++ ++#endif /* _SSP_DRV_H_ */ +diff --git a/include/asm-arm/arch-ep93xx/ssp.h b/include/asm-arm/arch-ep93xx/ssp.h +new file mode 100644 +index 0000000..9102233 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/ssp.h +@@ -0,0 +1,121 @@ ++/* ++ * ssp.h ++ * ++ * Copyright (C) 2004 Ray Lehtiniemi, All Rights Reserved. ++ * Copyright (C) 2004 Siconix, Inc., All Rights Reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef SSP_H ++#define SSP_H ++ ++#include <linux/list.h> ++#include <linux/completion.h> ++#include <asm/semaphore.h> ++ ++struct ssp_master_ops; ++struct ssp_slave; ++ ++struct ssp_transfer { ++ ++ /* how many _bytes_ per unit of data */ ++ int size; ++ ++ /* how many units of data left to be clocked out */ ++ int len; ++ ++ /* how many units of data left to be clocked in */ ++ int rlen; ++ ++ /* buffer of units to shift out to slave */ ++ void *tx; ++ ++ /* buffer to hold units shifted in from slave */ ++ void *rx; ++ ++ /* signaled when complete */ ++ struct completion *c; ++}; ++ ++struct ssp_master { ++ ++ /* serialize access to the frontend */ ++ struct semaphore sem; ++ ++ /* synchronize the frontend and the backend */ ++ struct completion completion; ++ ++ /* the slave devices on this master */ ++ struct list_head slave; ++ ++ /* the active transfer on the bus */ ++ struct ssp_transfer transfer; ++ ++ /* methods for different master controllers */ ++ struct ssp_master_ops *ops; ++}; ++ ++struct ssp_master_ops { ++ ++ /* configure the master for accessing a particular slave */ ++ int (*configure) (struct ssp_slave *); ++ ++ /* enable the backend to start the transfer */ ++ int (*enable) (struct ssp_transfer *); ++ ++ /* disable the backend to stop the transfer */ ++ int (*disable) (void); ++}; ++ ++struct ssp_slave { ++ ++ /* our link in the masters list of slaves */ ++ struct list_head list; ++ ++ /* our master */ ++ struct ssp_master *master; ++#if 0 ++ /* the upper level protocol spoken by the device */ ++ struct ssp_protocol *protocol; ++#endif ++ /* the phase and polarity modes we support */ ++ unsigned long supported_modes; ++ ++ /* our maximum clock rate, in Hz */ ++ unsigned long max_clock_rate; ++ ++ /* our data unit size, in bits */ ++ int word_size; ++ ++ /* our data unit size, in bytes */ ++ int nbytes; ++ ++ /* assert or negate the chip select line for this device */ ++ void (*chip_select) (struct ssp_slave *, int); ++}; ++ ++/* manage the master-slave list */ ++extern int ssp_add_slave(struct ssp_master *, struct ssp_slave *); ++extern void ssp_remove_slave(struct ssp_master *, struct ssp_slave *); ++ ++/* perform a single transaction */ ++extern int ssp_do(struct ssp_slave *s, int len, void *tx, void *rx); ++ ++/* perform each step of a transaction */ ++extern int ssp_start(struct ssp_slave *s); /* grab master, blocking */ ++extern int ssp_trystart(struct ssp_slave *s); /* grab master, non-blocking */ ++extern void ssp_select(struct ssp_slave *s); /* assert CS */ ++extern int ssp_post(struct ssp_slave *s, int len, void *tx, void *rx); /* start a transfer */ ++extern int ssp_wait(struct ssp_slave *s); /* wait for completion */ ++ /*extern int ssp_disable (struct ssp_slave *s); *//* stop a transfer */ ++extern void ssp_deselect(struct ssp_slave *s); /* negate CS */ ++extern void ssp_finish(struct ssp_slave *s); /* release master */ ++ ++/* module stuff */ ++extern int ssp_init(void); ++extern void ssp_exit(void); ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/ssp2.h b/include/asm-arm/arch-ep93xx/ssp2.h +new file mode 100644 +index 0000000..93823a0 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/ssp2.h +@@ -0,0 +1,29 @@ ++/* ++ * ssp.h ++ * ++ * Copyright (C) 2004 Ray Lehtiniemi, All Rights Reserved. ++ * Copyright (C) 2004 Siconix, Inc., All Rights Reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef SSP2_H ++#define SSP2_H ++ ++#include <asm/arch/ssp.h> ++ ++struct ep93xx_ssp_slave { ++ struct ssp_slave slave; ++ unsigned long cr0; ++ unsigned long cr1; ++ unsigned long cpsr; ++}; ++ ++extern struct ssp_master ep93xx_ssp_master; ++ ++extern int ep93xx_ssp_init(void); ++extern void ep93xx_ssp_exit(void); ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/system.h b/include/asm-arm/arch-ep93xx/system.h +new file mode 100644 +index 0000000..1030210 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/system.h +@@ -0,0 +1,68 @@ ++/* ++ * linux/include/asm-arm/arch-ep93xx/system.h ++ * ++ * Copyright (C) 1999 ARM Limited ++ * Copyright (C) 2000 Deep Blue Solutions Ltd ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef __ASM_ARCH_SYSTEM_H ++#define __ASM_ARCH_SYSTEM_H ++ ++#include <asm/arch/platform.h> ++#include <asm/hardware.h> ++#include <asm/io.h> ++ ++static void arch_idle(void) ++{ ++ unsigned long val = readl(SYSCON_DEVCFG); ++ val = ep93xx_SYSCON_DEVCFG(val | SYSCON_DEVCFG_SHena); ++ SysconSetLocked(SYSCON_DEVCFG, val); ++ readl(SYSCON_HALT); ++} ++ ++#if defined(CONFIG_MACH_TTML) ++ ++#include <asm/arch/mach-ttml.h> ++extern __inline__ void arch_reset(char mode) ++{ ++ /* reboot using micro */ ++ unsigned char msg[4] = { 0xaa, 0x90, 0xa0, 0x65 }; ++ unsigned char reply[10]; ++ (void)ssp_do_ttml(&ep93xx_ssp_micro, msg, 4, reply, 10); ++ while (1) ; ++} ++ ++#else ++ ++extern __inline__ void arch_reset(char mode) ++{ ++#if 1 ++ /* reboot using SW_RESET bit in devcfg register */ ++ unsigned long val = readl(SYSCON_DEVCFG); ++ SysconSetLocked(SYSCON_DEVCFG, ++ ep93xx_SYSCON_DEVCFG(val | SYSCON_DEVCFG_SWRST)); ++ SysconSetLocked(SYSCON_DEVCFG, ++ ep93xx_SYSCON_DEVCFG(val & ~SYSCON_DEVCFG_SWRST)); ++ ++#else ++ /* reboot using 0.250 second onboard watchdog timeout */ ++ writel(0xaaaa, WATCHDOG); ++ while (1) ; ++#endif ++} ++#endif ++ ++#endif +diff --git a/include/asm-arm/arch-ep93xx/timex.h b/include/asm-arm/arch-ep93xx/timex.h +new file mode 100644 +index 0000000..87a7628 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/timex.h +@@ -0,0 +1,26 @@ ++/* ++ * linux/include/asm-arm/arch-integrator/timex.h ++ * ++ * Integrator architecture timex specifications ++ * ++ * Copyright (C) 1999 ARM Limited ++ * ++ * 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 ++ */ ++ ++/* ++ * ?? ++ */ ++#define CLOCK_TICK_RATE (50000000 / 16) +diff --git a/include/asm-arm/arch-ep93xx/uncompress.h b/include/asm-arm/arch-ep93xx/uncompress.h +new file mode 100644 +index 0000000..f76de3c +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/uncompress.h +@@ -0,0 +1,91 @@ ++/* ++ * linux/include/asm-arm/arch-ep93xx/uncompress.h ++ * ++ * Copyright (C) 1999 ARM Limited ++ * ++ * 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 <asm/io.h> ++#include <asm/hardware.h> ++ ++#if defined(CONFIG_MACH_ZEFEERDZA) || defined(CONFIG_MACH_ZEFEERDZB) || \ ++ defined(CONFIG_MACH_ZEFEERDZG) || defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ) ++# define BAUDRATE ((EP93XX_UART_CLK/(16 * 115200)) - 1) ++#else ++# define BAUDRATE ((EP93XX_UART_CLK/(16 * 57600)) - 1) ++#endif ++ ++#define HW_PREG(reg) ((unsigned int volatile *)(io_v2p(reg))) ++ ++static void putstr(const char *s) ++{ ++ while (*s) { ++ while (*HW_PREG(UART1FR) & UARTFR_TXFF) ; ++ ++ *HW_PREG(UART1DR) = *s; ++ ++ if (*s == '\n') { ++ while (*HW_PREG(UART1FR) & UARTFR_TXFF) ; ++ ++ *HW_PREG(UART1DR) = '\r'; ++ } ++ s++; ++ } ++ while (*HW_PREG(UART1FR) & UARTFR_BUSY) ; ++} ++ ++static void EnableUart(void) ++{ ++ /* ++ * Ensure that the base clock to the UARTS is 14.7456Mhz ++ * and that UART1 is enabled. ++ */ ++ *HW_PREG(SYSCON_PWRCNT) = SYSCON_PWRCNT_UARTBAUD; ++ ++ *HW_PREG(SYSCON_SWLOCK) = 0xaa; ++ *HW_PREG(SYSCON_DEVCFG) = (*HW_PREG(SYSCON_DEVCFG)) | SYSCON_DEVCFG_U1EN; ++ ++ /* Disable the UARTS and clear out the old settings. */ ++ *HW_PREG(UART1MCR) = 0; ++ *HW_PREG(UART1CR) = 0; ++ *HW_PREG(UART1RSR) = 0; ++ *HW_PREG(UART1CR_L) = 0; ++ *HW_PREG(UART1CR_M) = 0; ++ *HW_PREG(UART1CR_H) = 0; ++ ++ /* Set the baud rate and framing */ ++ *HW_PREG(UART1CR_L) = (BAUDRATE & 0x0FF); ++ *HW_PREG(UART1CR_M) = ((BAUDRATE >> 8) & 0x0FF); ++ ++ /* 8 Data bits, No Parity, 1 Stop bit. */ ++ *HW_PREG(UART1CR_H) = (UARTLCR_H_WLEN_8_DATA | UARTLCR_H_FEN); ++ ++ /* Enable Uart */ ++ *HW_PREG(UART1CR) = UARTCR_UARTE; ++} ++ ++#if defined(CONFIG_MACH_ADSSPHERE) ++#define arch_decomp_setup() ++#else ++ ++/* Called early before the UART is used for output by the compressed loader. */ ++static void arch_decomp_setup(void) ++{ ++ EnableUart(); ++} ++#endif ++ ++#define arch_decomp_wdog() +diff --git a/include/asm-arm/arch-ep93xx/vmalloc.h b/include/asm-arm/arch-ep93xx/vmalloc.h +new file mode 100644 +index 0000000..ec8f98d +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/vmalloc.h +@@ -0,0 +1,32 @@ ++/* ++ * linux/include/asm-arm/arch-integrator/vmalloc.h ++ * ++ * Copyright (C) 2000 Russell King. ++ * ++ * 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 ++ */ ++ ++/* ++ * Just any arbitrary offset to the start of the vmalloc VM area: the ++ * current 8MB value just means that there will be a 8MB "hole" after the ++ * physical memory until the kernel virtual memory starts. That means that ++ * any out-of-bounds memory accesses will hopefully be caught. ++ * The vmalloc() routines leaves a hole of 4kB between each vmalloced ++ * area for the same reason. ;) ++ */ ++#define VMALLOC_OFFSET (8*1024*1024) ++#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)) ++#define VMALLOC_VMADDR(x) ((unsigned long)(x)) ++#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +diff --git a/include/asm-arm/arch-ep93xx/zefeerevb.h b/include/asm-arm/arch-ep93xx/zefeerevb.h +new file mode 100644 +index 0000000..2cb3f84 +--- /dev/null ++++ b/include/asm-arm/arch-ep93xx/zefeerevb.h +@@ -0,0 +1,51 @@ ++/* ++ * linux/include/asm-arm/arch-ep93xx/platform.h ++ * ++ * Copyright (C) 2004 DAVE Srl <www.dave-tech.it> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++#ifndef ASM_ARCH_ZEFEEREVB_H ++#define ASM_ARCH_ZEFEEREVB_H ++ ++#ifdef CONFIG_MACH_ZEFEER_EVBL_107 ++/* GPIO pins used to drive NAND chip mounted on old EVB */ ++/* ++ nCE = EGPIO2 ++ CLE = EGPIO0 ++ ALE = EGPIO1 ++ R/B = EGPIO3 ++*/ ++# define NAND_EVB_nCE_GPIO_PIN (1 << 2) ++# define NAND_EVB_CLE_GPIO_PIN (1 << 0) ++# define NAND_EVB_ALE_GPIO_PIN (1 << 1) ++# define NAND_EVB_RB_GPIO_PIN (1 << 3) ++#else ++/* GPIO pins used to drive NAND chip mounted on EVB */ ++/* ++ nCE = EGPIO6 ++ CLE = EGPIO4 ++ ALE = EGPIO5 ++ R/B = EGPIO7 ++*/ ++# define NAND_EVB_nCE_GPIO_PIN (1 << 6) ++# define NAND_EVB_CLE_GPIO_PIN (1 << 4) ++# define NAND_EVB_ALE_GPIO_PIN (1 << 5) ++# define NAND_EVB_RB_GPIO_PIN (1 << 7) ++#endif ++ ++#define ZEFEEREVB_NAND_PADDR 0x20000000 ++ ++#endif /* ASM_ARCH_ZEFEEREVB_H */ +diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h +index 59975ee..755d9de 100644 +--- a/include/asm-arm/irq.h ++++ b/include/asm-arm/irq.h +@@ -38,6 +38,12 @@ extern void enable_irq(unsigned int); + #define IRQT_HIGH (__IRQT_HIGHLVL) + #define IRQT_PROBE (1 << 4) + ++/* ++ * Flags for enable and disable debounce ++ */ ++#define IRQT_DB ( 1 << 5 ) ++#define IRQT_NOTDB ( 1 << 6 ) ++ + int set_irq_type(unsigned int irq, unsigned int type); + void disable_irq_wake(unsigned int irq); + void enable_irq_wake(unsigned int irq); +diff --git a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h +index a9c75b2..556e5d8 100644 +--- a/include/asm-arm/procinfo.h ++++ b/include/asm-arm/procinfo.h +@@ -56,5 +56,6 @@ extern unsigned int elf_hwcap; + #define HWCAP_VFP 64 + #define HWCAP_EDSP 128 + #define HWCAP_JAVA 256 ++#define HWCAP_CRUNCH 512 + + #endif +diff --git a/include/linux/can/oki_ml9620_ctrl.h b/include/linux/can/oki_ml9620_ctrl.h +new file mode 100644 +index 0000000..d2cfbea +--- /dev/null ++++ b/include/linux/can/oki_ml9620_ctrl.h +@@ -0,0 +1,54 @@ ++/* ++ * include/linux/can/oki_ml9620_ctrl.h ++ * ++ * OKI ML9620 CAN Controler driver ++ * ++ * Author: Manfred Gruber <manfred.gruber@contec.at> ++ * ++ * Copyright 2004 (c) Manfred Gruber ++ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H ++ * Kufstein/Austria www.contec.at ++ * ++ * This driver was written for Contec hypercontrol Micro9 Board ++ * 1. CAN Controller is on Hypercontrol Micro9 CPU board ++ * 2. CAN Controller is on Hypercontrol Micro9 eval board ++ * ++ * This file is licensed under the terms of the GNU General Public ++ * License version 2. This program is licensed "as is" without any ++ * warranty of any kind, whether express or implied. ++ */ ++ ++#ifndef _OKI_ML9620_CTRL_H_ ++#define _OKI_ML9620_CTRL_H_ ++ ++#ifdef __KERNEL__ ++struct can_msg { ++ unsigned short id; /* identifier */ ++ unsigned short dlc : 4; /* bitfield 4: data length code [0..8] */ ++ unsigned short rtr : 1; /* bitfield 1: rtr bit */ ++ unsigned short ext : 1; /* bitfield 1: extended ID */ ++ unsigned short pad : 10; /* workaround alignment issues: ++ FIXME: completely remove that bitfield junk */ ++ unsigned char data[8]; /* data bytes */ ++}; ++#endif ++ ++#define CAN_STS_CNTRL_OFF 0 /*!< set CAN controller off */ ++#define CAN_STS_CNTRL_ON 1 /*!< set CAN controller on */ ++#define CAN_STS_CNTRL_SLEEP 2 /*!< set CAN controller sleep mode */ ++#define CAN_STS_CNTRL_AWAKE 3 /*!< set CAN controller wake up */ ++#define CAN_STS_NORMAL 0x00 /*!< CAN controller status normal */ ++#define CAN_STS_RESET 0x01 /*!< CAN controller status reset */ ++#define CAN_STS_WARNING 0x02 /*!< CAN controller status warning */ ++#define CAN_STS_BUS_OFF 0x04 /*!< CAN controller status bus off */ ++#define CAN_STS_SLEEPING 0x08 /*!< CAN controller status sleeping */ ++#define CAN_STS_OVERRUN 0x10 /*!< CAN controller status overrun */ ++#define CAN_STS_TXOK 0x20 /*!< CAN message transmitted */ ++ ++#define COMMAND 0 ++#define CONFIG 1 ++#define SEND 2 ++#define RECEIVE 3 ++#define STATUS 4 ++ ++#endif +diff --git a/include/linux/input.h b/include/linux/input.h +index 3c58233..8ea2247 100644 +--- a/include/linux/input.h ++++ b/include/linux/input.h +@@ -414,6 +414,7 @@ struct input_absinfo { + #define BTN_STYLUS2 0x14c + #define BTN_TOOL_DOUBLETAP 0x14d + #define BTN_TOOL_TRIPLETAP 0x14e ++#define BTN_RAW 0x14f + + #define BTN_WHEEL 0x150 + #define BTN_GEAR_DOWN 0x150 +diff --git a/include/linux/irda.h b/include/linux/irda.h +index 95dee17..3172c96 100644 +--- a/include/linux/irda.h ++++ b/include/linux/irda.h +@@ -76,6 +76,7 @@ typedef enum { + IRDA_MCP2120_DONGLE = 9, + IRDA_ACT200L_DONGLE = 10, + IRDA_MA600_DONGLE = 11, ++ IRDA_EP93XX_SIR = 12, + } IRDA_DONGLE; + + /* Protocol types to be used for SOCK_DGRAM */ +diff --git a/include/linux/sched.h b/include/linux/sched.h +index b0ad6f3..2ee1652 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -883,6 +883,11 @@ extern void __put_task_struct(struct tas + #define put_task_struct(tsk) \ + do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) + ++#ifdef CONFIG_EP93XX_CRUNCH ++#define PF_USEDCRUNCH 0x00200000 /* introduced to preserve PF_USEDFPU ++ meaning across the architecture */ ++#endif ++ + /* + * Per process flags + */ +diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h +index e3710d7..a1c9b53 100644 +--- a/include/linux/serial_core.h ++++ b/include/linux/serial_core.h +@@ -124,6 +124,9 @@ + /* Hilscher netx */ + #define PORT_NETX 71 + ++/* Cirrus EP93xx family */ ++#define PORT_EP93XX 65 ++ + #ifdef __KERNEL__ + + #include <linux/config.h> +diff --git a/include/linux/ttml.h b/include/linux/ttml.h +new file mode 100644 +index 0000000..2b0e327 +--- /dev/null ++++ b/include/linux/ttml.h +@@ -0,0 +1,61 @@ ++/* ++ * include/linux/ttml.h ++ * ++ * TTML TripDawg system devices. ++ * ++ * Copyright 2004, Ray Lehtiniemi ++ * Copyright 2004, Siconix, Inc ++ */ ++ ++#ifndef __TTML_H ++#define __TTML_H ++ ++#define TTML_MAJOR MISC_MAJOR ++ ++#define TTML_MINOR_LED 240 ++#define TTML_MINOR_BUZZER 241 ++#define TTML_MINOR_SPEEDO 242 ++#define TTML_MINOR_GPIO 243 ++#define TTML_MINOR_BUTTON 244 ++#define TTML_MINOR_WD 245 ++ ++#define MAX_TTML_MINORS 6 ++ ++struct ttml_ioctl_led { ++ int blue; ++ int red; ++ int yellow; ++}; ++ ++struct ttml_ioctl_buzzer { ++ int buzzer1; ++}; ++ ++struct ttml_ioctl_speedo { ++ int instant; ++ int average; ++}; ++ ++struct ttml_ioctl_gpio { ++ int pto; ++ int ignition; ++ int spare; ++}; ++ ++struct ttml_ioctl_button { ++ int button1; ++ int portf; ++}; ++ ++#define TTML_IOCTL 't' ++ ++#define TTML_GET_LED _IOR(TTML_IOCTL, 0, struct ttml_ioctl_led) ++#define TTML_GET_BUZZER _IOR(TTML_IOCTL, 1, struct ttml_ioctl_buzzer) ++#define TTML_GET_SPEEDO _IOR(TTML_IOCTL, 2, struct ttml_ioctl_speedo) ++#define TTML_GET_GPIO _IOR(TTML_IOCTL, 3, struct ttml_ioctl_gpio) ++#define TTML_GET_BUTTON _IOR(TTML_IOCTL, 4, struct ttml_ioctl_button) ++ ++#define TTML_SET_LED _IOW(TTML_IOCTL, 16, struct ttml_ioctl_led) ++#define TTML_SET_BUZZER _IOW(TTML_IOCTL, 17, struct ttml_ioctl_buzzer) ++ ++#endif +diff --git a/include/net/irda/ep93xx_irda.h b/include/net/irda/ep93xx_irda.h +new file mode 100644 +index 0000000..0ee919d +--- /dev/null ++++ b/include/net/irda/ep93xx_irda.h +@@ -0,0 +1,261 @@ ++ /********************************************************************* ++ * ++ * Filename: ep93xx_irda.h ++ * Version: 0.2 ++ * Description: Header for the EP93xx SOC IrDA driver. ++ * Status: Experimental. ++ * ++ * Copyright 2003 Cirrus Logic, Inc. ++ * ++ * Based on the ali-ircc.c implementation: ++ * Author: Benjamin Kong <benjamin_kong@ali.com.tw> ++ * Created at: 2000/10/16 03:46PM ++ * Modified at: 2001/1/3 02:55PM ++ * Modified by: Benjamin Kong <benjamin_kong@ali.com.tw> ++ * ++ * Copyright (c) 2000 Benjamin Kong <benjamin_kong@ali.com.tw> ++ * All Rights Reserved ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, or (at your option) any later version. ++ * ++ * 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: ++ * Free Software Foundation, Inc. ++ * 59 Temple Place, Suite 330 ++ * Boston, MA 02111-1307 USA ++ ********************************************************************/ ++ ++#ifndef EP93XX_IRDA_H ++#define EP93XX_IRDA_H ++ ++#include <linux/time.h> ++ ++#include <linux/spinlock.h> ++#include <linux/pm.h> ++#include <asm/io.h> ++ ++/* ++ * Number of DMA channels used ++ */ ++#define DMA_COUNT 3 ++ ++/* ++ * TX/RX window queues ++ */ ++#define MAX_TX_WINDOW 7 ++#define MAX_RX_WINDOW 7 ++ ++struct ep93xx_chip { ++ char *name; ++ int iSIR_IRQ, iMFIR_IRQ; ++ ep93xx_dma_dev_t eSIR_DMATx; ++ ep93xx_dma_dev_t eMFIR_DMATx; ++ ep93xx_dma_dev_t eMFIR_DMARx; ++ int (*init) (struct ep93xx_chip * chip); ++}; ++ ++/* For storing entries in the status FIFO */ ++ ++struct st_fifo_entry { ++ int status; ++ int len; ++}; ++ ++struct st_fifo { ++ struct st_fifo_entry entries[MAX_RX_WINDOW]; ++ int pending_bytes; ++ int head; ++ int tail; ++ int len; ++}; ++ ++struct frame_cb { ++ void *start; /* Start of frame in DMA mem */ ++ int len; /* Lenght of frame in DMA mem */ ++}; ++ ++struct tx_fifo { ++ struct frame_cb queue[MAX_TX_WINDOW]; /* Info about frames in queue */ ++ int ptr; /* Currently being sent */ ++ int len; /* Length of queue */ ++ int free; /* Next free slot */ ++ void *tail; /* Next free start in DMA mem */ ++}; ++ ++/* Private data for each instance */ ++struct ep93xx_irda_cb { ++ struct st_fifo st_fifo; /* Info about received frames */ ++ struct tx_fifo tx_fifo; /* Info about frames to be transmitted */ ++ ++ struct net_device *netdev; /* Net device pointer */ ++ struct net_device_stats stats; /* Net device stats */ ++ ++ struct irlap_cb *irlap; /* The link layer we are binded with */ ++ struct qos_info qos; /* QoS capabilities for this device */ ++ ++ int iSIR_irq, iMFIR_irq; /* Interrupts used */ ++ ++ ep93xx_dma_dev_t ePorts[DMA_COUNT]; /* DMA port ids */ ++ ++ int iDMAh[DMA_COUNT]; /* handles for DMA channels */ ++ dma_addr_t rx_dmaphysh, tx_dmaphysh; ++ ++ int fifo_size; /* FIFO size */ ++ iobuff_t tx_buff; /* Transmit buffer */ ++ iobuff_t rx_buff; /* Receive buffer */ ++ ++ char *conv_buf; /* Buffer used for SIR conversion */ ++ ++ struct timeval stamp; /* ? */ ++ struct timeval now; /* ? */ ++ ++ spinlock_t lock; /* Used for serializing operations */ ++ ++ __u32 flags; /* Interface flags */ ++ ++ __u8 direction; /* TX/RX flag */ ++ ++ __u32 speed; /* Currently used speed */ ++ __u32 new_speed; /* New target tx/rx speed */ ++ ++ int index; /* Instance index */ ++ ++ int suspended; /* APM suspend flag */ ++ struct pm_dev *dev; /* Power Management device */ ++ ++}; ++ ++/* ++ * DMA array handle index meanings ++ */ ++#define DMA_SIR_TX 0 ++#define DMA_MFIR_TX 1 ++#define DMA_MFIR_RX 2 ++ ++/* ++ * Directional defines ++ */ ++#define DIR_TX 0x01 ++#define DIR_RX 0x02 ++#define DIR_BOTH 0x03 ++ ++/* ++ * Modes support flag defines. ++ */ ++#define CLK_SIR 0x01 ++#define CLK_MIR 0x02 ++#define CLK_FIR 0x04 ++ ++/* Name friendly bit defines for register accesses */ ++ ++/* UART2/SIR */ ++#define U2RSR_OvnErr 0x08 ++#define U2RSR_BrkErr 0x04 ++#define U2RSR_PtyErr 0x02 ++#define U2RSR_FrmErr 0x01 ++ ++#define U2CRH_WLen 0x60 ++#define U2CRH_FEn 0x10 ++#define U2CRH_Stp2 0x08 ++#define U2CRH_EPS 0x04 ++#define U2CRH_PEn 0x02 ++#define U2CRH_Brk 0x01 ++ ++#define U2CR_LoopBk 0x80 ++#define U2CR_RxTO 0x40 ++#define U2CR_TxIrq 0x20 ++#define U2CR_RxIrq 0x10 ++#define U2CR_MdmStsIrq 0x08 ++#define U2CR_SIRLowPwr 0x04 ++#define U2CR_SIR 0x02 ++#define U2CR_UART 0x01 ++ ++#define U2FR_TXFE 0x80 ++#define U2FR_RXFF 0x40 ++#define U2FR_TXFF 0x20 ++#define U2FR_RXFE 0x10 ++#define U2FR_BUSY 0x08 ++#define U2FR_DCD 0x04 ++#define U2FR_DSR 0x02 ++#define U2FR_CTS 0x01 ++ ++#define U2IICR_RXTOIRQ 0x08 ++#define U2IICR_TXIRQ 0x04 ++#define U2IICR_RXIRQ 0x02 ++#define U2IICR_MDMIRQ 0x01 ++ ++#define U2DMACR_DMAErr 0x04 ++#define U2DMACR_TXDMA 0x02 ++#define U2DMACR_RXDMA 0x01 ++ ++#define IrENABLE_SIR 0x01 ++ ++/* IrDA block - MIR/FIR */ ++#define IrENABLE_FIR 0x03 ++#define IrENABLE_MIR 0x02 ++ ++#define IrCONTROL_RXRP 0x40 ++#define IrCONTROL_TXRP 0x20 ++#define IrCONTROL_RXON 0x10 ++#define IrCONTROL_TXON 0x08 ++#define IrCONTROL_TXUNDER 0x04 ++#define IrCONTROL_MIRBR 0x02 ++ ++#define IrFLAG_TXBUSY 0x200 ++#define IrFLAG_RXINFRM 0x100 ++#define IrFLAG_RXSYNC 0x80 ++#define IrFLAG_EOF 0x40 ++#define IrFLAG_WIDTHST 0x30 ++#define IrFLAG_FIRFE 0x08 ++#define IrFLAG_RXOR 0x04 ++#define IrFLAG_CRCERR 0x02 ++#define IrFLAG_RXABORT 0x01 ++ ++#define IrRIB_ByteCt 0x7FF0 ++#define IrRIB_BUFFE 0x08 ++#define IrRIB_BUFOR 0x04 ++#define IrRIB_BUFCRCERR 0x02 ++#define IrRIB_BUFRXABORT 0x01 ++ ++#define IrDMACR_DMAERR 0x04 ++#define IrDMACR_DMATXE 0x02 ++#define IrDMACR_DMARXE 0x01 ++ ++#define MFISR_RXFL 0x40 ++#define MFISR_RXIL 0x20 ++#define MFISR_RXFC 0x10 ++#define MFISR_RXFS 0x08 ++#define MFISR_TXFABORT 0x04 ++#define MFISR_TXFC 0x02 ++#define MFISR_TXSR 0x01 ++ ++#define MFIMR_RXFL 0x40 ++#define MFIMR_RXIL 0x20 ++#define MFIMR_RXFC 0x10 ++#define MFIMR_RXFS 0x08 ++#define MFIMR_TXABORT 0x04 ++#define MFIMR_TXFC 0x02 ++#define MFIMR_TXFS 0x01 ++ ++#define MFIIR_RXFL 0x40 ++#define MFIIR_RXIL 0x20 ++#define MFIIR_RXFC 0x10 ++#define MFIIR_RXFS 0x08 ++#define MFIIR_TXABORT 0x04 ++#define MFIIR_TXFC 0x02 ++#define MFIIR_TXFS 0x01 ++ ++#endif /* EP93XX_IRDA_H */ +diff --git a/init/do_mounts.c b/init/do_mounts.c +index b27c110..29d2d52 100644 +--- a/init/do_mounts.c ++++ b/init/do_mounts.c +@@ -410,7 +410,9 @@ void __init prepare_namespace(void) + root_device_name += 5; + } + +- is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; ++ /* llandre */ ++ /* To retrieve ramdisk from MTD partition we must add major 31 as suggested by rmk */ ++ is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR || MAJOR(ROOT_DEV) == 31; + + if (initrd_load()) + goto out; +diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig +index 88e52dc..cda016b 100644 +--- a/sound/oss/Kconfig ++++ b/sound/oss/Kconfig +@@ -1004,6 +1004,26 @@ config SOUND_AEDSP16 + <file:Documentation/sound/oss/AudioExcelDSP16> to get more information + about this driver and its configuration. + ++ ++config SOUND_EP93XX_AC97 ++ tristate "EP93xx AC97 Support" ++ depends on SOUND_OSS && ARCH_EP93XX ++ ---help--- ++ AC97 sound support for Cirrus EP93xx ++ ++config SOUND_EP93XX_AC97_CODEC_CS4297 ++ bool "CS4297" ++ depends on SOUND_EP93XX_AC97 ++ help ++ Say Y here if you have CS4297 Codec. ++ ++config SOUND_EP93XX_AUDIO_PIO ++ bool "EP93xx AC97 in PIO mode" ++ depends on SOUND_EP93XX_AC97 ++ ---help--- ++ Run EP93XX AC97 in PIO MODE. ++ !!! NOT TESTED !!! ++ + config SC6600 + bool "SC-6600 based audio cards (new Audio Excel DSP 16)" + depends on SOUND_AEDSP16 +diff --git a/sound/oss/Makefile b/sound/oss/Makefile +index 9bf3ee5..c7c1927 100644 +--- a/sound/oss/Makefile ++++ b/sound/oss/Makefile +@@ -91,6 +91,9 @@ obj-$(CONFIG_SOUND_EMU10K1) += emu10k1/ + obj-$(CONFIG_SOUND_CS4281) += cs4281/ + obj-$(CONFIG_DMASOUND) += dmasound/ + ++obj-$(CONFIG_SOUND_EP93XX_I2S) += ep93xx-audio.o ep93xx-i2s.o ++obj-$(CONFIG_SOUND_EP93XX_AC97) += ep93xx-audio.o ep93xx-ac97.o ++ + # Declare multi-part drivers. + + sound-objs := \ +diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c +index fd25aca..c7c9a02 100644 +--- a/sound/oss/ac97_codec.c ++++ b/sound/oss/ac97_codec.c +@@ -156,6 +156,8 @@ static const struct { + {0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops}, + {0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops}, + {0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops}, ++ {0x4352594d, "Cirrus Logic CS4201", &crystal_digital_ops}, ++ {0x43525973, "Cirrus Logic CS4202", &crystal_digital_ops}, + {0x43585430, "CXT48", &default_ops, AC97_DELUDED_MODEM }, + {0x43585442, "CXT66", &default_ops, AC97_DELUDED_MODEM }, + {0x44543031, "Diamond Technology DT0893", &default_ops}, +diff --git a/sound/oss/ep93xx-ac97.c b/sound/oss/ep93xx-ac97.c +new file mode 100644 +index 0000000..a967f19 +--- /dev/null ++++ b/sound/oss/ep93xx-ac97.c +@@ -0,0 +1,1200 @@ ++/* ++ * Glue audio driver for the Cirrus EP93xx Ac97 Controller ++ * ++ * Copyright (c) 2003 Cirrus Logic Corp. ++ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License. ++ * ++ * This file taken from h3600-uda1341.c ++ * The mixer code is from ac97_codec.c ++ * ++ * History: ++ * ++ * 2000-05-21 Nicolas Pitre Initial UDA1341 driver release. ++ * ++ * 2000-07-?? George France Bitsy support. ++ * ++ * 2000-12-13 Deborah Wallach Fixed power handling for iPAQ/h3600 ++ * ++ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on ++ * the former sa1100-uda1341.c driver. ++ * ++ * 2001-07-13 Nicolas Pitre Fixes for all supported samplerates. ++ * ++ * 2003-04-04 adt Changes for Cirrus Logic EP93xx I2S ++ * ++ * 2003-04-25 adt Changes for Cirrus Logic EP93xx Ac97 ++ * ++ * 2005-05-11 Manfred Gruber Ported this from Cirrus Logic Virgo 1-4-3 release ++ * to Kernel 2.6.11.X ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/fs.h> ++#include <linux/delay.h> ++#include <linux/pm.h> ++#include <linux/errno.h> ++#include <linux/sound.h> ++#include <linux/soundcard.h> ++#include <linux/bitops.h> ++ ++#include <asm/semaphore.h> ++#include <asm/uaccess.h> ++#include <asm/hardware.h> ++#include <asm/dma.h> ++#include <asm/arch/clocks.h> ++#include <asm/io.h> ++#include <asm/arch/dma.h> ++#include <linux/dma-mapping.h> ++ ++#include "ep93xx-audio.h" ++ ++#undef DEBUG ++//#define DEBUG 1 ++#ifdef DEBUG ++#define DPRINTK( x... ) printk( x ) ++#else ++#define DPRINTK( x... ) ++#endif ++ ++#define AUDIO_NAME "ep93xx_ac97" ++ ++#ifdef CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297 ++#define AUDIO_SAMPLE_RATE_DEFAULT 48000 ++#else ++#define AUDIO_SAMPLE_RATE_DEFAULT 44100 ++#endif ++ ++/* original check is not good enough in case FOO is greater than ++ * SOUND_MIXER_NRDEVICES because the supported_mixers has exactly ++ * SOUND_MIXER_NRDEVICES elements. ++ * before matching the given mixer against the bitmask in supported_mixers we ++ * check if mixer number exceeds maximum allowed size which is as mentioned ++ * above SOUND_MIXER_NRDEVICES */ ++#define supported_mixer(FOO) \ ++ ( (FOO >= 0) && \ ++ (FOO < SOUND_MIXER_NRDEVICES) && \ ++ codec_supported_mixers & (1<<FOO) ) ++ ++/* ++ * Available record sources. ++ * LINE1 refers to AUX in. ++ * IGAIN refers to input gain which means stereo mix. ++ */ ++#define AC97_RECORD_MASK \ ++ (SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN | SOUND_MASK_VIDEO |\ ++ SOUND_MASK_LINE1 | SOUND_MASK_LINE | SOUND_MASK_PHONEIN) ++ ++#define AC97_STEREO_MASK \ ++ (SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_CD | \ ++ SOUND_MASK_ALTPCM | SOUND_MASK_IGAIN | SOUND_MASK_LINE1 | SOUND_MASK_VIDEO) ++ ++#define AC97_SUPPORTED_MASK \ ++ (AC97_STEREO_MASK | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \ ++ SOUND_MASK_SPEAKER | SOUND_MASK_MIC | \ ++ SOUND_MASK_PHONEIN | SOUND_MASK_PHONEOUT) ++ ++/* ++ * Function prototypes. ++ */ ++static int peek(unsigned int uiAddress); ++static int poke(unsigned int uiAddress, unsigned int uiValue); ++static void ep93xx_setup_src(void); ++static void ep93xx_set_samplerate(struct audio_stream_t *stream, ++ long lSampleRate); ++static void ep93xx_init_ac97_codec(void); ++static void ep93xx_set_hw_format(struct audio_stream_t *stream, long format); ++static void ep93xx_init_ac97_controller(void); ++static int ep93xx_mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ++ ulong arg); ++static void ep93xx_audio_init(void *dummy); ++static int ep93xx_audio_ioctl(struct inode *inode, struct file *file, uint cmd, ++ ulong arg); ++ ++static int ep93xx_audio_open(struct inode *inode, struct file *file); ++static int __init ep93xx_ac97_init(void); ++static void __exit ep93xx_ac97_exit(void); ++static void ep93xx_init_mixer(void); ++static void ep93xx_audio_enable(struct audio_stream_t *stream); ++static void ep93xx_audio_disable(struct audio_stream_t *stream); ++ ++/* ++ * Statics ++ */ ++// KERNEL2.4 ++//static long audio_samplerate = AUDIO_SAMPLE_RATE_DEFAULT; ++static int ac_link_enabled = 0; ++static int codec_supported_mixers; ++ ++/* this table has default mixer values for all OSS mixers. */ ++struct mixer_defaults_t { ++ int mixer; ++ unsigned int value; ++}; ++ ++/* ++ * Default mixer settings that are set up during boot. ++ * ++ * These values are 16 bit numbers in which the upper byte is right volume ++ * and the lower byte is left volume or mono volume for mono controls. ++ * ++ * OSS Range for each of left and right volumes is 0 to 100 (0x00 to 0x64). ++ * ++ */ ++static struct mixer_defaults_t mixer_defaults[SOUND_MIXER_NRDEVICES] = { ++ /* Outputs */ ++ {SOUND_MIXER_VOLUME, 0x6464}, /* 0 dB *//* -46.5dB to 0 dB */ ++ {SOUND_MIXER_ALTPCM, 0x6464}, /* 0 dB *//* -46.5dB to 0 dB */ ++ {SOUND_MIXER_PHONEOUT, 0x6464}, /* 0 dB *//* -46.5dB to 0 dB */ ++ ++ /* PCM playback gain */ ++ {SOUND_MIXER_PCM, 0x4b4b}, /* 0 dB *//* -34.5dB to +12dB */ ++ ++ /* Record gain */ ++ {SOUND_MIXER_IGAIN, 0x0000}, /* 0 dB *//* 0 to +22.5 dB */ ++ ++ /* Inputs */ ++ {SOUND_MIXER_MIC, 0x0000}, /* mute *//* -34.5dB to +12dB */ ++ {SOUND_MIXER_LINE, 0x4b4b}, /* 0 dB *//* -34.5dB to +12dB */ ++ ++ /* Inputs that are not connected. */ ++ {SOUND_MIXER_SPEAKER, 0x0000}, /* mute *//* -45dB to 0dB */ ++ {SOUND_MIXER_PHONEIN, 0x0000}, /* mute *//* -34.5dB to +12dB */ ++ {SOUND_MIXER_CD, 0x0000}, /* mute *//* -34.5dB to +12dB */ ++ {SOUND_MIXER_VIDEO, 0x0000}, /* mute *//* -34.5dB to +12dB */ ++ {SOUND_MIXER_LINE1, 0x0000}, /* mute *//* -34.5dB to +12dB */ ++ ++ {-1, 0} /* last entry */ ++}; ++ ++static unsigned int guiOSS_Volume[SOUND_MIXER_NRDEVICES]; ++ ++/* table to scale scale from OSS mixer value to AC97 mixer register value */ ++struct ac97_mixer_hw_t { ++ unsigned int offset; ++ int scale; ++}; ++ ++static struct ac97_mixer_hw_t ac97_hw[SOUND_MIXER_NRDEVICES] = { ++ [SOUND_MIXER_VOLUME] = {AC97_02_MASTER_VOL, 64}, ++ [SOUND_MIXER_BASS] = {0, 0}, ++ [SOUND_MIXER_TREBLE] = {0, 0}, ++ [SOUND_MIXER_SYNTH] = {0, 0}, ++ [SOUND_MIXER_PCM] = {AC97_18_PCM_OUT_VOL, 32}, ++ [SOUND_MIXER_SPEAKER] = {AC97_0A_PC_BEEP_VOL, 32}, ++ [SOUND_MIXER_LINE] = {AC97_10_LINE_IN_VOL, 32}, ++ [SOUND_MIXER_MIC] = {AC97_0E_MIC_VOL, 32}, ++ [SOUND_MIXER_CD] = {AC97_12_CD_VOL, 32}, ++ [SOUND_MIXER_IMIX] = {0, 0}, ++ [SOUND_MIXER_ALTPCM] = {AC97_04_HEADPHONE_VOL, 64}, ++ [SOUND_MIXER_RECLEV] = {0, 0}, ++ [SOUND_MIXER_IGAIN] = {AC97_1C_RECORD_GAIN, 16}, ++ [SOUND_MIXER_OGAIN] = {0, 0}, ++ [SOUND_MIXER_LINE1] = {AC97_16_AUX_VOL, 32}, ++ [SOUND_MIXER_LINE2] = {0, 0}, ++ [SOUND_MIXER_LINE3] = {0, 0}, ++ [SOUND_MIXER_DIGITAL1] = {0, 0}, ++ [SOUND_MIXER_DIGITAL2] = {0, 0}, ++ [SOUND_MIXER_DIGITAL3] = {0, 0}, ++ [SOUND_MIXER_PHONEIN] = {AC97_0C_PHONE_VOL, 32}, ++ [SOUND_MIXER_PHONEOUT] = {AC97_06_MONO_VOL, 64}, ++ [SOUND_MIXER_VIDEO] = {AC97_14_VIDEO_VOL, 32}, ++ [SOUND_MIXER_RADIO] = {0, 0}, ++ [SOUND_MIXER_MONITOR] = {0, 0}, ++}; ++ ++/* the following tables allow us to go from OSS <-> ac97 quickly. */ ++enum ac97_recsettings { ++ AC97_REC_MIC = 0, ++ AC97_REC_CD, ++ AC97_REC_VIDEO, ++ AC97_REC_AUX, ++ AC97_REC_LINE, ++ AC97_REC_STEREO, /* combination of all enabled outputs.. */ ++ AC97_REC_MONO, /*.. or the mono equivalent */ ++ AC97_REC_PHONE ++}; ++ ++static const unsigned int ac97_rm2oss[] = { ++ [AC97_REC_MIC] = SOUND_MIXER_MIC, ++ [AC97_REC_CD] = SOUND_MIXER_CD, ++ [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO, ++ [AC97_REC_AUX] = SOUND_MIXER_LINE1, ++ [AC97_REC_LINE] = SOUND_MIXER_LINE, ++ [AC97_REC_STEREO] = SOUND_MIXER_IGAIN, ++ [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN ++}; ++ ++/* indexed by bit position */ ++static const unsigned int ac97_oss_rm[] = { ++ [SOUND_MIXER_MIC] = AC97_REC_MIC, ++ [SOUND_MIXER_CD] = AC97_REC_CD, ++ [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO, ++ [SOUND_MIXER_LINE1] = AC97_REC_AUX, ++ [SOUND_MIXER_LINE] = AC97_REC_LINE, ++ [SOUND_MIXER_IGAIN] = AC97_REC_STEREO, ++ [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE ++}; ++ ++static struct audio_stream_t ac97_output_stream0 = { ++ audio_num_channels:EP93XX_DEFAULT_NUM_CHANNELS, ++ audio_format:EP93XX_DEFAULT_FORMAT, ++ audio_stream_bitwidth:EP93XX_DEFAULT_BIT_WIDTH, ++ devicename:"Ac97_out", ++ dmachannel:{DMATx_AAC1, UNDEF, UNDEF}, ++ sample_rate:0, ++ hw_bit_width:16, ++ bCompactMode:1, ++}; ++ ++static struct audio_stream_t ac97_input_stream0 = { ++ audio_num_channels:EP93XX_DEFAULT_NUM_CHANNELS, ++ audio_format:EP93XX_DEFAULT_FORMAT, ++ audio_stream_bitwidth:EP93XX_DEFAULT_BIT_WIDTH, ++ devicename:"Ac97_in", ++ dmachannel:{DMARx_AAC1, UNDEF, UNDEF}, ++ sample_rate:0, ++ hw_bit_width:16, ++ bCompactMode:1, ++}; ++ ++static struct audio_hw_t ep93xx_ac97_hw = { ++ hw_enable:ep93xx_audio_enable, ++ hw_disable:ep93xx_audio_disable, ++ hw_clear_fifo:0, ++ client_ioctl:ep93xx_audio_ioctl, ++ ++ set_hw_serial_format:ep93xx_set_hw_format, ++ ++ txdmachannels:{DMATx_AAC1, DMATx_AAC2, DMATx_AAC3}, ++ rxdmachannels:{DMARx_AAC1, DMARx_AAC2, DMARx_AAC3}, ++ ++ MaxTxDmaChannels:3, ++ MaxRxDmaChannels:3, ++ ++ modcnt:0, ++}; ++ ++static struct audio_state_t ac97_audio_state0 = { ++ output_stream:&ac97_output_stream0, ++ input_stream:&ac97_input_stream0, ++ // KERNEL2.4 deleted internal sema intialisier, do it in function ++ hw:&ep93xx_ac97_hw, ++ wr_ref:0, ++ rd_ref:0, ++}; ++ ++/* ++ * peek ++ * ++ * Reads an AC97 codec register. Returns -1 if there was an error. ++ */ ++static int peek(unsigned int uiAddress) ++{ ++ unsigned int uiAC97RGIS, uiTemp; ++ ++ if (!ac_link_enabled) { ++ DPRINTK ++ ("ep93xx ac97 peek: attempt to peek before enabling ac-link.\n"); ++ return -1; ++ } ++ ++ /* ++ * Check to make sure that the address is aligned on a word boundary ++ * and is 7E or less. ++ */ ++ if (((uiAddress & 0x1) != 0) || (uiAddress > 0x007e)) { ++ return -1; ++ } ++ ++ /* ++ * How it is supposed to work is: ++ * - The ac97 controller sends out a read addr in slot 1. ++ * - In the next frame, the codec will echo that address back in slot 1 ++ * and send the data in slot 2. SLOT2RXVALID will be set to 1. ++ * ++ * Read until SLOT2RXVALID goes to 1. Reading the data in AC97S2DATA ++ * clears SLOT2RXVALID. ++ */ ++ ++ /* ++ * First, delay one frame in case of back to back peeks/pokes. ++ */ ++ mdelay(1); ++ ++ /* ++ * Write the address to AC97S1DATA, delay 1 frame, read the flags. ++ */ ++ outl(uiAddress, AC97S1DATA); ++ uiTemp = inl(AC97GCR); /* read to push write out the wrapper */ ++ ++ udelay(21 * 4); ++ uiAC97RGIS = inl(AC97RGIS); ++ ++ /* ++ * Return error if we timed out. ++ */ ++ if (((uiAC97RGIS & AC97RGIS_SLOT1TXCOMPLETE) == 0) && ++ ((uiAC97RGIS & AC97RGIS_SLOT2RXVALID) == 0)) { ++ DPRINTK("ep93xx-ac97 - peek failed reading reg 0x%02x.\n", ++ uiAddress); ++ return -1; ++ } ++ ++ return (inl(AC97S2DATA) & 0x000fffff); ++} ++ ++/* ++ * poke ++ * ++ * Writes an AC97 codec Register. Return -1 if error. ++ */ ++static int poke(unsigned int uiAddress, unsigned int uiValue) ++{ ++ unsigned int uiAC97RGIS, uiTemp; ++ ++ if (!ac_link_enabled) { ++ DPRINTK ++ ("ep93xx ac97 poke: attempt to poke before enabling ac-link.\n"); ++ return -1; ++ } ++ ++ /* ++ * Check to make sure that the address is align on a word boundary and ++ * is 7E or less. And that the value is a 16 bit value. ++ */ ++ if (((uiAddress & 0x1) != 0) || (uiAddress > 0x007e)) { ++ return -1; ++ } ++ ++ /* ++ * First, delay one frame in case of back to back peeks/pokes. ++ */ ++ mdelay(1); ++ ++ /* ++ * Write the data to AC97S2DATA, then the address to AC97S1DATA. ++ */ ++ outl(uiValue, AC97S2DATA); ++ outl(uiAddress, AC97S1DATA); ++ uiTemp = inl(AC97GCR); /* read to push writes out the wrapper */ ++ ++ /* ++ * Wait for the tx to complete, get status. ++ */ ++ udelay(42); ++ uiAC97RGIS = inl(AC97RGIS); ++ ++ /* ++ * Return error if we timed out. ++ */ ++ if (!(inl(AC97RGIS) & AC97RGIS_SLOT1TXCOMPLETE)) { ++ DPRINTK ++ ("ep93xx-ac97: poke failed writing reg 0x%02x value 0x%02x.\n", ++ uiAddress, uiValue); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++/* ++ * When we get to the multichannel case the pre-fill and enable code ++ * will go to the dma driver's start routine. ++ */ ++static void ep93xx_audio_enable(struct audio_stream_t *stream) ++{ ++ unsigned int uiTemp; ++ ++ DPRINTK("ep93xx_audio_enable\n"); ++ ++ /* ++ * Enable the rx or tx channel ++ */ ++ if (stream->dmachannel[0] == DMATx_AAC1) { ++ uiTemp = inl(AC97TXCR1); ++ outl((uiTemp | AC97TXCR_TEN), AC97TXCR1); ++ uiTemp = inl(AC97TXCR1); ++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO ++ outl(inl(AC97IE1) | AC97ISR_TIS, AC97IE1); ++#endif ++ } ++ ++ if (stream->dmachannel[0] == DMARx_AAC1) { ++ uiTemp = inl(AC97RXCR1); ++ outl((uiTemp | AC97RXCR_REN), AC97RXCR1); ++ uiTemp = inl(AC97RXCR1); ++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO ++ outl(inl(AC97IE1) | AC97ISR_RIS, AC97IE1); ++#endif ++ } ++ //DPRINTK("ep93xx_audio_enable - EXIT\n"); ++} ++ ++static void ep93xx_audio_disable(struct audio_stream_t *stream) ++{ ++ unsigned int uiControl, uiStatus; ++ ++ DPRINTK("ep93xx_audio_disable\n"); ++ ++ /* ++ * Disable the rx or tx channel ++ */ ++ if (stream->dmachannel[0] == DMATx_AAC1) { ++ uiControl = inl(AC97TXCR1); ++ if (uiControl & AC97TXCR_TEN) { ++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO ++ outl(inl(AC97IE1) & ~AC97ISR_TIS, AC97IE1); ++#else ++ /* ++ * Wait for fifo to empty. We've shut down the dma ++ * so that should happen soon. ++ */ ++ do { ++ uiStatus = inl(AC97SR1); ++ } while (((uiStatus & 0x82) == 0)); ++ //} while( ((uiStatus & 0x20)!=0) ;&& ++ //((uiStatus & 0x82)==0) ); ++#endif ++ ++ outl((uiControl & ~AC97TXCR_TEN), AC97TXCR1); ++ uiControl = inl(AC97TXCR1); ++ } ++ } ++ ++ if (stream->dmachannel[0] == DMARx_AAC1) { ++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO ++ outl(inl(AC97IE1) & ~AC97ISR_RIS, AC97IE1); ++#endif ++ uiControl = inl(AC97RXCR1); ++ outl((uiControl & ~AC97RXCR_REN), AC97RXCR1); ++ uiControl = inl(AC97RXCR1); ++ } ++ //DPRINTK("ep93xx_audio_disable - EXIT\n"); ++} ++ ++/* ++ * ep93xx_setup_src ++ * ++ * Once the ac-link is up and all is good, we want to set the codec to a ++ * usable mode. ++ */ ++static void ep93xx_setup_src(void) ++{ ++ int iTemp; ++ ++ /* ++ * Set the VRA bit to enable the SRC. ++ */ ++ iTemp = peek(AC97_2A_EXT_AUDIO_POWER); ++ poke(AC97_2A_EXT_AUDIO_POWER, (iTemp | 0x1)); ++ ++ /* ++ * Set the DSRC/ASRC bits to enable the variable rate SRC. ++ */ ++ iTemp = peek(AC97_60_MISC_CRYSTAL_CONTROL); ++ poke(AC97_60_MISC_CRYSTAL_CONTROL, (iTemp | 0x0300)); ++} ++ ++/* ++ * ep93xx_set_samplerate ++ * ++ * lFrequency - Sample Rate in Hz ++ * bTx - 1 to set Tx sample rate ++ * bRx - 1 to set Rx sample rate ++ */ ++static void ep93xx_set_samplerate(struct audio_stream_t *stream, ++ long lSampleRate) ++{ ++#ifndef CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297 ++ unsigned short usDivider, usPhase; ++ ++ DPRINTK("ep93xx_set_samplerate - Fs = %d\n", (int)lSampleRate); ++ ++ if ((lSampleRate < 7200) || (lSampleRate > 48000)) { ++ DPRINTK("ep93xx_set_samplerate - invalid Fs = %d\n", ++ (int)lSampleRate); ++ return; ++ } ++ ++ /* ++ * Calculate divider and phase increment. ++ * ++ * divider = round( 0x1770000 / lSampleRate ) ++ * Note that usually rounding is done by adding 0.5 to a floating ++ * value and then truncating. To do this without using floating ++ * point, I multiply the fraction by two, do the division, then add one, ++ * then divide the whole by 2 and then truncate. ++ * Same effect, no floating point math. ++ * ++ * Ph incr = trunc( (0x1000000 / usDivider) + 1 ) ++ */ ++ ++ usDivider = (unsigned short)(((2 * 0x1770000 / lSampleRate) + 1) / 2); ++ ++ usPhase = (0x1000000 / usDivider) + 1; ++ ++ /* ++ * Write them in the registers. Spec says divider must be ++ * written after phase incr. ++ */ ++ if (stream->dmachannel[0] == DMATx_AAC1) { ++ poke(AC97_2C_PCM_FRONT_DAC_RATE, usDivider); ++ poke(AC97_64_DAC_SRC_PHASE_INCR, usPhase); ++ } ++ ++ if (stream->dmachannel[0] == DMARx_AAC1) { ++ ++ poke(AC97_32_PCM_LR_ADC_RATE, usDivider); ++ poke(AC97_66_ADC_SRC_PHASE_INCR, usPhase); ++ } ++ ++ DPRINTK("ep93xx_set_samplerate - phase = %d, divider = %d\n", ++ (unsigned int)usPhase, (unsigned int)usDivider); ++ ++ /* ++ * We sorta should report the actual samplerate back to the calling ++ * application. But some applications freak out if they don't get ++ * exactly what they asked for. So we fudge and tell them what ++ * they want to hear. ++ */ ++ stream->sample_rate = lSampleRate; ++ ++ DPRINTK("ep93xx_set_samplerate - EXIT\n"); ++#else ++ stream->sample_rate = AUDIO_SAMPLE_RATE_DEFAULT; ++#endif ++} ++ ++/* ++ * ep93xx_set_hw_format ++ * ++ * Sets up whether the controller is expecting 20 bit data in 32 bit words ++ * or 16 bit data compacted to have a stereo sample in each 32 bit word. ++ */ ++static void ep93xx_set_hw_format(struct audio_stream_t *stream, long format) ++{ ++ int bCompactMode, uiTemp, iWidth; ++ unsigned long ulRegValue; ++ ++ switch (format) { ++ /* ++ * Here's all the <=16 bit formats. We can squeeze both L and R ++ * into one 32 bit sample so use compact mode. ++ */ ++ case AFMT_U8: ++ case AFMT_S8: ++ case AFMT_S16_LE: ++ case AFMT_U16_LE: ++ bCompactMode = 1; ++ ulRegValue = 0x00008018; ++ iWidth = 16; ++ break; ++ ++ /* ++ * Add any other >16 bit formats here... ++ */ ++ case AFMT_S32_BLOCKED: ++ default: ++ bCompactMode = 0; ++ ulRegValue = 0x00004018; ++ iWidth = 20; ++ break; ++ } ++ ++ if (stream->dmachannel[0] == DMARx_AAC1) { ++ uiTemp = inl(AC97RXCR1); ++ if (ulRegValue != uiTemp) { ++ outl(ulRegValue, AC97RXCR1); ++ uiTemp = inl(AC97RXCR1); ++ } ++ stream->hw_bit_width = iWidth; ++ stream->bCompactMode = bCompactMode; ++ } ++ ++ if (stream->dmachannel[0] == DMATx_AAC1) { ++ uiTemp = inl(AC97TXCR1); ++ if (ulRegValue != uiTemp) { ++ outl(ulRegValue, AC97TXCR1); ++ uiTemp = inl(AC97TXCR1); ++ } ++ stream->hw_bit_width = iWidth; ++ stream->bCompactMode = bCompactMode; ++ } ++ ++} ++ ++/* ++ * ep93xx_init_ac97_controller ++ * ++ * This routine sets up the Ac'97 Controller. ++ */ ++static void ep93xx_init_ac97_controller(void) ++{ ++ unsigned int uiDEVCFG, uiTemp; ++ ++ DPRINTK("ep93xx_init_ac97_controller - enter\n"); ++ ++ /* ++ * Configure the multiplexed Ac'97 pins to be Ac97 not I2s. ++ * Configure the EGPIO4 and EGPIO6 to be GPIOS, not to be ++ * SDOUT's for the second and third I2S controller channels. ++ */ ++ uiDEVCFG = inl(SYSCON_DEVCFG); ++ ++ uiDEVCFG &= ~(SYSCON_DEVCFG_I2SonAC97 | ++ SYSCON_DEVCFG_A1onG | SYSCON_DEVCFG_A2onG); ++ ++ SysconSetLocked(SYSCON_DEVCFG, uiDEVCFG); ++ ++ /* ++ * Disable the AC97 controller internal loopback. ++ * Disable Override codec ready. ++ */ ++ outl(0, AC97GCR); ++ ++ /* ++ * Enable the AC97 Link. ++ */ ++ uiTemp = inl(AC97GCR); ++ outl((uiTemp | AC97GSR_IFE), AC97GCR); ++ uiTemp = inl(AC97GCR); /* read to push write out the wrapper */ ++ ++ /* ++ * Set the TIMEDRESET bit. Will cause a > 1uSec reset of the ac-link. ++ * This bit is self resetting. ++ */ ++ outl(AC97RESET_TIMEDRESET, AC97RESET); ++ uiTemp = inl(AC97GCR); /* read to push write out the wrapper */ ++ ++ /* ++ * Delay briefly, but let's not hog the processor. ++ */ ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(5); /* 50 mSec */ ++ ++ /* ++ * Read the AC97 status register to see if we've seen a CODECREADY ++ * signal from the AC97 codec. ++ */ ++ if (!(inl(AC97RGIS) & AC97RGIS_CODECREADY)) { ++ DPRINTK("ep93xx-ac97 - FAIL: CODECREADY still low!\n"); ++ return; ++ } ++ ++ /* ++ * Delay for a second, not hogging the processor ++ */ ++ set_current_state(TASK_INTERRUPTIBLE); ++ schedule_timeout(HZ); /* 1 Sec */ ++ ++ /* ++ * Now the Ac-link is up. We can read and write codec registers. ++ */ ++ ac_link_enabled = 1; ++ ++ /* ++ * Set up the rx and tx channels ++ * Set the CM bit, data size=16 bits, enable tx slots 3 & 4. ++ */ ++ ep93xx_set_hw_format(&ac97_output_stream0, EP93XX_DEFAULT_FORMAT); ++ ep93xx_set_hw_format(&ac97_input_stream0, EP93XX_DEFAULT_FORMAT); ++ ++ DPRINTK("ep93xx-ac97 -- AC97RXCR1: %08x\n", inl(AC97RXCR1)); ++ DPRINTK("ep93xx-ac97 -- AC97TXCR1: %08x\n", inl(AC97TXCR1)); ++ ++ DPRINTK("ep93xx_init_ac97_controller - EXIT - success\n"); ++ ++} ++ ++/* ++ * ep93xx_init_ac97_codec ++ * ++ * Program up the external Ac97 codec. ++ * ++ */ ++static void ep93xx_init_ac97_codec(void) ++{ ++ DPRINTK("ep93xx_init_ac97_codec - enter\n"); ++ ++ ep93xx_setup_src(); ++ ep93xx_set_samplerate(&ac97_output_stream0, AUDIO_SAMPLE_RATE_DEFAULT); ++ ep93xx_set_samplerate(&ac97_input_stream0, AUDIO_SAMPLE_RATE_DEFAULT); ++ ep93xx_init_mixer(); ++ ++ DPRINTK("ep93xx_init_ac97_codec - EXIT\n"); ++ ++} ++ ++#ifdef DEBUG ++static void ep93xx_dump_ac97_regs(void) ++{ ++ int i; ++ unsigned int reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7; ++ ++ DPRINTK("---------------------------------------------\n"); ++ DPRINTK(" : 0 2 4 6 8 A C E\n"); ++ ++ for (i = 0; i < 0x80; i += 0x10) { ++ reg0 = 0xffff & (unsigned int)peek(i); ++ reg1 = 0xffff & (unsigned int)peek(i + 0x2); ++ reg2 = 0xffff & (unsigned int)peek(i + 0x4); ++ reg3 = 0xffff & (unsigned int)peek(i + 0x6); ++ reg4 = 0xffff & (unsigned int)peek(i + 0x8); ++ reg5 = 0xffff & (unsigned int)peek(i + 0xa); ++ reg6 = 0xffff & (unsigned int)peek(i + 0xc); ++ reg7 = 0xffff & (unsigned int)peek(i + 0xe); ++ ++ DPRINTK(" %02x : %04x %04x %04x %04x %04x %04x %04x %04x\n", ++ i, reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7); ++ } ++} ++#endif ++ ++static void ep93xx_set_volume(unsigned int oss_channel, unsigned int oss_val) { ++ unsigned int left, right; ++ u16 val = 0; ++ struct ac97_mixer_hw_t *mh = &ac97_hw[oss_channel]; ++ ++ if (!mh->scale) { ++ DPRINTK ++ ("ep93xx-ac97.c: ep93xx_set_volume - not a valid OSS channel\n"); ++ return; ++ } ++ ++ /* cleanse input a little */ ++ right = ((oss_val >> 8) & 0xff); ++ left = (oss_val & 0xff); ++ ++ if (right > 100) ++ right = 100; ++ if (left > 100) ++ left = 100; ++ ++ DPRINTK("ac97_codec: wrote OSS channel#%2d (ac97 reg 0x%02x), " ++ "l:%2d, r:%2d:", oss_channel, mh->offset, left, right); ++ ++ if (AC97_STEREO_MASK & (1 << oss_channel)) { ++ /* stereo mixers */ ++ if (oss_channel == SOUND_MIXER_IGAIN) { ++ right = ((100 - right) * (mh->scale - 1)) / 100; ++ left = ((100 - left) * (mh->scale - 1)) / 100; ++ if (right >= mh->scale) ++ right = mh->scale - 1; ++ if (left >= mh->scale) ++ left = mh->scale - 1; ++ right = (mh->scale - 1) - right; ++ left = (mh->scale - 1) - left; ++ val = (left << 8) | right; ++ } else { ++ if (left == 0 && right == 0) { ++ val = 0x8000; ++ } else { ++ right = ((100 - right) * (mh->scale - 1)) / 100; ++ left = ((100 - left) * (mh->scale - 1)) / 100; ++ if (right >= mh->scale) ++ right = mh->scale - 1; ++ if (left >= mh->scale) ++ left = mh->scale - 1; ++ val = (left << 8) | right; ++ } ++ } ++ } else if (left == 0) { ++ val = 0x8000; ++ } else if ((oss_channel == SOUND_MIXER_SPEAKER) || ++ (oss_channel == SOUND_MIXER_PHONEIN) || ++ (oss_channel == SOUND_MIXER_PHONEOUT)) { ++ left = ((100 - left) * (mh->scale - 1)) / 100; ++ if (left >= mh->scale) ++ left = mh->scale - 1; ++ val = left; ++ } else if (oss_channel == SOUND_MIXER_MIC) { ++ val = peek(mh->offset) & ~0x801f; ++ left = ((100 - left) * (mh->scale - 1)) / 100; ++ if (left >= mh->scale) ++ left = mh->scale - 1; ++ val |= left; ++ } ++ /* ++ * For bass and treble, the low bit is optional. Masking it ++ * lets us avoid the 0xf 'bypass'. ++ * Do a read, modify, write as we have two contols in one reg. ++ */ ++ else if (oss_channel == SOUND_MIXER_BASS) { ++ val = peek(mh->offset) & ~0x0f00; ++ left = ((100 - left) * (mh->scale - 1)) / 100; ++ if (left >= mh->scale) ++ left = mh->scale - 1; ++ val |= (left << 8) & 0x0e00; ++ } else if (oss_channel == SOUND_MIXER_TREBLE) { ++ val = peek(mh->offset) & ~0x000f; ++ left = ((100 - left) * (mh->scale - 1)) / 100; ++ if (left >= mh->scale) ++ left = mh->scale - 1; ++ val |= left & 0x000e; ++ } ++ ++ DPRINTK(" 0x%04x", val); ++ ++ poke(mh->offset, val); ++ ++#ifdef DEBUG ++ val = peek(mh->offset); ++ DPRINTK(" (read back 0x%04x)\n", val); ++#endif ++ ++ guiOSS_Volume[oss_channel] = oss_val; ++} ++ ++static void ep93xx_init_mixer(void) ++{ ++ u16 cap; ++ int i; ++ ++ /* mixer masks */ ++ codec_supported_mixers = AC97_SUPPORTED_MASK; ++ ++ cap = peek(AC97_00_RESET); ++ if (!(cap & 0x04)) { ++ codec_supported_mixers &= ++ ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE); ++ } ++ if (!(cap & 0x10)) { ++ codec_supported_mixers &= ~SOUND_MASK_ALTPCM; ++ } ++ ++ /* ++ * Detect bit resolution of output volume controls by writing to the ++ * 6th bit (not unmuting yet) ++ */ ++ poke(AC97_02_MASTER_VOL, 0xa020); ++ if (peek(AC97_02_MASTER_VOL) != 0xa020) { ++ ac97_hw[SOUND_MIXER_VOLUME].scale = 32; ++ } ++ ++ poke(AC97_04_HEADPHONE_VOL, 0xa020); ++ if (peek(AC97_04_HEADPHONE_VOL) != 0xa020) { ++ ac97_hw[AC97_04_HEADPHONE_VOL].scale = 32; ++ } ++ ++ poke(AC97_06_MONO_VOL, 0x8020); ++ if (peek(AC97_06_MONO_VOL) != 0x8020) { ++ ac97_hw[AC97_06_MONO_VOL].scale = 32; ++ } ++ ++ /* initialize mixer channel volumes */ ++ for (i = 0; ++ (i < SOUND_MIXER_NRDEVICES) && (mixer_defaults[i].mixer != -1); ++ i++) { ++ if (!supported_mixer(mixer_defaults[i].mixer)) { ++ continue; ++ } ++ ++ ep93xx_set_volume(mixer_defaults[i].mixer, ++ mixer_defaults[i].value); ++ } ++ ++} ++ ++/* ++ * ac97_recmask_io ++ * ++ * Read or write the record source. ++ */ ++static int ep93xx_read_recsource(void) ++{ ++ unsigned int val; ++ ++ /* read it from the card */ ++ val = peek(AC97_1A_RECORD_SELECT); ++ ++ DPRINTK("ac97_codec: ac97 recmask to set to 0x%04x\n", val); ++ ++ return (1 << ac97_rm2oss[val & 0x07]); ++} ++ ++static int ep93xx_set_recsource(int mask) ++{ ++ unsigned int val; ++ ++ /* Arg contains a bit for each recording source */ ++ if (mask == 0) { ++ return 0; ++ } ++ ++ mask &= AC97_RECORD_MASK; ++ ++ if (mask == 0) { ++ return -EINVAL; ++ } ++ ++ /* ++ * May have more than one bit set. So clear out currently selected ++ * record source value first (AC97 supports only 1 input) ++ */ ++ val = (1 << ac97_rm2oss[peek(AC97_1A_RECORD_SELECT) & 0x07]); ++ if (mask != val) ++ mask &= ~val; ++ ++ val = ffs(mask); ++ val = ac97_oss_rm[val - 1]; ++ val |= val << 8; /* set both channels */ ++ ++ DPRINTK("ac97_codec: setting ac97 recmask to 0x%04x\n", val); ++ ++ poke(AC97_1A_RECORD_SELECT, val); ++ ++ return 0; ++} ++ ++static int ep93xx_mixer_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = &ep93xx_ac97_hw; ++ return 0; ++} ++ ++static int ep93xx_mixer_release(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int ++ep93xx_mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) ++{ ++ int val, nr; ++ ++ struct audio_hw_t *hw = (struct audio_hw_t *)file->private_data; ++ ++ DPRINTK("ep93xx_mixer_ioctl - enter. IOC_TYPE is %c \n", ++ _IOC_TYPE(cmd)); ++ ++ if (cmd == SOUND_MIXER_INFO) { ++ mixer_info info; ++ strncpy(info.id, "CS4202", sizeof(info.id)); ++ strncpy(info.name, "Cirrus CS4202", sizeof(info.name)); ++ info.modify_counter = hw->modcnt; ++ if (copy_to_user((void *)arg, &info, sizeof(info))) { ++ return -EFAULT; ++ } ++ return 0; ++ } ++ if (cmd == SOUND_OLD_MIXER_INFO) { ++ _old_mixer_info info; ++ strncpy(info.id, "CS4202", sizeof(info.id)); ++ strncpy(info.name, "Cirrus CS4202", sizeof(info.name)); ++ if (copy_to_user((void *)arg, &info, sizeof(info))) { ++ return -EFAULT; ++ } ++ return 0; ++ } ++ ++ if ((_IOC_TYPE(cmd) != 'M') || (_SIOC_SIZE(cmd) != sizeof(int))) ++ return -EINVAL; ++ ++ if (cmd == OSS_GETVERSION) ++ return put_user(SOUND_VERSION, (int *)arg); ++ ++ nr = _IOC_NR(cmd); ++ ++ if (_SIOC_DIR(cmd) == _SIOC_READ) { ++ switch (nr) { ++ case SOUND_MIXER_RECSRC: ++ /* Read the current record source */ ++ val = ep93xx_read_recsource(); ++ break; ++ ++ case SOUND_MIXER_DEVMASK: ++ /* give them the supported mixers */ ++ val = codec_supported_mixers; ++ break; ++ ++ case SOUND_MIXER_RECMASK: ++ /* Arg contains a bit for each supported recording source */ ++ val = AC97_RECORD_MASK; ++ break; ++ ++ case SOUND_MIXER_STEREODEVS: ++ /* Mixer channels supporting stereo */ ++ val = AC97_STEREO_MASK; ++ break; ++ ++ case SOUND_MIXER_CAPS: ++ val = SOUND_CAP_EXCL_INPUT; ++ break; ++ ++ default: ++ if (!supported_mixer(nr)) ++ return -EINVAL; ++ ++ val = guiOSS_Volume[nr]; ++ break; ++ ++ } /* switch */ ++ ++ return put_user(val, (int *)arg); ++ } ++ ++ if (_SIOC_DIR(cmd) == (_SIOC_WRITE | _SIOC_READ)) { ++ if (get_user(val, (int *)arg)) ++ return -EFAULT; ++ ++ switch (nr) { ++ case SOUND_MIXER_RECSRC: ++ return ep93xx_set_recsource(val); ++ ++ default: ++ if (!supported_mixer(nr)) ++ return -EINVAL; ++ ++ ep93xx_set_volume(nr, val); ++ hw->modcnt++; ++ return 0; ++ } ++ } ++ ++ return -EINVAL; ++} ++ ++static struct file_operations ep93xx_mixer_fops = { ++ owner:THIS_MODULE, ++ llseek:no_llseek, ++ ioctl:ep93xx_mixer_ioctl, ++ open:ep93xx_mixer_open, ++ release:ep93xx_mixer_release, ++}; ++ ++/* ++ * Audio interface ++ */ ++static void ep93xx_audio_init(void *dummy) ++{ ++ DPRINTK("ep93xx_audio_init - enter\n"); ++ ++ /* ++ * Init the controller, enable the ac-link. ++ * Initialize the codec. ++ */ ++ ep93xx_init_ac97_controller(); ++ ep93xx_init_ac97_codec(); ++ ++#ifdef DEBUG ++ ep93xx_dump_ac97_regs(); ++#endif ++ ++ DPRINTK("ep93xx_audio_init - EXIT\n"); ++} ++ ++static int ep93xx_audio_ioctl(struct inode *inode, struct file *file, ++ uint cmd, ulong arg) ++{ ++ struct audio_state_t *state = ++ (struct audio_state_t *)file->private_data; ++ struct audio_stream_t *os = state->output_stream; ++ struct audio_stream_t *is = state->input_stream; ++ long val; ++ int ret = 0; ++ ++ /* ++ * These are platform dependent ioctls which are not handled by the ++ * generic ep93xx-audio module. ++ */ ++ switch (cmd) { ++ case SNDCTL_DSP_SPEED: ++ ++ DPRINTK("ep93xx_audio_ioctl - SNDCTL_DSP_SPEED\n"); ++ ++ if (get_user(val, (int *)arg)) { ++ return -EFAULT; ++ } ++ ++ if ((file->f_mode & FMODE_WRITE) && (val != os->sample_rate)) { ++ ep93xx_set_samplerate(os, val); ++ } ++ if ((file->f_mode & FMODE_READ) && (val != is->sample_rate)) { ++ ep93xx_set_samplerate(is, val); ++ } ++ ++ return put_user(val, (long *)arg); ++ ++ case SOUND_PCM_READ_RATE: ++ DPRINTK("ep93xx_audio_ioctl - SOUND_PCM_READ_RATE\n"); ++ if (file->f_mode & FMODE_WRITE) { ++ return put_user(os->sample_rate, (long *)arg); ++ } ++ return put_user(is->sample_rate, (long *)arg); ++ ++ default: ++ DPRINTK("ep93xx_audio_ioctl-->ep93xx_mixer_ioctl\n"); ++ /* Maybe this is meant for the mixer (As per OSS Docs) */ ++ return ep93xx_mixer_ioctl(inode, file, cmd, arg); ++ } ++ ++ return ret; ++} ++ ++static int ep93xx_audio_open(struct inode *inode, struct file *file) ++{ ++ DPRINTK("ep93xx_audio_open\n"); ++ return ep93xx_audio_attach(inode, file, &ac97_audio_state0); ++} ++ ++/* ++ * Missing fields of this structure will be patched with the call ++ * to ep93xx_audio_attach(). ++ */ ++static struct file_operations ep93xx_audio_fops = { ++ open:ep93xx_audio_open, ++ owner:THIS_MODULE ++}; ++ ++static int audio_dev_id, mixer_dev_id; ++ ++static int __init ep93xx_ac97_init(void) ++{ ++ DPRINTK("ep93xx_ac97_init - enter\n"); ++ ++ // KERNEL2.4 ++ sema_init(&ac97_audio_state0.sem, 1); ++ ++ /* ++ * Enable audio early on, give the DAC time to come up. ++ */ ++ ep93xx_audio_init(0); ++ ++ /* ++ * Register devices using sound_core.c's devfs stuff ++ */ ++ audio_dev_id = register_sound_dsp(&ep93xx_audio_fops, -1); ++ if (audio_dev_id < 0) { ++ DPRINTK ++ (" ep93xx_ac97_init: register_sound_dsp failed for dsp.\n"); ++ return -ENODEV; ++ } ++ ++ mixer_dev_id = register_sound_mixer(&ep93xx_mixer_fops, -1); ++ if (mixer_dev_id < 0) { ++ DPRINTK ++ (" ep93xx_ac97_init: register_sound_dsp failed for mixer.\n"); ++ return -ENODEV; ++ } ++ ++ printk(KERN_INFO "EP93xx Ac97 audio support initialized.\n"); ++ return 0; ++} ++ ++static void __exit ep93xx_ac97_exit(void) ++{ ++ unregister_sound_dsp(audio_dev_id); ++ unregister_sound_mixer(mixer_dev_id); ++} ++ ++module_init(ep93xx_ac97_init); ++module_exit(ep93xx_ac97_exit); ++ ++MODULE_DESCRIPTION("Audio driver for the Cirrus EP93xx Ac97 controller."); ++MODULE_LICENSE("GPL"); ++/* EXPORT_NO_SYMBOLS; */ +diff --git a/sound/oss/ep93xx-audio.c b/sound/oss/ep93xx-audio.c +new file mode 100644 +index 0000000..7e00d6d +--- /dev/null ++++ b/sound/oss/ep93xx-audio.c +@@ -0,0 +1,3821 @@ ++/* ++ * ep93xx-audio.c ++ * ++ * Common audio handling for the Cirrus EP93xx processor. ++ * ++ * Copyright (c) 2003 Cirrus Logic Corp. ++ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License. ++ * ++ * Taken from sa1100-audio.c ++ * ++ * This module handles the generic buffering/DMA/mmap audio interface for ++ * codecs connected to the EP93xx chip. All features depending on specific ++ * hardware implementations like supported audio formats or samplerates are ++ * relegated to separate specific modules. ++ * ++ * ++ * History: ++ * ++ * 2000-05-21 Nicolas Pitre Initial release. ++ * ++ * 2000-06-10 Erik Bunce Add initial poll support. ++ * ++ * 2000-08-22 Nicolas Pitre Removed all DMA stuff. Now using the ++ * generic SA1100 DMA interface. ++ * ++ * 2000-11-30 Nicolas Pitre - Validation of opened instances; ++ * - Power handling at open/release time instead ++ * of driver load/unload; ++ * ++ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on ++ * the former sa1100-uda1341.c driver. ++ * ++ * 2001-07-22 Nicolas Pitre - added mmap() and realtime support ++ * - corrected many details to better comply ++ * with the OSS API ++ * ++ * 2001-10-19 Nicolas Pitre - brought DMA registration processing ++ * into this module for better ressource ++ * management. This also fixes a bug ++ * with the suspend/resume logic. ++ * ++ * 2003-04-04 Adapted for EP93xx I2S/Ac97 audio. ++ * ++ * 2004-04-23 Added support for multiple stereo streams. ++ * ++ * 2005-05-11 Manfred Gruber - Ported this from Cirrus Logic Virgo 1-4-3 release ++ * to Kernel 2.6.11.X ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/fs.h> ++#include <linux/mm.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include <linux/poll.h> ++#include <linux/pm.h> ++#include <linux/errno.h> ++#include <linux/sound.h> ++#include <linux/soundcard.h> ++#include <linux/sysrq.h> ++#include <linux/delay.h> ++#include <linux/kernel_stat.h> ++#include <asm/arch/dma.h> ++#include <linux/dma-mapping.h> ++ ++#include <asm/uaccess.h> ++//#include <asm/fiq.h> ++#include <asm/io.h> ++#include <asm/hardware.h> ++#include <asm/semaphore.h> ++#include <asm/arch/dma.h> ++#include <asm/arch/irqs.h> ++ ++#include "ep93xx-audio.h" ++ ++#undef DEBUG ++//#define DEBUG 1 ++#ifdef DEBUG ++#define DPRINTK( fmt, arg... ) printk( fmt, ##arg ) ++#else ++#define DPRINTK( fmt, arg... ) ++#endif ++ ++/* Mostly just prints what ioctls got called */ ++//#define DEBUG 1 ++#ifdef DEBUG ++#define DPRINTK_IOCTL( fmt, arg... ) printk( fmt, ##arg ) ++#else ++#define DPRINTK_IOCTL( fmt, arg... ) ++#endif ++ ++/* ++ * Experiencing gaps in your audio? Try upping the AUDIO_NBFRAGS_DEFAULT! ++ * Experiencing memory problems? Try lowering them. ++ * DMA memory space is precious and rare on ARM. ++ * ++ */ ++ ++// ++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO ++#define AUDIO_NBFRAGS_DEFAULT 31 ++#define AUDIO_FRAGSIZE_DEFAULT 65536 ++#define AUDIO_NBFRAGS_MAX 31 ++#else ++#ifdef CONFIG_SOUND_EP93XX_AC97 ++// Values changed from KERNEL2.4 ++#define AUDIO_NBFRAGS_DEFAULT 4 ++#define AUDIO_FRAGSIZE_DEFAULT 8192 // max is 65536 ++#define AUDIO_NBFRAGS_MAX 4 ++#else ++#define AUDIO_NBFRAGS_DEFAULT 16 ++#define AUDIO_FRAGSIZE_DEFAULT 32768 // max is 65536 ++#define AUDIO_NBFRAGS_MAX 16 ++#endif ++#endif ++ ++/* ++ * NEXT_BUF ++ * ++ * Translates to: ++ * stream->dma_buffer_index++; ++ * stream->dma_buffer_index %= stream->nbfrags; ++ * stream->dma_buffer = stream->buffers + stream->dma_buffer_index; ++ * ++ * So stream->dma_buffer always points to the stream->dma_buffer_index-nth element ++ * of stream->buffers. ++ */ ++#define NEXT_BUF(_s_,_b_) { \ ++ (_s_)->_b_##_index++; \ ++ (_s_)->_b_##_index %= (_s_)->nbfrags; \ ++ (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_index; } ++ ++#define AUDIO_ACTIVE(state) ((state)->rd_ref || (state)->wr_ref) ++ ++/* Function prototypes */ ++static __inline__ int copy_to_user_with_conversion ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount); ++ ++static __inline__ int copy_from_user_with_conversion ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount); ++ ++static void audio_dma_start(struct audio_state_t *state, ++ struct audio_stream_t *stream); ++static void audio_dma_pause(struct audio_state_t *state, ++ struct audio_stream_t *stream); ++static void audio_prime_dma(struct audio_state_t *state, ++ struct audio_stream_t *stream); ++ ++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO ++#define DMA_ADD_BUFFER pio_add_buffer ++#define DMA_CONFIG pio_config ++#define DMA_FLUSH pio_flush ++#define DMA_FREE pio_free ++#define DMA_GET_POSITION pio_get_position ++#define DMA_PAUSE pio_pause ++#define DMA_REMOVE_BUFFER pio_remove_buffer ++#define DMA_REQUEST pio_request ++#define DMA_START pio_start ++#else ++#define DMA_ADD_BUFFER ep93xx_dma_add_buffer ++#define DMA_CONFIG ep93xx_dma_config ++#define DMA_FLUSH ep93xx_dma_flush ++#define DMA_FREE ep93xx_dma_free ++#define DMA_GET_POSITION ep93xx_dma_get_position ++#define DMA_PAUSE ep93xx_dma_pause ++#define DMA_REMOVE_BUFFER ep93xx_dma_remove_buffer ++#define DMA_REQUEST ep93xx_dma_request ++#define DMA_START ep93xx_dma_start ++#endif ++ ++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO ++/* ++ * The maximum number of buffers accepted by the PIO interface. ++ */ ++#define PIO_MAX_BUFFERS 32 ++ ++/* ++ * A convenienced macro to advance from one buffer to the next. ++ */ ++#define PIO_NEXT(x) (((x) + 1) % PIO_MAX_BUFFERS) ++ ++/* ++ * A structure to remember information about a buffer. ++ */ ++struct pio_buffer { ++ unsigned int source; ++ unsigned int pos; ++ unsigned int size; ++ int buf_id; ++}; ++ ++/* ++ * A structure to remember information about a stream. ++ */ ++struct pio_stream { ++ int assigned; ++ struct pio_buffer queue[PIO_MAX_BUFFERS]; ++ ep93xx_dma_dev_t device; ++ int first; ++ int cur; ++ int last; ++ int bytes; ++ int pause; ++ dma_callback callback; ++ unsigned int user_data; ++}; ++ ++/* ++ * The twelve streams that we can handle. ++ */ ++static struct pio_stream pio_streams[12]; ++ ++/* ++ * Reference counts for the two interrupt handlers. ++ */ ++static int pio_irq_ref_count[2]; ++ ++/* ++ * The registers that enable the three I2S transmitters. ++ */ ++static const unsigned int i2s_txenable[3] = { ++ I2STX0En, ++ I2STX1En, ++ I2STX2En ++}; ++ ++/* ++ * The flag that indicates a FIFO full condition on the three I2S transmitters. ++ */ ++static const unsigned int i2s_txflag[3] = { ++ TX0_FIFO_FULL, ++ TX1_FIFO_FULL, ++ TX2_FIFO_FULL ++}; ++ ++/* ++ * The register that contains the left channel data for the three I2S ++ * transmitters. ++ */ ++static const unsigned int i2s_tx_lft[3] = { ++ I2STX0Lft, ++ I2STX1Lft, ++ I2STX2Lft ++}; ++ ++/* ++ * The register that contains the right channel data for the three I2S ++ * transmitters. ++ */ ++static const unsigned int i2s_tx_rt[3] = { ++ I2STX0Rt, ++ I2STX1Rt, ++ I2STX2Rt ++}; ++ ++/* ++ * The registers that enable the three I2S receivers. ++ */ ++static const unsigned int i2s_rxenable[3] = { ++ I2SRX0En, ++ I2SRX1En, ++ I2SRX2En ++}; ++ ++/* ++ * The flag that indicates a FIFO empty condition on the three I2S receivers. ++ */ ++static const unsigned int i2s_rxflag[3] = { ++ RX0_FIFO_EMPTY, ++ RX1_FIFO_EMPTY, ++ RX2_FIFO_EMPTY ++}; ++ ++/* ++ * The register that contains the left channel data for the three I2S ++ * receivers. ++ */ ++static const unsigned int i2s_rx_lft[3] = { ++ I2SRX0Lft, ++ I2SRX1Lft, ++ I2SRX2Lft ++}; ++ ++/* ++ * The register that contains the right channel data for the three I2S ++ * receivers. ++ */ ++static const unsigned int i2s_rx_rt[3] = { ++ I2SRX0Rt, ++ I2SRX1Rt, ++ I2SRX2Rt ++}; ++ ++/* ++ * The registers that contain the status for the three AC'97 transceivers. ++ */ ++static const unsigned int ac97_status[3] = { ++ AC97SR1, ++ AC97SR2, ++ AC97SR3 ++}; ++ ++/* ++ * The registers that contain the audio data for the three AC'97 transceivers. ++ */ ++static const unsigned int ac97_data[3] = { ++ AC97DR1, ++ AC97DR2, ++ AC97DR3 ++}; ++ ++/* ++ * The registers that control the three AC'97 transmitters. ++ */ ++static const unsigned int ac97_txctrl[3] = { ++ AC97TXCR1, ++ AC97TXCR2, ++ AC97TXCR3 ++}; ++ ++/* ++ * The registers that control the three AC'97 receivers. ++ */ ++static const unsigned int ac97_rxctrl[3] = { ++ AC97RXCR1, ++ AC97RXCR2, ++ AC97RXCR3 ++}; ++ ++/* ++ * The descriptor for our FIQ handler. ++ */ ++static struct fiq_handler fh = { NULL, "pio_audio", NULL, NULL }; ++ ++/* ++ * Stack space for our FIQ handler. ++ */ ++static unsigned char fiq_stack[1024]; ++ ++/* ++ * References to the labels in the inline assembly. ++ */ ++extern void i2s_fiq_begin; ++extern void i2s_fiq_end; ++extern void ac97_fiq_begin; ++extern void ac97_fiq_end; ++ ++/* ++ * The FIQ handler for I2S audio. This stub is copied into the vector area and ++ * simply calls the I2S interrupt handler. ++ */ ++void pio_i2s_fiq_handler(void) ++{ ++ __asm__ __volatile__("\n\ ++i2s_fiq_begin:\n\ ++ stmdb r13!, {r0-r7, lr}\n\ ++ ldr r0, =pio_i2s_irq_handler\n\ ++ mov lr, pc\n\ ++ mov pc, r0\n\ ++ ldmia r13!, {r0-r7, lr}\n\ ++ subs pc, lr, #4\n\ ++ .ltorg\n\ ++i2s_fiq_end:"); ++} ++ ++/* ++ * The FIQ handler for AC'97 audio. This stub is copied into the vector area ++ * and simply calls the AC'97 interrupt handler. ++ */ ++void pio_ac97_fiq_handler(void) ++{ ++ __asm__ __volatile__("\n\ ++ac97_fiq_begin:\n\ ++ stmdb r13!, {r0-r7, lr}\n\ ++ ldr r0, =pio_ac97_irq_handler\n\ ++ mov lr, pc\n\ ++ mov pc, r0\n\ ++ ldmia r13!, {r0-r7, lr}\n\ ++ subs pc, lr, #4\n\ ++ .ltorg\n\ ++ac97_fiq_end:"); ++} ++ ++/* ++ * The interrupt handler for I2S audio. ++ */ ++static void pio_i2s_irq_handler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct pio_stream *p; ++ struct pio_buffer *b; ++ int idx; ++ ++ /* ++ * Increment the count of interrupts. ++ */ ++ kstat.irqs[smp_processor_id()][IRQ_SAI]++; ++ ++ /* ++ * Loop through the three transmitters. ++ */ ++ for (idx = 0; idx < 3; idx++) { ++ /* ++ * Do nothing if this transmitter is not enabled. ++ */ ++ if (!inl(i2s_txenable[idx])) ++ continue; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[idx]; ++ ++ /* ++ * Loop while the transmit FIFO is not full. ++ */ ++ while (!(inl(I2SGlSts) & i2s_txflag[idx])) { ++ /* ++ * If the stream is not assigned, is paused, or has no ++ * data, then write out silence. ++ */ ++ if (!p->assigned || p->pause || (p->cur == p->last)) { ++ outl(0, i2s_tx_lft[idx]); ++ outl(0, i2s_tx_rt[idx]); ++ } else { ++ /* ++ * Get a pointer to the current buffer. ++ */ ++ b = &p->queue[p->cur]; ++ ++ /* ++ * Write out the next sample. ++ */ ++ outl(*(unsigned long *)b->source, ++ i2s_tx_lft[idx]); ++ outl(*(unsigned long *)(b->source + 4), ++ i2s_tx_rt[idx]); ++ ++ /* ++ * Increment past the next sample. ++ */ ++ b->source += 8; ++ b->pos += 8; ++ ++ /* ++ * See if the buffer has been consumed. ++ */ ++ if (b->pos == b->size) { ++ /* ++ * Increment the count of bytes ++ * transmitted. ++ */ ++ p->bytes += b->size; ++ ++ /* ++ * Go to the next buffer. ++ */ ++ p->cur = PIO_NEXT(p->cur); ++ ++ /* ++ * Call the callback if there is one. ++ */ ++ if (p->callback) ++ p->callback(NFB, p->device, ++ p->user_data); ++ } ++ } ++ } ++ } ++ ++ /* ++ * Loop through the three receivers. ++ */ ++ for (idx = 0; idx < 3; idx++) { ++ /* ++ * Do nothing if this receiver is not enabled. ++ */ ++ if (!inl(i2s_rxenable[idx])) ++ continue; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[idx + 3]; ++ ++ /* ++ * Loop while the receive FIFO is not empty. ++ */ ++ while (!(inl(I2SGlSts) & i2s_rxflag[idx])) { ++ /* ++ * If the stream is not assigned, is paused, or has no ++ * buffer space, then throw away the data. ++ */ ++ if (!p->assigned || p->pause || (p->cur == p->last)) { ++ inl(i2s_rx_lft[idx]); ++ inl(i2s_rx_rt[idx]); ++ } else { ++ /* ++ * Get a pointer to the current buffer. ++ */ ++ b = &p->queue[p->cur]; ++ ++ /* ++ * Read in the next sample. ++ */ ++ *(unsigned long *)b->source = ++ inl(i2s_rx_lft[idx]); ++ *(unsigned long *)(b->source + 4) = ++ inl(i2s_rx_rt[idx]); ++ ++ /* ++ * Increment past the next sample. ++ */ ++ b->source += 8; ++ b->pos += 8; ++ ++ /* ++ * See if the buffer has been consumed. ++ */ ++ if (b->pos == b->size) { ++ /* ++ * Increment the count of bytes ++ * received. ++ */ ++ p->bytes += b->size; ++ ++ /* ++ * Go to the next buffer. ++ */ ++ p->cur = PIO_NEXT(p->cur); ++ ++ /* ++ * Call the callback if there is one. ++ */ ++ if (p->callback) ++ p->callback(NFB, p->device, ++ p->user_data); ++ } ++ } ++ } ++ } ++ ++ /* ++ * Clear any overrun or underrun conditions that may exist. ++ */ ++ outl(0, I2SGlSts); ++} ++ ++/* ++ * The interrupt handler for AC'97 audio. ++*/ ++static void pio_ac97_irq_handler(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct pio_stream *p; ++ struct pio_buffer *b; ++ int idx, cm; ++ ++ /* ++ * Increment the count of interrupts. ++ */ ++ kstat.irqs[smp_processor_id()][IRQ_AAC]++; ++ ++ /* ++ * Loop through the three transmitters. ++ */ ++ for (idx = 0; idx < 3; idx++) { ++ /* ++ * Do nothing if this transmitter is not enabled. ++ */ ++ if (!(inl(ac97_txctrl[idx]) & AC97TXCR_TEN)) ++ continue; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[idx + 6]; ++ ++ /* ++ * See if this transmitter is in compact mode. ++ */ ++ cm = inl(ac97_txctrl[idx]) & AC97TXCR_CM; ++ ++ /* ++ * Loop while the transmit FIFO is not full. ++ */ ++ while (!(inl(ac97_status[idx]) & AC97SR_TXFF)) { ++ /* ++ * If the stream is not assigned, is paused, or has no ++ * data, then write out silence. ++ */ ++ if (!p->assigned || p->pause || (p->cur == p->last)) { ++ outl(0, ac97_data[idx]); ++ if (!cm) ++ outl(0, ac97_data[idx]); ++ } else { ++ /* ++ * Get a pointer to the current buffer. ++ */ ++ b = &p->queue[p->cur]; ++ ++ /* ++ * Write out the next sample. ++ */ ++ outl(*(unsigned long *)b->source, ++ ac97_data[idx]); ++ ++ /* ++ * Increment past the next sample. ++ */ ++ b->source += 4; ++ b->pos += 4; ++ ++ /* ++ * Write another sample if we are not in ++ * compact mode. ++ */ ++ if (!cm) { ++ outl(*(unsigned long *)b->source, ++ ac97_data[idx]); ++ b->source += 4; ++ b->pos += 4; ++ } ++ ++ /* ++ * See if the buffer has been consumed. ++ */ ++ if (b->pos == b->size) { ++ /* ++ * Increment the count of bytes ++ * transmitted. ++ */ ++ p->bytes += b->size; ++ ++ /* ++ * Go to the next buffer. ++ */ ++ p->cur = PIO_NEXT(p->cur); ++ ++ /* ++ * Call the callback if there is one. ++ */ ++ if (p->callback) ++ p->callback(NFB, p->device, ++ p->user_data); ++ } ++ } ++ } ++ } ++ ++ /* ++ * Loop through the three receivers. ++ */ ++ for (idx = 0; idx < 3; idx++) { ++ /* ++ * Do nothing if this receiver is not enabled. ++ */ ++ if (!(inl(ac97_rxctrl[idx]) & AC97RXCR_REN)) ++ continue; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[idx + 9]; ++ ++ /* ++ * See if this receiver is in compact mode. ++ */ ++ cm = inl(ac97_rxctrl[idx]) & AC97RXCR_CM; ++ ++ /* ++ * Loop while the receive FIFO is not empty. ++ */ ++ while (!(inl(ac97_status[idx]) & AC97SR_RXFE)) { ++ /* ++ * If the stream is not assigned, is paused, or has no ++ * buffer space, then throw away the data. ++ */ ++ if (!p->assigned || p->pause || (p->cur == p->last)) { ++ inl(ac97_data[idx]); ++ if (!cm) ++ inl(ac97_data[idx]); ++ } else { ++ /* ++ * Get a pointer to the current buffer. ++ */ ++ b = &p->queue[p->cur]; ++ ++ /* ++ * Read in the next sample. ++ */ ++ *(unsigned long *)b->source = ++ inl(ac97_data[idx]); ++ ++ /* ++ * Increment past the next sample. ++ */ ++ b->source += 4; ++ b->pos += 4; ++ ++ /* ++ * Read another sample if we are not in compact ++ * mode. ++ */ ++ if (!cm) { ++ *(unsigned long *)b->source = ++ inl(ac97_data[idx]); ++ b->source += 4; ++ b->pos += 4; ++ } ++ ++ /* ++ * See if the buffer has been consumed. ++ */ ++ if (b->pos == b->size) { ++ /* ++ * Increment the count of bytes ++ * received. ++ */ ++ p->bytes += b->size; ++ ++ /* ++ * Go to the next buffer. ++ */ ++ p->cur = PIO_NEXT(p->cur); ++ ++ /* ++ * Call the callback if there is one. ++ */ ++ if (p->callback) ++ p->callback(NFB, p->device, ++ p->user_data); ++ } ++ } ++ } ++ } ++} ++ ++/* ++ * Add a buffer to a PIO stream. ++ */ ++static int ++pio_add_buffer(int handle, unsigned int source, unsigned int dest, ++ unsigned int size, unsigned int last, unsigned int buf_id) ++{ ++ struct pio_stream *p; ++ struct pio_buffer *b; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[handle]; ++ ++ /* ++ * Fail if there is not space for another buffer. ++ */ ++ if (PIO_NEXT(p->last) == p->first) ++ return -1; ++ ++ /* ++ * Get a pointer to the next buffer. ++ */ ++ b = &p->queue[p->last]; ++ ++ /* ++ * Save the information about this buffer. ++ */ ++ b->source = (unsigned int)phys_to_virt(source); ++ b->pos = 0; ++ b->size = size; ++ b->buf_id = buf_id; ++ ++ /* ++ * Increment the last pointer. ++ */ ++ p->last = PIO_NEXT(p->last); ++ ++ /* ++ * Success. ++ */ ++ return 0; ++} ++ ++/* ++ * Configure a PIO stream. ++ */ ++static int ++pio_config(int handle, unsigned int flags_m2p, unsigned int flags_m2m, ++ dma_callback callback, unsigned int user_data) ++{ ++ struct pio_stream *p; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[handle]; ++ ++ /* ++ * This puts the stream into pause mode. ++ */ ++ p->pause = 1; ++ ++ /* ++ * Save the callback function information. ++ */ ++ p->callback = callback; ++ p->user_data = user_data; ++ ++ /* ++ * Success. ++ */ ++ return 0; ++} ++ ++/* ++ * Flush all data from a PIO stream. ++ */ ++static int pio_flush(int handle) ++{ ++ struct pio_stream *p; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[handle]; ++ ++ /* ++ * Disable interrupts. ++ */ ++ clf(); ++ ++ /* ++ * Blast all buffer information from this stream. ++ */ ++ p->first = 0; ++ p->cur = 0; ++ p->last = 0; ++ p->bytes = 0; ++ ++ /* ++ * Enable interrupts. ++ */ ++ stf(); ++ ++ /* ++ * Success. ++ */ ++ return 0; ++} ++ ++/* ++ * Free a PIO stream. ++ */ ++static int pio_free(int handle) ++{ ++ /* ++ * See if this is a I2S or AC'97 stream. ++ */ ++ if (handle < 6) { ++ /* ++ * Decrement the I2S reference count. ++ */ ++ pio_irq_ref_count[0]--; ++ ++ /* ++ * See if the reference count is now zero. ++ */ ++ if (pio_irq_ref_count[0] == 0) { ++ /* ++ * Make the I2S interrupt an IRQ instead of a FIQ. ++ */ ++ outl(inl(VIC1INTSELECT) & ~(1 << (IRQ_SAI - 32)), ++ VIC1INTSELECT); ++ ++ /* ++ * Disable I2S interrupts in the I2S block. ++ */ ++ outl(0, I2STXCtrl); ++ outl(0, I2SRXCtrl); ++ ++ /* ++ * Release the I2S interrupt. ++ */ ++ free_irq(IRQ_SAI, (void *)&pio_i2s_irq_handler); ++ ++ /* ++ * Release the FIQ. ++ */ ++ release_fiq(&fh); ++ } ++ } else { ++ /* ++ * Decrement the AC'97 reference count. ++ */ ++ pio_irq_ref_count[1]--; ++ ++ /* ++ * See if the reference count is now zero. ++ */ ++ if (pio_irq_ref_count[1] == 0) { ++ /* ++ * Make the AC'97 interrupt an IRQ instead of a FIQ. ++ */ ++ outl(inl(VIC0INTSELECT) & ~(1 << IRQ_AAC), ++ VIC0INTSELECT); ++ ++ /* ++ * Release the AC'97 interrupt. ++ */ ++ free_irq(IRQ_AAC, (void *)&pio_ac97_irq_handler); ++ ++ /* ++ * Release the FIQ. ++ */ ++ release_fiq(&fh); ++ } ++ } ++ ++ /* ++ * Mark this stream as unassigned. ++ */ ++ pio_streams[handle].assigned = 0; ++ ++ /* ++ * Success. ++ */ ++ return 0; ++} ++ ++/* ++ * Get the current position in a PIO stream. ++ */ ++static int ++pio_get_position(int handle, unsigned int *buf_id, unsigned int *total, ++ unsigned int *current_frac) ++{ ++ struct pio_stream *p; ++ struct pio_buffer *b; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[handle]; ++ ++ /* ++ * Disable interrupts. ++ */ ++ clf(); ++ ++ /* ++ * Get a pointer to the current buffer. ++ */ ++ b = &p->queue[p->cur]; ++ ++ /* ++ * If the buffer is is being requested, then return it. ++ */ ++ if (buf_id) ++ *buf_id = b->buf_id; ++ ++ /* ++ * If the total bytes transferred is being requested, then return it. ++ */ ++ if (total) ++ *total = p->bytes; ++ ++ /* ++ * If the bytes transferred from the current buffer is being requested, ++ * then return it. ++ */ ++ if (current_frac) ++ *current_frac = b->size - b->pos; ++ ++ /* ++ * Enable interrupts. ++ */ ++ stf(); ++ ++ /* ++ * Success. ++ */ ++ return 0; ++} ++ ++/* ++ * Pause a PIO stream. ++ */ ++static int pio_pause(int handle, unsigned int channels, unsigned int *handles) ++{ ++ struct pio_stream *p; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[handle]; ++ ++ /* ++ * Pause the stream. ++ */ ++ p->pause = 1; ++ ++ /* ++ * Success. ++ */ ++ return 0; ++} ++ ++/* ++ * Remove a consumed buffer from a PIO stream. ++ */ ++static int pio_remove_buffer(int handle, unsigned int *buf_id) ++{ ++ struct pio_stream *p; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[handle]; ++ ++ /* ++ * Fail if there are not consumed buffers. ++ */ ++ if (p->first == p->cur) ++ return -1; ++ ++ /* ++ * Return the ID of the next fully consumed buffer. ++ */ ++ *buf_id = p->queue[p->first].buf_id; ++ ++ /* ++ * Increment the first pointer. ++ */ ++ p->first = PIO_NEXT(p->first); ++ ++ /* ++ * Success. ++ */ ++ return 0; ++} ++ ++/* ++ * Request a PIO stream. ++ */ ++static int ++pio_request(int *handle, const char *device_id, ep93xx_dma_dev_t device) ++{ ++ struct pio_stream *p; ++ struct pt_regs regs; ++ int idx, error; ++ ++ /* ++ * Get the stream index from the DMA device we are emulating. ++ */ ++ switch (device) { ++ case DMATx_I2S1: ++ idx = 0; ++ break; ++ case DMATx_I2S2: ++ idx = 1; ++ break; ++ case DMATx_I2S3: ++ idx = 2; ++ break; ++ case DMARx_I2S1: ++ idx = 3; ++ break; ++ case DMARx_I2S2: ++ idx = 4; ++ break; ++ case DMARx_I2S3: ++ idx = 5; ++ break; ++ case DMATx_AAC1: ++ idx = 6; ++ break; ++ case DMATx_AAC2: ++ idx = 7; ++ break; ++ case DMATx_AAC3: ++ idx = 8; ++ break; ++ case DMARx_AAC1: ++ idx = 9; ++ break; ++ case DMARx_AAC2: ++ idx = 10; ++ break; ++ case DMARx_AAC3: ++ idx = 11; ++ break; ++ default: ++ return -ENODEV; ++ } ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[idx]; ++ ++ /* ++ * Fail if this stream is already assigned. ++ */ ++ if (p->assigned) ++ return -EBUSY; ++ ++ /* ++ * Initialize this stream. ++ */ ++ memset(p->queue, 0, sizeof(p->queue)); ++ p->device = device; ++ p->first = 0; ++ p->cur = 0; ++ p->last = 0; ++ p->bytes = 0; ++ p->pause = 0; ++ p->callback = 0; ++ p->user_data = 0; ++ ++ /* ++ * Mark this stream as assigned. ++ */ ++ p->assigned = 1; ++ ++ /* ++ * See if this is a I2S or AC'97 stream. ++ */ ++ if (idx < 6) { ++ /* ++ * If there is already a AC'97 stream in use, then do not allow ++ * I2S streams. ++ */ ++ if (pio_irq_ref_count[1]) ++ return -EBUSY; ++ ++ /* ++ * See if there is another I2S stream. ++ */ ++ if (pio_irq_ref_count[0] == 0) { ++ /* ++ * Claim the FIQ handler. ++ */ ++ if (claim_fiq(&fh)) ++ return -EBUSY; ++ ++ /* ++ * Request the I2S interrupt. ++ */ ++ error = request_irq(IRQ_SAI, pio_i2s_irq_handler, ++ SA_INTERRUPT, "i2s", ++ (void *)&pio_i2s_irq_handler); ++ if (error) { ++ release_fiq(&fh); ++ return error; ++ } ++ ++ /* ++ * Set the FIQ mode registers. ++ */ ++ regs.ARM_sp = (long)fiq_stack + sizeof(fiq_stack); ++ set_fiq_regs(®s); ++ ++ /* ++ * Set the FIQ handler. ++ */ ++ set_fiq_handler(&i2s_fiq_begin, ++ &i2s_fiq_end - &i2s_fiq_begin); ++ ++ /* ++ * Make the I2S interrupt a FIQ instead of an IRQ. ++ */ ++ outl(inl(VIC1INTSELECT) | (1 << (IRQ_SAI - 32)), ++ VIC1INTSELECT); ++ ++ /* ++ * Enable transmit half empty and receive half full ++ * interrupts in the I2S block. ++ */ ++ outl(2, I2STXCtrl); ++ outl(2, I2SRXCtrl); ++ } ++ ++ /* ++ * Increment the I2S interrupt reference count. ++ */ ++ pio_irq_ref_count[0]++; ++ } else { ++ /* ++ * If there is already a I2S stream in use, then do not allow ++ * AC'97 streams. ++ */ ++ if (pio_irq_ref_count[0]) ++ return -EBUSY; ++ ++ /* ++ * See if there is another AC'97 stream. ++ */ ++ if (pio_irq_ref_count[1] == 0) { ++ /* ++ * Claim the FIQ handler. ++ */ ++ if (claim_fiq(&fh)) ++ return -EBUSY; ++ ++ /* ++ * Request the AC'97 interrupt. ++ */ ++ error = request_irq(IRQ_AAC, pio_ac97_irq_handler, ++ SA_INTERRUPT, "ac-97", ++ (void *)&pio_ac97_irq_handler); ++ if (error) { ++ release_fiq(&fh); ++ return error; ++ } ++ ++ /* ++ * Set the FIQ mode registers. ++ */ ++ regs.ARM_sp = (long)fiq_stack + sizeof(fiq_stack); ++ set_fiq_regs(®s); ++ ++ /* ++ * Set the FIQ handler. ++ */ ++ set_fiq_handler(&ac97_fiq_begin, ++ &ac97_fiq_end - &ac97_fiq_begin); ++ ++ /* ++ * Make the AC'97 interrupt a FIQ instead of an IRQ. ++ */ ++ outl(inl(VIC0INTSELECT) | (1 << IRQ_AAC), ++ VIC0INTSELECT); ++ } ++ ++ /* ++ * Increment the AC'97 interrupt reference count. ++ */ ++ pio_irq_ref_count[1]++; ++ } ++ ++ /* ++ * Return a handle to this stream. ++ */ ++ *handle = idx; ++ ++ /* ++ * Success. ++ */ ++ return 0; ++} ++ ++/* ++ * Start a PIO stream. ++ */ ++static int pio_start(int handle, unsigned int channels, unsigned int *handles) ++{ ++ struct pio_stream *p; ++ ++ /* ++ * Get a pointer to this stream's structure. ++ */ ++ p = &pio_streams[handle]; ++ ++ /* ++ * Start the stream. ++ */ ++ p->pause = 0; ++ ++ /* ++ * Success. ++ */ ++ return 0; ++} ++#endif ++ ++/* ++ * calculate_dma2usr_ratio_etc() ++ * ++ * For audio playback, we convert samples of arbitrary format to be 32 bit ++ * for our hardware. We're scaling a user buffer to a dma buffer. So when ++ * report byte counts, we scale them acording to the ratio of DMA sample ++ * size to user buffer sample size. When we report # of DMA fragments, ++ * we don't scale that. So: ++ * - The fragment size the app sees = (stream->fragsize/stream->dma2usr_ratio) ++ * - The # of fragments the app sees = stream->nbfrags ++ * ++ * User sample type can be stereo/mono/8/16/32 bit. ++ * DMA sample type will be either CM (compact mode) where two 16 bit ++ * samples together in a 32 bit word become a stereo sample or non-CM ++ * where each channel gets a 32 bit word. ++ * ++ * Any time usr sample type changes, we need to call this function. ++ * ++ * Also adjust the size and number of dma fragments if sample size changed. ++ * ++ * Input format Input sample Output sample size ratio (out:in) ++ * bits channels size (bytes) CM non-CM CM non-CM ++ * 8 mono 1 4 8 4:1 8:1 ++ * 8 stereo 2 4 8 2:1 4:1 ++ * 16 mono 2 4 8 2:1 4:1 ++ * 16 stereo 4 4 8 1:1 2:1 ++ * ++ * 24 mono 3 4 8 X 8:3 not a real case ++ * 24 stereo 6 4 8 X 8:6 not a real case ++ * 32 mono 4 4 8 X 2:1 ++ * 32 stereo 8 4 8 X 1:1 ++ * ++ */ ++static void calculate_dma2usr_ratio_etc(struct audio_stream_t *stream) ++{ ++ unsigned int dma_sample_size, user_sample_size; ++ ++ if (stream->bCompactMode) ++ dma_sample_size = 4; /* each stereo sample is 2 * 16 bits */ ++ else ++ dma_sample_size = 8; /* each stereo sample is 2 * 32 bits */ ++ ++ if (stream->audio_num_channels != 1) { ++ // If stereo 16 bit, user sample is 4 bytes. ++ // If stereo 8 bit, user sample is 2 bytes. ++ user_sample_size = stream->audio_stream_bitwidth / 4; ++ } else { ++ // If mono 16 bit, user sample is 2 bytes. ++ // If mono 8 bit, user sample is 1 bytes. ++ user_sample_size = stream->audio_stream_bitwidth / 8; ++ } ++ ++ /* ++ * dma2usr_ratio = (4 or 8) / (4, 2, or 1) = 8, 4, 2, or 1 ++ */ ++ stream->dma2usr_ratio = dma_sample_size / user_sample_size; ++ ++ DPRINTK(" samplesize: dma %d user %d dma/usr ratio %d\n", ++ dma_sample_size, user_sample_size, stream->dma2usr_ratio); ++ DPRINTK ++ (" requested: fragsize %d num frags %d total bytes %d total samples %d\n", ++ stream->requested_fragsize, stream->requested_nbfrags, ++ stream->requested_fragsize * stream->requested_nbfrags, ++ (stream->requested_fragsize * stream->requested_nbfrags) / ++ user_sample_size); ++ DPRINTK ++ (" usr : fragsize %d num frags %d total bytes %d total samples %d\n", ++ (stream->fragsize / stream->dma2usr_ratio), stream->nbfrags, ++ stream->fragsize * stream->nbfrags / stream->dma2usr_ratio, ++ (stream->fragsize * stream->nbfrags) / (stream->dma2usr_ratio * ++ user_sample_size)); ++ DPRINTK ++ (" dma: fragsize %d num frags %d total bytes %d total samples %d\n", ++ stream->fragsize, stream->nbfrags, ++ stream->fragsize * stream->nbfrags, ++ (stream->fragsize * stream->nbfrags) / dma_sample_size); ++ ++} ++ ++/* ++ * audio_deallocate_buffers ++ * ++ * This function frees all buffers ++ */ ++static void audio_deallocate_buffers(struct audio_state_t *state, ++ struct audio_stream_t *stream) ++{ ++ int frag, i; ++ ++ DPRINTK("EP93xx - audio_deallocate_buffers\n"); ++ ++ /* ensure DMA won't run anymore */ ++ audio_dma_pause(state, stream); ++ stream->active = 0; ++ stream->stopped = 0; ++ ++ for (i = 0; i < stream->NumDmaChannels; i++) ++ DMA_FLUSH(stream->dmahandles[i]); ++ ++ if (stream->buffers) { ++ for (frag = 0; frag < stream->nbfrags; frag++) { ++ if (!stream->buffers[frag].master) { ++ continue; ++ } ++ // KERNEL2.4 ++ //consistent_free(stream->buffers[frag].start, ++ // stream->buffers[frag].master, ++ // stream->buffers[frag].dma_addr); ++ dma_free_coherent(NULL, stream->buffers[frag].master, ++ stream->buffers[frag].start, ++ stream->buffers[frag].dma_addr); ++ ++ } ++ ++ /* ++ * Free the space allocated to the array of dma_buffer structs. ++ */ ++ kfree(stream->buffers); ++ stream->buffers = NULL; ++ } ++ ++ stream->buffered_bytes_to_play = 0; ++ stream->dma_buffer_index = 0; ++ stream->dma_buffer = NULL; ++ stream->bytecount = 0; ++ stream->getptrCount = 0; ++ stream->fragcount = 0; ++ ++ DPRINTK("EP93xx - audio_deallocate_buffers - EXIT\n"); ++} ++ ++/* ++ * audio_allocate_buffers ++ * ++ * This function allocates the buffer structure array and buffer data space ++ * according to the current number of fragments and fragment size. ++ * Note that the output_stream and input_stream structs are allocated ++ * in ep93xx-ac97.c or ep93xx-i2s.c. ++ */ ++static int audio_allocate_buffers(struct audio_state_t *state, ++ struct audio_stream_t *stream) ++{ ++ int frag; ++ int dmasize = 0; ++ char *dmabuf = NULL; ++ dma_addr_t dmaphys = 0; ++ int buf_num = 0; ++ ++ if (stream->buffers) ++ return -EBUSY; ++ ++ DPRINTK("EP93xx audio_allocate_buffers\n"); ++ ++ /* ++ * Allocate space for the array of struct audio_buf_t structs. ++ */ ++ stream->buffers = (struct audio_buf_t *) ++ kmalloc(sizeof(struct audio_buf_t) * stream->nbfrags, GFP_KERNEL); ++ ++ if (!stream->buffers) { ++ DPRINTK("ep93xx-audio: unable to allocate audio memory\n "); ++ audio_deallocate_buffers(state, stream); ++ return -ENOMEM; ++ } ++ ++ /* ++ * If the audio app hasn't requested a specific fragsize and nbfrags, ++ * we stay with our default. ++ */ ++ if ((stream->requested_fragsize != 0) ++ && (stream->requested_nbfrags != 0)) { ++ /* ++ * Adjust the fragsize to take into account how big actual samples in ++ * the dma buffer are. Max dma buf size is 64K. ++ */ ++ stream->fragsize = ++ stream->requested_fragsize * stream->dma2usr_ratio; ++ } ++ ++ if (stream->fragsize > 65536) ++ stream->fragsize = 65536; ++ if (stream->fragsize < 8192) ++ stream->fragsize = 8192; ++ ++ /* ++ * Adjust num of frags so we have as many samples of buffer as were requested ++ * even if the fragment size changed. ++ */ ++ if ((stream->requested_fragsize != 0) ++ && (stream->requested_nbfrags != 0)) { ++ stream->nbfrags = ++ (stream->requested_fragsize * stream->requested_nbfrags * ++ stream->dma2usr_ratio) ++ / stream->fragsize; ++ } ++ ++ if (stream->nbfrags < 2) ++ stream->nbfrags = 2; ++ if (stream->nbfrags > AUDIO_NBFRAGS_MAX) ++ stream->nbfrags = AUDIO_NBFRAGS_MAX; ++ ++ memset(stream->buffers, 0, ++ sizeof(struct audio_buf_t) * stream->nbfrags); ++ ++ /* ++ * Let's allocate non-cached memory for DMA buffers. ++ * We try to allocate all memory at once. ++ * If this fails (a common reason is memory fragmentation), ++ * then we allocate more smaller buffers. ++ */ ++ for (frag = 0; frag < stream->nbfrags; frag++) { ++ struct audio_buf_t *dma_buffer = &stream->buffers[frag]; ++ ++ if (!dmasize) { ++ /* ++ * First try to allocate enough for all the frags that ++ * don't yet have memory allocated. ++ */ ++ dmasize = (stream->nbfrags - frag) * stream->fragsize; ++ do { ++ // GRM ++ //dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA, ++ // dmasize, &dmaphys); ++ dmabuf = dma_alloc_coherent(NULL, ++ dmasize, &dmaphys, ++ GFP_KERNEL | ++ GFP_DMA); ++ ++ /* ++ * If that fails, try to allocate a chunk of memory ++ * that is one less fragment is size. ++ */ ++ if (!dmabuf) ++ dmasize -= stream->fragsize; ++ ++ /* ++ * Keep trying but the minimum we'll attempt is one ++ * fragment. If we can't even get that, give up. ++ */ ++ } while (!dmabuf && dmasize); ++ ++ /* ++ * If we do fail to allocate enough for all the frags, ++ * deallocate whatever we did get and quit. ++ */ ++ if (!dmabuf) { ++ DPRINTK ++ ("ep93xx-audio: unable to allocate audio memory\n "); ++ audio_deallocate_buffers(state, stream); ++ return -ENOMEM; ++ } ++ ++ DPRINTK ++ ("EP93xx allocated %d bytes: dmabuf=0x%08x dmaphys=0x%08x\n", ++ dmasize, (int)dmabuf, (int)dmaphys); ++ ++ /* ++ * Success! Save the size of this chunk to use when we deallocate it. ++ */ ++ dma_buffer->master = dmasize; ++ memzero(dmabuf, dmasize); ++ } ++ ++ /* ++ * Save the start address of the dma_buffer fragment. ++ * We know the size of the fragment is fragsize. ++ */ ++ dma_buffer->start = dmabuf; ++ dma_buffer->dma_addr = dmaphys; ++ dma_buffer->stream = stream; ++ dma_buffer->size = 0; ++ dma_buffer->sent = 0; ++ dma_buffer->num = buf_num++; ++ ++ dma_buffer->owner = 0; ++ ++ /* ++ * Now if we only allocated the minimal one frag of space, the ++ * dmasize will be ==0 after this subtraction so it will allocate more ++ * for the next frag. Otherwise, the next time(s) thru this for loop ++ * will dole out frag sized pieces of this big master chunk. ++ */ ++ dmabuf += stream->fragsize; ++ dmaphys += stream->fragsize; ++ dmasize -= stream->fragsize; ++ } ++ ++ /* ++ * Initialize the stream. ++ */ ++ stream->buffered_bytes_to_play = 0; ++ stream->dma_buffer_index = 0; /* Init the current buffer index. */ ++ stream->dma_buffer = &stream->buffers[0]; /* Point dma_buffer to the current buffer struct. */ ++ stream->bytecount = 0; ++ stream->getptrCount = 0; ++ stream->fragcount = 0; ++ ++ DPRINTK("EP93xx audio_allocate_buffers -- exit SUCCESS\n"); ++ return 0; ++ ++} ++ ++/* ++ * audio_reset_buffers ++ * ++ * This function stops and flushes the dma, gets all buffers back ++ * from the DMA driver and resets them ready to be used again. ++ */ ++static void audio_reset_buffers(struct audio_state_t *state, ++ struct audio_stream_t *stream) ++{ ++ int frag, i; ++ ++ audio_dma_pause(state, stream); ++ stream->active = 0; ++ stream->stopped = 0; ++ ++ for (i = 0; i < stream->NumDmaChannels; i++) ++ DMA_FLUSH(stream->dmahandles[i]); ++ ++ if (stream->buffers) { ++ for (frag = 0; frag < stream->nbfrags; frag++) { ++ struct audio_buf_t *dma_buffer = &stream->buffers[frag]; ++ dma_buffer->size = 0; ++ dma_buffer->sent = 0; ++ dma_buffer->owner = 0; ++ } ++ } ++ ++ stream->buffered_bytes_to_play = 0; ++ stream->bytecount = 0; ++ stream->getptrCount = 0; ++ stream->fragcount = 0; ++} ++ ++/* ++ * DMA callback functions ++ */ ++static void audio_dma_tx_callback ++ (ep93xx_dma_int_t DMAInt, ep93xx_dma_dev_t device, unsigned int user_data) { ++ unsigned int buf_id; ++ int handle, i; ++ ++ struct audio_state_t *state = (struct audio_state_t *)user_data; ++ struct audio_stream_t *stream = state->output_stream; ++ ++ /* DPRINTK( "audio_dma_tx_callback - %s\n", stream->devicename ); */ ++ ++ /* ++ * Get the DMA handle that corresponds to the dma channel ++ * that needs servicing. A multichannel audio stream will ++ * have a DMA handle for each stereo pair that it uses. ++ */ ++ for (i = 0; ++ (i < stream->NumDmaChannels) && (stream->dmachannel[i] != device); ++ i++) ; ++ handle = stream->dmahandles[i]; ++ ++ if (stream->mapped) { ++ /* ++ * If we are mapped, get one dma buffer back and recycle it. ++ */ ++ if (DMA_REMOVE_BUFFER(handle, &buf_id) >= 0) { ++ struct audio_buf_t *dma_buffer = ++ (struct audio_buf_t *)buf_id; ++ ++ /* DPRINTK( "audio_dma_tx_callback - got dma buffer index=%d\n", buf_id); */ ++ ++ /* Accounting */ ++ stream->buffered_bytes_to_play -= dma_buffer->size; ++ ++ /* bytecount and fragcount will overflow */ ++ stream->bytecount += dma_buffer->size; ++ if (stream->bytecount < 0) ++ stream->bytecount = 0; ++ ++ stream->fragcount++; ++ if (stream->fragcount < 0) ++ stream->fragcount = 0; ++ ++ dma_buffer->size = 0; ++ ++ /* Recycle dma buffer */ ++ dma_buffer->size = stream->fragsize; ++ ++ DMA_ADD_BUFFER(handle, /* dma instance */ ++ (unsigned int)dma_buffer->dma_addr, /* source */ ++ 0, /* dest */ ++ stream->fragsize, /* size */ ++ 0, /* is the last chunk? */ ++ (unsigned int)dma_buffer); /* buf id */ ++ ++ dma_buffer->sent = 1; ++ } ++ } else { ++ /* ++ * Get all buffers that are free'ed back and clear their semephores. ++ */ ++ while (DMA_REMOVE_BUFFER(handle, &buf_id) >= 0) { ++ struct audio_buf_t *dma_buffer = ++ (struct audio_buf_t *)buf_id; ++ ++ /* DPRINTK( "audio_dma_tx_callback - got dma buffer index=%d\n", buf_id); */ ++ ++ /* Accounting */ ++ stream->buffered_bytes_to_play -= dma_buffer->size; ++ ++ stream->bytecount += dma_buffer->size; ++ if (stream->bytecount < 0) ++ stream->bytecount = 0; ++ ++ stream->fragcount++; ++ if (stream->fragcount < 0) ++ stream->fragcount = 0; ++ ++ dma_buffer->size = 0; ++ dma_buffer->sent = 0; ++ ++ /* ++ * Release the semaphore on this dma_buffer. ++ * If write is waiting on this dma_buffer then it can go ++ * ahead and fill it and send it to the dma. ++ */ ++ dma_buffer->owner = 0; ++ } ++ } ++ ++ /* And any process polling on write. */ ++ wake_up(&stream->wq); ++} ++ ++static void audio_dma_rx_callback ++ (ep93xx_dma_int_t DMAInt, ep93xx_dma_dev_t device, unsigned int user_data) { ++ unsigned int buf_id; ++ int handle, i; ++ ++ struct audio_state_t *state = (struct audio_state_t *)user_data; ++ struct audio_stream_t *stream = state->input_stream; ++ ++ //DPRINTK("audio_dma_rx_callback\n"); ++ ++ /* ++ * Get the DMA handle that corresponds to the dma channel ++ * that needs servicing. A multichannel audio stream will ++ * have a DMA handle for each stereo pair that it uses. ++ */ ++ for (i = 0; ++ (i < stream->NumDmaChannels) && (stream->dmachannel[i] != device); ++ i++) ; ++ handle = stream->dmahandles[i]; ++ ++ /* ++ * Keep removing and recycling buffers as long as there are buffers ++ * to remove. ++ */ ++ while (!DMA_REMOVE_BUFFER(handle, &buf_id)) { ++ struct audio_buf_t *dma_buffer = (struct audio_buf_t *)buf_id; ++ ++ /* Accounting */ ++ stream->bytecount += stream->fragsize; ++ if (stream->bytecount < 0) ++ stream->bytecount = 0; ++ ++ stream->fragcount++; ++ if (stream->fragcount < 0) ++ stream->fragcount = 0; ++ ++ /* Recycle dma buffer */ ++ if (stream->mapped) { ++ DMA_ADD_BUFFER(handle, /* dma instance */ ++ (unsigned int)dma_buffer->dma_addr, /* source */ ++ 0, /* dest */ ++ stream->fragsize, /* size */ ++ 0, /* is the last chunk? */ ++ (unsigned int)dma_buffer); /* buf id */ ++ } else { ++ dma_buffer->size = stream->fragsize; ++ dma_buffer->owner = 0; ++ } ++ ++ /* And any process polling on write. */ ++ wake_up(&stream->wq); ++ } ++} ++ ++/* ++ * audio_sync ++ * ++ * Wait until the last byte written to this device has been played. ++ */ ++static int audio_sync(struct file *file) ++{ ++ struct audio_state_t *state = ++ (struct audio_state_t *)file->private_data; ++ struct audio_stream_t *stream = state->output_stream; ++ struct audio_buf_t *dma_buffer; ++ int buf_wait_index; ++ ++ DPRINTK("audio_sync - enter\n"); ++ ++ if (!(file->f_mode & FMODE_WRITE) || !stream->buffers || stream->mapped) { ++ DPRINTK("audio_sync - exit immediately.\n"); ++ return 0; ++ } ++ ++ /* ++ * Send current dma buffer if it contains data and hasn't been sent. ++ */ ++ dma_buffer = stream->dma_buffer; ++ ++ if (dma_buffer->size && !dma_buffer->sent) { ++ DPRINTK("audio_sync -- SENDING BUFFER index=%d size=%d\n", ++ stream->dma_buffer_index, dma_buffer->size); ++ ++ while (dma_buffer->owner == 1) ++ schedule(); ++ dma_buffer->owner = 1; ++ DMA_ADD_BUFFER(stream->dmahandles[0], /* dma instance */ ++ (unsigned int)dma_buffer->dma_addr, /* source */ ++ 0, /* dest */ ++ dma_buffer->size, /* size */ ++ 0, /* is the last chunk? */ ++ (unsigned int)dma_buffer); /* dma_buffer id */ ++ dma_buffer->sent = 1; ++ NEXT_BUF(stream, dma_buffer); ++ } ++ ++ /* ++ * Let's wait for the last dma buffer we sent i.e. the one before the ++ * current dma_buffer_index. When we acquire the semaphore, this means either: ++ * - DMA on the buffer completed or ++ * - the buffer was already free thus nothing else to sync. ++ */ ++ buf_wait_index = ++ ((stream->nbfrags + stream->dma_buffer_index - ++ 1) % stream->nbfrags); ++ dma_buffer = stream->buffers + buf_wait_index; ++ ++ DPRINTK("audio_sync - waiting on down_interruptible\n"); ++ while (dma_buffer->owner == 1) { ++ if (signal_pending(current)) ++ return -ERESTARTSYS; ++ schedule(); ++ } ++ ++ DPRINTK("audio_sync - EXIT\n"); ++ return 0; ++} ++ ++//static int iWriteCount = 0; ++ ++/* ++ * Need to convert to 32 bit stereo format: ++ * 16 bit signed ++ * 16 bit unsigned ++ * 8 bit signed ++ * 8 bit unsigned ++ */ ++static int audio_write ++ (struct file *file, ++ const char *user_buffer, size_t src_count, loff_t * ppos) { ++ const char *user_buffer_start = user_buffer; ++ struct audio_state_t *state = ++ (struct audio_state_t *)file->private_data; ++ struct audio_stream_t *stream = state->output_stream; ++ unsigned int dma_xfer_count, src_xfer_count, expanded_count; ++ int ret = 0; ++// int i,j; ++ ++ /* DPRINTK_IOCTL( "EP93xx - audio_write: count=%d\n", src_count ); */ ++ ++ // KERNEL2.4 ++ /*if (ppos != &file->f_pos) ++ return -ESPIPE; */ ++ ++ if (stream->mapped) ++ return -ENXIO; ++ ++ if (!access_ok(VERIFY_READ, user_buffer, src_count)) { ++ DPRINTK("access_ok failed for audio_write!!!!\n"); ++ return -EFAULT; ++ } ++ ++ /* ++ * Allocate dma buffers if we haven't already done so. ++ */ ++ if (!stream->buffers && audio_allocate_buffers(state, stream)) ++ return -ENOMEM; ++ ++// if( iWriteCount > 40 ) ++// { ++// for( i=0; i<4 ; i++ ) ++// { ++// for( j=0; j<8 ; j++ ) ++// { ++// printk("%02x ", user_buffer[(i*8)+j] ); ++// } ++// printk("\n"); ++// } ++// iWriteCount = 0; ++// } ++// iWriteCount++; ++ ++ /* ++ * Stay in this loop until we have copied all of the file ++ * into user memory. ++ */ ++ while (src_count > 0) { ++ struct audio_buf_t *dma_buffer = stream->dma_buffer; ++ ++ /* Wait for a dma buffer to become free */ ++ if (file->f_flags & O_NONBLOCK) { ++ ret = -EAGAIN; ++ if (dma_buffer->owner != 0) ++ break; ++ } else { ++ while (dma_buffer->owner == 1) { ++ if (signal_pending(current)) ++ return -ERESTARTSYS; ++ schedule(); ++ } ++ } ++ ++ /* ++ * Feed the current dma buffer (stream->dma_buffer) ++ * This involves expanding sample size from the user_buffer ++ * to be 32 bit stereo for our dma. ++ */ ++ ++ /* ++ * How much space is left in the current dma buffer? ++ * ++ * dma_xfer_count is # of bytes placed into the dma buffer ++ * where each sample is 8 bytes (4 bytes left, 4 bytes right) ++ * because that's what the I2S is set up for - 32 bit samples. ++ */ ++ dma_xfer_count = stream->fragsize - dma_buffer->size; ++ ++ /* ++ * user_buffer is src_count (bytes) of whatever format. ++ * How big will src_count be when sample size is expanded ++ * to 32 bit samples for our hardware? ++ */ ++ expanded_count = src_count * stream->dma2usr_ratio; ++ ++ /* ++ * See if we can fit all the remaining user_buffer in ++ * the current dma buffer... ++ */ ++ if (dma_xfer_count > expanded_count) ++ dma_xfer_count = expanded_count; ++ ++ //DPRINTK( "EP93xx - audio_write: %d to dma_buffer # %d\n", dma_xfer_count, stream->dma_buffer_index ); ++ ++ src_xfer_count = copy_from_user_with_conversion(state, ++ dma_buffer-> ++ start + ++ dma_buffer-> ++ size, ++ user_buffer, ++ dma_xfer_count); ++ if (src_xfer_count <= 0) ++ return -EFAULT; ++ ++ /* ++ * Increment dma buffer pointer. ++ */ ++ dma_buffer->size += dma_xfer_count; ++ ++ /* ++ * Increment user_buffer pointer. ++ * Decrement the user_buffer size count. ++ */ ++ user_buffer += src_xfer_count; ++ src_count -= src_xfer_count; ++ ++ /* ++ * If we haven't already started the DMA start it. ++ * But don't start it if we are waiting on a trigger. ++ */ ++ if (!stream->active && !stream->stopped) { ++ stream->active = 1; ++ audio_dma_start(state, stream); ++ } ++ ++ /* ++ * Note that we've 'downed' the semiphore for this buffer. But the ++ * dma driver doesn't know about it until we've added it to the DMA ++ * driver's buffer queue. So let's do that now. ++ */ ++ dma_buffer->owner = 1; ++ DMA_ADD_BUFFER(stream->dmahandles[0], /* dma instance */ ++ (unsigned int)dma_buffer->dma_addr, /* source */ ++ 0, /* dest */ ++ dma_buffer->size, /* size */ ++ 0, /* is the last chunk? */ ++ (unsigned int)dma_buffer); /* buf id */ ++ ++ /* ++ * Note that we added a buffer to play for the benefit of calculating ++ * ODELAY. ++ */ ++ stream->buffered_bytes_to_play += dma_buffer->size; ++ ++ /* ++ * Indicate that the dma buffer has been sent. Not the same as the ++ * buffer's semiphore. ++ */ ++ dma_buffer->sent = 1; ++ ++ NEXT_BUF(stream, dma_buffer); ++ } ++ ++ /* ++ * Return the number of bytes transferred. ++ */ ++ if ((int)user_buffer - (int)user_buffer_start) ++ ret = (int)user_buffer - (int)user_buffer_start; ++ ++/* DPRINTK( "EP93xx - audio_write: return=%d\n", ret );*/ ++ return ret; ++} ++ ++/* ++ * audio_dma_start ++ * ++ * Our Ac97 has a specific start order that it likes. Enable the ++ * Ac97 channel AFTER enabling DMA. Our I2S is not so picky. ++ */ ++void audio_dma_start(struct audio_state_t *state, struct audio_stream_t *stream) ++{ ++ DMA_START(stream->dmahandles[0], ++ stream->NumDmaChannels, stream->dmahandles); ++ ++ if (state->hw->hw_enable) ++ state->hw->hw_enable(stream); ++ ++} ++ ++/* ++ * audio_dma_pause ++ */ ++void audio_dma_pause(struct audio_state_t *state, struct audio_stream_t *stream) ++{ ++ DPRINTK("audio_dma_pause - enter\n"); ++ ++ DMA_PAUSE(stream->dmahandles[0], ++ stream->NumDmaChannels, stream->dmahandles); ++ ++ if (state->hw->hw_disable) ++ state->hw->hw_disable(stream); ++ ++ if (state->hw->hw_clear_fifo) ++ state->hw->hw_clear_fifo(stream); ++ ++ DPRINTK("audio_dma_pause - EXIT\n"); ++} ++ ++static void audio_prime_dma(struct audio_state_t *state, ++ struct audio_stream_t *stream) ++{ ++ int i; ++ ++ DPRINTK("audio_prime_dma\n"); ++ ++ /* ++ * If we haven't already started the DMA start it. ++ * But don't start it if we are waiting on a trigger. ++ */ ++ if (!stream->active && !stream->stopped) { ++ stream->active = 1; ++ audio_dma_start(state, stream); ++ } ++ ++ for (i = 0; i < stream->nbfrags; i++) { ++ struct audio_buf_t *dma_buffer = stream->dma_buffer; ++ ++ dma_buffer->owner = 1; ++ DMA_ADD_BUFFER(stream->dmahandles[0], /* dma instance */ ++ (unsigned int)dma_buffer->dma_addr, /* source */ ++ 0, /* dest */ ++ stream->fragsize, /* size */ ++ 0, /* is the last chunk? */ ++ (unsigned int)dma_buffer); /* buf id */ ++ NEXT_BUF(stream, dma_buffer); ++ } ++} ++ ++/* ++ * audio_read ++ * ++ * Audio capture function. ++ */ ++static int audio_read ++ (struct file *file, char *user_buffer, size_t count, loff_t * ppos) { ++ char *user_buffer_start = user_buffer; ++ struct audio_state_t *state = ++ (struct audio_state_t *)file->private_data; ++ struct audio_stream_t *stream = state->input_stream; ++ unsigned int user_buffer_xfer_count = 0, dma_buffer_xfer_count = 0; ++ int ret = 0; ++ ++ DPRINTK("EP93xx - audio_read: count=%d\n", count); ++ ++ // KERNEL2.4 ++ /*if (ppos != &file->f_pos) ++ return -ESPIPE; */ ++ ++ if (stream->mapped) ++ return -ENXIO; ++ ++ if (!access_ok(VERIFY_WRITE, user_buffer, count)) { ++ DPRINTK("access_ok failed for audio_read!!!!\n"); ++ return -EFAULT; ++ } ++ ++ if (!stream->active) { ++ if (!stream->buffers && audio_allocate_buffers(state, stream)) ++ return -ENOMEM; ++ ++ audio_prime_dma(state, stream); ++ } ++ ++ while (count > 0) { ++ /* ++ * Get the current buffer. ++ */ ++ struct audio_buf_t *dma_buffer = stream->dma_buffer; ++ ++ /* ++ * Wait for a dma buffer to become full ++ */ ++ if (file->f_flags & O_NONBLOCK) { ++ //DPRINTK("file->f_flags & O_NONBLOCK\n"); ++ ret = -EAGAIN; ++ if (dma_buffer->owner != 0) ++ break; ++ } else { ++ while (dma_buffer->owner == 1) { ++ if (signal_pending(current)) ++ return -ERESTARTSYS; ++ schedule(); ++ } ++ } ++ ++ /* ++ * If this is the first buffer captured, ++ * dump the first 8 samples of the dma buffer. ++ */ ++ if (stream->bFirstCaptureBuffer) { ++ dma_buffer->size -= 64; ++ stream->bFirstCaptureBuffer = 0; ++ } ++ ++ /* ++ * How much user buffer would a whole DMA buffer fill? ++ */ ++ user_buffer_xfer_count = ++ dma_buffer->size / stream->dma2usr_ratio; ++ ++ if (user_buffer_xfer_count > count) ++ user_buffer_xfer_count = count; ++ ++ dma_buffer_xfer_count = ++ user_buffer_xfer_count * stream->dma2usr_ratio; ++ ++ DPRINTK("dma_buffer: start=0x%08x fragsz=%d size=%d\n", ++ (int)dma_buffer->start, (int)stream->fragsize, ++ dma_buffer->size); ++ ++ DPRINTK ++ ("user_buffer=0x%08x from=0x%08x user_count=%d dma_count=%d\n", ++ (int)user_buffer, ++ (int)dma_buffer->start + stream->fragsize - ++ dma_buffer->size, user_buffer_xfer_count, ++ dma_buffer_xfer_count); ++ ++ if (copy_to_user_with_conversion(state, ++ user_buffer, ++ dma_buffer->start + ++ stream->fragsize - ++ dma_buffer->size, ++ user_buffer_xfer_count) <= 0) ++ return -EFAULT; ++ ++ dma_buffer->size -= dma_buffer_xfer_count; ++ ++ user_buffer += user_buffer_xfer_count; ++ count -= user_buffer_xfer_count; ++ ++ /* ++ * Grab data from the current dma buffer ++ */ ++ //DPRINTK("Read: read %d bytes from %d. dmabufsize=%d. count=%d\n", ++ // user_buffer_xfer_count, stream->dma_buffer_index, ++ // dma_buffer->size, count); ++ ++ /* ++ * If there's still data in this buffer to be read, release ++ * the semiphore and don't give it back yet. We may come back ++ * and read from it in a minute when the app calls for another read. ++ */ ++ if (dma_buffer->size > 0) ++ break; ++ ++ /* Make current dma buffer available for DMA again */ ++ dma_buffer->owner = 1; ++ DMA_ADD_BUFFER(stream->dmahandles[0], /* dma instance */ ++ (unsigned int)dma_buffer->dma_addr, /* source */ ++ 0, /* dest */ ++ stream->fragsize, /* size */ ++ 0, /* the last chunk? */ ++ (unsigned int)dma_buffer); /* buf id */ ++ ++ NEXT_BUF(stream, dma_buffer); ++ } ++ ++ if ((int)user_buffer - (int)user_buffer_start) ++ ret = (int)user_buffer - (int)user_buffer_start; ++ ++ //DPRINTK("EP93xx - audio_read: return=%d\n", ret); ++ ++ return ret; ++} ++ ++static int audio_mmap(struct file *file, struct vm_area_struct *vma) ++{ ++ struct audio_state_t *state = ++ (struct audio_state_t *)file->private_data; ++ struct audio_stream_t *stream = 0; ++ unsigned long size, vma_addr; ++ int i, ret; ++ ++ if (vma->vm_pgoff != 0) ++ return -EINVAL; ++ ++ if (vma->vm_flags & VM_WRITE) { ++ if (!state->wr_ref) ++ return -EINVAL; ++ ++ stream = state->output_stream; ++ } else if (vma->vm_flags & VM_READ) { ++ if (!state->rd_ref) ++ return -EINVAL; ++ ++ stream = state->input_stream; ++ } else { ++ return -EINVAL; ++ } ++ ++ if (stream->mapped) ++ return -EINVAL; ++ ++ size = vma->vm_end - vma->vm_start; ++ ++ if (size != stream->fragsize * stream->nbfrags) ++ return -EINVAL; ++ ++ if (!stream->buffers && audio_allocate_buffers(state, stream)) ++ return -ENOMEM; ++ ++ vma_addr = vma->vm_start; ++ ++ for (i = 0; i < stream->nbfrags; i++) { ++ struct audio_buf_t *dma_buffer = &stream->buffers[i]; ++ ++ if (!dma_buffer->master) { ++ continue; ++ } ++ // KERNEL2.4 ++ //ret = remap_page_range(vma_addr, dma_buffer->dma_addr, dma_buffer->master, vma->vm_page_prot); ++ ret = ++ remap_pfn_range(vma, vma_addr, dma_buffer->dma_addr, ++ dma_buffer->master, vma->vm_page_prot); ++ ++ if (ret) ++ return ret; ++ ++ vma_addr += dma_buffer->master; ++ } ++ ++ stream->mapped = 1; ++ ++ return 0; ++} ++ ++static unsigned int audio_poll(struct file *file, ++ struct poll_table_struct *wait) ++{ ++ struct audio_state_t *state = ++ (struct audio_state_t *)file->private_data; ++ struct audio_stream_t *is = state->input_stream; ++ struct audio_stream_t *os = state->output_stream; ++ unsigned int mask = 0; ++ int i; ++ ++ DPRINTK("EP93xx - audio_poll(): mode=%s%s\n", ++ (file->f_mode & FMODE_READ) ? "r" : "", ++ (file->f_mode & FMODE_WRITE) ? "w" : ""); ++ ++ if (file->f_mode & FMODE_READ) { ++ /* Start audio input if not already active */ ++ if (!is->active) { ++ if (!is->buffers && audio_allocate_buffers(state, is)) ++ return -ENOMEM; ++ ++ audio_prime_dma(state, is); ++ } ++ ++ poll_wait(file, &is->wq, wait); ++ } ++ ++ if (file->f_mode & FMODE_WRITE) { ++ if (!os->buffers && audio_allocate_buffers(state, os)) ++ return -ENOMEM; ++ ++ poll_wait(file, &os->wq, wait); ++ } ++ ++ if (file->f_mode & FMODE_READ) { ++ if (is->mapped) { ++ /* ++ * if the buffer is mapped assume we care that there are ++ * more bytes available than when we last asked using ++ * SNDCTL_DSP_GETxPTR ++ */ ++ if (is->bytecount != is->getptrCount) ++ mask |= POLLIN | POLLRDNORM; ++ } else { ++ for (i = 0; i < is->nbfrags; i++) { ++ if (is->buffers[i].owner != 0) { ++ mask |= POLLIN | POLLRDNORM; ++ break; ++ } ++ } ++ } ++ } ++ ++ if (file->f_mode & FMODE_WRITE) { ++ if (os->mapped) { ++ if (os->bytecount != os->getptrCount) ++ mask |= POLLOUT | POLLWRNORM; ++ } else { ++ for (i = 0; i < os->nbfrags; i++) { ++ if (os->buffers[i].owner != 0) { ++ mask |= POLLOUT | POLLWRNORM; ++ break; ++ } ++ } ++ } ++ } ++ ++ DPRINTK("EP93xx - audio_poll() returned mask of %s%s\n", ++ (mask & POLLIN) ? "r" : "", (mask & POLLOUT) ? "w" : ""); ++ ++ return mask; ++} ++ ++/* ++ * audio_set_fragments ++ * ++ * Used to process SNDCTL_DSP_SETFRAGMENT. ++ * ++ * Argument is 0xMMMMSSSS where: ++ * MMMM sets number of fragments. ++ * SSSS sets dma fragment (dma_buffer) size. size = 2^SSSS bytes ++ */ ++static int audio_set_fragments(struct audio_state_t *state, ++ struct audio_stream_t *stream, int val) ++{ ++ if (stream->active) ++ return -EBUSY; ++ ++ stream->requested_fragsize = 1 << (val & 0x000ffff); ++ stream->requested_nbfrags = (val >> 16) & 0x7FFF; ++ ++ return 0; ++} ++ ++static void print_audio_format(long format) ++{ ++ switch (format) { ++ case AFMT_U8: ++ DPRINTK_IOCTL("AFMT_U8\n"); ++ break; ++ ++ case AFMT_S8: ++ DPRINTK_IOCTL("AFMT_S8\n"); ++ break; ++ ++ case AFMT_S32_BLOCKED: ++ DPRINTK_IOCTL("AFMT_S32_BLOCKED\n"); ++ break; ++ ++ case AFMT_S16_LE: ++ DPRINTK_IOCTL("AFMT_S16_LE\n"); ++ break; ++ ++ case AFMT_S16_BE: ++ DPRINTK_IOCTL("AFMT_S16_BE\n"); ++ break; ++ ++ case AFMT_U16_LE: ++ DPRINTK_IOCTL("AFMT_U16_LE\n"); ++ break; ++ ++ case AFMT_U16_BE: ++ default: ++ DPRINTK_IOCTL("AFMT_U16_BE\n"); ++ break; ++ } ++} ++ ++/* ++ * We convert to 24 bit samples that occupy 32 bits each. ++ * Formats we support: ++ * ++ * AFMT_U8 ++ * AFMT_S16_LE Little endian signed 16 ++ * AFMT_S8 ++ * AFMT_U16_LE Little endian U16 ++ * AFMT_S32_BLOCKED 32 bit little endian format, taken from the rme96xx driver. ++ * ++ */ ++static long audio_set_format(struct audio_stream_t *stream, long val) ++{ ++ DPRINTK_IOCTL("audio_set_format enter. Format requested (%d) ", ++ (int)val); ++ print_audio_format(val); ++ ++ switch (val) { ++ case AFMT_QUERY: ++ break; ++ ++ case AFMT_U8: ++ stream->audio_format = val; ++ stream->audio_stream_bitwidth = 8; ++ break; ++ ++ case AFMT_S8: ++ stream->audio_format = val; ++ stream->audio_stream_bitwidth = 8; ++ break; ++ ++ case AFMT_S32_BLOCKED: ++ stream->audio_format = val; ++ stream->audio_stream_bitwidth = 32; ++ break; ++ ++ case AFMT_S16_LE: ++ case AFMT_S16_BE: ++ stream->audio_format = AFMT_S16_LE; ++ stream->audio_stream_bitwidth = 16; ++ break; ++ ++ case AFMT_U16_LE: ++ case AFMT_U16_BE: ++ default: ++ stream->audio_format = AFMT_U16_LE; ++ stream->audio_stream_bitwidth = 16; ++ break; ++ } ++ ++ DPRINTK_IOCTL("audio_set_format EXIT format set to be (%d) ", ++ (int)stream->audio_format); ++ print_audio_format((long)stream->audio_format); ++ ++ return stream->audio_format; ++} ++ ++static __inline__ unsigned long copy_to_user_U16_LE_CM ++ (struct audio_state_t *state, ++ const char *to, const char *from, unsigned long to_count) { ++ int total_to_count = to_count; ++ unsigned short *user_ptr = (unsigned short *)to; /* 16 bit user buffer */ ++ short *dma_ptr = (short *)from; ++ short right, left; ++ ++ /* ++ * Compact mode - left is the lower 16 bits. right is the upper 16 bits. ++ */ ++ ++ if (state->input_stream->audio_num_channels != 1) { ++ while (to_count > 0) { ++ right = *dma_ptr++; ++ left = *dma_ptr++; ++ __put_user(left ^ 0x8000, user_ptr++); ++ __put_user(right ^ 0x8000, user_ptr++); ++ to_count -= 4; ++ } ++ } else { ++ while (to_count > 0) { ++ dma_ptr++; /* skip right channel sample */ ++ left = *dma_ptr++; ++ __put_user(left ^ 0x8000, user_ptr++); ++ to_count -= 2; ++ } ++ } ++ ++ return total_to_count; ++} ++ ++static __inline__ unsigned long copy_to_user_U16_LE ++ (struct audio_state_t *state, ++ const char *to, const char *from, unsigned long to_count) { ++ int total_to_count = to_count; ++ short *user_ptr = (short *)to; /* 16 bit user buffer */ ++ int *dma_ptr = (int *)from; /* 32 bit dma buffer */ ++ ++ int shift = state->input_stream->hw_bit_width - 16; ++ ++ if (state->input_stream->audio_num_channels != 1) { ++ while (to_count > 0) { ++ __put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000, ++ user_ptr++); ++ __put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000, ++ user_ptr++); ++ to_count -= 4; ++ } ++ } else { ++ while (to_count > 0) { ++ __put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000, ++ user_ptr++); ++ dma_ptr++; /* skip right channel sample */ ++ to_count -= 2; ++ } ++ } ++ ++ return total_to_count; ++} ++ ++static __inline__ unsigned long copy_to_user_S16_LE_CM ++ (struct audio_state_t *state, ++ const char *to, const char *from, unsigned long to_count) { ++ int total_to_count = to_count; ++ short *user_ptr = (short *)to; /* 16 bit user buffer */ ++ short *dma_ptr = (short *)from; ++ short left, right; ++ ++ /* ++ * Compact mode - left is the lower 16 bits. right is the upper 16 bits. ++ */ ++ ++ if (state->input_stream->audio_num_channels != 1) { ++ while (to_count > 0) { ++ right = *dma_ptr++; ++ left = *dma_ptr++; ++ __put_user(left, user_ptr++); ++ __put_user(right, user_ptr++); ++ to_count -= 4; ++ } ++ } else { ++ while (to_count > 0) { ++ dma_ptr++; /* skip right sample */ ++ left = *dma_ptr++; ++ __put_user(left, user_ptr++); ++ to_count -= 2; ++ } ++ } ++ ++ return total_to_count; ++} ++ ++static __inline__ unsigned long copy_to_user_S16_LE ++ (struct audio_state_t *state, ++ const char *to, const char *from, unsigned long to_count) { ++ int total_to_count = to_count; ++ short *user_ptr = (short *)to; /* 16 bit user buffer */ ++ int *dma_ptr = (int *)from; /* 32 bit dma buffer */ ++ ++ int shift = state->input_stream->hw_bit_width - 16; ++ ++ if (state->input_stream->audio_num_channels != 1) { ++ while (to_count > 0) { ++ __put_user((short)((*dma_ptr++) >> shift), user_ptr++); ++ __put_user((short)((*dma_ptr++) >> shift), user_ptr++); ++ to_count -= 4; ++ } ++ } else { ++ while (to_count > 0) { ++ __put_user((short)((*dma_ptr++) >> shift), user_ptr++); ++ dma_ptr++; /* skip right channel sample */ ++ to_count -= 2; ++ } ++ } ++ ++ return total_to_count; ++} ++ ++static __inline__ unsigned long copy_to_user_S8_CM ++ (struct audio_state_t *state, ++ const char *to, const char *from, unsigned long to_count) { ++ int total_to_count = to_count; ++ char *user_ptr = (char *)to; /* 8 bit user buffer */ ++ unsigned short *dma_ptr = (unsigned short *)from; /* 16 bit dma buffer */ ++ char right, left; ++ ++ if (state->input_stream->audio_num_channels != 1) { ++ while (to_count > 0) { ++ right = ((char)(*dma_ptr++ >> 8)); ++ left = ((char)(*dma_ptr++ >> 8)); ++ __put_user(left, user_ptr++); ++ __put_user(right, user_ptr++); ++ to_count -= 2; ++ } ++ } else { ++ while (to_count > 0) { ++ dma_ptr++; /* skip right channel sample */ ++ left = ((char)(*dma_ptr++ >> 8)); ++ __put_user(left, user_ptr++); ++ to_count--; ++ } ++ } ++ ++ return total_to_count; ++} ++ ++static __inline__ unsigned long copy_to_user_S8 ++ (struct audio_state_t *state, ++ const char *to, const char *from, unsigned long to_count) { ++ int total_to_count = to_count; ++ char *user_ptr = (char *)to; /* 8 bit user buffer */ ++ int *dma_ptr = (int *)from; /* 32 bit dma buffer */ ++ ++ int shift = state->input_stream->hw_bit_width - 8; ++ ++ if (state->input_stream->audio_num_channels != 1) { ++ while (to_count > 0) { ++ __put_user((char)((*dma_ptr++) >> shift), user_ptr++); ++ __put_user((char)((*dma_ptr++) >> shift), user_ptr++); ++ to_count -= 2; ++ } ++ } else { ++ while (to_count > 0) { ++ __put_user((char)((*dma_ptr++) >> shift), user_ptr++); ++ dma_ptr++; /* skip right channel sample */ ++ to_count--; ++ } ++ } ++ ++ return total_to_count; ++} ++ ++static __inline__ unsigned long copy_to_user_U8_CM ++ (struct audio_state_t *state, ++ const char *to, const char *from, unsigned long to_count) { ++ int total_to_count = to_count; ++ char *user_ptr = (char *)to; /* 8 bit user buffer */ ++ unsigned short *dma_ptr = (unsigned short *)from; /* 16 bit dma buffer */ ++ char right, left; ++ ++ if (state->input_stream->audio_num_channels != 1) { ++ while (to_count > 0) { ++ right = ((char)(*dma_ptr++ >> 8)) ^ 0x80; ++ left = ((char)(*dma_ptr++ >> 8)) ^ 0x80; ++ __put_user(left, user_ptr++); ++ __put_user(right, user_ptr++); ++ to_count -= 2; ++ } ++ } else { ++ while (to_count > 0) { ++ dma_ptr++; /* skip right channel sample */ ++ left = ((char)(*dma_ptr++ >> 8)) ^ 0x80; ++ __put_user(left, user_ptr++); ++ to_count--; ++ } ++ } ++ ++ return total_to_count; ++} ++ ++static __inline__ unsigned long copy_to_user_U8 ++ (struct audio_state_t *state, ++ const char *to, const char *from, unsigned long to_count) { ++ int total_to_count = to_count; ++ char *user_ptr = (char *)to; /* 8 bit user buffer */ ++ int *dma_ptr = (int *)from; /* 32 bit dma buffer */ ++ ++ int shift = state->input_stream->hw_bit_width - 8; ++ ++ if (state->input_stream->audio_num_channels != 1) { ++ while (to_count > 0) { ++ __put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80, ++ user_ptr++); ++ __put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80, ++ user_ptr++); ++ to_count -= 2; ++ } ++ } else { ++ while (to_count > 0) { ++ __put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80, ++ user_ptr++); ++ dma_ptr++; /* skip right channel sample */ ++ to_count--; ++ } ++ } ++ ++ return total_to_count; ++} ++ ++/* ++ * Returns negative for error ++ * Returns # of bytes transferred out of the from buffer ++ * for success. ++ */ ++static __inline__ int copy_to_user_with_conversion ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount) { ++ int ret = 0; ++ ++ if (toCount == 0) { ++ DPRINTK("copy_to_user_with_conversion - nothing to copy!\n"); ++ } ++ ++ /* ++ * Compact Mode means that each 32 bit word has both the ++ * left and right sample in it. ++ */ ++ if (state->input_stream->bCompactMode) { ++ switch (state->input_stream->audio_format) { ++ case AFMT_U8: ++ ret = copy_to_user_U8_CM(state, to, from, toCount); ++ break; ++ ++ case AFMT_S16_LE: ++ ret = copy_to_user_S16_LE_CM(state, to, from, toCount); ++ break; ++ ++ case AFMT_S8: ++ ret = copy_to_user_S8_CM(state, to, from, toCount); ++ break; ++ ++ case AFMT_U16_LE: ++ ret = copy_to_user_U16_LE_CM(state, to, from, toCount); ++ break; ++ ++ case AFMT_S32_BLOCKED: ++ default: ++ break; ++ } ++ } else { ++ switch (state->input_stream->audio_format) { ++ case AFMT_U8: ++ ret = copy_to_user_U8(state, to, from, toCount); ++ break; ++ ++ case AFMT_S16_LE: ++ ret = copy_to_user_S16_LE(state, to, from, toCount); ++ break; ++ ++ case AFMT_S8: ++ ret = copy_to_user_S8(state, to, from, toCount); ++ break; ++ ++ case AFMT_U16_LE: ++ ret = copy_to_user_U16_LE(state, to, from, toCount); ++ break; ++ ++ case AFMT_S32_BLOCKED: ++ default: ++ __copy_to_user((char *)to, from, toCount); ++ ret = toCount; ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++static __inline__ int copy_from_user_U16_LE_CM ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount) { ++ unsigned short *dma_buffer = (unsigned short *)to; ++ unsigned short *user_buffer = (unsigned short *)from; ++ unsigned short data; ++ ++ int toCount0 = toCount; ++ int mono = (state->output_stream->audio_num_channels == 1); ++ ++ /* ++ * Compact mode - left is the lower 16 bits. right is the upper 16 bits. ++ */ ++ ++ if (!mono) { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = data ^ 0x8000; ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = data ^ 0x8000; ++ toCount -= 4; ++ } ++ } else { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ data = data ^ 0x8000; ++ *dma_buffer++ = data; ++ *dma_buffer++ = data; ++ toCount -= 4; ++ } ++ } ++ ++ /* ++ * Each mono or stereo 16 bit sample going in results ++ * in one stereo 32 bit sample going out. So ++ * mono = (2 bytes in)/(4 bytes out) ++ * stereo = (4 bytes in)/(4 bytes out) ++ */ ++ if (mono) { ++ return toCount0 / 2; ++ } ++ ++ return toCount0; ++} ++ ++static __inline__ int copy_from_user_U16_LE ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount) { ++ int *dma_buffer = (int *)to; ++ int val; ++ unsigned short *user_buffer = (unsigned short *)from; ++ unsigned short data; ++ ++ int toCount0 = toCount; ++ int mono = (state->output_stream->audio_num_channels == 1); ++ int shift = state->output_stream->hw_bit_width - 16; ++ ++ if (!mono) { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = ((unsigned int)data ^ 0x8000) << shift; ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = ((unsigned int)data ^ 0x8000) << shift; ++ toCount -= 8; ++ } ++ } else { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ val = ((unsigned int)data ^ 0x8000) << shift; ++ *dma_buffer++ = val; ++ *dma_buffer++ = val; ++ toCount -= 8; ++ } ++ } ++ ++ /* ++ * Each mono or stereo 16 bit sample going in results ++ * in a two 32 bit (left & right) samples going out. So ++ * mono = (2 bytes in)/(8 bytes out) ++ * stereo = (4 bytes in)/(8 bytes out) ++ */ ++ if (mono) ++ return toCount0 / 4; ++ ++ return toCount0 / 2; ++} ++ ++static __inline__ int copy_from_user_S16_LE_CM ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount) { ++ short *dma_buffer = (short *)to; ++ unsigned short *user_buffer = (unsigned short *)from; ++ unsigned short data; ++ ++ int toCount0 = toCount; ++ int mono = (state->output_stream->audio_num_channels == 1); ++ ++ /* ++ * Compact mode - left is the lower 16 bits. right is the upper 16 bits. ++ */ ++ ++ if (!mono) { ++ __copy_from_user((char *)to, from, toCount); ++ } else { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = data; ++ *dma_buffer++ = data; ++ toCount -= 4; ++ } ++ } ++ ++ /* ++ * Each mono or stereo 16 bit sample going in results ++ * in one stereo 32 bit sample going out. So ++ * mono = (2 bytes in)/(4 bytes out) ++ * stereo = (4 bytes in)/(4 bytes out) ++ */ ++ if (mono) ++ return toCount0 / 2; ++ ++ return toCount0; ++} ++ ++static __inline__ int copy_from_user_S16_LE ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount) { ++ int *dma_buffer = (int *)to; ++ int val; ++ unsigned short *user_buffer = (unsigned short *)from; ++ unsigned short data; ++ ++ int toCount0 = toCount; ++ int mono = (state->output_stream->audio_num_channels == 1); ++ int shift = state->output_stream->hw_bit_width - 16; ++ ++ if (!mono) { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = (unsigned int)data << shift; ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = (unsigned int)data << shift; ++ toCount -= 8; ++ } ++ } else { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ val = (unsigned int)data << shift; ++ *dma_buffer++ = val; ++ *dma_buffer++ = val; ++ toCount -= 8; ++ } ++ } ++ ++ /* ++ * Each mono or stereo 16 bit sample going in results ++ * in a two 32 bit samples (left & right) going out. So ++ * mono = (2 bytes in)/(8 bytes out) ++ * stereo = (4 bytes in)/(8 bytes out) ++ */ ++ if (mono) ++ return toCount0 / 4; ++ ++ return toCount0 / 2; ++} ++ ++static __inline__ int copy_from_user_S8_CM ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount) { ++ short *dma_buffer = (short *)to; ++ short val; ++ unsigned char *user_buffer = (unsigned char *)from; ++ unsigned char data; ++ ++ int toCount0 = toCount; ++ int mono = (state->output_stream->audio_num_channels == 1); ++ ++ /* ++ * Compact mode - left is the lower 16 bits. right is the upper 16 bits. ++ */ ++ ++ if (!mono) { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = (unsigned short)data << 8; ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = (unsigned short)data << 8; ++ toCount -= 4; ++ } ++ } else { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ val = (unsigned short)data << 8; ++ *dma_buffer++ = val; ++ *dma_buffer++ = val; ++ toCount -= 4; ++ } ++ } ++ ++ /* ++ * Each mono or stereo 8 bit sample going in results ++ * in one stereo 32 bit sample going out. So ++ * mono = (1 byte in)/(4 bytes out) ++ * stereo = (2 bytes in)/(4 bytes out) ++ */ ++ if (mono) ++ return toCount0 / 4; ++ ++ return toCount0 / 2; ++} ++ ++static __inline__ int copy_from_user_S8 ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount) { ++ int *dma_buffer = (int *)to; ++ int val; ++ unsigned char *user_buffer = (unsigned char *)from; ++ unsigned char data; ++ ++ int toCount0 = toCount; ++ int mono = (state->output_stream->audio_num_channels == 1); ++ int shift = state->output_stream->hw_bit_width - 8; ++ ++ if (!mono) { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = (unsigned int)data << shift; ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = (unsigned int)data << shift; ++ toCount -= 8; ++ } ++ } else { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ val = (unsigned int)data << shift; ++ *dma_buffer++ = val; ++ *dma_buffer++ = val; ++ toCount -= 8; ++ } ++ } ++ ++ /* ++ * Each mono or stereo 8 bit sample going in results ++ * in a two 32 bit samples (left & right) going out. So ++ * mono = (1 byte in)/(8 bytes out) ++ * stereo = (2 bytes in)/(8 bytes out) ++ */ ++ if (mono) ++ return toCount0 / 8; ++ ++ return toCount0 / 4; ++} ++ ++static __inline__ int copy_from_user_U8_CM ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount) { ++ unsigned short *dma_buffer = (unsigned short *)to; ++ unsigned short val; ++ unsigned char *user_buffer = (unsigned char *)from; ++ unsigned char data; ++ ++ int toCount0 = toCount; ++ int mono = (state->output_stream->audio_num_channels == 1); ++ ++ if (!mono) { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = ((unsigned short)data ^ 0x80) << 8; ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = ((unsigned short)data ^ 0x80) << 8; ++ toCount -= 4; ++ } ++ } else { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ val = ((unsigned short)data ^ 0x80) << 8; ++ *dma_buffer++ = val; ++ *dma_buffer++ = val; ++ toCount -= 4; ++ } ++ } ++ ++ /* ++ * Each mono or stereo 8 bit sample going in results ++ * in one stereo 32 bit sample going out. So ++ * mono = (1 byte in)/(4 bytes out) ++ * stereo = (2 bytes in)/(4 bytes out) ++ */ ++ if (mono) ++ return toCount0 / 4; ++ ++ return toCount0 / 2; ++} ++ ++static __inline__ int copy_from_user_U8 ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount) { ++ unsigned int *dma_buffer = (unsigned int *)to; ++ unsigned int val; ++ unsigned char *user_buffer = (unsigned char *)from; ++ unsigned char data; ++ ++ int toCount0 = toCount; ++ int mono = (state->output_stream->audio_num_channels == 1); ++ int shift = state->output_stream->hw_bit_width - 8; ++ ++ if (!mono) { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = ((unsigned int)data ^ 0x80) << shift; ++ __get_user(data, user_buffer++); ++ *dma_buffer++ = ((unsigned int)data ^ 0x80) << shift; ++ toCount -= 8; ++ } ++ } else { ++ while (toCount > 0) { ++ __get_user(data, user_buffer++); ++ val = ((unsigned int)data ^ 0x80) << shift; ++ *dma_buffer++ = val; ++ *dma_buffer++ = val; ++ toCount -= 8; ++ } ++ } ++ ++ /* ++ * Each mono or stereo 8 bit sample going in results ++ * in a two 32 bit samples (left & right) going out. So ++ * mono = (1 byte in)/(8 bytes out) ++ * stereo = (2 bytes in)/(8 bytes out) ++ */ ++ if (mono) ++ return toCount0 / 8; ++ ++ return toCount0 / 4; ++} ++ ++/* ++ * Returns negative for error ++ * Returns # of bytes transferred out of the from buffer ++ * for success. ++ */ ++static __inline__ int copy_from_user_with_conversion ++ (struct audio_state_t *state, ++ const char *to, const char *from, int toCount) { ++ int ret = 0; ++ ++ if (toCount == 0) { ++ DPRINTK("copy_from_user_with_conversion - nothing to copy!\n"); ++ } ++ ++ /* ++ * Compact Mode means that each 32 bit word has both the ++ * left and right sample in it. ++ */ ++ if (state->output_stream->bCompactMode) { ++ switch (state->output_stream->audio_format) { ++ case AFMT_U8: ++ ret = copy_from_user_U8_CM(state, to, from, toCount); ++ break; ++ ++ case AFMT_S16_LE: ++ ret = ++ copy_from_user_S16_LE_CM(state, to, from, toCount); ++ break; ++ ++ case AFMT_S8: ++ ret = copy_from_user_S8_CM(state, to, from, toCount); ++ break; ++ ++ case AFMT_U16_LE: ++ ret = ++ copy_from_user_U16_LE_CM(state, to, from, toCount); ++ break; ++ ++ case AFMT_S32_BLOCKED: ++ default: ++ break; ++ } ++ } else { ++ switch (state->output_stream->audio_format) { ++ case AFMT_U8: ++ ret = copy_from_user_U8(state, to, from, toCount); ++ break; ++ ++ case AFMT_S16_LE: ++ ret = copy_from_user_S16_LE(state, to, from, toCount); ++ break; ++ ++ case AFMT_S8: ++ ret = copy_from_user_S8(state, to, from, toCount); ++ break; ++ ++ case AFMT_U16_LE: ++ ret = copy_from_user_U16_LE(state, to, from, toCount); ++ break; ++ ++ case AFMT_S32_BLOCKED: ++ default: ++ __copy_from_user((char *)to, from, toCount); ++ ret = toCount; ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++static int audio_ioctl(struct inode *inode, struct file *file, ++ uint cmd, ulong arg) ++{ ++ struct audio_state_t *state = ++ (struct audio_state_t *)file->private_data; ++ struct audio_stream_t *os = state->output_stream; ++ struct audio_stream_t *is = state->input_stream; ++ long val = 0; ++ ++ switch (cmd) { ++ case SNDCTL_DSP_STEREO: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_STEREO\n"); ++ if (get_user(val, (int *)arg) || (val > 1) || (val < 0)) ++ return -EFAULT; ++ ++ if (file->f_mode & FMODE_WRITE) { ++ if (os->audio_num_channels != (val + 1)) { ++ os->audio_num_channels = val + 1; ++ calculate_dma2usr_ratio_etc(os); ++ } ++ } ++ ++ if (file->f_mode & FMODE_READ) { ++ if (is->audio_num_channels != (val + 1)) { ++ is->audio_num_channels = val + 1; ++ calculate_dma2usr_ratio_etc(is); ++ } ++ } ++ ++ return put_user(val, (long *)arg); ++ ++ case SNDCTL_DSP_CHANNELS: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_CHANNELS\n"); ++ if (get_user(val, (int *)arg) || (val > 2) || (val < 0)) ++ return -EFAULT; ++ ++ // Calling with value of 0 is a query. ++ if (val == 0) { ++ if (file->f_mode & FMODE_WRITE) ++ val = os->audio_num_channels; ++ else ++ val = is->audio_num_channels; ++ } else { ++ if (file->f_mode & FMODE_WRITE) { ++ if (os->audio_num_channels != val) { ++ os->audio_num_channels = val; ++ calculate_dma2usr_ratio_etc(os); ++ } ++ } ++ if (file->f_mode & FMODE_READ) { ++ if (is->audio_num_channels != val) { ++ is->audio_num_channels = val; ++ calculate_dma2usr_ratio_etc(is); ++ } ++ } ++ } ++ ++ return put_user(val, (long *)arg); ++ ++ case SOUND_PCM_READ_CHANNELS: ++ DPRINTK_IOCTL("audio_ioctl - SOUND_PCM_READ_CHANNELS\n"); ++ if (file->f_mode & FMODE_WRITE) ++ val = os->audio_num_channels; ++ else ++ val = is->audio_num_channels; ++ return put_user(val, (long *)arg); ++ ++ case SNDCTL_DSP_SETFMT: ++ { ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETFMT\n"); ++ ++ if (get_user(val, (int *)arg)) ++ return -EFAULT; ++ ++ if (val != AFMT_QUERY) { ++ if ((file->f_mode & FMODE_WRITE) ++ && (val != os->audio_format)) { ++ audio_set_format(os, val); ++ calculate_dma2usr_ratio_etc(os); ++ if (state->hw->set_hw_serial_format) ++ state->hw-> ++ set_hw_serial_format(os, ++ val); ++ } ++ if ((file->f_mode & FMODE_READ) ++ && (val != is->audio_format)) { ++ audio_set_format(is, val); ++ calculate_dma2usr_ratio_etc(is); ++ if (state->hw->set_hw_serial_format) ++ state->hw-> ++ set_hw_serial_format(is, ++ val); ++ } ++ } ++ ++ if (file->f_mode & FMODE_WRITE) ++ return put_user(os->audio_format, (long *)arg); ++ return put_user(is->audio_format, (long *)arg); ++ } ++ ++ case SNDCTL_DSP_GETFMTS: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETFMTS\n"); ++ return put_user((AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE), ++ (long *)arg); ++ ++ case OSS_GETVERSION: ++ DPRINTK_IOCTL("audio_ioctl - OSS_GETVERSION\n"); ++ return put_user(SOUND_VERSION, (int *)arg); ++ ++ case SNDCTL_DSP_GETBLKSIZE: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETBLKSIZE\n"); ++ if (file->f_mode & FMODE_WRITE) ++ return put_user(os->fragsize, (int *)arg); ++ return put_user(is->fragsize, (int *)arg); ++ ++ case SNDCTL_DSP_GETCAPS: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETCAPS\n"); ++ val = DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP; ++ if (is && os) ++ val |= DSP_CAP_DUPLEX; ++ return put_user(val, (int *)arg); ++ ++ case SNDCTL_DSP_SETFRAGMENT: ++ { ++ int ret; ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETFRAGMENT\n"); ++ if (get_user(val, (long *)arg)) ++ return -EFAULT; ++ ++ if (file->f_mode & FMODE_READ) { ++ ret = audio_set_fragments(state, is, val); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (file->f_mode & FMODE_WRITE) { ++ ret = audio_set_fragments(state, os, val); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++ } ++ ++ case SNDCTL_DSP_SYNC: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SYNC\n"); ++ return audio_sync(file); ++ ++ case SNDCTL_DSP_SETDUPLEX: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETDUPLEX\n"); ++ return 0; ++ ++ case SNDCTL_DSP_POST: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_POST\n"); ++ return 0; ++ ++ case SNDCTL_DSP_GETTRIGGER: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETTRIGGER\n"); ++ val = 0; ++ ++ if (file->f_mode & FMODE_READ && is->active && !is->stopped) ++ val |= PCM_ENABLE_INPUT; ++ ++ if (file->f_mode & FMODE_WRITE && os->active && !os->stopped) ++ val |= PCM_ENABLE_OUTPUT; ++ ++ return put_user(val, (int *)arg); ++ ++ case SNDCTL_DSP_SETTRIGGER: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETTRIGGER\n"); ++ if (get_user(val, (int *)arg)) ++ return -EFAULT; ++ ++ if (file->f_mode & FMODE_READ) { ++ if (val & PCM_ENABLE_INPUT) { ++ if (!is->active) { ++ if (!is->buffers ++ && audio_allocate_buffers(state, ++ is)) ++ return -ENOMEM; ++ audio_prime_dma(state, is); ++ } ++ ++ if (is->stopped) { ++ is->stopped = 0; ++ os->active = 1; ++ audio_dma_start(state, is); ++ } ++ } else { ++ audio_dma_pause(state, is); ++ is->stopped = 1; ++ is->active = 0; ++ } ++ } ++ ++ if (file->f_mode & FMODE_WRITE) { ++ if (val & PCM_ENABLE_OUTPUT) { ++ if (!os->active) { ++ if (!os->buffers ++ && audio_allocate_buffers(state, ++ os)) ++ return -ENOMEM; ++ ++ if (os->mapped) ++ audio_prime_dma(state, os); ++ } ++ ++ if (os->stopped) { ++ os->stopped = 0; ++ os->active = 1; ++ audio_dma_start(state, os); ++ } ++ } else { ++ audio_dma_pause(state, os); ++ os->stopped = 1; ++ os->active = 0; ++ } ++ } ++ return 0; ++ ++ case SNDCTL_DSP_GETOPTR: ++ case SNDCTL_DSP_GETIPTR: ++ { ++ count_info inf = { 0, }; ++ struct audio_stream_t *stream = ++ (cmd == SNDCTL_DSP_GETOPTR) ? os : is; ++ int bytecount, fragcount, buf_num = 0; ++ unsigned int current_frac, buf_id; ++ // KERNEL2.4 SNIP ++ unsigned long flags; ++ unsigned int total = 0; ++ // KERNEL2.4 SNAP ++ ++ DPRINTK_IOCTL ++ ("audio_ioctl - called SNDCTL_DSP_GETOPTR.\n"); ++ ++ if ((stream == is && !(file->f_mode & FMODE_READ)) || ++ (stream == os && !(file->f_mode & FMODE_WRITE))) ++ return -EINVAL; ++ ++ if (!stream->active) ++ return copy_to_user((void *)arg, &inf, ++ sizeof(inf)); ++ ++ // KERNEL2.4 ++ //save_flags_cli(flags); ++ local_irq_save(flags); ++ ++ // KERNEL2.4 ++ //DMA_GET_POSITION( stream->dmahandles[0], &buf_id, 0, ++ // ¤t_frac ); ++ DMA_GET_POSITION(stream->dmahandles[0], &buf_id, &total, ++ ¤t_frac); ++ ++ /* ++ * Out of a set of nbfrags buffers, which one is the current one? ++ */ ++ if (buf_id) ++ buf_num = ((struct audio_buf_t *)buf_id)->num; ++ ++ /* ++ * The ep93xx-audio ISRs keep track of bytecount and fragcount. ++ * This bytecount isn't cleared except when the driver is opened ++ * or when it overflows. ++ */ ++ bytecount = stream->bytecount; ++ ++ /* so poll can tell if it changes */ ++ stream->getptrCount = stream->bytecount; ++ ++ /* ++ * Return the number of fragment transitions counted in our dma ISR ++ * since the previous call to this ioctl, then clear that counter. ++ */ ++ fragcount = stream->fragcount; ++ stream->fragcount = 0; ++ ++ // KERNEL2.4 ++ //restore_flags(flags); ++ local_irq_restore(flags); ++ ++ /* ++ * When reporting position to user app, scale byte counts and the ++ * ptr to reflect the difference in sample size between dma samples ++ * and user samples. But don't scale the # of fragments. ++ */ ++ inf.blocks = fragcount; ++ inf.bytes = ++ (bytecount + current_frac) / stream->dma2usr_ratio; ++ inf.ptr = ++ ((buf_num * stream->fragsize) + ++ current_frac) / stream->dma2usr_ratio; ++ ++ return copy_to_user((void *)arg, &inf, sizeof(inf)); ++ } ++ ++ case SNDCTL_DSP_GETODELAY: ++ { ++ int buffered_bytes_left, count; ++ //unsigned int current_frac; ++ // KERNEL2.4 SNIP ++ unsigned int current_frac = 0; ++ unsigned long flags; ++ unsigned int total = 0, buf_id = 0; ++ // KERNEL2.4SNAP ++ ++ if (!(file->f_mode & FMODE_WRITE)) ++ return -EINVAL; ++ ++ DPRINTK_IOCTL ++ ("audio_ioctl - called SNDCTL_DSP_GETODELAY.\n"); ++ ++ // KERNEL2.4 ++ //save_flags_cli(flags); ++ local_irq_save(flags); ++ ++ // KERNEL2.4 ++ //DMA_GET_POSITION( os->dmahandles[0], 0, 0, ¤t_frac ); ++ DMA_GET_POSITION(os->dmahandles[0], &buf_id, &total, ++ ¤t_frac); ++ ++ buffered_bytes_left = os->buffered_bytes_to_play; ++ ++ // KERNEL2.4 ++ //restore_flags(flags); ++ local_irq_restore(flags); ++ ++ count = ++ (buffered_bytes_left - ++ current_frac) / os->dma2usr_ratio; ++ ++ return put_user(count, (int *)arg); ++ } ++ ++ case SNDCTL_DSP_GETOSPACE: ++ { ++ /* ++ * It looks like this code is assuming that nobody ++ * is writing the device while calling this ioctl ++ * which may be a reasonable assumption. I hope. ++ * Maybe. ++ */ ++ audio_buf_info inf = { 0, }; ++ int i; ++ ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETOSPACE\n"); ++ ++ if (!(file->f_mode & FMODE_WRITE)) ++ return -EINVAL; ++ if (!os->buffers && audio_allocate_buffers(state, os)) ++ return -ENOMEM; ++ ++ for (i = 0; i < os->nbfrags; i++) { ++ /* ++ * If the semaphore is 1, the buffer is available. ++ */ ++ if (os->buffers[i].owner != 0) { ++ if (os->buffers[i].size == 0) ++ inf.fragments++; ++ ++ inf.bytes += ++ os->fragsize - os->buffers[i].size; ++ } ++ } ++ ++ inf.fragsize = os->fragsize / os->dma2usr_ratio; ++ inf.fragstotal = os->nbfrags; ++ inf.bytes = inf.bytes / os->dma2usr_ratio; ++ ++ return copy_to_user((void *)arg, &inf, sizeof(inf)); ++ } ++ ++ case SNDCTL_DSP_GETISPACE: ++ { ++ audio_buf_info inf = { 0, }; ++ int i; ++ ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETISPACE\n"); ++ ++ if (!(file->f_mode & FMODE_READ)) ++ return -EINVAL; ++ if (!is->buffers && audio_allocate_buffers(state, is)) ++ return -ENOMEM; ++ ++ for (i = 0; i < is->nbfrags; i++) { ++ if (is->buffers[i].owner != 0) { ++ if (is->buffers[i].size == is->fragsize) ++ inf.fragments++; ++ ++ inf.bytes += is->buffers[i].size; ++ } ++ } ++ ++ inf.fragsize = is->fragsize / is->dma2usr_ratio; ++ inf.fragstotal = is->nbfrags; ++ inf.bytes = inf.bytes / is->dma2usr_ratio; ++ ++ return copy_to_user((void *)arg, &inf, sizeof(inf)); ++ } ++ ++ case SNDCTL_DSP_NONBLOCK: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_NONBLOCK\n"); ++ file->f_flags |= O_NONBLOCK; ++ return 0; ++ ++ case SNDCTL_DSP_RESET: ++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_RESET\n"); ++ if (file->f_mode & FMODE_READ) ++ audio_reset_buffers(state, is); ++ if (file->f_mode & FMODE_WRITE) ++ audio_reset_buffers(state, os); ++ return 0; ++ ++ default: ++ /* ++ * Let the client of this module handle the ++ * non generic ioctls ++ */ ++ return state->hw->client_ioctl(inode, file, cmd, arg); ++ } ++ ++ return 0; ++} ++ ++static int audio_release(struct inode *inode, struct file *file) ++{ ++ struct audio_state_t *state = ++ (struct audio_state_t *)file->private_data; ++ int i; ++ ++ DPRINTK("EP93xx - audio_release -- enter. Write=%d Read=%d\n", ++ ((file->f_mode & FMODE_WRITE) != 0), ++ ((file->f_mode & FMODE_READ) != 0)); ++ ++ down(&state->sem); ++ ++ if (file->f_mode & FMODE_READ) { ++ audio_deallocate_buffers(state, state->input_stream); ++ ++ for (i = 0; i < state->input_stream->NumDmaChannels; i++) ++ DMA_FREE(state->input_stream->dmahandles[i]); ++ ++ state->rd_ref = 0; ++ } ++ ++ if (file->f_mode & FMODE_WRITE) { ++ /* ++ * Wait for all our buffers to play. ++ */ ++ audio_sync(file); ++ ++ /* ++ * audio_deallocate_buffers will pause and flush the dma ++ * then deallocate the buffers. ++ */ ++ audio_deallocate_buffers(state, state->output_stream); ++ for (i = 0; i < state->output_stream->NumDmaChannels; i++) ++ DMA_FREE(state->output_stream->dmahandles[i]); ++ ++ state->wr_ref = 0; ++ } ++ ++ up(&state->sem); ++ ++ DPRINTK("EP93xx - audio_release -- EXIT\n"); ++ ++ return 0; ++} ++ ++/* ++ * ep93xx_clear_stream_struct ++ * ++ * Initialize stuff or at least clear it to zero for a stream structure. ++ */ ++static void ep93xx_clear_stream_struct(struct audio_stream_t *stream) ++{ ++ ++ stream->dmahandles[0] = 0; /* handles for dma driver instances */ ++ stream->dmahandles[1] = 0; /* handles for dma driver instances */ ++ stream->dmahandles[2] = 0; /* handles for dma driver instances */ ++ stream->NumDmaChannels = 0; /* 1, 2, or 3 DMA channels */ ++ stream->TX_dma_ch_bitfield = 0; /* which dma channels used for strm */ ++ stream->RX_dma_ch_bitfield = 0; /* which dma channels used for strm */ ++ stream->buffers = 0; /* array of audio buffer structures */ ++ stream->dma_buffer = 0; /* current buffer used by read/write */ ++ stream->dma_buffer_index = 0; /* index for the pointer above... */ ++ stream->fragsize = AUDIO_FRAGSIZE_DEFAULT; /* fragment i.e. buffer size */ ++ stream->nbfrags = AUDIO_NBFRAGS_DEFAULT; /* nbr of fragments i.e. buffers */ ++ stream->requested_fragsize = 0; /* This is ignored if 0 */ ++ stream->requested_nbfrags = 0; /* This is ignored if 0 */ ++ stream->bytecount = 0; /* nbr of processed bytes */ ++ stream->getptrCount = 0; /* value of bytecount last time */ ++ /* anyone asked via GETxPTR */ ++ stream->fragcount = 0; /* nbr of fragment transitions */ ++ stream->mapped = 0; /* mmap()'ed buffers */ ++ stream->active = 0; /* actually in progress */ ++ stream->stopped = 0; /* might be active but stopped */ ++ stream->bFirstCaptureBuffer = 1; /* flag meaning there is junk in rx fifo */ ++ stream->buffered_bytes_to_play = 0; ++ ++ calculate_dma2usr_ratio_etc(stream); ++} ++ ++/* ++ * ep93xx_audio_attach ++ * ++ * Initialize the state structure for read or write. Allocate dma channels. ++ * Currently each s is a stereo s (one dma channel). ++ * ++ */ ++int ep93xx_audio_attach ++ (struct inode *inode, struct file *file, struct audio_state_t *state) { ++ int err, i; ++ struct audio_stream_t *os = state->output_stream; ++ struct audio_stream_t *is = state->input_stream; ++ ++ DPRINTK("ep93xx_audio_attach -- enter. Write=%d Read=%d\n", ++ ((file->f_mode & FMODE_WRITE) != 0), ++ ((file->f_mode & FMODE_READ) != 0)); ++ ++ down(&state->sem); ++ ++ /* access control */ ++ if (((file->f_mode & FMODE_WRITE) && !os) || ++ ((file->f_mode & FMODE_READ) && !is)) { ++ up(&state->sem); ++ return -ENODEV; ++ } ++ ++ if (((file->f_mode & FMODE_WRITE) && state->wr_ref) || ++ ((file->f_mode & FMODE_READ) && state->rd_ref)) { ++ up(&state->sem); ++ return -EBUSY; ++ } ++ ++ /* ++ * Request DMA channels ++ */ ++ if (file->f_mode & FMODE_WRITE) { ++ DPRINTK("ep93xx_audio_attach -- FMODE_WRITE\n"); ++ ++ state->wr_ref = 1; ++ ++ ep93xx_clear_stream_struct(os); ++ ++ err = DMA_REQUEST(&os->dmahandles[0], ++ os->devicename, os->dmachannel[0]); ++ if (err) { ++ up(&state->sem); ++ DPRINTK ++ ("ep93xx_audio_attach -- EXIT ERROR dma request failed\n"); ++ return err; ++ } ++ ++ err = DMA_CONFIG(os->dmahandles[0], ++ IGNORE_CHANNEL_ERROR, ++ 0, audio_dma_tx_callback, (unsigned int)state); ++ if (err) { ++ DMA_FREE(os->dmahandles[0]); ++ up(&state->sem); ++ DPRINTK ++ ("ep93xx_audio_attach -- EXIT ERROR dma config failed\n"); ++ return err; ++ } ++ ++ /* ++ * Assuming each audio stream is mono or stereo. ++ */ ++ os->NumDmaChannels = 1; ++ ++ /* ++ * Automatically set up the bit field of dma channels used for ++ * this stream. ++ */ ++ for (i = 0; (i < state->hw->MaxTxDmaChannels); i++) { ++ if (os->dmachannel[i] == state->hw->txdmachannels[0]) ++ os->TX_dma_ch_bitfield |= 1; ++ ++ if (os->dmachannel[i] == state->hw->txdmachannels[1]) ++ os->TX_dma_ch_bitfield |= 2; ++ ++ if (os->dmachannel[i] == state->hw->txdmachannels[2]) ++ os->TX_dma_ch_bitfield |= 4; ++ } ++ ++ DPRINTK("DMA Tx channel bitfield = %x\n", ++ os->TX_dma_ch_bitfield); ++ ++ if (state->hw->hw_clear_fifo) ++ state->hw->hw_clear_fifo(os); ++ ++ init_waitqueue_head(&os->wq); ++ } ++ ++ if (file->f_mode & FMODE_READ) { ++ state->rd_ref = 1; ++ ++ ep93xx_clear_stream_struct(is); ++ ++ err = DMA_REQUEST(&is->dmahandles[0], ++ is->devicename, is->dmachannel[0]); ++ if (err) { ++ up(&state->sem); ++ DPRINTK ++ ("ep93xx_audio_attach -- EXIT ERROR dma request failed\n"); ++ return err; ++ } ++ ++ err = DMA_CONFIG(is->dmahandles[0], ++ IGNORE_CHANNEL_ERROR, ++ 0, audio_dma_rx_callback, (unsigned int)state); ++ if (err) { ++ DMA_FREE(is->dmahandles[0]); ++ up(&state->sem); ++ DPRINTK ++ ("ep93xx_audio_attach -- EXIT ERROR dma config failed\n"); ++ return err; ++ } ++ ++ is->NumDmaChannels = 1; ++ ++ /* ++ * Automatically set up the bit field of dma channels used for ++ * this stream. ++ */ ++ for (i = 0; (i < state->hw->MaxRxDmaChannels); i++) { ++ if (is->dmachannel[i] == state->hw->rxdmachannels[0]) ++ is->RX_dma_ch_bitfield |= 1; ++ ++ if (is->dmachannel[i] == state->hw->rxdmachannels[1]) ++ is->RX_dma_ch_bitfield |= 2; ++ ++ if (is->dmachannel[i] == state->hw->rxdmachannels[2]) ++ is->RX_dma_ch_bitfield |= 4; ++ } ++ ++ DPRINTK("DMA Rx channel bitfield = %x\n", ++ is->RX_dma_ch_bitfield); ++ ++ init_waitqueue_head(&is->wq); ++ } ++ ++ /* ++ * Fill out the rest of the file_operations struct. ++ */ ++ file->private_data = state; ++ file->f_op->release = audio_release; ++ file->f_op->write = audio_write; ++ file->f_op->read = audio_read; ++ file->f_op->mmap = audio_mmap; ++ file->f_op->poll = audio_poll; ++ file->f_op->ioctl = audio_ioctl; ++ file->f_op->llseek = no_llseek; ++ ++ up(&state->sem); ++ ++ DPRINTK("ep93xx_audio_attach -- EXIT\n"); ++ ++ return 0; ++} ++ ++EXPORT_SYMBOL(ep93xx_audio_attach); ++ ++MODULE_DESCRIPTION("Common audio handling for the Cirrus EP93xx processor"); ++MODULE_LICENSE("GPL"); +diff --git a/sound/oss/ep93xx-audio.h b/sound/oss/ep93xx-audio.h +new file mode 100644 +index 0000000..04a0581 +--- /dev/null ++++ b/sound/oss/ep93xx-audio.h +@@ -0,0 +1,149 @@ ++/* ++ * ep93xx-audio.h ++ * ++ * Common audio handling for the Cirrus Logic EP93xx ++ * ++ * Copyright (c) 2003 Cirrus Logic Corp. ++ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org> ++ * ++ * Taken from sa1100-audio.h ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License. ++ */ ++ ++/* ++ * Getting this from the rme96xx driver. Has same numerical value ++ * as AC3. Hmmmm. ++ */ ++#ifndef AFMT_S32_BLOCKED ++#define AFMT_S32_BLOCKED 0x0000400 ++#endif ++ ++#define EP93XX_DEFAULT_NUM_CHANNELS 2 ++#define EP93XX_DEFAULT_FORMAT AFMT_S16_LE ++#define EP93XX_DEFAULT_BIT_WIDTH 16 ++ ++/* ++ * Buffer Management ++ */ ++ ++struct audio_buf_t { ++ ++ int size; /* buffer size */ ++ int sent; /* indicates that dma has the dma_buffer */ ++ char *start; /* points to actual buffer */ ++ dma_addr_t dma_addr; /* physical buffer address */ ++ int owner; ++ struct semaphore sem; /* down before touching the buffer */ ++ int master; /* owner for buffer allocation, */ ++ /* contains size when true */ ++ int num; /* which out of nbfrags buffers is this? */ ++ struct audio_stream_t *stream; /* owning stream */ ++ ++}; ++ ++#define MAX_DEVICE_NAME 20 ++ ++struct audio_stream_t { ++ ++ /* dma stuff */ ++ int dmahandles[3]; /* handles for dma driver instances */ ++ char devicename[MAX_DEVICE_NAME]; /* string - name of device */ ++ int NumDmaChannels; /* 1, 2, or 3 DMA channels */ ++ ep93xx_dma_dev_t dmachannel[3]; /* dma channel numbers */ ++ ++ struct audio_buf_t *buffers; /* array of audio buffer structures */ ++ struct audio_buf_t *dma_buffer; /* current buffer used by read/write */ ++ u_int dma_buffer_index; /* index for the pointer above... */ ++ ++ u_int fragsize; /* fragment i.e. buffer size */ ++ u_int nbfrags; /* nbr of fragments i.e. buffers */ ++ u_int requested_fragsize; ++ u_int requested_nbfrags; ++ ++ int bytecount; /* nbr of processed bytes */ ++ int getptrCount; /* value of bytecount last time */ ++ /* anyone asked via GETxPTR */ ++ int fragcount; /* nbr of fragment transitions */ ++ wait_queue_head_t wq; /* for poll */ ++ int mapped:1; /* mmap()'ed buffers */ ++ int active:1; /* actually in progress */ ++ int stopped:1; /* might be active but stopped */ ++ u_int TX_dma_ch_bitfield; /* bit0 = txdma1, bit1= txdma2, etc */ ++ u_int RX_dma_ch_bitfield; /* bit0 = rxdma1, bit1= rxdma2, etc */ ++ int bFirstCaptureBuffer; /* flag meaning there is junk in rx fifo */ ++ ++ /* ++ * Data about the file format that we are configured to play. ++ */ ++ long audio_num_channels; /* Range: 1 to 6 */ ++ long audio_format; ++ long audio_stream_bitwidth; /* Range: 8, 16, 24, 32 */ ++ ++ long sample_rate; /* Fs in Hz. */ ++ ++ /* ++ * Data about how the audio controller and codec are set up. ++ */ ++ int hw_bit_width; /* width of dac or adc */ ++ int bCompactMode; /* set if 32bits == a stereo sample */ ++ ++ /* ++ * dma2usr_ratio = dma sample size (8 or 4 bytes) / usr sample size (8,4,2,1) ++ */ ++ int dma2usr_ratio; ++ ++ /* ++ * This provides a way of determining audio playback position that will not ++ * overflow. This is (size of buffers written) - (buffers we've gotten back) ++ */ ++ int buffered_bytes_to_play; ++ ++}; ++ ++/* ++ * No matter how many streams are going, we are using one hardware device. ++ * This struct describes that hardware. ++ */ ++struct audio_hw_t { ++ ++ ep93xx_dma_dev_t txdmachannels[3]; /* all dma channels available for */ ++ ep93xx_dma_dev_t rxdmachannels[3]; /* this audio ctrlr */ ++ ++ int MaxTxDmaChannels; /* number of tx and rx channels */ ++ int MaxRxDmaChannels; /* number of tx and rx channels */ ++ ++ /* ++ * Pointers to init, shutdown, and ioctl functions. ++ */ ++ void (*hw_enable) (struct audio_stream_t * stream); ++ void (*hw_disable) (struct audio_stream_t * stream); ++ void (*hw_clear_fifo) (struct audio_stream_t * stream); ++ int (*client_ioctl) (struct inode *, struct file *, uint, ulong); ++ void (*set_hw_serial_format) (struct audio_stream_t *, long); ++ ++ unsigned int modcnt; /* count the # of volume writes */ ++ ++}; ++ ++/* ++ * State structure for one instance ++ */ ++struct audio_state_t { ++ struct audio_stream_t *output_stream; ++ struct audio_stream_t *input_stream; ++ ++ struct audio_hw_t *hw; /* hw info */ ++ ++ int rd_ref:1; /* open reference for recording */ ++ int wr_ref:1; /* open reference for playback */ ++ ++ struct semaphore sem; /* to protect against races in attach() */ ++ ++}; ++ ++/* ++ * Functions exported by this module ++ */ ++extern int ep93xx_audio_attach(struct inode *inode, struct file *file, ++ struct audio_state_t *state); |