summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/arm/XScale/ADIFCC/80200EVB111
-rw-r--r--Documentation/arm/XScale/IOP310/IQ80310295
-rw-r--r--arch/arm/Makefile20
-rw-r--r--arch/arm/boot/compressed/Makefile2
-rw-r--r--arch/arm/boot/compressed/head.S58
-rw-r--r--arch/arm/boot/compressed/ll_char_wr.S216
-rw-r--r--arch/arm/config.in4
-rw-r--r--arch/arm/kernel/arch.c1
-rw-r--r--arch/arm/kernel/bios32.c32
-rw-r--r--arch/arm/kernel/ecard.c116
-rw-r--r--arch/arm/kernel/entry-armv.S15
-rw-r--r--arch/arm/kernel/process.c4
-rw-r--r--arch/arm/kernel/ptrace.c139
-rw-r--r--arch/arm/kernel/setup.c27
-rw-r--r--arch/arm/kernel/signal.c36
-rw-r--r--arch/arm/kernel/time-acorn.c33
-rw-r--r--arch/arm/kernel/time.c9
-rw-r--r--arch/arm/kernel/traps.c25
-rw-r--r--arch/arm/mach-integrator/cpu.c90
-rw-r--r--arch/arm/mach-iop310/iop310-pci.c12
-rw-r--r--arch/arm/mach-iop310/iq80310-time.c2
-rw-r--r--arch/arm/mach-sa1100/Makefile12
-rw-r--r--arch/arm/mach-sa1100/assabet.c27
-rw-r--r--arch/arm/mach-sa1100/generic.c4
-rw-r--r--arch/arm/mach-sa1100/neponset.c26
-rw-r--r--arch/arm/mach-sa1100/sa1111.c391
-rw-r--r--arch/arm/mm/fault-armv.c2
-rw-r--r--arch/arm/mm/init.c6
-rw-r--r--arch/arm/mm/minicache.c2
-rw-r--r--arch/arm/mm/mm-armv.c85
-rw-r--r--arch/arm/mm/proc-syms.c14
-rw-r--r--arch/arm/mm/tlb-v3.S46
-rw-r--r--arch/arm/mm/tlb-v4.S60
-rw-r--r--arch/arm/mm/tlb-v4wb.S99
-rw-r--r--arch/arm/vmlinux.lds.S4
-rw-r--r--drivers/acorn/block/fd1772.c26
-rw-r--r--drivers/acorn/char/Makefile15
-rw-r--r--drivers/acorn/char/i2c.c4
-rw-r--r--drivers/acorn/char/keyb_ps2.c416
-rw-r--r--drivers/acorn/char/mouse_rpc.c91
-rw-r--r--drivers/acorn/char/serial-atomwide.c23
-rw-r--r--drivers/acorn/char/serial-card.c120
-rw-r--r--drivers/acorn/char/serial-dualsp.c21
-rw-r--r--drivers/acorn/net/ether1.c112
-rw-r--r--drivers/acorn/net/ether3.c124
-rw-r--r--drivers/acorn/net/etherh.c168
-rw-r--r--drivers/acorn/scsi/acornscsi.c16
-rw-r--r--drivers/acorn/scsi/acornscsi.h2
-rw-r--r--drivers/acorn/scsi/cumana_1.c16
-rw-r--r--drivers/acorn/scsi/ecoscsi.c14
-rw-r--r--drivers/acorn/scsi/fas216.c14
-rw-r--r--drivers/acorn/scsi/fas216.h2
-rw-r--r--drivers/acorn/scsi/oak.c12
-rw-r--r--drivers/acorn/scsi/queue.c2
-rw-r--r--drivers/acorn/scsi/queue.h2
-rw-r--r--drivers/acorn/scsi/scsi.h4
-rw-r--r--drivers/mtd/afs.c9
-rw-r--r--drivers/mtd/maps/integrator-flash.c8
-rw-r--r--drivers/pcmcia/sa1100_adsbitsy.c16
-rw-r--r--drivers/pcmcia/sa1100_assabet.c17
-rw-r--r--drivers/pcmcia/sa1100_badge4.c16
-rw-r--r--drivers/pcmcia/sa1100_cerf.c17
-rw-r--r--drivers/pcmcia/sa1100_flexanet.c17
-rw-r--r--drivers/pcmcia/sa1100_freebird.c17
-rw-r--r--drivers/pcmcia/sa1100_generic.c34
-rw-r--r--drivers/pcmcia/sa1100_graphicsclient.c17
-rw-r--r--drivers/pcmcia/sa1100_graphicsmaster.c16
-rw-r--r--drivers/pcmcia/sa1100_h3600.c33
-rw-r--r--drivers/pcmcia/sa1100_jornada720.c16
-rw-r--r--drivers/pcmcia/sa1100_neponset.c16
-rw-r--r--drivers/pcmcia/sa1100_pangolin.c13
-rw-r--r--drivers/pcmcia/sa1100_pfs168.c16
-rw-r--r--drivers/pcmcia/sa1100_shannon.c17
-rw-r--r--drivers/pcmcia/sa1100_simpad.c17
-rw-r--r--drivers/pcmcia/sa1100_stork.c17
-rw-r--r--drivers/pcmcia/sa1100_system3.c16
-rw-r--r--drivers/pcmcia/sa1100_trizeps.c15
-rw-r--r--drivers/pcmcia/sa1100_xp860.c16
-rw-r--r--drivers/pcmcia/sa1100_yopy.c17
-rw-r--r--drivers/serial/8250_acorn.c150
-rw-r--r--drivers/serial/Config.help17
-rw-r--r--drivers/serial/Config.in3
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/video/acornfb.c190
-rw-r--r--drivers/video/acornfb.h3
-rw-r--r--drivers/video/clps711xfb.c174
-rw-r--r--drivers/video/cyber2000fb.c734
-rw-r--r--drivers/video/cyber2000fb.h71
-rw-r--r--fs/adfs/dir_f.c10
-rw-r--r--fs/adfs/dir_fplus.c8
-rw-r--r--include/asm-arm/arch-ebsa285/time.h4
-rw-r--r--include/asm-arm/arch-rpc/ide.h2
-rw-r--r--include/asm-arm/arch-rpc/serial.h2
-rw-r--r--include/asm-arm/arch-rpc/uncompress.h24
-rw-r--r--include/asm-arm/arch-sa1100/irqs.h2
-rw-r--r--include/asm-arm/arch-sa1100/time.h2
-rw-r--r--include/asm-arm/ecard.h29
-rw-r--r--include/asm-arm/glue.h118
-rw-r--r--include/asm-arm/hardirq.h12
-rw-r--r--include/asm-arm/hardware/sa1111.h14
-rw-r--r--include/asm-arm/ide.h1
-rw-r--r--include/asm-arm/numnodes.h17
-rw-r--r--include/asm-arm/page.h64
-rw-r--r--include/asm-arm/pci.h4
-rw-r--r--include/asm-arm/pgalloc.h3
-rw-r--r--include/asm-arm/pgtable.h1
-rw-r--r--include/asm-arm/proc-armo/system.h2
-rw-r--r--include/asm-arm/proc-armv/pgalloc.h1
-rw-r--r--include/asm-arm/proc-armv/tlbflush.h230
-rw-r--r--include/asm-arm/processor.h26
-rw-r--r--include/asm-arm/procinfo.h2
-rw-r--r--include/asm-arm/tlb.h77
112 files changed, 3079 insertions, 2541 deletions
diff --git a/Documentation/arm/XScale/ADIFCC/80200EVB b/Documentation/arm/XScale/ADIFCC/80200EVB
new file mode 100644
index 000000000000..1be2f340eb78
--- /dev/null
+++ b/Documentation/arm/XScale/ADIFCC/80200EVB
@@ -0,0 +1,111 @@
+
+Board Overview
+-----------------------------
+
+This is an beta release of the Xscale Linux port to the ADI 80200EVB
+evaluation board.
+
+The 80200EVB is an evaluation platform for ADI Engineering's high-performance
+80200FCC chipset for the Intel 80200 XScale CPU. The 80200FCC is an open
+source FPGA based system that contains a PCI unit and a high performance
+memory controller.
+
+In addition to the 80200FCC, the board also contains a 16C550 UART, and 4MB
+of flash.
+
+The board is still under development and currently only the UART is functional
+as the PCI bits have not been programmed into the FPGA.
+
+For more information on the board, see http://www.adiengineering.com
+
+Port Status
+-----------------------------
+
+Supported:
+
+- Onboard UART (Polled operation only)
+- Cache/TLB locking on 80200 CPU
+
+TODO:
+
+- PCI when hardware supports it
+
+Building the Kernel
+-----------------------------
+change Linux makefile
+make adi_evb_config
+make oldconfig
+make dep
+make zImage
+
+Loading Linux
+-----------------------------
+
+Before you can use Linux on the ADI board, you need to grab the following:
+
+ADI 80200EVB Monitor:
+ ftp://source.mvista.com/pub/xscale/ADI_EVB/monitor.srec
+
+ADI JFFS2 Image:
+ ftp://source.mvista.com/pub/xscale/ADI_EVB/adi.jffs2
+
+Once you've got the Cygnus prompt, type in the following command:
+
+ load
+
+On another terminal window:
+
+ cat monitor.srec > /dev/ttyS0
+
+(replace ttyS0 with the serial port you are using)
+
+Once completed, just type 'go' at the cygmon prompt and you should see:
+
+ MontaVista IQ80310 Monitor Version 0.1
+ monitor>
+
+Type 'b 115200' at the prompt and change your terminal speed to 115200
+
+The first thing to do is to upload and burn the jffs2 filesystem image
+onto the boards 4MB of flash:
+
+ monitor> u c1000000
+ Uploading file at 0xc1000000
+ Now send file with ymodem
+
+Do as the monitor says and transfer the file adi.jffs2. Once complete,
+the following will copy the jffs2 image to location 0x80000 in the flash.
+
+ monitor> f 8000 c1000000 200000
+ Erasing sector 0x00080000
+ Writing sector 0x00080000 with data at 0xC1000000
+ Erasing sector 0x000A0000
+ Writing sector 0x000A0000 with data at 0xC1020000
+ Erasing sector 0x000C0000
+ ...
+
+Now use the same command as above to upload your zImage to location c1000000.
+When you've done that, type 'j c1000000' to run Linux. Login as
+root and you're all set to go.
+
+Misc Notes
+-----------------------------
+
+The current version of the HW does not have an onboard timer, so the 80200
+PMU is not available for general use as it is being used for a timer source.
+
+By default, the MTD driver reserves the first 512K for bootloaders and
+the remaining 3.5MB for the filesystem. You can edit drivers/mtd/map/adi_evb.c
+to change this as needed for your application.
+
+Contributors
+-----------------------------
+
+Thanks to ADI Engineering for providing the hardware for development
+
+Deepak Saxena <dsaxena@mvista.com> - Initial port
+
+-----------------------------
+Enjoy. If you have any problem please contact Deepak Saxena
+dsaxena@mvista.com
+
diff --git a/Documentation/arm/XScale/IOP310/IQ80310 b/Documentation/arm/XScale/IOP310/IQ80310
new file mode 100644
index 000000000000..4284d458e6f9
--- /dev/null
+++ b/Documentation/arm/XScale/IOP310/IQ80310
@@ -0,0 +1,295 @@
+
+Board Overview
+-----------------------------
+
+The Cyclone IQ80310 board is an evaluation platform for Intel's 80200 Xscale
+CPU and 80312 Intelligent I/O chipset (collectively called IOP310 chipset).
+
+The 80312 contains dual PCI hoses (called the ATUs), a PCI-to-PCI bridge,
+three DMA channels (1 on secondary PCI, one on primary PCI ), I2C, I2O
+messaging unit, XOR unit for RAID operations, a bus performance monitoring
+unit, and a memory controller with ECC features.
+
+For more information on the board, see http://developer.intel.com/iio
+
+Port Status
+-----------------------------
+
+Supported:
+
+- MTD/JFFS/JFFS2
+- NFS root
+- RAMDISK root
+- 2ndary PCI slots
+- Onboard ethernet
+- Serial ports (ttyS0/S1)
+- Cache/TLB locking on 80200 CPU
+- Performance monitoring unit on 80200 CPU
+- 80200 Performance Monitoring Unit
+- Acting as a system controller on Cyclone 80303BP PCI backplane
+- DMA engines (EXPERIMENTAL)
+- 80312 Bus Performance Monitor (EXPERIMENTAL)
+- Application Accelerator Unit (XOR engine for RAID) (EXPERIMENTAL)
+- Messaging Unit (EXPERIMENTAL)
+
+TODO:
+- I2C
+
+Building the Kernel
+-----------------------------
+make iq80310_config
+make oldconfig
+make dep
+make zImage
+
+This will build an image setup for BOOTP/NFS root support. To change this,
+just run make menuconfig and disable nfs root or add a "root=" option.
+
+Preparing the Hardware
+-----------------------------
+
+This document assumes you're using a Rev D or newer board running
+Redboot as the bootloader.
+
+The as-supplied RedBoot image appears to leave the first page of RAM
+in a corrupt state such that certain words in that page are unwritable
+and contain random data. The value of the data, and the location within
+the first page changes with each boot, but is generally in the range
+0xa0000150 to 0xa0000fff.
+
+You can grab the source from the ECOS CVS or you can get a prebuilt image
+from:
+
+ ftp://source.mvista.com/pub/xscale/iop310/IQ80310/redboot.bin
+
+which is:
+
+ # strings redboot.bin | grep bootstrap
+ RedBoot(tm) bootstrap and debug environment, version UNKNOWN - built 14:58:21, Aug 15 2001
+
+md5sum of this version:
+
+ bcb96edbc6f8e55b16c165930b6e4439 redboot.bin
+
+You have two options to program it:
+
+1. Using the FRU program (see the instructions in the user manual).
+
+2. Using a Linux host, with MTD support built into the host kernel:
+ - ensure that the RedBoot image is not locked (issue the following
+ command under the existing RedBoot image):
+ RedBoot> fis unlock -f 0 -l 0x40000
+ - switch S3-1 and S3-2 on.
+ - reboot the host
+ - login as root
+ - identify the 80310 card:
+ # lspci
+ ...
+ 00:0c.1 Memory controller: Intel Corporation 80310 IOP [IO Processor] (rev 01)
+ - in this example, bus 0, slot 0c, function 1.
+ - insert the MTD modules, and the PCI map module:
+ # insmod drivers/mtd/maps/pci.o
+ - locate the MTD device (using the bus, slot, function)
+ # cat /proc/mtd
+ dev: size erasesize name
+ mtd0: 00800000 00020000 "00:0c.1"
+ - in this example, it is mtd device 0. Yours will be different.
+ Check carefully.
+ - program the flash
+ # cat redboot.bin > /dev/mtdblock0
+ - check the kernel message log for errors (some cat commands don't
+ error on failure)
+ # dmesg
+ - switch S3-1 and S3-2 off
+ - reboot host
+
+In any case, make sure you do an 'fis init' command once you boot with the new
+RedBoot image.
+
+
+
+Downloading Linux
+-----------------------------
+
+Assuming you have your development system setup to act as a bootp/dhcp
+server and running tftp:
+
+ RedBoot> load -r -b 0xa1008000 /tftpboot/zImage.xs
+ Raw file loaded 0xa1008000-0xa1094bd8
+
+If you're not using dhcp/tftp, you can use y-modem instead:
+
+ RedBoot> load -r -b 0xa1008000 -m y
+
+Note that on Rev D. of the board, tftp does not work due to intermittent
+interrupt issues, so you need to download using ymodem.
+
+Once the download is completed:
+
+ RedBoot> go 0xa1008000
+
+Root Devices
+-----------------------------
+
+A kernel is not useful without a root filesystem, and you have several
+choices with this board: NFS root, RAMDISK, or JFFS/JFFS2. For development
+purposes, it is suggested that you use NFS root for easy access to various
+tools. Once you're ready to deploy, probably want to utilize JFFS/JFFS2 on
+the flash device.
+
+MTD on the IQ80310
+-----------------------------
+
+Linux on the IQ80310 supports RedBoot FIS paritioning if it is enabled.
+Out of the box, once you've done 'fis init' on RedBoot, you will get
+the following partitioning scheme:
+
+ root@192.168.0.14:~# cat /proc/mtd
+ dev: size erasesize name
+ mtd0: 00040000 00020000 "RedBoot"
+ mtd1: 00040000 00020000 "RedBoot[backup]"
+ mtd2: 0075f000 00020000 "unallocated space"
+ mtd3: 00001000 00020000 "RedBoot config"
+ mtd4: 00020000 00020000 "FIS directory"
+
+To create an FIS directory, you need to use the fis command in RedBoot.
+As an example, you can burn the kernel into the flash once it's downloaded:
+
+ RedBoot> fis create -b 0xa1008000 -l 0x8CBAC -r 0xa1008000 -f 0x80000 kernel
+ ... Erase from 0x00080000-0x00120000: .....
+ ... Program from 0xa1008000-0xa1094bac at 0x00080000: .....
+ ... Unlock from 0x007e0000-0x00800000: .
+ ... Erase from 0x007e0000-0x00800000: .
+ ... Program from 0xa1fdf000-0xa1fff000 at 0x007e0000: .
+ ... Lock from 0x007e0000-0x00800000: .
+
+ RedBoot> fis list
+ Name FLASH addr Mem addr Length Entry point
+ RedBoot 0x00000000 0x00000000 0x00040000 0x00000000
+ RedBoot[backup] 0x00040000 0x00040000 0x00040000 0x00000000
+ RedBoot config 0x007DF000 0x007DF000 0x00001000 0x00000000
+ FIS directory 0x007E0000 0x007E0000 0x00020000 0x00000000
+ kernel 0x00080000 0xA1008000 0x000A0000 0x00000000
+
+This leads to the following Linux MTD setup:
+
+ mtroot@192.168.0.14:~# cat /proc/mtd
+ dev: size erasesize name
+ mtd0: 00040000 00020000 "RedBoot"
+ mtd1: 00040000 00020000 "RedBoot[backup]"
+ mtd2: 000a0000 00020000 "kernel"
+ mtd3: 006bf000 00020000 "unallocated space"
+ mtd4: 00001000 00020000 "RedBoot config"
+ mtd5: 00020000 00020000 "FIS directory"
+
+Note that there is not a 1:1 mapping to the number of RedBoot paritions to
+MTD partitions as unused space also gets allocated into MTD partitions.
+
+As an aside, the -r option when creating the Kernel entry allows you to
+simply do an 'fis load kernel' to copy the image from flash into memory.
+You can then do an 'fis go 0xa1008000' to start Linux.
+
+If you choose to use static partitioning instead of the RedBoot partioning:
+
+ /dev/mtd0 0x00000000 - 0x0007ffff: Boot Monitor (512k)
+ /dev/mtd1 0x00080000 - 0x0011ffff: Kernel Image (640K)
+ /dev/mtd2 0x00120000 - 0x0071ffff: File System (6M)
+ /dev/mtd3 0x00720000 - 0x00800000: RedBoot Reserved (896K)
+
+To use a JFFS1/2 root FS, you need to donwload the JFFS image using either
+tftp or ymodem, and then copy it to flash:
+
+ RedBoot> load -r -b 0xa1000000 /tftpboot/jffs.img
+ Raw file loaded 0xa1000000-0xa1600000
+ RedBoot> fis create -b 0xa1000000 -l 0x600000 -f 0x120000 jffs
+ ... Erase from 0x00120000-0x00720000: ..................................
+ ... Program from 0xa1000000-0xa1600000 at 0x00120000: ..................
+ ......................
+ ... Unlock from 0x007e0000-0x00800000: .
+ ... Erase from 0x007e0000-0x00800000: .
+ ... Program from 0xa1fdf000-0xa1fff000 at 0x007e0000: .
+ ... Lock from 0x007e0000-0x00800000: .
+ RedBoot> fis list
+ Name FLASH addr Mem addr Length Entry point
+ RedBoot 0x00000000 0x00000000 0x00040000 0x00000000
+ RedBoot[backup] 0x00040000 0x00040000 0x00040000 0x00000000
+ RedBoot config 0x007DF000 0x007DF000 0x00001000 0x00000000
+ FIS directory 0x007E0000 0x007E0000 0x00020000 0x00000000
+ kernel 0x00080000 0xA1008000 0x000A0000 0xA1008000
+ jffs 0x00120000 0x00120000 0x00600000 0x00000000
+
+This looks like this in Linux:
+
+ root@192.168.0.14:~# cat /proc/mtd
+ dev: size erasesize name
+ mtd0: 00040000 00020000 "RedBoot"
+ mtd1: 00040000 00020000 "RedBoot[backup]"
+ mtd2: 000a0000 00020000 "kernel"
+ mtd3: 00600000 00020000 "jffs"
+ mtd4: 000bf000 00020000 "unallocated space"
+ mtd5: 00001000 00020000 "RedBoot config"
+ mtd6: 00020000 00020000 "FIS directory"
+
+You need to boot the kernel once and watch the boot messages to see how the
+JFFS RedBoot partition mapped into the MTD partition scheme.
+
+You can grab a pre-built JFFS image to use as a root file system at:
+
+ ftp://source.mvista.com/pub/xscale/iop310/IQ80310/jffs.img
+
+For detailed info on using MTD and creating a JFFS image go to:
+
+ http://www.linux-mtd.infradead.org.
+
+For details on using RedBoot's FIS commands, type 'fis help' or consult
+your RedBoot manual.
+
+Contributors
+-----------------------------
+
+Thanks to Intel Corporation for providing the hardware.
+
+John Clark <jclark@teamasa.com> - Initial discovery of RedBoot issues
+Dave Jiang <dave.jiang@intel.com> - IRQ demux fixes, AAU, DMA, MU
+Nicolas Pitre <nico@cam.org> - Initial port, cleanup, debugging
+Matt Porter <mporter@mvista.com> - PCI subsystem development, debugging
+Tim Sanders <tsanders@sanders.org> - Initial PCI code
+Mark Salter <msalter@redhat.com> - RedBoot fixes
+Deepak Saxena <dsaxena@mvista.com> - Cleanup, debug, cache lock, PMU
+
+-----------------------------
+Enjoy.
+
+If you have any problems please contact Deepak Saxena <dsaxena@mvista.com>
+
+A few notes from rmk
+-----------------------------
+
+These are notes of my initial experience getting the IQ80310 Rev D up and
+running. In total, it has taken many hours to work out what's going on...
+The version of redboot used is:
+
+ RedBoot(tm) bootstrap and debug environment, version UNKNOWN - built 14:58:21, Aug 15 2001
+
+
+1. I've had a corrupted download of the redboot.bin file from Montavista's
+ FTP site. It would be a good idea if there were md5sums, sum or gpg
+ signatures available to ensure the integrity of the downloaded files.
+ The result of this was an apparantly 100% dead card.
+
+2. RedBoot Intel EtherExpress Pro 100 driver seems to be very unstable -
+ I've had it take out the whole of a 100mbit network for several minutes.
+ The Hub indiates ZERO activity, despite machines attempting to communicate.
+ Further to this, while tftping the kernel, the transfer will stall regularly,
+ and might even drop the link LED.
+
+3. There appears to be a bug in the Intel Documentation Pack that comes with
+ the IQ80310 board. Serial port 1, which is the socket next to the LEDs
+ is address 0xfe810000, not 0xfe800000.
+
+ Note that RedBoot uses either serial port 1 OR serial port 2, so if you
+ have your console connected to the wrong port, you'll see redboot messages
+ but not kernel boot messages.
+
+4. Trying to use fconfig to setup a boot script fails - it hangs when trying
+ to erase the flash.
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index d57501118e68..c38ea2d36835 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -8,6 +8,7 @@
# Copyright (C) 1995-2001 by Russell King
LDFLAGS_vmlinux :=-p -X
+AFLAGS_vmlinux.lds.o = -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
OBJCOPYFLAGS :=-O binary -R .note -R .comment -S
GZFLAGS :=-9
#CFLAGS +=-pipe
@@ -50,18 +51,29 @@ tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
tune-$(CONFIG_CPU_XSCALE) :=-mtune=strongarm #-mtune=xscale
-CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
-CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
-AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float
+# Force -mno-fpu to be passed to the assembler. Some versions of gcc don't
+# do this with -msoft-float
+CFLAGS_BOOT :=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu
+CFLAGS +=$(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float -Wa,-mno-fpu
+AFLAGS +=$(apcs-y) $(arch-y) -mno-fpu -msoft-float -Wa,-mno-fpu
ifeq ($(CONFIG_CPU_26),y)
PROCESSOR := armo
HEAD := arch/arm/mach-arc/head.o arch/arm/kernel/init_task.o
+ ifeq ($(CONFIG_ROM_KERNEL),y)
+ DATAADDR = 0x02080000
+ TEXTADDR = 0x03800000
+ LDSCRIPT = arch/arm/vmlinux-armo-rom.lds.in
+ else
+ TEXTADDR = 0x02080000
+ LDSCRIPT = arch/arm/vmlinux-armo.lds.in
+ endif
endif
ifeq ($(CONFIG_CPU_32),y)
PROCESSOR = armv
HEAD := arch/arm/kernel/head.o arch/arm/kernel/init_task.o
+TEXTADDR = 0xC0008000
endif
ifeq ($(CONFIG_ARCH_ARCA5K),y)
@@ -175,7 +187,7 @@ core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/
-drivers-$(CONFIG_ARCH_L7200)) += drivers/acorn/char/
+drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/
libs-y += arch/arm/lib/
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 67278fa673f1..7078453e2c44 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -18,7 +18,7 @@ ZLDFLAGS = -p -X -T vmlinux.lds
#
ifeq ($(CONFIG_ARCH_ACORN),y)
OBJS += ll_char_wr.o font.o
-ZLDFLAGS += -defsym params=$(PARAMS_PHYS)
+CFLAGS += -DPARAMS_PHYS=$(PARAMS_PHYS)
endif
ifeq ($(CONFIG_ARCH_NETWINDER),y)
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index 4f22cecbb047..824831c320b0 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -55,6 +55,18 @@
.macro writeb, rb
strb \rb, [r3, #0]
.endm
+#elif defined(CONFIG_ARCH_SA1100)
+ .macro loadsp, rb
+ mov \rb, #0x80000000 @ physical base address
+# if defined(CONFIG_DEBUG_LL_SER3)
+ add \rb, \rb, #0x00050000 @ Ser3
+# else
+ add \rb, \rb, #0x00010000 @ Ser1
+# endif
+ .endm
+ .macro writeb, rb
+ str \rb, [r3, #0x14] @ UTDR
+ .endm
#else
#error no serial architecture defined
#endif
@@ -151,22 +163,55 @@ not_angel:
ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp}
subs r0, r0, r1 @ calculate the delta offset
- teq r0, #0 @ if delta is zero, we're
+ @ if delta is zero, we're
beq not_relocated @ running at the address we
@ were linked at.
- add r2, r2, r0 @ different address, so we
- add r3, r3, r0 @ need to fix up various
- add r5, r5, r0 @ pointers.
+ /*
+ * We're running at a different address. We need to fix
+ * up various pointers:
+ * r5 - zImage base address
+ * r6 - GOT start
+ * ip - GOT end
+ */
+ add r5, r5, r0
add r6, r6, r0
add ip, ip, r0
+
+#ifndef CONFIG_ZBOOT_ROM
+ /*
+ * If we're running fully PIC === CONFIG_ZBOOT_ROM = n,
+ * we need to fix up pointers into the BSS region.
+ * r2 - BSS start
+ * r3 - BSS end
+ * sp - stack pointer
+ */
+ add r2, r2, r0
+ add r3, r3, r0
add sp, sp, r0
+ /*
+ * Relocate all entries in the GOT table.
+ */
1: ldr r1, [r6, #0] @ relocate entries in the GOT
add r1, r1, r0 @ table. This fixes up the
str r1, [r6], #4 @ C references.
cmp r6, ip
blo 1b
+#else
+
+ /*
+ * Relocate entries in the GOT table. We only relocate
+ * the entries that are outside the (relocated) BSS region.
+ */
+1: ldr r1, [r6, #0] @ relocate entries in the GOT
+ cmp r1, r2 @ entry < bss_start ||
+ cmphs r3, r1 @ _end < entry
+ addlo r1, r1, r0 @ table. This fixes up the
+ str r1, [r6], #4 @ C references.
+ cmp r6, ip
+ blo 1b
+#endif
not_relocated: mov r0, #0
1: str r0, [r2], #4 @ clear bss
@@ -176,6 +221,11 @@ not_relocated: mov r0, #0
cmp r2, r3
blo 1b
+ /*
+ * The C runtime environment should now be setup
+ * sufficiently. Turn the cache on, set up some
+ * pointers, and start decompressing.
+ */
bl cache_on
mov r1, sp @ malloc space above stack
diff --git a/arch/arm/boot/compressed/ll_char_wr.S b/arch/arm/boot/compressed/ll_char_wr.S
index c25ce8129aa6..d7bbd9da2fca 100644
--- a/arch/arm/boot/compressed/ll_char_wr.S
+++ b/arch/arm/boot/compressed/ll_char_wr.S
@@ -19,144 +19,116 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
- .text
+ .text
-#define BOLD 0x01
-#define ITALIC 0x02
-#define UNDERLINE 0x04
-#define FLASH 0x08
-#define INVERSE 0x10
-
-LC0: .word bytes_per_char_h
- .word video_size_row
- .word acorndata_8x8
- .word con_charconvtable
+LC0: .word LC0
+ .word bytes_per_char_h
+ .word video_size_row
+ .word acorndata_8x8
+ .word con_charconvtable
+/*
+ * r0 = ptr
+ * r1 = char
+ * r2 = white
+ */
ENTRY(ll_write_char)
- stmfd sp!, {r4 - r7, lr}
+ stmfd sp!, {r4 - r7, lr}
@
@ Smashable regs: {r0 - r3}, [r4 - r7], (r8 - fp), [ip], (sp), [lr], (pc)
@
- eor ip, r1, #UNDERLINE << 9
-/*
- * calculate colours
- */
- tst r1, #INVERSE << 9
- moveq r2, r1, lsr #16
- moveq r3, r1, lsr #24
- movne r2, r1, lsr #24
- movne r3, r1, lsr #16
- and r3, r3, #255
- and r2, r2, #255
-/*
- * calculate offset into character table
- */
- mov r1, r1, lsl #23
- mov r1, r1, lsr #20
-/*
- * calculate offset required for each row [maybe I should make this an argument to this fn.
- * Have to see what the register usage is like in the calling routines.
- */
- adr r4, LC0
- ldmia r4, {r4, r5, r6, lr}
- ldr r4, [r4]
- ldr r5, [r5]
-/*
- * Go to resolution-dependent routine...
- */
- cmp r4, #4
- blt Lrow1bpp
- eor r2, r3, r2 @ Create eor mask to change colour from bg
- orr r3, r3, r3, lsl #8 @ to fg.
- orr r3, r3, r3, lsl #16
- add r0, r0, r5, lsl #3 @ Move to bottom of character
- add r1, r1, #7
- ldrb r7, [r6, r1]
- tst ip, #UNDERLINE << 9
- eoreq r7, r7, #255
- teq r4, #8
- beq Lrow8bpplp
+ /*
+ * calculate offset into character table
+ */
+ mov r1, r1, lsl #3
+ /*
+ * calculate offset required for each row.
+ */
+ adr ip, LC0
+ ldmia ip, {r3, r4, r5, r6, lr}
+ sub ip, ip, r3
+ add r6, r6, ip
+ add lr, lr, ip
+ ldr r4, [r4, ip]
+ ldr r5, [r5, ip]
+ /*
+ * Go to resolution-dependent routine...
+ */
+ cmp r4, #4
+ blt Lrow1bpp
+ add r0, r0, r5, lsl #3 @ Move to bottom of character
+ orr r1, r1, #7
+ ldrb r7, [r6, r1]
+ teq r4, #8
+ beq Lrow8bpplp
@
@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc)
@
- orr r3, r3, r3, lsl #4
-Lrow4bpplp: ldr r7, [lr, r7, lsl #2]
- mul r7, r2, r7
- tst r1, #7 @ avoid using r7 directly after
- eor ip, r3, r7
- str ip, [r0, -r5]!
- LOADREGS(eqfd, sp!, {r4 - r7, pc})
- sub r1, r1, #1
- ldrb r7, [r6, r1]
- ldr r7, [lr, r7, lsl #2]
- mul r7, r2, r7
- tst r1, #7 @ avoid using r7 directly after
- eor ip, r3, r7
- str ip, [r0, -r5]!
- subne r1, r1, #1
- ldrneb r7, [r6, r1]
- bne Lrow4bpplp
- LOADREGS(fd, sp!, {r4 - r7, pc})
+Lrow4bpplp:
+ ldr r7, [lr, r7, lsl #2]
+ mul r7, r2, r7
+ sub r1, r1, #1 @ avoid using r7 directly after
+ str r7, [r0, -r5]!
+ ldrb r7, [r6, r1]
+ ldr r7, [lr, r7, lsl #2]
+ mul r7, r2, r7
+ tst r1, #7 @ avoid using r7 directly after
+ str r7, [r0, -r5]!
+ subne r1, r1, #1
+ ldrneb r7, [r6, r1]
+ bne Lrow4bpplp
+ LOADREGS(fd, sp!, {r4 - r7, pc})
@
@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc)
@
-Lrow8bpplp: mov ip, r7, lsr #4
- ldr ip, [lr, ip, lsl #2]
- mul r4, r2, ip
- and ip, r7, #15 @ avoid r4
- ldr ip, [lr, ip, lsl #2] @ avoid r4
- mul ip, r2, ip @ avoid r4
- eor r4, r3, r4 @ avoid ip
- tst r1, #7 @ avoid ip
- sub r0, r0, r5 @ avoid ip
- eor ip, r3, ip
- stmia r0, {r4, ip}
- LOADREGS(eqfd, sp!, {r4 - r7, pc})
- sub r1, r1, #1
- ldrb r7, [r6, r1]
- mov ip, r7, lsr #4
- ldr ip, [lr, ip, lsl #2]
- mul r4, r2, ip
- and ip, r7, #15 @ avoid r4
- ldr ip, [lr, ip, lsl #2] @ avoid r4
- mul ip, r2, ip @ avoid r4
- eor r4, r3, r4 @ avoid ip
- tst r1, #7 @ avoid ip
- sub r0, r0, r5 @ avoid ip
- eor ip, r3, ip
- stmia r0, {r4, ip}
- subne r1, r1, #1
- ldrneb r7, [r6, r1]
- bne Lrow8bpplp
- LOADREGS(fd, sp!, {r4 - r7, pc})
+Lrow8bpplp:
+ mov ip, r7, lsr #4
+ ldr ip, [lr, ip, lsl #2]
+ mul r4, r2, ip
+ and ip, r7, #15 @ avoid r4
+ ldr ip, [lr, ip, lsl #2] @ avoid r4
+ mul ip, r2, ip @ avoid r4
+ sub r1, r1, #1 @ avoid ip
+ sub r0, r0, r5 @ avoid ip
+ stmia r0, {r4, ip}
+ ldrb r7, [r6, r1]
+ mov ip, r7, lsr #4
+ ldr ip, [lr, ip, lsl #2]
+ mul r4, r2, ip
+ and ip, r7, #15 @ avoid r4
+ ldr ip, [lr, ip, lsl #2] @ avoid r4
+ mul ip, r2, ip @ avoid r4
+ tst r1, #7 @ avoid ip
+ sub r0, r0, r5 @ avoid ip
+ stmia r0, {r4, ip}
+ subne r1, r1, #1
+ ldrneb r7, [r6, r1]
+ bne Lrow8bpplp
+ LOADREGS(fd, sp!, {r4 - r7, pc})
@
@ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc)
@
-Lrow1bpp: add r6, r6, r1
- ldmia r6, {r4, r7}
- tst ip, #INVERSE << 9
- mvnne r4, r4
- mvnne r7, r7
- strb r4, [r0], r5
- mov r4, r4, lsr #8
- strb r4, [r0], r5
- mov r4, r4, lsr #8
- strb r4, [r0], r5
- mov r4, r4, lsr #8
- strb r4, [r0], r5
- strb r7, [r0], r5
- mov r7, r7, lsr #8
- strb r7, [r0], r5
- mov r7, r7, lsr #8
- strb r7, [r0], r5
- mov r7, r7, lsr #8
- tst ip, #UNDERLINE << 9
- mvneq r7, r7
- strb r7, [r0], r5
- LOADREGS(fd, sp!, {r4 - r7, pc})
+Lrow1bpp:
+ add r6, r6, r1
+ ldmia r6, {r4, r7}
+ strb r4, [r0], r5
+ mov r4, r4, lsr #8
+ strb r4, [r0], r5
+ mov r4, r4, lsr #8
+ strb r4, [r0], r5
+ mov r4, r4, lsr #8
+ strb r4, [r0], r5
+ strb r7, [r0], r5
+ mov r7, r7, lsr #8
+ strb r7, [r0], r5
+ mov r7, r7, lsr #8
+ strb r7, [r0], r5
+ mov r7, r7, lsr #8
+ strb r7, [r0], r5
+ LOADREGS(fd, sp!, {r4 - r7, pc})
- .bss
+ .bss
ENTRY(con_charconvtable)
- .space 1024
+ .space 1024
diff --git a/arch/arm/config.in b/arch/arm/config.in
index 635874b18bfc..9e6605c5a4e4 100644
--- a/arch/arm/config.in
+++ b/arch/arm/config.in
@@ -94,6 +94,8 @@ if [ "$CONFIG_ASSABET_NEPONSET" = "y" -o \
"$CONFIG_SA1100_XP860" = "y" ]; then
define_bool CONFIG_SA1111 y
define_int CONFIG_FORCE_MAX_ZONEORDER 9
+else
+ define_bool CONFIG_SA1111 n
fi
comment 'Processor Type'
@@ -231,6 +233,8 @@ if [ "$CONFIG_CPU_ARM720T" = "y" -o "$CONFIG_CPU_ARM920T" = "y" -o \
"$CONFIG_CPU_ARM922T" = "y" -o "$CONFIG_CPU_ARM926T" = "y" -o \
"$CONFIG_CPU_ARM1020" = "y" -o "$CONFIG_CPU_XSCALE" = "y" ]; then
dep_bool 'Support Thumb instructions (EXPERIMENTAL)' CONFIG_ARM_THUMB $CONFIG_EXPERIMENTAL
+else
+ define_bool CONFIG_ARM_THUMB n
fi
if [ "$CONFIG_CPU_ARM920T" = "y" -o "$CONFIG_CPU_ARM922T" = "y" -o \
"$CONFIG_CPU_ARM926T" = "y" -o "$CONFIG_CPU_ARM1020" = "y" ]; then
diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c
index e1e97a8b7bce..ba96bea03746 100644
--- a/arch/arm/kernel/arch.c
+++ b/arch/arm/kernel/arch.c
@@ -8,6 +8,7 @@
#include <linux/types.h>
#include <asm/elf.h>
+#include <asm/page.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 201f14368eb2..8b359fa51a47 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -599,7 +599,7 @@ void pcibios_align_resource(void *data, struct resource *res,
* pcibios_enable_device - Enable I/O and memory.
* @dev: PCI device to be enabled
*/
-int pcibios_enable_device(struct pci_dev *dev)
+int pcibios_enable_device(struct pci_dev *dev, int mask)
{
u16 cmd, old_cmd;
int idx;
@@ -608,6 +608,10 @@ int pcibios_enable_device(struct pci_dev *dev)
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
for (idx = 0; idx < 6; idx++) {
+ /* Only set up the requested stuff */
+ if (!(mask & (1 << idx)))
+ continue;
+
r = dev->resource + idx;
if (!r->start && r->end) {
printk(KERN_ERR "PCI: Device %s not available because"
@@ -626,3 +630,29 @@ int pcibios_enable_device(struct pci_dev *dev)
}
return 0;
}
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ struct pci_sys_data *root = dev->sysdata;
+ unsigned long prot, phys;
+
+ if (mmap_state == pci_mmap_io) {
+ return -EINVAL;
+ } else {
+ phys = root->mem_offset + (vma->vm_pgoff << PAGE_SHIFT);
+ }
+
+ /*
+ * Mark this as IO
+ */
+ vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_page_range(vma, vma->vm_start, phys,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot))
+ return -EAGAIN;
+
+ return 0;
+}
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 4a4d89003ecc..4cb68c31b86e 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -38,6 +38,7 @@
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/notifier.h>
+#include <linux/device.h>
#include <linux/init.h>
#include <asm/dma.h>
@@ -48,6 +49,7 @@
#include <asm/pgalloc.h>
#include <asm/mmu_context.h>
#include <asm/mach/irq.h>
+#include <asm/tlbflush.h>
#ifndef CONFIG_ARCH_RPC
#define HAVE_EXPMASK
@@ -92,6 +94,8 @@ ecard_loader_reset(volatile unsigned char *pa, loader_t loader);
asmlinkage extern int
ecard_loader_read(int off, volatile unsigned char *pa, loader_t loader);
+static const struct ecard_id *
+ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec);
static inline unsigned short
ecard_getu16(unsigned char *v)
@@ -969,6 +973,14 @@ ecard_probe(int slot, card_type_t type)
*ecp = ec;
slot_to_expcard[slot] = ec;
+
+ snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
+ strcpy(ec->dev.name, "fixme!");
+ ec->dev.parent = NULL;
+ ec->dev.bus = &ecard_bus_type;
+
+ device_register(&ec->dev);
+
return 0;
nodev:
@@ -995,22 +1007,17 @@ ecard_t *ecard_find(int cid, const card_ids *cids)
if (finding_pos->claimed)
continue;
+ if (finding_pos->dev.driver)
+ continue;
+
if (!cids) {
if ((finding_pos->cid.id ^ cid) == 0)
break;
} else {
- unsigned int manufacturer, product;
- int i;
-
- manufacturer = finding_pos->cid.manufacturer;
- product = finding_pos->cid.product;
-
- for (i = 0; cids[i].manufacturer != 65535; i++)
- if (manufacturer == cids[i].manufacturer &&
- product == cids[i].product)
- break;
+ const struct ecard_id *id;
- if (cids[i].manufacturer != 65535)
+ id = ecard_match_device(cids, finding_pos);
+ if (id)
break;
}
}
@@ -1023,7 +1030,7 @@ ecard_t *ecard_find(int cid, const card_ids *cids)
* Locate all hardware - interrupt management and
* actual cards.
*/
-void __init ecard_init(void)
+static int __init ecard_init(void)
{
int slot, irqhw;
@@ -1053,11 +1060,96 @@ void __init ecard_init(void)
irqhw ? ecard_irqexp_handler : ecard_irq_handler);
ecard_proc_init();
+
+ return 0;
}
subsys_initcall(ecard_init);
+/*
+ * ECARD "bus"
+ */
+static const struct ecard_id *
+ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec)
+{
+ int i;
+
+ for (i = 0; ids[i].manufacturer != 65535; i++)
+ if (ec->cid.manufacturer == ids[i].manufacturer &&
+ ec->cid.product == ids[i].product)
+ return ids + i;
+
+ return NULL;
+}
+
+static int ecard_drv_probe(struct device *dev)
+{
+ struct expansion_card *ec = ECARD_DEV(dev);
+ struct ecard_driver *drv = ECARD_DRV(dev->driver);
+ const struct ecard_id *id;
+
+ id = ecard_match_device(drv->id_table, ec);
+
+ return drv->probe(ec, id);
+}
+
+static int ecard_drv_remove(struct device *dev)
+{
+ struct expansion_card *ec = ECARD_DEV(dev);
+ struct ecard_driver *drv = ECARD_DRV(dev->driver);
+
+ drv->remove(ec);
+
+ return 0;
+}
+
+int ecard_register_driver(struct ecard_driver *drv)
+{
+ drv->drv.bus = &ecard_bus_type;
+ drv->drv.probe = ecard_drv_probe;
+ drv->drv.remove = ecard_drv_remove;
+
+ return driver_register(&drv->drv);
+}
+
+void ecard_remove_driver(struct ecard_driver *drv)
+{
+ remove_driver(&drv->drv);
+}
+
+static int ecard_match(struct device *_dev, struct device_driver *_drv)
+{
+ struct expansion_card *ec = ECARD_DEV(_dev);
+ struct ecard_driver *drv = ECARD_DRV(_drv);
+ int ret;
+
+ if (drv->id_table) {
+ ret = ecard_match_device(drv->id_table, ec) != NULL;
+ } else {
+ ret = ec->cid.id == drv->id;
+ }
+
+ return ret;
+}
+
+struct bus_type ecard_bus_type = {
+ .name = "ecard",
+ .match = ecard_match,
+};
+
+static int ecard_bus_init(void)
+{
+ return bus_register(&ecard_bus_type);
+}
+
+postcore_initcall(ecard_bus_init);
+
EXPORT_SYMBOL(ecard_startfind);
EXPORT_SYMBOL(ecard_find);
EXPORT_SYMBOL(ecard_readchunk);
EXPORT_SYMBOL(ecard_address);
+
+EXPORT_SYMBOL(ecard_register_driver);
+EXPORT_SYMBOL(ecard_remove_driver);
+
+EXPORT_SYMBOL(ecard_bus_type);
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index e1c42aa3ec1e..3bafe5bb1c97 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -189,11 +189,10 @@ irq_prio_ld: .byte 40,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
mov r4, #0xe0000000
- orr r4, r4, #0x20
mov \irqstat, #0x0C
- strb \irqstat, [r4] @outb(0x0C, 0x20) /* Poll command */
- ldrb \irqnr, [r4] @irq = inb(0x20) & 7
+ strb \irqstat, [r4, #0x20] @outb(0x0C, 0x20) /* Poll command */
+ ldrb \irqnr, [r4, #0x10] @irq = inb(0x20) & 7
and \irqstat, \irqnr, #0x80
teq \irqstat, #0
beq 43f
@@ -201,8 +200,8 @@ irq_prio_ld: .byte 40,40,41,40,42,42,42,42,43,43,43,43,43,43,43,43
teq \irqnr, #2
bne 44f
43: mov \irqstat, #0x0C
- strb \irqstat, [r4, #0x80] @outb(0x0C, 0xA0) /* Poll command */
- ldrb \irqnr, [r4, #0x80] @irq = (inb(0xA0) & 7) + 8
+ strb \irqstat, [r4, #0xa0] @outb(0x0C, 0xA0) /* Poll command */
+ ldrb \irqnr, [r4, #0xa0] @irq = (inb(0xA0) & 7) + 8
and \irqstat, \irqnr, #0x80
teq \irqstat, #0
beq 44f
@@ -655,7 +654,7 @@ __und_invalid: sub sp, sp, #S_FRAME_SIZE
and r2, r6, #31 @ int mode
b bad_mode
-#if defined CONFIG_FPE_NWFPE || defined CONFIG_FPE_FASTFPE
+#if 1 /* defined CONFIG_FPE_NWFPE || defined CONFIG_FPE_FASTFPE */
/* The FPE is always present */
.equ fpe_not_present, fpundefinstr
#else
@@ -766,6 +765,8 @@ preempt_return:
msr spsr, r0
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
+ .ltorg
+
#ifdef CONFIG_PREEMPT
svc_preempt: teq r9, #0 @ was preempt count = 0
ldreq r6, .LCirq_stat
@@ -902,6 +903,8 @@ __irq_usr: sub sp, sp, #S_FRAME_SIZE
mov why, #0
b ret_to_user
+ .ltorg
+
.align 5
__und_usr: sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmia sp, {r0 - r12} @ Save r0 - r12
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index eff2a147014b..cff2f0508439 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -367,8 +367,8 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->u_debugreg[0] = tsk->thread.debug.bp[0].address;
dump->u_debugreg[1] = tsk->thread.debug.bp[1].address;
- dump->u_debugreg[2] = tsk->thread.debug.bp[0].insn;
- dump->u_debugreg[3] = tsk->thread.debug.bp[1].insn;
+ dump->u_debugreg[2] = tsk->thread.debug.bp[0].insn.arm;
+ dump->u_debugreg[3] = tsk->thread.debug.bp[1].insn.arm;
dump->u_debugreg[4] = tsk->thread.debug.nsaved;
if (dump->start_stack < 0x04000000)
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 65a96d722b29..8e4b131eff89 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -32,10 +32,24 @@
* in exit.c or in signal.c.
*/
+#if 1
/*
* Breakpoint SWI instruction: SWI &9F0001
*/
#define BREAKINST_ARM 0xef9f0001
+#define BREAKINST_THUMB 0xdf00 /* fill this in later */
+#else
+/*
+ * New breakpoints - use an undefined instruction. The ARM architecture
+ * reference manual guarantees that the following instruction space
+ * will produce an undefined instruction exception on all CPUs:
+ *
+ * ARM: xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
+ * Thumb: 1101 1110 xxxx xxxx
+ */
+#define BREAKINST_ARM 0xe7f001f0
+#define BREAKINST_THUMB 0xde01
+#endif
/*
* Get the address of the live pt_regs for the specified task.
@@ -89,23 +103,32 @@ put_user_reg(struct task_struct *task, int offset, long data)
}
static inline int
-read_tsk_long(struct task_struct *child, unsigned long addr, unsigned long *res)
+read_u32(struct task_struct *task, unsigned long addr, u32 *res)
{
- int copied;
+ int ret;
- copied = access_process_vm(child, addr, res, sizeof(*res), 0);
+ ret = access_process_vm(task, addr, res, sizeof(*res), 0);
- return copied != sizeof(*res) ? -EIO : 0;
+ return ret == sizeof(*res) ? 0 : -EIO;
}
static inline int
-write_tsk_long(struct task_struct *child, unsigned long addr, unsigned long val)
+read_instr(struct task_struct *task, unsigned long addr, u32 *res)
{
- int copied;
-
- copied = access_process_vm(child, addr, &val, sizeof(val), 1);
+ int ret;
- return copied != sizeof(val) ? -EIO : 0;
+ if (addr & 1) {
+ u16 val;
+ ret = access_process_vm(task, addr & ~1, &val, sizeof(val), 0);
+ ret = ret == sizeof(val) ? 0 : -EIO;
+ *res = val;
+ } else {
+ u32 val;
+ ret = access_process_vm(task, addr & ~3, &val, sizeof(val), 0);
+ ret = ret == sizeof(val) ? 0 : -EIO;
+ *res = val;
+ }
+ return ret;
}
/*
@@ -206,7 +229,7 @@ ptrace_getldrop2(struct task_struct *child, unsigned long insn)
static unsigned long
get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn)
{
- unsigned long alt = 0;
+ u32 alt = 0;
switch (insn & 0x0e000000) {
case 0x00000000:
@@ -262,7 +285,7 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
else
base -= aluop2;
}
- if (read_tsk_long(child, base, &alt) == 0)
+ if (read_u32(child, base, &alt) == 0)
alt = pc_pointer(alt);
}
break;
@@ -289,7 +312,7 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
base = ptrace_getrn(child, insn);
- if (read_tsk_long(child, base + nr_regs, &alt) == 0)
+ if (read_u32(child, base + nr_regs, &alt) == 0)
alt = pc_pointer(alt);
break;
}
@@ -319,30 +342,71 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
}
static int
-add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long addr)
+swap_insn(struct task_struct *task, unsigned long addr,
+ void *old_insn, void *new_insn, int size)
+{
+ int ret;
+
+ ret = access_process_vm(task, addr, old_insn, size, 0);
+ if (ret == size)
+ ret = access_process_vm(task, addr, new_insn, size, 1);
+ return ret;
+}
+
+static void
+add_breakpoint(struct task_struct *task, struct debug_info *dbg, unsigned long addr)
{
int nr = dbg->nsaved;
- int res = -EINVAL;
if (nr < 2) {
- res = read_tsk_long(child, addr, &dbg->bp[nr].insn);
- if (res == 0)
- res = write_tsk_long(child, addr, BREAKINST_ARM);
+ u32 new_insn = BREAKINST_ARM;
+ int res;
- if (res == 0) {
+ res = swap_insn(task, addr, &dbg->bp[nr].insn, &new_insn, 4);
+
+ if (res == 4) {
dbg->bp[nr].address = addr;
dbg->nsaved += 1;
}
} else
printk(KERN_ERR "ptrace: too many breakpoints\n");
+}
+
+/*
+ * Clear one breakpoint in the user program. We copy what the hardware
+ * does and use bit 0 of the address to indicate whether this is a Thumb
+ * breakpoint or an ARM breakpoint.
+ */
+static void clear_breakpoint(struct task_struct *task, struct debug_entry *bp)
+{
+ unsigned long addr = bp->address;
+ union debug_insn old_insn;
+ int ret;
+
+ if (addr & 1) {
+ ret = swap_insn(task, addr & ~1, &old_insn.thumb,
+ &bp->insn.thumb, 2);
- return res;
+ if (ret != 2 || old_insn.thumb != BREAKINST_THUMB)
+ printk(KERN_ERR "%s:%d: corrupted Thumb breakpoint at "
+ "0x%08lx (0x%04x)\n", task->comm, task->pid,
+ addr, old_insn.thumb);
+ } else {
+ ret = swap_insn(task, addr & ~3, &old_insn.arm,
+ &bp->insn.arm, 4);
+
+ if (ret != 4 || old_insn.arm != BREAKINST_ARM)
+ printk(KERN_ERR "%s:%d: corrupted ARM breakpoint at "
+ "0x%08lx (0x%08x)\n", task->comm, task->pid,
+ addr, old_insn.arm);
+ }
}
void ptrace_set_bpt(struct task_struct *child)
{
struct pt_regs *regs;
- unsigned long pc, insn;
+ unsigned long pc;
+ u32 insn;
int res;
regs = get_user_regs(child);
@@ -353,7 +417,7 @@ void ptrace_set_bpt(struct task_struct *child)
return;
}
- res = read_tsk_long(child, pc, &insn);
+ res = read_instr(child, pc, &insn);
if (!res) {
struct debug_info *dbg = &child->thread.debug;
unsigned long alt;
@@ -362,7 +426,7 @@ void ptrace_set_bpt(struct task_struct *child)
alt = get_branch_address(child, pc, insn);
if (alt)
- res = add_breakpoint(child, dbg, alt);
+ add_breakpoint(child, dbg, alt);
/*
* Note that we ignore the result of setting the above
@@ -374,7 +438,7 @@ void ptrace_set_bpt(struct task_struct *child)
* loose control of the thread during single stepping.
*/
if (!alt || predicate(insn) != PREDICATE_ALWAYS)
- res = add_breakpoint(child, dbg, pc + 4);
+ add_breakpoint(child, dbg, pc + 4);
}
}
@@ -384,24 +448,17 @@ void ptrace_set_bpt(struct task_struct *child)
*/
void __ptrace_cancel_bpt(struct task_struct *child)
{
- struct debug_info *dbg = &child->thread.debug;
- int i, nsaved = dbg->nsaved;
+ int i, nsaved = child->thread.debug.nsaved;
- dbg->nsaved = 0;
+ child->thread.debug.nsaved = 0;
if (nsaved > 2) {
printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
nsaved = 2;
}
- for (i = 0; i < nsaved; i++) {
- unsigned long tmp;
-
- read_tsk_long(child, dbg->bp[i].address, &tmp);
- write_tsk_long(child, dbg->bp[i].address, dbg->bp[i].insn);
- if (tmp != BREAKINST_ARM)
- printk(KERN_ERR "ptrace_cancel_bpt: weirdness\n");
- }
+ for (i = 0; i < nsaved; i++)
+ clear_breakpoint(child, &child->thread.debug.bp[i]);
}
/*
@@ -537,9 +594,12 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
*/
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
- ret = read_tsk_long(child, addr, &tmp);
- if (!ret)
+ ret = access_process_vm(child, addr, &tmp,
+ sizeof(unsigned long), 0);
+ if (ret == sizeof(unsigned long))
ret = put_user(tmp, (unsigned long *) data);
+ else
+ ret = -EIO;
break;
case PTRACE_PEEKUSR:
@@ -551,7 +611,12 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
*/
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
- ret = write_tsk_long(child, addr, data);
+ ret = access_process_vm(child, addr, &data,
+ sizeof(unsigned long), 1);
+ if (ret == sizeof(unsigned long))
+ ret = 0;
+ else
+ ret = -EIO;
break;
case PTRACE_POKEUSR:
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index cf6c528b3947..51463c237002 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -193,26 +193,25 @@ static inline void dump_cache(const char *prefix, unsigned int cache)
CACHE_LINE(cache)));
}
-static inline void dump_cpu_cache_id(void)
+static void __init dump_cpu_info(void)
{
- unsigned int cache_info;
+ unsigned int info;
- asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
+ asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (info));
- if (cache_info == processor_id)
- return;
-
- printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(cache_info)]);
- if (CACHE_S(cache_info)) {
- dump_cache("CPU: I cache", CACHE_ISIZE(cache_info));
- dump_cache("CPU: D cache", CACHE_DSIZE(cache_info));
- } else {
- dump_cache("CPU: cache", CACHE_ISIZE(cache_info));
+ if (info != processor_id) {
+ printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(info)]);
+ if (CACHE_S(info)) {
+ dump_cache("CPU: I cache", CACHE_ISIZE(info));
+ dump_cache("CPU: D cache", CACHE_DSIZE(info));
+ } else {
+ dump_cache("CPU: cache", CACHE_ISIZE(info));
+ }
}
}
#else
-#define dump_cpu_cache_id() do { } while (0)
+#define dump_cpu_info() do { } while (0)
#endif
static void __init setup_processor(void)
@@ -255,7 +254,7 @@ static void __init setup_processor(void)
proc_info.manufacturer, proc_info.cpu_name,
(int)processor_id & 15);
- dump_cpu_cache_id();
+ dump_cpu_info();
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 6f6701c99712..93dc50e3ccc6 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -59,11 +59,11 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t m
sigset_t saveset;
mask &= _BLOCKABLE;
- spin_lock_irq(&current->sigmask_lock);
+ spin_lock_irq(&current->sig->siglock);
saveset = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
- spin_unlock_irq(&current->sigmask_lock);
+ spin_unlock_irq(&current->sig->siglock);
regs->ARM_r0 = -EINTR;
while (1) {
@@ -87,11 +87,11 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs)
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
+ spin_lock_irq(&current->sig->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
- spin_unlock_irq(&current->sigmask_lock);
+ spin_unlock_irq(&current->sig->siglock);
regs->ARM_r0 = -EINTR;
while (1) {
@@ -207,10 +207,10 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
+ spin_lock_irq(&current->sig->siglock);
current->blocked = set;
recalc_sigpending();
- spin_unlock_irq(&current->sigmask_lock);
+ spin_unlock_irq(&current->sig->siglock);
if (restore_sigcontext(regs, &frame->sc))
goto badframe;
@@ -247,10 +247,10 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sigmask_lock);
+ spin_lock_irq(&current->sig->siglock);
current->blocked = set;
recalc_sigpending();
- spin_unlock_irq(&current->sigmask_lock);
+ spin_unlock_irq(&current->sig->siglock);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
@@ -477,12 +477,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
ka->sa.sa_handler = SIG_DFL;
if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&tsk->sigmask_lock);
+ spin_lock_irq(&tsk->sig->siglock);
sigorsets(&tsk->blocked, &tsk->blocked,
&ka->sa.sa_mask);
sigaddset(&tsk->blocked, sig);
recalc_sigpending();
- spin_unlock_irq(&tsk->sigmask_lock);
+ spin_unlock_irq(&tsk->sig->siglock);
}
return;
}
@@ -520,20 +520,10 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
for (;;) {
unsigned long signr = 0;
struct k_sigaction *ka;
- sigset_t *mask = &current->blocked;
- local_irq_disable();
- if (current->sig->shared_pending.head) {
- spin_lock(&current->sig->siglock);
- signr = dequeue_signal(&current->sig->shared_pending, mask, &info);
- spin_unlock(&current->sig->siglock);
- }
- if (!signr) {
- spin_lock(&current->sigmask_lock);
- signr = dequeue_signal(&current->pending, mask, &info);
- spin_unlock(&current->sigmask_lock);
- }
- local_irq_enable();
+ spin_lock_irq(&current->sig->siglock);
+ signr = dequeue_signal(&current->blocked, &info);
+ spin_unlock_irq(&current->sig->siglock);
if (!signr)
break;
diff --git a/arch/arm/kernel/time-acorn.c b/arch/arm/kernel/time-acorn.c
index 91f9e1a134c2..eb637801c7a5 100644
--- a/arch/arm/kernel/time-acorn.c
+++ b/arch/arm/kernel/time-acorn.c
@@ -25,44 +25,37 @@ extern unsigned long (*gettimeoffset)(void);
static unsigned long ioctime_gettimeoffset(void)
{
- unsigned int count1, count2, status1, status2;
- unsigned long offset = 0;
+ unsigned int count1, count2, status;
+ long offset;
- status1 = ioc_readb(IOC_IRQREQA);
- barrier ();
ioc_writeb (0, IOC_T0LATCH);
barrier ();
count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
barrier ();
- status2 = ioc_readb(IOC_IRQREQA);
+ status = ioc_readb(IOC_IRQREQA);
barrier ();
ioc_writeb (0, IOC_T0LATCH);
barrier ();
count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
+ offset = count2;
if (count2 < count1) {
/*
- * This means that we haven't just had an interrupt
- * while reading into status2.
+ * We have not had an interrupt between reading count1
+ * and count2.
*/
- if (status2 & (1 << 5))
- offset = tick;
- count1 = count2;
+ if (status & (1 << 5))
+ offset -= LATCH;
} else if (count2 > count1) {
/*
- * We have just had another interrupt while reading
- * status2.
+ * We have just had another interrupt between reading
+ * count1 and count2.
*/
- offset += tick;
- count1 = count2;
+ offset -= LATCH;
}
- count1 = LATCH - count1;
- /*
- * count1 = number of clock ticks since last interrupt
- */
- offset += count1 * tick / LATCH;
- return offset;
+ offset = (LATCH - offset) * (tick_nsec / 1000);
+ return (offset + LATCH/2) / LATCH;
}
void __init ioctime_init(void)
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 3d79e5c47367..07df8125c4cb 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -115,8 +115,8 @@ static inline void do_set_rtc(void)
time_before(xtime.tv_sec, next_rtc_update))
return;
- if (xtime.tv_usec < 50000 - (tick >> 1) &&
- xtime.tv_usec >= 50000 + (tick >> 1))
+ if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) &&
+ xtime.tv_nsec >= 500000000 + ((unsigned) tick_nsec >> 1))
return;
if (set_rtc())
@@ -166,7 +166,7 @@ void do_gettimeofday(struct timeval *tv)
usec += lost * USECS_PER_JIFFY;
sec = xtime.tv_sec;
- usec += xtime.tv_usec;
+ usec += xtime.tv_nsec / 1000;
read_unlock_irqrestore(&xtime_lock, flags);
/* usec may have gone up a lot: be safe */
@@ -196,7 +196,8 @@ void do_settimeofday(struct timeval *tv)
tv->tv_sec--;
}
- xtime = *tv;
+ xtime.tv_sec = tv->tv_sec;
+ xtime.tv_nsec = tv->tv_usec * 1000;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index f0f7daf2d7d6..86a60a6e5022 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -32,6 +32,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
+#include <asm/semaphore.h>
#include "ptrace.h"
@@ -77,8 +78,7 @@ static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
fs = get_fs();
set_fs(KERNEL_DS);
- printk("%s", str);
- printk("(0x%08lx to 0x%08lx)\n", bottom, top);
+ printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
for (p = bottom & ~31; p < top;) {
printk("%04lx: ", p & 0xffff);
@@ -136,7 +136,7 @@ static void dump_instr(struct pt_regs *regs)
set_fs(fs);
}
-static void dump_stack(struct task_struct *tsk, unsigned long sp)
+static void __dump_stack(struct task_struct *tsk, unsigned long sp)
{
dump_mem("Stack: ", sp, 8192+(unsigned long)tsk->thread_info);
}
@@ -163,15 +163,20 @@ static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
}
/*
- * This is called from SysRq-T (show_task) to display the current
- * call trace for each process. Very useful.
+ * This is called from SysRq-T (show_task) to display the current call
+ * trace for each process. This version will also display the running
+ * threads call trace (ie, us.)
*/
void show_trace_task(struct task_struct *tsk)
{
- if (tsk != current) {
- unsigned int fp = thread_saved_fp(tsk);
- c_backtrace(fp, 0x10);
- }
+ unsigned int fp;
+
+ if (tsk != current)
+ fp = thread_saved_fp(tsk);
+ else
+ asm("mov%? %0, fp" : "=r" (fp));
+
+ c_backtrace(fp, 0x10);
}
spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
@@ -193,7 +198,7 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
current->comm, current->pid, tsk->thread_info + 1);
if (!user_mode(regs) || in_interrupt()) {
- dump_stack(tsk, (unsigned long)(regs + 1));
+ __dump_stack(tsk, (unsigned long)(regs + 1));
dump_backtrace(regs, tsk);
dump_instr(regs);
}
diff --git a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
index 17acb2bc21da..773955c92d14 100644
--- a/arch/arm/mach-integrator/cpu.c
+++ b/arch/arm/mach-integrator/cpu.c
@@ -73,36 +73,37 @@ static struct vco freq_to_vco(unsigned int freq_khz, int factor)
* Validate the speed in khz. If it is outside our
* range, then return the lowest.
*/
-static unsigned int
-integrator_validatespeed(unsigned int cpu, unsigned int freq_khz)
+static void integrator_verify_speed(struct cpufreq_policy *policy)
{
struct vco vco;
- if (freq_khz < 12000)
- freq_khz = 12000;
- if (freq_khz > 160000)
- freq_khz = 160000;
+ if (policy->max > policy->max_cpu_freq)
+ policy->max = policy->max_cpu_freq;
- vco = freq_to_vco(freq_khz, 1);
+ if (policy->max < 12000)
+ policy->max = 12000;
+ if (policy->max > 160000)
+ policy->max = 160000;
- if (vco.vdw < 4 || vco.vdw > 152)
- return -EINVAL;
+ vco = freq_to_vco(policy->max, 1);
- return vco_to_freq(vco, 1);
+ if (vco.vdw < 4)
+ vco.vdw = 4;
+ if (vco.vdw > 152)
+ vco.vdw = 152;
+
+ policy->min = policy->max = vco_to_freq(vco, 1);
}
-static void integrator_setspeed(unsigned int cpu, unsigned int freq_khz)
+static void do_set_policy(int cpu, struct cpufreq_policy *policy)
{
- struct vco vco = freq_to_vco(freq_khz, 1);
- unsigned long cpus_allowed;
+ struct vco vco = freq_to_vco(policy->max, 1);
u_int cm_osc;
/*
- * Save this threads cpus_allowed mask, and bind to the
- * specified CPU. When this call returns, we should be
- * running on the right CPU.
+ * Bind to the specified CPU. When this call returns,
+ * we should be running on the right CPU.
*/
- cpus_allowed = current->cpus_allowed;
set_cpus_allowed(current, 1 << cpu);
BUG_ON(cpu != smp_processor_id());
@@ -113,6 +114,26 @@ static void integrator_setspeed(unsigned int cpu, unsigned int freq_khz)
__raw_writel(0xa05f, CM_LOCK);
__raw_writel(cm_osc, CM_OSC);
__raw_writel(0, CM_LOCK);
+}
+
+static void integrator_set_policy(struct cpufreq_policy *policy)
+{
+ unsigned long cpus_allowed;
+ int cpu;
+
+ /*
+ * Save this threads cpus_allowed mask.
+ */
+ cpus_allowed = current->cpus_allowed;
+
+ if (policy->cpu == CPUFREQ_ALL_CPUS) {
+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ if (!cpu_online(cpu))
+ continue;
+ do_set_policy(cpu, policy);
+ }
+ } else
+ do_set_policy(policy->cpu, policy);
/*
* Restore the CPUs allowed mask.
@@ -120,23 +141,30 @@ static void integrator_setspeed(unsigned int cpu, unsigned int freq_khz)
set_cpus_allowed(current, cpus_allowed);
}
+static struct cpufreq_policy integrator_policy = {
+ .cpu = 0,
+ .policy = CPUFREQ_POLICY_POWERSAVE,
+ .max_cpu_freq = 160000,
+};
+
static struct cpufreq_driver integrator_driver = {
- .validate = integrator_validatespeed,
- .setspeed = integrator_setspeed,
- .sync = 1,
+ .verify = integrator_verify_speed,
+ .setpolicy = integrator_set_policy,
+ .policy = &integrator_policy,
+ .cpu_min_freq = 12000,
};
#endif
static int __init integrator_cpu_init(void)
{
- struct cpufreq_freqs *freqs;
+ struct cpufreq_policy *policies;
unsigned long cpus_allowed;
int cpu;
- freqs = kmalloc(sizeof(struct cpufreq_freqs) * NR_CPUS,
- GFP_KERNEL);
- if (!freqs) {
- printk(KERN_ERR "CPU: unable to allocate cpufreqs structure\n");
+ policies = kmalloc(sizeof(struct cpufreq_freqs) * NR_CPUS,
+ GFP_KERNEL);
+ if (!policies) {
+ printk(KERN_ERR "CPU: unable to allocate policies structure\n");
return -ENOMEM;
}
@@ -164,18 +192,20 @@ static int __init integrator_cpu_init(void)
vco.od = (cm_osc >> 8) & 7;
vco.vdw = cm_osc & 255;
- freqs[cpu].min = 12000;
- freqs[cpu].max = 160000;
- freqs[cpu].cur = vco_to_freq(vco, 1);
+ policies[cpu].cpu = cpu;
+ policies[cpu].policy = CPUFREQ_POLICY_POWERSAVE,
+ policies[cpu].max_cpu_freq = 160000;
+ policies[cpu].min =
+ policies[cpu].max = vco_to_freq(vco, 1);
}
set_cpus_allowed(current, cpus_allowed);
#ifdef CONFIG_CPU_FREQ
- integrator_driver.freq = freqs;
+ integrator_driver.policy = policies;
cpufreq_register(&integrator_driver);
#else
- kfree(freqs);
+ kfree(policies);
#endif
return 0;
diff --git a/arch/arm/mach-iop310/iop310-pci.c b/arch/arm/mach-iop310/iop310-pci.c
index c7fddcdf9107..50faa6fecfcd 100644
--- a/arch/arm/mach-iop310/iop310-pci.c
+++ b/arch/arm/mach-iop310/iop310-pci.c
@@ -145,7 +145,7 @@ iop310_pri_read_config(struct pci_bus *bus, unsigned int devfn, int where,
}
static int
-iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where
+iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 value)
{
unsigned long addr = iop310_cfg_address(bus, devfn, where);
@@ -163,7 +163,7 @@ iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where
else
val &= ~(0xffff << where);
- *IOP310_POCCDR = val | v << where;
+ *IOP310_POCCDR = val | value << where;
} else {
asm volatile(
"str %1, [%2]\n\t"
@@ -173,7 +173,7 @@ iop310_pri_write_config(struct pci_bus *bus, unsigned int devfn, int where
"nop\n\t"
"nop\n\t"
:
- : "r" (val), "r" (addr),
+ : "r" (value), "r" (addr),
"r" (IOP310_POCCAR), "r" (IOP310_POCCDR));
}
@@ -246,7 +246,7 @@ iop310_sec_read_config(struct pci_bus *bus, unsigned int devfn, int where,
}
static int
-iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where
+iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 value)
{
unsigned long addr = iop310_cfg_address(bus, devfn, where);
@@ -265,7 +265,7 @@ iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where
else
val &= ~(0xffff << where);
- *IOP310_SOCCDR = val | v << where;
+ *IOP310_SOCCDR = val | value << where;
} else {
asm volatile(
"str %1, [%2]\n\t"
@@ -275,7 +275,7 @@ iop310_sec_write_config(struct pci_bus *bus, unsigned int devfn, int where
"nop\n\t"
"nop\n\t"
:
- : "r" (val), "r" (addr),
+ : "r" (value), "r" (addr),
"r" (IOP310_SOCCAR), "r" (IOP310_SOCCDR));
}
diff --git a/arch/arm/mach-iop310/iq80310-time.c b/arch/arm/mach-iop310/iq80310-time.c
index a986a2346836..1151c6b3db28 100644
--- a/arch/arm/mach-iop310/iq80310-time.c
+++ b/arch/arm/mach-iop310/iq80310-time.c
@@ -85,7 +85,7 @@ static unsigned long iq80310_gettimeoffset (void)
/*
* Now convert them to usec.
*/
- usec = (unsigned long)(elapsed*tick)/LATCH;
+ usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
return usec;
}
diff --git a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile
index d5b92e4637ad..520d8fefdcd0 100644
--- a/arch/arm/mach-sa1100/Makefile
+++ b/arch/arm/mach-sa1100/Makefile
@@ -2,20 +2,17 @@
# Makefile for the linux kernel.
#
-# Common support (must be linked before board specific support)
+# Common support
obj-y := generic.o irq.o dma.o
obj-m :=
obj-n :=
obj- :=
led-y := leds.o
-export-objs := dma.o generic.o pcipool.o pm.o sa1111.o sa1111-pcibuf.o \
- usb_ctl.o usb_recv.o usb_send.o
+export-objs := dma.o generic.o pcipool.o pm.o sa1111.o sa1111-pcibuf.o
# This needs to be cleaned up. We probably need to have SA1100
# and SA1110 config symbols.
-#
-# We link the CPU support next, so that RAM timings can be tuned.
ifeq ($(CONFIG_CPU_FREQ),y)
obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o
obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o
@@ -107,10 +104,7 @@ export-objs += yopy.o
obj-$(CONFIG_LEDS) += $(led-y)
# SA1110 USB client support
-sa1100usb_core-objs := usb_ctl.o usb_ep0.o usb_recv.o usb_send.o
-obj-$(CONFIG_SA1100_USB) += sa1100usb_core.o
-obj-$(CONFIG_SA1100_USB_NETLINK) += usb-eth.o
-obj-$(CONFIG_SA1100_USB_CHAR) += usb-char.o
+#obj-$(CONFIG_SA1100_USB) += usb/
# Miscelaneous functions
obj-$(CONFIG_PM) += pm.o sleep.o
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index b05c727a5b6a..d538b98d4284 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -302,21 +302,24 @@ static void __init assabet_map_io(void)
*/
neponset_map_io();
#endif
- /*
- * When Neponset is attached, the first UART should be
- * UART3. That's what Angel is doing and many documents
- * are stating this.
- * We do the Neponset mapping even if Neponset support
- * isn't compiled in so the user will still get something on
- * the expected physical serial port.
- */
- sa1100_register_uart(0, 3);
- sa1100_register_uart(2, 1);
} else {
sa1100_register_uart_fns(&assabet_port_fns);
- sa1100_register_uart(0, 1); /* com port */
- sa1100_register_uart(2, 3); /* radio module */
}
+
+ /*
+ * When Neponset is attached, the first UART should be
+ * UART3. That's what Angel is doing and many documents
+ * are stating this.
+ *
+ * We do the Neponset mapping even if Neponset support
+ * isn't compiled in so the user will still get something on
+ * the expected physical serial port.
+ *
+ * We no longer do this; not all boot loaders support it,
+ * and UART3 appears to be somewhat unreliable with blob.
+ */
+ sa1100_register_uart(0, 1);
+ sa1100_register_uart(2, 3);
}
diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
index 45eae6434f68..461bec6b956b 100644
--- a/arch/arm/mach-sa1100/generic.c
+++ b/arch/arm/mach-sa1100/generic.c
@@ -55,8 +55,8 @@ unsigned int sa11x0_freq_to_ppcr(unsigned int khz)
khz /= 100;
- for (i = 0; i < ARRAY_SIZE(cclk_frequency_100khz); i--)
- if (cclk_frequency_100khz[i] >= khz)
+ for (i = NR_FREQS - 1; i > 0; i--)
+ if (cclk_frequency_100khz[i] <= khz)
break;
return i;
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index 9d3a939de4ae..71c60c3c1467 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -193,20 +193,30 @@ static int neponset_resume(struct device *dev, u32 level)
}
static struct device_driver neponset_device_driver = {
- .suspend = neponset_suspend,
- .resume = neponset_resume,
+ .name = "NEPONSET",
+ .bus = &system_bus_type,
+ .suspend = neponset_suspend,
+ .resume = neponset_resume,
};
-static struct device neponset_device = {
- .name = "Neponset",
- .bus_id = "neponset",
- .driver = &neponset_device_driver,
+static struct sys_device neponset_device = {
+ .name = "NEPONSET",
+ .id = 0,
+ .root = NULL,
+ .dev = {
+ .name = "Neponset",
+ .bus_id = "neponset",
+ .bus = &system_bus_type,
+ .driver = &neponset_device_driver,
+ },
};
static int __init neponset_init(void)
{
int ret;
+ driver_register(&neponset_device_driver);
+
/*
* The Neponset is only present on the Assabet machine type.
*/
@@ -231,7 +241,7 @@ static int __init neponset_init(void)
return -ENODEV;
}
- ret = register_sys_device(&neponset_device);
+ ret = sys_device_register(&neponset_device);
if (ret)
return ret;
@@ -256,7 +266,7 @@ static int __init neponset_init(void)
return sa1111_init(0x40000000, IRQ_NEPONSET_SA1111);
}
-arch_initcall(neponset_init);
+subsys_initcall(neponset_init);
static struct map_desc neponset_io_desc[] __initdata = {
/* virtual physical length type */
diff --git a/arch/arm/mach-sa1100/sa1111.c b/arch/arm/mach-sa1100/sa1111.c
index 9ded8fe5f98e..54a40462b2dc 100644
--- a/arch/arm/mach-sa1100/sa1111.c
+++ b/arch/arm/mach-sa1100/sa1111.c
@@ -43,7 +43,7 @@
* anchor point for all the other drivers.
*/
struct sa1111 {
- struct device dev;
+ struct device *dev;
struct resource res;
int irq;
spinlock_t lock;
@@ -64,7 +64,7 @@ static struct sa1111_dev usb_dev = {
.devid = SA1111_DEVID_USB,
.irq = {
IRQ_USBPWR,
- IRQ_NHCIM,
+ IRQ_HCIM,
IRQ_HCIBUFFACC,
IRQ_HCIRMTWKP,
IRQ_NHCIMFCIR,
@@ -148,7 +148,6 @@ static struct sa1111_dev *devs[] = {
&ssp_dev,
&kbd_dev,
&mse_dev,
- &int_dev,
&pcmcia_dev,
};
@@ -158,7 +157,6 @@ static unsigned int dev_offset[] = {
0x0800,
SA1111_KBD,
SA1111_MSE,
- SA1111_INTC,
0x1800,
};
@@ -372,7 +370,106 @@ static void __init sa1111_init_irq(struct sa1111_dev *sadev)
set_irq_chained_handler(sadev->irq[0], sa1111_irq_handler);
}
-static struct device_driver sa1111_device_driver;
+/*
+ * Bring the SA1111 out of reset. This requires a set procedure:
+ * 1. nRESET asserted (by hardware)
+ * 2. CLK turned on from SA1110
+ * 3. nRESET deasserted
+ * 4. VCO turned on, PLL_BYPASS turned off
+ * 5. Wait lock time, then assert RCLKEn
+ * 7. PCR set to allow clocking of individual functions
+ *
+ * Until we've done this, the only registers we can access are:
+ * SBI_SKCR
+ * SBI_SMCR
+ * SBI_SKID
+ */
+static void sa1111_wake(struct sa1111 *sachip)
+{
+ unsigned long flags, r;
+
+ spin_lock_irqsave(&sachip->lock, flags);
+
+ /*
+ * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
+ * (SA-1110 Developer's Manual, section 9.1.2.1)
+ */
+ GAFR |= GPIO_32_768kHz;
+ GPDR |= GPIO_32_768kHz;
+ TUCR = TUCR_3_6864MHz;
+
+ /*
+ * Turn VCO on, and disable PLL Bypass.
+ */
+ r = sa1111_readl(sachip->base + SA1111_SKCR);
+ r &= ~SKCR_VCO_OFF;
+ sa1111_writel(r, sachip->base + SA1111_SKCR);
+ r |= SKCR_PLL_BYPASS | SKCR_OE_EN;
+ sa1111_writel(r, sachip->base + SA1111_SKCR);
+
+ /*
+ * Wait lock time. SA1111 manual _doesn't_
+ * specify a figure for this! We choose 100us.
+ */
+ udelay(100);
+
+ /*
+ * Enable RCLK. We also ensure that RDYEN is set.
+ */
+ r |= SKCR_RCLKEN | SKCR_RDYEN;
+ sa1111_writel(r, sachip->base + SA1111_SKCR);
+
+ /*
+ * Wait 14 RCLK cycles for the chip to finish coming out
+ * of reset. (RCLK=24MHz). This is 590ns.
+ */
+ udelay(1);
+
+ /*
+ * Ensure all clocks are initially off.
+ */
+ sa1111_writel(0, sachip->base + SA1111_SKPCR);
+
+ spin_unlock_irqrestore(&sachip->lock, flags);
+}
+
+/*
+ * Configure the SA1111 shared memory controller.
+ */
+void
+sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
+ unsigned int cas_latency)
+{
+ unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC);
+
+ if (cas_latency == 3)
+ smcr |= SMCR_CLAT;
+
+ sa1111_writel(smcr, sachip->base + SA1111_SMCR);
+}
+
+static void
+sa1111_init_one_child(struct sa1111 *sachip, struct sa1111_dev *sadev, unsigned int offset)
+{
+ snprintf(sadev->dev.bus_id, sizeof(sadev->dev.bus_id),
+ "%4.4x", offset);
+
+ sadev->dev.parent = sachip->dev;
+ sadev->dev.bus = &sa1111_bus_type;
+ sadev->res.start = sachip->res.start + offset;
+ sadev->res.end = sadev->res.start + 511;
+ sadev->res.name = sadev->dev.name;
+ sadev->res.flags = IORESOURCE_MEM;
+ sadev->mapbase = sachip->base + offset;
+
+ if (request_resource(&sachip->res, &sadev->res)) {
+ printk("SA1111: failed to allocate resource for %s\n",
+ sadev->res.name);
+ return;
+ }
+
+ device_register(&sadev->dev);
+}
/**
* sa1111_probe - probe for a single SA1111 chip.
@@ -387,11 +484,11 @@ static struct device_driver sa1111_device_driver;
* %0 successful.
*/
static int __init
-sa1111_probe(unsigned long phys_addr, int irq)
+__sa1111_probe(struct device *me, unsigned long phys_addr, int irq)
{
struct sa1111 *sachip;
unsigned long id;
- unsigned int has_devs;
+ unsigned int has_devs, val;
int i, ret = -ENODEV;
sachip = kmalloc(sizeof(struct sa1111), GFP_KERNEL);
@@ -402,12 +499,10 @@ sa1111_probe(unsigned long phys_addr, int irq)
spin_lock_init(&sachip->lock);
- strncpy(sachip->dev.name, "Intel Corporation SA1111", sizeof(sachip->dev.name));
- snprintf(sachip->dev.bus_id, sizeof(sachip->dev.bus_id), "%8.8lx", phys_addr);
- sachip->dev.driver = &sa1111_device_driver;
- sachip->dev.driver_data = sachip;
+ sachip->dev = me;
+ dev_set_drvdata(sachip->dev, sachip);
- sachip->res.name = sachip->dev.name;
+ sachip->res.name = me->name;
sachip->res.start = phys_addr;
sachip->res.end = phys_addr + 0x2000;
sachip->irq = irq;
@@ -417,6 +512,10 @@ sa1111_probe(unsigned long phys_addr, int irq)
goto out;
}
+ /*
+ * Map the whole region. This also maps the
+ * registers for our children.
+ */
sachip->base = ioremap(phys_addr, PAGE_SIZE * 2);
if (!sachip->base) {
ret = -ENOMEM;
@@ -433,17 +532,47 @@ sa1111_probe(unsigned long phys_addr, int irq)
goto unmap;
}
- /*
- * We found the chip.
- */
- ret = register_sys_device(&sachip->dev);
- if (ret)
- printk("sa1111 device_register failed: %d\n", ret);
-
printk(KERN_INFO "SA1111 Microprocessor Companion Chip: "
"silicon revision %lx, metal revision %lx\n",
(id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
+ /*
+ * We found it. Wake the chip up, and initialise.
+ */
+ sa1111_wake(sachip);
+
+ /*
+ * The SDRAM configuration of the SA1110 and the SA1111 must
+ * match. This is very important to ensure that SA1111 accesses
+ * don't corrupt the SDRAM. Note that this ungates the SA1111's
+ * MBGNT signal, so we must have called sa1110_mb_disable()
+ * beforehand.
+ */
+ sa1111_configure_smc(sachip, 1,
+ FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
+ FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
+
+ /*
+ * We only need to turn on DCLK whenever we want to use the
+ * DMA. It can otherwise be held firmly in the off position.
+ * (currently, we always enable it.)
+ */
+ val = sa1111_readl(sachip->base + SA1111_SKPCR);
+ sa1111_writel(val | SKPCR_DCLKEN, sachip->base + SA1111_SKPCR);
+
+ /*
+ * Enable the SA1110 memory bus request and grant signals.
+ */
+ sa1110_mb_enable();
+
+ /*
+ * The interrupt controller must be initialised before any
+ * other device to ensure that the interrupts are available.
+ */
+ int_dev.irq[0] = irq;
+ sa1111_init_one_child(sachip, &int_dev, SA1111_INTC);
+ sa1111_init_irq(&int_dev);
+
g_sa1111 = sachip;
has_devs = ~0;
@@ -453,29 +582,9 @@ sa1111_probe(unsigned long phys_addr, int irq)
else
has_devs &= ~(1 << 1);
- for (i = 0; i < ARRAY_SIZE(devs); i++) {
- if (!(has_devs & (1 << i)))
- continue;
-
- snprintf(devs[i]->dev.bus_id, sizeof(devs[i]->dev.bus_id),
- "%4.4x", dev_offset[i]);
-
- devs[i]->dev.parent = &sachip->dev;
- devs[i]->dev.bus = &sa1111_bus_type;
- devs[i]->res.start = sachip->res.start + dev_offset[i];
- devs[i]->res.end = devs[i]->res.start + 511;
- devs[i]->res.name = devs[i]->dev.name;
- devs[i]->res.flags = IORESOURCE_MEM;
- devs[i]->mapbase = sachip->base + dev_offset[i];
-
- if (request_resource(&sachip->res, &devs[i]->res)) {
- printk("SA1111: failed to allocate resource for %s\n",
- devs[i]->res.name);
- continue;
- }
-
- device_register(&devs[i]->dev);
- }
+ for (i = 0; i < ARRAY_SIZE(devs); i++)
+ if (has_devs & (1 << i))
+ sa1111_init_one_child(sachip, devs[i], dev_offset[i]);
return 0;
@@ -503,84 +612,6 @@ static void __sa1111_remove(struct sa1111 *sachip)
}
/*
- * Bring the SA1111 out of reset. This requires a set procedure:
- * 1. nRESET asserted (by hardware)
- * 2. CLK turned on from SA1110
- * 3. nRESET deasserted
- * 4. VCO turned on, PLL_BYPASS turned off
- * 5. Wait lock time, then assert RCLKEn
- * 7. PCR set to allow clocking of individual functions
- *
- * Until we've done this, the only registers we can access are:
- * SBI_SKCR
- * SBI_SMCR
- * SBI_SKID
- */
-static void sa1111_wake(struct sa1111 *sachip)
-{
- unsigned long flags, r;
-
- spin_lock_irqsave(&sachip->lock, flags);
-
- /*
- * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
- * (SA-1110 Developer's Manual, section 9.1.2.1)
- */
- GAFR |= GPIO_32_768kHz;
- GPDR |= GPIO_32_768kHz;
- TUCR = TUCR_3_6864MHz;
-
- /*
- * Turn VCO on, and disable PLL Bypass.
- */
- r = sa1111_readl(sachip->base + SA1111_SKCR);
- r &= ~SKCR_VCO_OFF;
- sa1111_writel(r, sachip->base + SA1111_SKCR);
- r |= SKCR_PLL_BYPASS | SKCR_OE_EN;
- sa1111_writel(r, sachip->base + SA1111_SKCR);
-
- /*
- * Wait lock time. SA1111 manual _doesn't_
- * specify a figure for this! We choose 100us.
- */
- udelay(100);
-
- /*
- * Enable RCLK. We also ensure that RDYEN is set.
- */
- r |= SKCR_RCLKEN | SKCR_RDYEN;
- sa1111_writel(r, sachip->base + SA1111_SKCR);
-
- /*
- * Wait 14 RCLK cycles for the chip to finish coming out
- * of reset. (RCLK=24MHz). This is 590ns.
- */
- udelay(1);
-
- /*
- * Ensure all clocks are initially off.
- */
- sa1111_writel(0, sachip->base + SA1111_SKPCR);
-
- spin_unlock_irqrestore(&sachip->lock, flags);
-}
-
-/*
- * Configure the SA1111 shared memory controller.
- */
-void
-sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
- unsigned int cas_latency)
-{
- unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC);
-
- if (cas_latency == 3)
- smcr |= SMCR_CLAT;
-
- sa1111_writel(smcr, sachip->base + SA1111_SMCR);
-}
-
-/*
* According to the "Intel StrongARM SA-1111 Microprocessor Companion
* Chip Specification Update" (June 2000), erratum #7, there is a
* significant bug in the SA1111 SDRAM shared memory controller. If
@@ -648,52 +679,6 @@ int sa1111_check_dma_bug(dma_addr_t addr)
return 0;
}
-int sa1111_init(unsigned long phys, unsigned int irq)
-{
- unsigned int val;
- int ret;
-
- ret = sa1111_probe(phys, irq);
- if (ret < 0)
- return ret;
-
- /*
- * We found it. Wake the chip up.
- */
- sa1111_wake(g_sa1111);
-
- /*
- * The SDRAM configuration of the SA1110 and the SA1111 must
- * match. This is very important to ensure that SA1111 accesses
- * don't corrupt the SDRAM. Note that this ungates the SA1111's
- * MBGNT signal, so we must have called sa1110_mb_disable()
- * beforehand.
- */
- sa1111_configure_smc(g_sa1111, 1,
- FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
- FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
-
- /*
- * We only need to turn on DCLK whenever we want to use the
- * DMA. It can otherwise be held firmly in the off position.
- */
- val = sa1111_readl(g_sa1111->base + SA1111_SKPCR);
- sa1111_writel(val | SKPCR_DCLKEN, g_sa1111->base + SA1111_SKPCR);
-
- /*
- * Enable the SA1110 memory bus request and grant signals.
- */
- sa1110_mb_enable();
-
- /*
- * Initialise SA1111 IRQs
- */
- int_dev.irq[0] = irq;
- sa1111_init_irq(&int_dev);
-
- return 0;
-}
-
struct sa1111_save_data {
unsigned int skcr;
unsigned int skpcr;
@@ -717,7 +702,7 @@ struct sa1111_save_data {
static int sa1111_suspend(struct device *dev, u32 state, u32 level)
{
- struct sa1111 *sachip = dev->driver_data;
+ struct sa1111 *sachip = dev_get_drvdata(dev);
unsigned long flags;
char *base;
@@ -789,7 +774,7 @@ static int sa1111_suspend(struct device *dev, u32 state, u32 level)
*/
static int sa1111_resume(struct device *dev, u32 level)
{
- struct sa1111 *sachip = dev->driver_data;
+ struct sa1111 *sachip = dev_get_drvdata(dev);
struct sa1111_save_data *save;
unsigned long flags, id;
char *base;
@@ -809,6 +794,7 @@ static int sa1111_resume(struct device *dev, u32 level)
id = sa1111_readl(sachip->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
__sa1111_remove(sachip);
+ dev_set_drvdata(dev, NULL);
kfree(save);
return 0;
}
@@ -840,18 +826,85 @@ static int sa1111_resume(struct device *dev, u32 level)
return 0;
}
+static int sa1111_probe(struct device *dev)
+{
+ return -ENODEV;
+}
+
+static int sa1111_remove(struct device *dev)
+{
+ struct sa1111 *sachip = dev_get_drvdata(dev);
+
+ if (sachip) {
+ __sa1111_remove(sachip);
+ dev_set_drvdata(dev, NULL);
+
+ kfree(dev->saved_state);
+ dev->saved_state = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * Not sure if this should be on the system bus or not yet.
+ * We really want some way to register a system device at
+ * the per-machine level, and then have this driver pick
+ * up the registered devices.
+ *
+ * We also need to handle the SDRAM configuration for
+ * PXA250/SA1110 machine classes.
+ */
static struct device_driver sa1111_device_driver = {
+ .name = "SA1111",
+ .bus = &system_bus_type,
+ .probe = sa1111_probe,
+ .remove = sa1111_remove,
.suspend = sa1111_suspend,
.resume = sa1111_resume,
};
/*
+ * Register the SA1111 driver with LDM.
+ */
+static int sa1111_driver_init(void)
+{
+ driver_register(&sa1111_device_driver);
+ return 0;
+}
+
+arch_initcall(sa1111_driver_init);
+
+static struct sys_device sa1111_device = {
+ .name = "SA1111",
+ .id = 0,
+ .root = NULL,
+ .dev = {
+ .name = "Intel Corporation SA1111",
+ .driver = &sa1111_device_driver,
+ },
+};
+
+int sa1111_init(unsigned long phys, unsigned int irq)
+{
+ int ret;
+
+ snprintf(sa1111_device.dev.bus_id, sizeof(sa1111_device.dev.bus_id), "%8.8lx", phys);
+
+ ret = sys_device_register(&sa1111_device);
+ if (ret)
+ printk("sa1111 device_register failed: %d\n", ret);
+
+ return __sa1111_probe(&sa1111_device.dev, phys, irq);
+}
+
+/*
* Get the parent device driver (us) structure
* from a child function device
*/
static inline struct sa1111 *sa1111_chip_driver(struct sa1111_dev *sadev)
{
- return (struct sa1111 *)sadev->dev.parent->driver_data;
+ return (struct sa1111 *)dev_get_drvdata(sadev->dev.parent);
}
/*
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index fb05656bdb6a..f8ad035fdf01 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -16,8 +16,10 @@
#include <linux/bitops.h>
#include <linux/init.h>
+#include <asm/cacheflush.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
#include "fault.h"
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 45b70123774c..ff3347e2669f 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -519,6 +519,10 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
bdata->node_boot_start >> PAGE_SHIFT, zhole_size);
}
+#ifndef CONFIG_DISCONTIGMEM
+ mem_map = contig_page_data.node_mem_map;
+#endif
+
/*
* finish off the bad pages once
* the mem_map is initialised
@@ -559,7 +563,9 @@ void __init mem_init(void)
initpages = &__init_end - &__init_begin;
high_memory = (void *)__va(meminfo.end);
+#ifndef CONFIG_DISCONTIGMEM
max_mapnr = virt_to_page(high_memory) - mem_map;
+#endif
/*
* We may have non-contiguous memory.
diff --git a/arch/arm/mm/minicache.c b/arch/arm/mm/minicache.c
index 96ae5be2b642..0ef53e8e4ec0 100644
--- a/arch/arm/mm/minicache.c
+++ b/arch/arm/mm/minicache.c
@@ -15,9 +15,11 @@
*/
#include <linux/init.h>
#include <linux/mm.h>
+
#include <asm/page.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
/*
* 0xffff8000 to 0xffffffff is reserved for any ARM architecture
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 259f7541a875..7898ede4b702 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -13,6 +13,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/bootmem.h>
+#include <linux/highmem.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -20,6 +21,7 @@
#include <asm/rmap.h>
#include <asm/io.h>
#include <asm/setup.h>
+#include <asm/tlbflush.h>
#include <asm/mach/map.h>
@@ -213,6 +215,50 @@ static inline void clear_mapping(unsigned long virt)
pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
}
+struct mem_types {
+ unsigned int prot_pte;
+ unsigned int prot_sect;
+ unsigned int domain;
+};
+
+static struct mem_types mem_types[] __initdata = {
+ [MT_DEVICE] = {
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_WRITE,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
+ .domain = DOMAIN_IO,
+ },
+ [MT_CACHECLEAN] = {
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_CACHEABLE | L_PTE_BUFFERABLE,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_CACHEABLE |
+ PMD_SECT_BUFFERABLE,
+ .domain = DOMAIN_KERNEL,
+ },
+ [MT_MINICLEAN] = {
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_CACHEABLE,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_CACHEABLE,
+ .domain = DOMAIN_KERNEL,
+ },
+ [MT_VECTORS] = {
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_CACHEABLE | L_PTE_BUFFERABLE |
+ L_PTE_EXEC,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_CACHEABLE |
+ PMD_SECT_BUFFERABLE,
+ .domain = DOMAIN_USER,
+ },
+ [MT_MEMORY] = {
+ .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
+ L_PTE_CACHEABLE | L_PTE_BUFFERABLE |
+ L_PTE_EXEC | L_PTE_WRITE,
+ .prot_sect = PMD_TYPE_SECT | PMD_SECT_CACHEABLE |
+ PMD_SECT_BUFFERABLE | PMD_SECT_AP_WRITE,
+ .domain = DOMAIN_KERNEL,
+ }
+};
+
/*
* Create the page directory entries and any necessary
* page tables for the mapping specified by `md'. We
@@ -232,42 +278,9 @@ static void __init create_mapping(struct map_desc *md)
return;
}
- prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY;
- prot_sect = PMD_TYPE_SECT;
-
- switch (md->type) {
- case MT_DEVICE:
- prot_pte |= L_PTE_WRITE;
- prot_sect |= PMD_SECT_AP_WRITE;
- domain = DOMAIN_IO;
- break;
-
- case MT_CACHECLEAN:
- prot_pte |= L_PTE_CACHEABLE | L_PTE_BUFFERABLE;
- prot_sect |= PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE;
- domain = DOMAIN_KERNEL;
- break;
-
- case MT_MINICLEAN:
- prot_pte |= L_PTE_CACHEABLE;
- prot_sect |= PMD_SECT_CACHEABLE;
- domain = DOMAIN_KERNEL;
- break;
-
- case MT_VECTORS:
- prot_pte |= L_PTE_EXEC | L_PTE_CACHEABLE | L_PTE_BUFFERABLE;
- prot_sect |= PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE;
- domain = DOMAIN_USER;
- break;
-
- case MT_MEMORY:
- prot_pte |= L_PTE_WRITE | L_PTE_EXEC | L_PTE_CACHEABLE | L_PTE_BUFFERABLE;
- prot_sect |= PMD_SECT_AP_WRITE | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE;
- domain = DOMAIN_KERNEL;
- break;
- }
-
- prot_sect |= PMD_DOMAIN(domain);
+ domain = mem_types[md->type].domain;
+ prot_pte = mem_types[md->type].prot_pte;
+ prot_sect = mem_types[md->type].prot_sect | PMD_DOMAIN(domain);
virt = md->virtual;
off = md->physical - virt;
diff --git a/arch/arm/mm/proc-syms.c b/arch/arm/mm/proc-syms.c
index c21c843ecd21..fe84d27a9681 100644
--- a/arch/arm/mm/proc-syms.c
+++ b/arch/arm/mm/proc-syms.c
@@ -10,8 +10,10 @@
#include <linux/module.h>
#include <linux/mm.h>
+#include <asm/cacheflush.h>
#include <asm/pgalloc.h>
#include <asm/proc-fns.h>
+#include <asm/tlbflush.h>
#ifndef MULTI_CPU
EXPORT_SYMBOL(cpu_cache_clean_invalidate_all);
@@ -29,11 +31,11 @@ EXPORT_SYMBOL(cpu_set_pte);
EXPORT_SYMBOL(processor);
#endif
-#ifndef MULTI_TLB
-EXPORT_SYMBOL_NOVERS(__cpu_flush_kern_tlb_all);
-EXPORT_SYMBOL_NOVERS(__cpu_flush_user_tlb_mm);
-EXPORT_SYMBOL_NOVERS(__cpu_flush_user_tlb_range);
-EXPORT_SYMBOL_NOVERS(__cpu_flush_user_tlb_page);
-#else
+/*
+ * No module should need to touch the TLB (and currently
+ * no modules do. We export this for "loadkernel" support
+ * (booting a new kernel from within a running kernel.)
+ */
+#ifdef MULTI_TLB
EXPORT_SYMBOL(cpu_tlb);
#endif
diff --git a/arch/arm/mm/tlb-v3.S b/arch/arm/mm/tlb-v3.S
index 270108bb40c0..063d50ab88dd 100644
--- a/arch/arm/mm/tlb-v3.S
+++ b/arch/arm/mm/tlb-v3.S
@@ -13,32 +13,11 @@
*/
#include <linux/linkage.h>
#include <asm/constants.h>
+#include <asm/tlbflush.h>
#include "proc-macros.S"
.align 5
/*
- * v3_flush_user_tlb_mm(mm)
- *
- * Invalidate all TLB entries in a particular address space
- *
- * - mm - mm_struct describing address space
- */
-ENTRY(v3_flush_user_tlb_mm)
- act_mm r1 @ get current->active_mm
- teq r0, r1 @ == mm ?
- movne pc, lr @ no, we dont do anything
-
-/*
- * v3_flush_kern_tlb_all()
- *
- * Invalidate the entire TLB
- */
-ENTRY(v3_flush_kern_tlb_all)
- mov r0, #0
- mcr p15, 0, r0, c5, c0, 0 @ invalidate TLB
- mov pc, lr
-
-/*
* v3_flush_user_tlb_range(start, end, mm)
*
* Invalidate a range of TLB entries in the specified address space.
@@ -62,32 +41,11 @@ ENTRY(v3_flush_kern_tlb_range)
blo 1b
mov pc, lr
-/*
- * v3_flush_user_tlb_page(vaddr,vma)
- *
- * Invalidate the specified page in the specified address space.
- *
- * - vaddr - virtual address (may not be aligned)
- * - vma - vma_struct describing address range
- */
- .align 5
-ENTRY(v3_flush_user_tlb_page)
- vma_vm_mm r2, r1 @ get vma->vm_mm
- act_mm r3 @ get current->active_mm
- teq r2, r3 @ equal
- movne pc, lr @ no
-ENTRY(v3_flush_kern_tlb_page)
- mcr p15, 0, r0, c6, c0, 0 @ invalidate TLB entry
- mov pc, lr
-
.section ".text.init", #alloc, #execinstr
.type v3_tlb_fns, #object
ENTRY(v3_tlb_fns)
- .long v3_flush_kern_tlb_all
- .long v3_flush_user_tlb_mm
.long v3_flush_user_tlb_range
- .long v3_flush_user_tlb_page
.long v3_flush_kern_tlb_range
- .long v3_flush_kern_tlb_page
+ .long v3_tlb_flags
.size v3_tlb_fns, . - v3_tlb_fns
diff --git a/arch/arm/mm/tlb-v4.S b/arch/arm/mm/tlb-v4.S
index 2dd035b2281f..2ab22d9f3454 100644
--- a/arch/arm/mm/tlb-v4.S
+++ b/arch/arm/mm/tlb-v4.S
@@ -14,32 +14,11 @@
*/
#include <linux/linkage.h>
#include <asm/constants.h>
+#include <asm/tlbflush.h>
#include "proc-macros.S"
.align 5
/*
- * v4_flush_user_tlb_mm(mm)
- *
- * Invalidate all TLB entries in a particular address space
- *
- * - mm - mm_struct describing address space
- */
-ENTRY(v4_flush_user_tlb_mm)
- act_mm r1 @ get current->active_mm
- teq r0, r1 @ == mm ?
- movne pc, lr @ no, we dont do anything
-
-/*
- * v4_flush_kern_tlb_all()
- *
- * Invalidate the entire TLB
- */
-ENTRY(v4_flush_kern_tlb_all)
- mov r0, #0
- mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
- mov pc, lr
-
-/*
* v4_flush_user_tlb_range(start, end, mm)
*
* Invalidate a range of TLB entries in the specified user address space.
@@ -65,25 +44,6 @@ ENTRY(v4_flush_user_tlb_range)
mov pc, lr
/*
- * v4_flush_user_tlb_page(vaddr,vma)
- *
- * Invalidate the specified page in the specified address space.
- *
- * - vaddr - virtual address (may not be aligned)
- * - vma - vma_struct describing address range
- */
- .align 5
-ENTRY(v4_flush_user_tlb_page)
- vma_vm_mm r2, r1 @ get vma->vm_mm
- act_mm r3 @ get current->active_mm
- teq r2, r3 @ equal
- movne pc, lr @ no
- vma_vm_flags r2, r1
-.v4_flush_kern_tlb_page:
- mcr p15, 0, r0, c8, c7, 1 @ invalidate TLB entry
- mov pc, lr
-
-/*
* v4_flush_kerm_tlb_range(start, end)
*
* Invalidate a range of TLB entries in the specified kernel
@@ -95,27 +55,11 @@ ENTRY(v4_flush_user_tlb_page)
.globl v4_flush_kern_tlb_range
.equ v4_flush_kern_tlb_range, .v4_flush_kern_tlb_range
-
-/*
- * v4_flush_kern_tlb_page(kaddr)
- *
- * Invalidate the TLB entry for the specified page. The address
- * will be in the kernels virtual memory space. Current uses
- * only require the D-TLB to be invalidated.
- *
- * - kaddr - Kernel virtual memory address
- */
-.globl v4_flush_kern_tlb_page
-.equ v4_flush_kern_tlb_page, .v4_flush_kern_tlb_page
-
.section ".text.init", #alloc, #execinstr
.type v4_tlb_fns, #object
ENTRY(v4_tlb_fns)
- .long v4_flush_kern_tlb_all
- .long v4_flush_user_tlb_mm
.long v4_flush_user_tlb_range
- .long v4_flush_user_tlb_page
.long v4_flush_kern_tlb_range
- .long v4_flush_kern_tlb_page
+ .long v4_tlb_flags
.size v4_tlb_fns, . - v4_tlb_fns
diff --git a/arch/arm/mm/tlb-v4wb.S b/arch/arm/mm/tlb-v4wb.S
index 3cdca44fcfb2..e9f8fb16b635 100644
--- a/arch/arm/mm/tlb-v4wb.S
+++ b/arch/arm/mm/tlb-v4wb.S
@@ -14,35 +14,11 @@
*/
#include <linux/linkage.h>
#include <asm/constants.h>
+#include <asm/tlbflush.h>
#include "proc-macros.S"
.align 5
/*
- * v4wb_flush_user_tlb_mm(mm)
- *
- * Invalidate all TLB entries in a particular address space
- *
- * - mm - mm_struct describing address space
- */
-ENTRY(v4wb_flush_user_tlb_mm)
-ENTRY(v4wbi_flush_user_tlb_mm)
- act_mm r1 @ get current->active_mm
- teq r0, r1 @ == mm ?
- movne pc, lr @ no, we dont do anything
-
-/*
- * v4wb_flush_tlb_all()
- *
- * Invalidate the entire TLB
- */
-ENTRY(v4wb_flush_kern_tlb_all)
-ENTRY(v4wbi_flush_kern_tlb_all)
- mov r0, #0
- mcr p15, 0, r0, c7, c10, 4 @ drain WB
- mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
- mov pc, lr
-
-/*
* v4wb_flush_user_tlb_range(start, end, mm)
*
* Invalidate a range of TLB entries in the specified address space.
@@ -70,28 +46,6 @@ ENTRY(v4wb_flush_user_tlb_range)
mov pc, lr
/*
- * v4wb_flush_user_tlb_page(vaddr,vma)
- *
- * Invalidate the specified page in the specified address space.
- *
- * - vaddr - virtual address (may not be aligned)
- * - vma - vma_struct describing address range
- */
- .align 5
-ENTRY(v4wb_flush_user_tlb_page)
- vma_vm_mm r2, r1 @ get vma->vm_mm
- act_mm r3 @ get current->active_mm
- teq r2, r3 @ equal
- movne pc, lr @ no
- vma_vm_flags r2, r1
- mov r3, #0
- mcr p15, 0, r3, c7, c10, 4 @ drain WB
- tst r2, #VM_EXEC
- mcrne p15, 0, r3, c8, c5, 0 @ invalidate I TLB
- mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
- mov pc, lr
-
-/*
* v4_flush_kerm_tlb_range(start, end)
*
* Invalidate a range of TLB entries in the specified kernel
@@ -113,20 +67,6 @@ ENTRY(v4wb_flush_kern_tlb_range)
mov pc, lr
/*
- * v4_flush_kern_tlb_page(kaddr)
- *
- * Invalidate the TLB entry for the specified page. The address
- * will be in the kernels virtual memory space. Current uses
- * only require the D-TLB to be invalidated.
- *
- * - kaddr - Kernel virtual memory address
- */
-ENTRY(v4wb_flush_kern_tlb_page)
- mcr p15, 0, r3, c8, c5, 0 @ invalidate I TLB
- mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
- mov pc, lr
-
-/*
* These two are optimised for ARM920, ARM922, ARM926, Xscale
*/
@@ -158,28 +98,6 @@ ENTRY(v4wbi_flush_user_tlb_range)
blo 1b
mov pc, lr
-/*
- * v4wb_flush_tlb_page(vaddr,vma)
- *
- * Invalidate the specified page in the specified address space.
- *
- * - vaddr - virtual address (may not be aligned)
- * - vma - vma_struct describing address range
- */
- .align 5
-ENTRY(v4wbi_flush_user_tlb_page)
- vma_vm_mm r2, r1 @ get vma->vm_mm
- act_mm r3 @ get current->active_mm
- teq r2, r3 @ equal
- movne pc, lr @ no
- vma_vm_flags r2, r1
- mov r3, #0
- mcr p15, 0, r3, c7, c10, 4 @ drain WB
- tst r2, #VM_EXEC
- mcrne p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
- mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
- mov pc, lr
-
ENTRY(v4wbi_flush_kern_tlb_range)
mov r3, #0
mcr p15, 0, r3, c7, c10, 4 @ drain WB
@@ -192,29 +110,18 @@ ENTRY(v4wbi_flush_kern_tlb_range)
blo 1b
mov pc, lr
-ENTRY(v4wbi_flush_kern_tlb_page)
- mcr p15, 0, r0, c8, c5, 1 @ invalidate I TLB entry
- mcr p15, 0, r0, c8, c6, 1 @ invalidate D TLB entry
- mov pc, lr
-
.section ".text.init", #alloc, #execinstr
.type v4wb_tlb_fns, #object
ENTRY(v4wb_tlb_fns)
- .long v4wb_flush_kern_tlb_all
- .long v4wb_flush_user_tlb_mm
.long v4wb_flush_user_tlb_range
- .long v4wb_flush_user_tlb_page
.long v4wb_flush_kern_tlb_range
- .long v4wb_flush_kern_tlb_page
+ .long v4wb_tlb_flags
.size v4wb_tlb_fns, . - v4wb_tlb_fns
.type v4wbi_tlb_fns, #object
ENTRY(v4wbi_tlb_fns)
- .long v4wbi_flush_kern_tlb_all
- .long v4wbi_flush_user_tlb_mm
.long v4wbi_flush_user_tlb_range
- .long v4wbi_flush_user_tlb_page
.long v4wbi_flush_kern_tlb_range
- .long v4wbi_flush_kern_tlb_page
+ .long v4wbi_tlb_flags
.size v4wbi_tlb_fns, . - v4wbi_tlb_fns
diff --git a/arch/arm/vmlinux.lds.S b/arch/arm/vmlinux.lds.S
index 008dbc027c57..ec99a51eece9 100644
--- a/arch/arm/vmlinux.lds.S
+++ b/arch/arm/vmlinux.lds.S
@@ -4,13 +4,10 @@
#ifdef CONFIG_ROM_KERNEL
-#define DATAADDR 0x02080000
-#define TEXTADDR 0x03800000
#include "vmlinux-armo-rom.lds.in"
#else
-#define TEXTADDR 0x02080000
#include "vmlinux-armo.lds.in"
#endif
@@ -19,7 +16,6 @@
#ifdef CONFIG_CPU_32
-#define TEXTADDR 0xC0008000
#include "vmlinux-armv.lds.in"
#endif
diff --git a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c
index d7d9939af12c..85b5b9cd8859 100644
--- a/drivers/acorn/block/fd1772.c
+++ b/drivers/acorn/block/fd1772.c
@@ -345,8 +345,6 @@ static void fd_select_drive(int drive);
static void fd_deselect(void);
static void fd_motor_off_timer(unsigned long dummy);
static void check_change(unsigned long dummy);
-static __inline__ void set_head_settle_flag(void);
-static __inline__ int get_head_settle_flag(void);
static void floppy_irqconsequencehandler(void);
static void fd_error(void);
static void do_fd_action(int drive);
@@ -363,7 +361,6 @@ static void fd_times_out(unsigned long dummy);
static void finish_fdc(void);
static void finish_fdc_done(int dummy);
static void floppy_off(unsigned int nr);
-static __inline__ void copy_buffer(void *from, void *to);
static void setup_req_params(int drive);
static void redo_fd_request(void);
static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int
@@ -543,12 +540,12 @@ static void check_change(unsigned long dummy)
* seek operation, because we don't use seeks with verify.
*/
-static __inline__ void set_head_settle_flag(void)
+static inline void set_head_settle_flag(void)
{
HeadSettleFlag = FDC1772CMDADD_E;
}
-static __inline__ int get_head_settle_flag(void)
+static inline int get_head_settle_flag(void)
{
int tmp = HeadSettleFlag;
HeadSettleFlag = 0;
@@ -560,6 +557,15 @@ static __inline__ int get_head_settle_flag(void)
/* General Interrupt Handling */
+static inline void copy_buffer(void *from, void *to)
+{
+ ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
+ int cnt;
+
+ for (cnt = 512 / 4; cnt; cnt--)
+ *p2++ = *p1++;
+}
+
static void (*FloppyIRQHandler) (int status) = NULL;
static void floppy_irqconsequencehandler(void)
@@ -1175,16 +1181,6 @@ static int floppy_revalidate(dev_t dev)
return 0;
}
-static __inline__ void copy_buffer(void *from, void *to)
-{
- ulong *p1 = (ulong *) from, *p2 = (ulong *) to;
- int cnt;
-
- for (cnt = 512 / 4; cnt; cnt--)
- *p2++ = *p1++;
-}
-
-
/* This sets up the global variables describing the current request. */
static void setup_req_params(int drive)
diff --git a/drivers/acorn/char/Makefile b/drivers/acorn/char/Makefile
index 456c7e3c5124..b5cc8486bbd2 100644
--- a/drivers/acorn/char/Makefile
+++ b/drivers/acorn/char/Makefile
@@ -3,18 +3,11 @@
#
# All the objects that export symbols.
-obj-arc := keyb_arc.o
-obj-rpc := keyb_ps2.o
-obj-clps7500 := keyb_ps2.o defkeymap-acorn.o
-
-obj-$(CONFIG_RPCMOUSE) += mouse_rpc.o
-obj-$(CONFIG_ATOMWIDE_SERIAL) += serial-atomwide.o
-obj-$(CONFIG_DUALSP_SERIAL) += serial-dualsp.o
-obj-$(CONFIG_ARCH_ACORN) += defkeymap-acorn.o i2c.o pcf8583.o
-obj-$(CONFIG_L7200_KEYB) += defkeymap-l7200.o keyb_l7200.o
+obj-arc := keyb_arc.o defkeymap-acorn.o
-# Do the i2c and rtc last
-obj-y += $(obj-$(MACHINE))
+obj-$(CONFIG_ARCH_ACORN) += i2c.o pcf8583.o
+obj-$(CONFIG_L7200_KEYB) += defkeymap-l7200.o keyb_l7200.o
+obj-y += $(obj-$(MACHINE))
include $(TOPDIR)/Rules.make
diff --git a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c
index e01e017dfcbe..6a5c0da68983 100644
--- a/drivers/acorn/char/i2c.c
+++ b/drivers/acorn/char/i2c.c
@@ -132,7 +132,7 @@ static int k_set_rtc_time(void)
if (rtc_command(RTC_GETDATETIME, &old_rtctm))
return 0;
- new_rtctm.cs = xtime.tv_usec / 10000;
+ new_rtctm.cs = xtime.tv_nsec / 10000000;
new_rtctm.secs = nowtime % 60; nowtime /= 60;
new_rtctm.mins = nowtime % 60; nowtime /= 60;
new_rtctm.hours = nowtime % 24;
@@ -283,7 +283,7 @@ static int ioc_client_reg(struct i2c_client *client)
rtc_client = client;
get_rtc_time(&rtctm, &year);
- xtime.tv_usec = rtctm.cs * 10000;
+ xtime.tv_nsec = rtctm.cs * 10000000;
xtime.tv_sec = mktime(year, rtctm.mon, rtctm.mday,
rtctm.hours, rtctm.mins, rtctm.secs);
set_rtc = k_set_rtc_time;
diff --git a/drivers/acorn/char/keyb_ps2.c b/drivers/acorn/char/keyb_ps2.c
deleted file mode 100644
index 033c111572a9..000000000000
--- a/drivers/acorn/char/keyb_ps2.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * linux/drivers/acorn/char/keyb_ps2.c
- *
- * 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 version 2 as
- * published by the Free Software Foundation.
- *
- * Keyboard driver for RiscPC ARM Linux.
- *
- * Note!!! This driver talks directly to the keyboard.
- */
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/ptrace.h>
-#include <linux/signal.h>
-#include <linux/timer.h>
-#include <linux/random.h>
-#include <linux/ctype.h>
-#include <linux/kbd_ll.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-
-#include <asm/bitops.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-#include <asm/keyboard.h>
-#include <asm/io.h>
-#include <asm/hardware/iomd.h>
-#include <asm/system.h>
-
-extern struct tasklet_struct keyboard_tasklet;
-extern void kbd_reset_kdown(void);
-int kbd_read_mask;
-
-#define TX_DONE 0
-#define TX_SENT 1
-#define TX_SEND 2
-
-static volatile int tx_state;
-
-#define VERSION 100
-
-#define KBD_REPORT_ERR
-#define KBD_REPORT_UNKN
-
-#define KBD_ESCAPEE0 0xe0 /* in */
-#define KBD_ESCAPEE1 0xe1 /* in */
-
-#define ESCE0(x) (0xe000|(x))
-#define ESCE1(x) (0xe100|(x))
-
-#define KBD_BAT 0xaa /* in */
-#define KBD_SETLEDS 0xed /* out */
-#define KBD_ECHO 0xee /* in/out */
-#define KBD_BREAK 0xf0 /* in */
-#define KBD_TYPRATEDLY 0xf3 /* out */
-#define KBD_SCANENABLE 0xf4 /* out */
-#define KBD_DEFDISABLE 0xf5 /* out */
-#define KBD_DEFAULT 0xf6 /* out */
-#define KBD_ACK 0xfa /* in */
-#define KBD_DIAGFAIL 0xfd /* in */
-#define KBD_RESEND 0xfe /* in/out */
-#define KBD_RESET 0xff /* out */
-
-#define CODE_BREAK 1
-#define CODE_ESCAPEE0 2
-#define CODE_ESCAPEE1 4
-#define CODE_ESCAPE12 8
-
-#define K_NONE 0x7f
-#define K_ESC 0x00
-#define K_F1 0x01
-#define K_F2 0x02
-#define K_F3 0x03
-#define K_F4 0x04
-#define K_F5 0x05
-#define K_F6 0x06
-#define K_F7 0x07
-#define K_F8 0x08
-#define K_F9 0x09
-#define K_F10 0x0a
-#define K_F11 0x0b
-#define K_F12 0x0c
-#define K_PRNT 0x0d
-#define K_SCRL 0x0e
-#define K_BRK 0x0f
-#define K_AGR 0x10
-#define K_1 0x11
-#define K_2 0x12
-#define K_3 0x13
-#define K_4 0x14
-#define K_5 0x15
-#define K_6 0x16
-#define K_7 0x17
-#define K_8 0x18
-#define K_9 0x19
-#define K_0 0x1a
-#define K_MINS 0x1b
-#define K_EQLS 0x1c
-#define K_BKSP 0x1e
-#define K_INS 0x1f
-#define K_HOME 0x20
-#define K_PGUP 0x21
-#define K_NUML 0x22
-#define KP_SLH 0x23
-#define KP_STR 0x24
-#define KP_MNS 0x3a
-#define K_TAB 0x26
-#define K_Q 0x27
-#define K_W 0x28
-#define K_E 0x29
-#define K_R 0x2a
-#define K_T 0x2b
-#define K_Y 0x2c
-#define K_U 0x2d
-#define K_I 0x2e
-#define K_O 0x2f
-#define K_P 0x30
-#define K_LSBK 0x31
-#define K_RSBK 0x32
-#define K_ENTR 0x47
-#define K_DEL 0x34
-#define K_END 0x35
-#define K_PGDN 0x36
-#define KP_7 0x37
-#define KP_8 0x38
-#define KP_9 0x39
-#define KP_PLS 0x4b
-#define K_CAPS 0x5d
-#define K_A 0x3c
-#define K_S 0x3d
-#define K_D 0x3e
-#define K_F 0x3f
-#define K_G 0x40
-#define K_H 0x41
-#define K_J 0x42
-#define K_K 0x43
-#define K_L 0x44
-#define K_SEMI 0x45
-#define K_SQOT 0x46
-#define K_HASH 0x1d
-#define KP_4 0x48
-#define KP_5 0x49
-#define KP_6 0x4a
-#define K_LSFT 0x4c
-#define K_BSLH 0x33
-#define K_Z 0x4e
-#define K_X 0x4f
-#define K_C 0x50
-#define K_V 0x51
-#define K_B 0x52
-#define K_N 0x53
-#define K_M 0x54
-#define K_COMA 0x55
-#define K_DOT 0x56
-#define K_FSLH 0x57
-#define K_RSFT 0x58
-#define K_UP 0x59
-#define KP_1 0x5a
-#define KP_2 0x5b
-#define KP_3 0x5c
-#define KP_ENT 0x67
-#define K_LCTL 0x3b
-#define K_LALT 0x5e
-#define K_SPCE 0x5f
-#define K_RALT 0x60
-#define K_RCTL 0x61
-#define K_LEFT 0x62
-#define K_DOWN 0x63
-#define K_RGHT 0x64
-#define KP_0 0x65
-#define KP_DOT 0x66
-
-static unsigned char keycode_translate[256] =
-{
-/* 00 */ K_NONE, K_F9 , K_NONE, K_F5 , K_F3 , K_F1 , K_F2 , K_F12 ,
-/* 08 */ K_NONE, K_F10 , K_F8 , K_F6 , K_F4 , K_TAB , K_AGR , K_NONE,
-/* 10 */ K_NONE, K_LALT, K_LSFT, K_NONE, K_LCTL, K_Q , K_1 , K_NONE,
-/* 18 */ K_NONE, K_NONE, K_Z , K_S , K_A , K_W , K_2 , K_NONE,
-/* 20 */ K_NONE, K_C , K_X , K_D , K_E , K_4 , K_3 , K_NONE,
-/* 28 */ K_NONE, K_SPCE, K_V , K_F , K_T , K_R , K_5 , K_NONE,
-/* 30 */ K_NONE, K_N , K_B , K_H , K_G , K_Y , K_6 , K_NONE,
-/* 38 */ K_NONE, K_NONE, K_M , K_J , K_U , K_7 , K_8 , K_NONE,
-/* 40 */ K_NONE, K_COMA, K_K , K_I , K_O , K_0 , K_9 , K_NONE,
-/* 48 */ K_NONE, K_DOT , K_FSLH, K_L , K_SEMI, K_P , K_MINS, K_NONE,
-/* 50 */ K_NONE, K_NONE, K_SQOT, K_NONE, K_LSBK, K_EQLS, K_NONE, K_NONE,
-/* 58 */ K_CAPS, K_RSFT, K_ENTR, K_RSBK, K_NONE, K_HASH, K_NONE, K_NONE,
-/* 60 */ K_NONE, K_BSLH, K_NONE, K_NONE, K_NONE, K_NONE, K_BKSP, K_NONE,
-/* 68 */ K_NONE, KP_1 , K_NONE, KP_4 , KP_7 , K_NONE, K_NONE, K_NONE,
-/* 70 */ KP_0 , KP_DOT, KP_2 , KP_5 , KP_6 , KP_8 , K_ESC , K_NUML,
-/* 78 */ K_F11 , KP_PLS, KP_3 , KP_MNS, KP_STR, KP_9 , K_SCRL, K_NONE,
- K_NONE, K_NONE, K_NONE, K_F7 , K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
- K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE
-};
-
-#ifdef CONFIG_MAGIC_SYSRQ
-static unsigned char ps2kbd_sysrq_xlate[] =
-{
- 27, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- '`', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', '0', '-', '=', '£', 127, 0,
- 0, 0, 0, '/', '*', '#', 9, 'q',
- 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o',
- 'p', '[', ']', '\\', 22, 23, 25, '7',
- '8', '9', '-', 0, 'a', 's', 'd', 'f',
- 'g', 'h', 'j', 'k', 'l', ';', '\'', 13,
- '4', '5', '6', '+', 0, 0, 'z', 'x',
- 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
- 0, 0, '1', '2', '3', 0, 0, ' ',
- 0, 0, 0, 0, 0, '0', '.', 10,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
-};
-#endif
-
-static inline void ps2kbd_key(unsigned int keycode, unsigned int up_flag)
-{
- handle_scancode(keycode, !up_flag);
-}
-
-static inline void ps2kbd_sendbyte(unsigned char val)
-{
- int tries = 3, timeout = 1000;
-
- tx_state = TX_SEND;
-
- do {
- switch (tx_state) {
- case TX_SEND:
- tx_state = TX_SENT;
- timeout = 1000;
- tries --;
-
- while(!(iomd_readb(IOMD_KCTRL) & (1 << 7)));
- iomd_writeb(val, IOMD_KARTTX);
- break;
-
- case TX_SENT:
- udelay(1000);
- if (--timeout == 0) {
- printk(KERN_ERR "Keyboard timeout\n");
- tx_state = TX_DONE;
- }
- break;
-
- case TX_DONE:
- break;
- }
- } while (tries > 0 && tx_state != TX_DONE);
-}
-
-static unsigned char status;
-static unsigned char ncodes;
-static unsigned char bi;
-static unsigned char buffer[4];
-
-static inline void ps2kbd_reset(void)
-{
- status = 0;
- kbd_reset_kdown();
-}
-
-static void handle_rawcode(int keyval)
-{
- int keysym;
-
- if (keyval > 0x83) {
- switch (keyval) {
- case KBD_ESCAPEE0:
- ncodes = 2;
- bi = 0;
- break;
-
- case KBD_ESCAPEE1:
- ncodes = 3;
- bi = 0;
- break;
-
- case KBD_ACK:
- tx_state = TX_DONE;
- return;
-
- case KBD_RESEND:
- tx_state = TX_SEND;
- return;
-
- case KBD_BREAK:
- status |= CODE_BREAK;
- return;
-
- default:
- return;
- }
- }
-
- if (ncodes) {
- buffer[bi++] = keyval;
- ncodes -= 1;
- if (ncodes)
- return;
- keysym = K_NONE;
- switch (buffer[0] << 8 | buffer[1]) {
- case ESCE0(0x11): keysym = K_RALT; break;
- case ESCE0(0x14): keysym = K_RCTL; break;
- /*
- * take care of MS extra keys (actually
- * 0x7d - 0x7f, but last one is already K_NONE
- */
- case ESCE0(0x1f): keysym = 124; break;
- case ESCE0(0x27): keysym = 125; break;
- case ESCE0(0x2f): keysym = 126; break;
- case ESCE0(0x4a): keysym = KP_SLH; break;
- case ESCE0(0x5a): keysym = KP_ENT; break;
- case ESCE0(0x69): keysym = K_END; break;
- case ESCE0(0x6b): keysym = K_LEFT; break;
- case ESCE0(0x6c): keysym = K_HOME; break;
- case ESCE0(0x70): keysym = K_INS; break;
- case ESCE0(0x71): keysym = K_DEL; break;
- case ESCE0(0x72): keysym = K_DOWN; break;
- case ESCE0(0x74): keysym = K_RGHT; break;
- case ESCE0(0x75): keysym = K_UP; break;
- case ESCE0(0x7a): keysym = K_PGDN; break;
- case ESCE0(0x7c): keysym = K_PRNT; break;
- case ESCE0(0x7d): keysym = K_PGUP; break;
- case ESCE1(0x14):
- if (buffer[2] == 0x77)
- keysym = K_BRK;
- break;
- case ESCE0(0x12): /* ignore escaped shift key */
- status = 0;
- return;
- }
- } else {
- bi = 0;
- keysym = keycode_translate[keyval];
- }
-
- if (keysym != K_NONE)
- ps2kbd_key(keysym, status & CODE_BREAK);
- status = 0;
-}
-
-static void ps2kbd_leds(unsigned char leds)
-{
- ps2kbd_sendbyte(KBD_SETLEDS);
- ps2kbd_sendbyte(leds);
- ps2kbd_sendbyte(KBD_SCANENABLE);
-}
-
-static void ps2kbd_rx(int irq, void *dev_id, struct pt_regs *regs)
-{
- kbd_pt_regs = regs;
-
- while (iomd_readb(IOMD_KCTRL) & (1 << 5))
- handle_rawcode(iomd_readb(IOMD_KARTRX));
- tasklet_schedule(&keyboard_tasklet);
-}
-
-static void ps2kbd_tx(int irq, void *dev_id, struct pt_regs *regs)
-{
-}
-
-static int ps2kbd_translate(unsigned char scancode, unsigned char *keycode, char rawmode)
-{
- *keycode = scancode;
- return 1;
-}
-
-static char ps2kbd_unexpected_up(unsigned char scancode)
-{
- return 0200;
-}
-
-int __init ps2kbd_init_hw(void)
-{
- /* Reset the keyboard state machine. */
- iomd_writeb(0, IOMD_KCTRL);
- iomd_writeb(8, IOMD_KCTRL);
- iomd_readb(IOMD_KARTRX);
-
- if (request_irq (IRQ_KEYBOARDRX, ps2kbd_rx, 0, "keyboard", NULL) != 0)
- panic("Could not allocate keyboard receive IRQ!");
- if (request_irq (IRQ_KEYBOARDTX, ps2kbd_tx, 0, "keyboard", NULL) != 0)
- panic("Could not allocate keyboard transmit IRQ!");
-
- k_translate = ps2kbd_translate;
- k_unexpected_up = ps2kbd_unexpected_up;
- k_leds = ps2kbd_leds;
-#ifdef CONFIG_MAGIC_SYSRQ
- k_sysrq_xlate = ps2kbd_sysrq_xlate;
- k_sysrq_key = 13;
-#endif
-
- return 0;
-}
diff --git a/drivers/acorn/char/mouse_rpc.c b/drivers/acorn/char/mouse_rpc.c
deleted file mode 100644
index bf6d2fd25923..000000000000
--- a/drivers/acorn/char/mouse_rpc.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * linux/drivers/char/mouse_rpc.c
- *
- * Copyright (C) 1996-1998 Russell King
- *
- * 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 handles the Acorn RiscPCs mouse. We basically have a couple
- * of hardware registers that track the sensor count for the X-Y movement
- * and another register holding the button state. On every VSYNC interrupt
- * we read the complete state and then work out if something has changed.
- */
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/hardware/iomd.h>
-
-#include "../../char/busmouse.h"
-
-static short old_x, old_y, old_b;
-static int mousedev;
-
-void
-mouse_rpc_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
- short x, y, dx, dy;
- int buttons;
-
- x = (short)iomd_readl(IOMD_MOUSEX);
- y = (short)iomd_readl(IOMD_MOUSEY);
- buttons = (__raw_readl(0xe0310000) >> 4) & 7;
-
- dx = x - old_x;
- old_x = x;
- dy = y - old_y;
- old_y = y;
-
- if (dx || dy || buttons != old_b) {
- busmouse_add_movementbuttons(mousedev, dx, dy, buttons);
- old_b = buttons;
- }
-}
-
-static struct busmouse rpcmouse = {
- 6, "arcmouse", NULL, NULL, NULL, 7
-};
-
-static int __init mouse_rpc_init(void)
-{
- mousedev = register_busmouse(&rpcmouse);
-
- if (mousedev < 0)
- printk("rpcmouse: could not register mouse driver\n");
- else {
- old_x = (short)iomd_readl(IOMD_MOUSEX);
- old_y = (short)iomd_readl(IOMD_MOUSEY);
- old_b = (__raw_readl(0xe0310000) >> 4) & 7;
- if (request_irq(IRQ_VSYNCPULSE, mouse_rpc_irq, SA_SHIRQ, "mouse", &mousedev)) {
- printk("rpcmouse: unable to allocate VSYNC interrupt\n");
- unregister_busmouse(mousedev);
- mousedev = -1;
- }
- }
-
- return mousedev >= 0 ? 0 : -ENODEV;
-}
-
-static void __exit mouse_rpc_exit(void)
-{
- if (mousedev >= 0) {
- unregister_busmouse(mousedev);
- free_irq(IRQ_VSYNCPULSE, &mousedev);
- }
-}
-
-module_init(mouse_rpc_init);
-module_exit(mouse_rpc_exit);
-
-MODULE_AUTHOR("Russell King");
-MODULE_DESCRIPTION("RiscPC mouse driver");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/acorn/char/serial-atomwide.c b/drivers/acorn/char/serial-atomwide.c
deleted file mode 100644
index 8f55b80c31de..000000000000
--- a/drivers/acorn/char/serial-atomwide.c
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/drivers/char/serial-atomwide.c
- *
- * Copyright (C) 1996 Russell King.
- *
- * 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.
- *
- * Changelog:
- * 02-05-1996 RMK Created
- * 07-05-1996 RMK Altered for greater number of cards.
- * 30-07-1996 RMK Now uses generic card code.
- */
-#define MY_CARD_LIST { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL }
-#define MY_NUMPORTS 3
-#define MY_BAUD_BASE (7372800 / 16)
-#define MY_BASE_ADDRESS(ec) \
- ecard_address ((ec), ECARD_IOC, ECARD_SLOW) + (0x2000 >> 2)
-#define MY_PORT_ADDRESS(port,cardaddr) \
- ((cardaddr) + 0x200 - (port) * 0x100)
-
-#include "serial-card.c"
diff --git a/drivers/acorn/char/serial-card.c b/drivers/acorn/char/serial-card.c
deleted file mode 100644
index ae05095bb6bc..000000000000
--- a/drivers/acorn/char/serial-card.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * linux/drivers/acorn/char/serial-card.c
- *
- * Copyright (C) 1996-1999 Russell King.
- *
- * 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.
- *
- * A generic handler of serial expansion cards that use 16550s or
- * the like.
- *
- * Definitions:
- * MY_PRODS Product numbers to identify this card by
- * MY_MANUS Manufacturer numbers to identify this card by
- * MY_NUMPORTS Number of ports per card
- * MY_BAUD_BASE Baud base for the card
- * MY_INIT Initialisation routine name
- * MY_BASE_ADDRESS(ec) Return base address for ports
- * MY_PORT_ADDRESS
- * (port,cardaddr) Return address for port using base address
- * from above.
- *
- * Changelog:
- * 30-07-1996 RMK Created
- * 22-04-1998 RMK Removed old register_pre_init_serial
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/serial.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-
-#include <asm/ecard.h>
-#include <asm/string.h>
-
-#ifndef NUM_SERIALS
-#define NUM_SERIALS MY_NUMPORTS * MAX_ECARDS
-#endif
-
-static int serial_ports[NUM_SERIALS];
-static int serial_pcount;
-static int serial_addr[NUM_SERIALS];
-static struct expansion_card *expcard[MAX_ECARDS];
-
-static const card_ids serial_cids[] = { MY_CARD_LIST, { 0xffff, 0xffff } };
-
-static inline int serial_register_onedev (unsigned long port, int irq)
-{
- struct serial_struct req;
-
- memset(&req, 0, sizeof(req));
- req.baud_base = MY_BAUD_BASE;
- req.irq = irq;
- req.port = port;
- req.flags = 0;
-
- return register_serial(&req);
-}
-
-static int __init serial_card_init(void)
-{
- int card = 0;
-
- ecard_startfind ();
-
- do {
- struct expansion_card *ec;
- unsigned long cardaddr;
- int port;
-
- ec = ecard_find (0, serial_cids);
- if (!ec)
- break;
-
- cardaddr = MY_BASE_ADDRESS(ec);
-
- for (port = 0; port < MY_NUMPORTS; port ++) {
- unsigned long address;
- int line;
-
- address = MY_PORT_ADDRESS(port, cardaddr);
-
- line = serial_register_onedev (address, ec->irq);
- if (line < 0)
- break;
- serial_ports[serial_pcount] = line;
- serial_addr[serial_pcount] = address;
- serial_pcount += 1;
- }
-
- if (port) {
- ecard_claim (ec);
- expcard[card] = ec;
- } else
- break;
- } while (++card < MAX_ECARDS);
- return card ? 0 : -ENODEV;
-}
-
-static void __exit serial_card_exit(void)
-{
- int i;
-
- for (i = 0; i < serial_pcount; i++) {
- unregister_serial(serial_ports[i]);
- release_region(serial_addr[i], 8);
- }
-
- for (i = 0; i < MAX_ECARDS; i++)
- if (expcard[i])
- ecard_release (expcard[i]);
-}
-
-MODULE_AUTHOR("Russell King");
-MODULE_LICENSE("GPL");
-
-module_init(serial_card_init);
-module_exit(serial_card_exit);
diff --git a/drivers/acorn/char/serial-dualsp.c b/drivers/acorn/char/serial-dualsp.c
deleted file mode 100644
index dcd26c1f8d29..000000000000
--- a/drivers/acorn/char/serial-dualsp.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * linux/drivers/acorn/char/serial-dualsp.c
- *
- * Copyright (C) 1996 Russell King.
- *
- * 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.
- *
- * Changelog:
- * 30-07-1996 RMK Created
- */
-#define MY_CARD_LIST { MANU_SERPORT, PROD_SERPORT_DSPORT }
-#define MY_NUMPORTS 2
-#define MY_BAUD_BASE (3686400 / 16)
-#define MY_BASE_ADDRESS(ec) \
- ecard_address (ec, ECARD_IOC, ECARD_SLOW) + (0x2000 >> 2)
-#define MY_PORT_ADDRESS(port,cardaddress) \
- ((cardaddress) + (port) * 8)
-
-#include "serial-card.c"
diff --git a/drivers/acorn/net/ether1.c b/drivers/acorn/net/ether1.c
index 9b91f7642abb..d20d361c85a6 100644
--- a/drivers/acorn/net/ether1.c
+++ b/drivers/acorn/net/ether1.c
@@ -43,6 +43,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
+#include <linux/device.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -80,11 +81,6 @@ static char version[] __initdata = "ether1 ethernet driver (c) 2000 Russell King
#define BUS_16 16
#define BUS_8 8
-static const card_ids __init ether1_cids[] = {
- { MANU_ACORN, PROD_ACORN_ETHER1 },
- { 0xffff, 0xffff }
-};
-
/* ------------------------------------------------------------------------- */
#define DISABLEIRQS 1
@@ -647,6 +643,12 @@ ether1_open (struct net_device *dev)
{
struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+ printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
+ dev->name);
+ return -EINVAL;
+ }
+
if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
return -EAGAIN;
@@ -971,6 +973,23 @@ ether1_getstats (struct net_device *dev)
return &priv->stats;
}
+static int
+ether1_set_mac_address(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ /*
+ * We'll set the MAC address on the chip when we open it.
+ */
+
+ return 0;
+}
+
/*
* Set or clear the multicast filter for this adaptor.
* num_addrs == -1 Promiscuous mode, receive all packets.
@@ -993,19 +1012,22 @@ static void __init ether1_banner(void)
printk(KERN_INFO "%s", version);
}
-static struct net_device * __init ether1_init_one(struct expansion_card *ec)
+static int __devinit
+ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct net_device *dev;
struct ether1_priv *priv;
- int i;
+ int i, ret = 0;
ether1_banner();
ecard_claim(ec);
dev = init_etherdev(NULL, sizeof(struct ether1_priv));
- if (!dev)
+ if (!dev) {
+ ret = -ENOMEM;
goto out;
+ }
SET_MODULE_OWNER(dev);
@@ -1019,8 +1041,10 @@ static struct net_device * __init ether1_init_one(struct expansion_card *ec)
request_region(dev->base_addr + 0x800, 4096, dev->name);
priv = (struct ether1_priv *)dev->priv;
- if ((priv->bus_type = ether1_reset(dev)) == 0)
+ if ((priv->bus_type = ether1_reset(dev)) == 0) {
+ ret = -ENODEV;
goto release;
+ }
printk(KERN_INFO "%s: ether1 in slot %d, ",
dev->name, ec->slot_no);
@@ -1030,16 +1054,21 @@ static struct net_device * __init ether1_init_one(struct expansion_card *ec)
printk ("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
}
- if (ether1_init_2(dev))
+ if (ether1_init_2(dev)) {
+ ret = -ENODEV;
goto release;
+ }
dev->open = ether1_open;
dev->stop = ether1_close;
dev->hard_start_xmit = ether1_sendpacket;
dev->get_stats = ether1_getstats;
dev->set_multicast_list = ether1_setmulticastlist;
+ dev->set_mac_address = ether1_set_mac_address;
dev->tx_timeout = ether1_timeout;
dev->watchdog_timeo = 5 * HZ / 100;
+
+ ecard_set_drvdata(ec, dev);
return 0;
release:
@@ -1049,55 +1078,46 @@ release:
kfree(dev);
out:
ecard_release(ec);
- return dev;
+ return ret;
}
-static struct expansion_card *e_card[MAX_ECARDS];
-static struct net_device *e_dev[MAX_ECARDS];
-
-static int __init ether1_init(void)
+static void __devexit ether1_remove(struct expansion_card *ec)
{
- int i, ret = -ENODEV;
+ struct net_device *dev = ecard_get_drvdata(ec);
- ecard_startfind();
+ ecard_set_drvdata(ec, NULL);
- for (i = 0; i < MAX_ECARDS; i++) {
- struct expansion_card *ec;
- struct net_device *dev;
+ unregister_netdev(dev);
- ec = ecard_find(0, ether1_cids);
- if (!ec)
- break;
+ release_region(dev->base_addr, 16);
+ release_region(dev->base_addr + 0x800, 4096);
+ kfree(dev);
- dev = ether1_init_one(ec);
- if (!dev)
- break;
+ ecard_release(ec);
+}
- e_card[i] = ec;
- e_dev[i] = dev;
- ret = 0;
- }
+static const struct ecard_id ether1_ids[] = {
+ { MANU_ACORN, PROD_ACORN_ETHER1 },
+ { 0xffff, 0xffff }
+};
- return ret;
+static struct ecard_driver ether1_driver = {
+ .probe = ether1_probe,
+ .remove = __devexit_p(ether1_remove),
+ .id_table = ether1_ids,
+ .drv = {
+ .name = "ether1",
+ },
+};
+
+static int __init ether1_init(void)
+{
+ return ecard_register_driver(&ether1_driver);
}
static void __exit ether1_exit(void)
{
- int i;
-
- for (i = 0; i < MAX_ECARDS; i++) {
- if (e_dev[i]) {
- unregister_netdev(e_dev[i]);
- release_region(e_dev[i]->base_addr, 16);
- release_region(e_dev[i]->base_addr + 0x800, 4096);
- kfree(e_dev[i]);
- e_dev[i] = NULL;
- }
- if (e_card[i]) {
- ecard_release(e_card[i]);
- e_card[i] = NULL;
- }
- }
+ ecard_remove_driver(&ether1_driver);
}
module_init(ether1_init);
diff --git a/drivers/acorn/net/ether3.c b/drivers/acorn/net/ether3.c
index 4f5dac26ad4d..1300a42e2b03 100644
--- a/drivers/acorn/net/ether3.c
+++ b/drivers/acorn/net/ether3.c
@@ -61,6 +61,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
+#include <linux/device.h>
#include <linux/init.h>
#include <linux/delay.h>
@@ -75,12 +76,6 @@ static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.Kin
#include "ether3.h"
static unsigned int net_debug = NET_DEBUG;
-static const card_ids __init ether3_cids[] = {
- { MANU_ANT2, PROD_ANT_ETHER3 },
- { MANU_ANT, PROD_ANT_ETHER3 },
- { MANU_ANT, PROD_ANT_ETHERB },
- { 0xffff, 0xffff }
-};
static void ether3_setmulticastlist(struct net_device *dev);
static int ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt);
@@ -417,6 +412,12 @@ ether3_probe_bus_16(struct net_device *dev, int val)
static int
ether3_open(struct net_device *dev)
{
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+ printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
+ dev->name);
+ return -EINVAL;
+ }
+
if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev))
return -EAGAIN;
@@ -460,6 +461,23 @@ static struct net_device_stats *ether3_getstats(struct net_device *dev)
return &priv->stats;
}
+static int
+ether3_set_mac_address(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ /*
+ * We'll set the MAC address on the chip when we open it.
+ */
+
+ return 0;
+}
+
/*
* Set or clear promiscuous/multicast mode filter for this adaptor.
*
@@ -784,6 +802,7 @@ static const char * __init
ether3_get_dev(struct net_device *dev, struct expansion_card *ec)
{
const char *name = "ether3";
+
dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
dev->irq = ec->irq;
@@ -796,38 +815,44 @@ ether3_get_dev(struct net_device *dev, struct expansion_card *ec)
ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr);
ec->irqmask = 0xf0;
- if (ether3_addr(dev->dev_addr, ec))
- name = NULL;
+ ether3_addr(dev->dev_addr, ec);
return name;
}
-static struct net_device * __init ether3_init_one(struct expansion_card *ec)
+static int __devinit
+ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct net_device *dev;
struct dev_priv *priv;
const char *name;
- int i, bus_type;
+ int i, bus_type, ret;
ether3_banner();
ecard_claim(ec);
dev = init_etherdev(NULL, sizeof(struct dev_priv));
- if (!dev)
+ if (!dev) {
+ ret = -ENOMEM;
goto out;
+ }
SET_MODULE_OWNER(dev);
name = ether3_get_dev(dev, ec);
- if (!name)
+ if (!name) {
+ ret = -ENODEV;
goto free;
+ }
/*
* this will not fail - the nature of the bus ensures this
*/
- if (!request_region(dev->base_addr, 128, dev->name))
+ if (!request_region(dev->base_addr, 128, dev->name)) {
+ ret = -EBUSY;
goto free;
+ }
priv = (struct dev_priv *) dev->priv;
@@ -852,11 +877,13 @@ static struct net_device * __init ether3_init_one(struct expansion_card *ec)
switch (bus_type) {
case BUS_UNKNOWN:
printk(KERN_ERR "%s: unable to identify bus width\n", dev->name);
+ ret = -ENODEV;
goto failed;
case BUS_8:
printk(KERN_ERR "%s: %s found, but is an unsupported "
"8-bit card\n", dev->name, name);
+ ret = -ENODEV;
goto failed;
default:
@@ -867,16 +894,21 @@ static struct net_device * __init ether3_init_one(struct expansion_card *ec)
for (i = 0; i < 6; i++)
printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
- if (ether3_init_2(dev))
+ if (ether3_init_2(dev)) {
+ ret = -ENODEV;
goto failed;
+ }
dev->open = ether3_open;
dev->stop = ether3_close;
dev->hard_start_xmit = ether3_sendpacket;
dev->get_stats = ether3_getstats;
dev->set_multicast_list = ether3_setmulticastlist;
+ dev->set_mac_address = ether3_set_mac_address;
dev->tx_timeout = ether3_timeout;
dev->watchdog_timeo = 5 * HZ / 100;
+
+ ecard_set_drvdata(ec, dev);
return 0;
failed:
@@ -886,54 +918,46 @@ free:
kfree(dev);
out:
ecard_release(ec);
- return NULL;
+ return ret;
}
-static struct expansion_card *e_card[MAX_ECARDS];
-static struct net_device *e_dev[MAX_ECARDS];
-
-static int ether3_init(void)
+static void __devexit ether3_remove(struct expansion_card *ec)
{
- int i, ret = -ENODEV;
+ struct net_device *dev = ecard_get_drvdata(ec);
- ecard_startfind();
+ ecard_set_drvdata(ec, NULL);
- for (i = 0; i < MAX_ECARDS; i++) {
- struct net_device *dev;
- struct expansion_card *ec;
+ unregister_netdev(dev);
+ release_region(dev->base_addr, 128);
+ kfree(dev);
- ec = ecard_find(0, ether3_cids);
- if (!ec)
- break;
+ ecard_release(ec);
+}
- dev = ether3_init_one(ec);
- if (!dev)
- break;
+static const struct ecard_id ether3_ids[] = {
+ { MANU_ANT2, PROD_ANT_ETHER3 },
+ { MANU_ANT, PROD_ANT_ETHER3 },
+ { MANU_ANT, PROD_ANT_ETHERB },
+ { 0xffff, 0xffff }
+};
- e_card[i] = ec;
- e_dev[i] = dev;
- ret = 0;
- }
+static struct ecard_driver ether3_driver = {
+ .probe = ether3_probe,
+ .remove = __devexit_p(ether3_remove),
+ .id_table = ether3_ids,
+ .drv = {
+ .name = "ether3",
+ },
+};
- return ret;
+static int __init ether3_init(void)
+{
+ return ecard_register_driver(&ether3_driver);
}
-static void ether3_exit(void)
+static void __exit ether3_exit(void)
{
- int i;
-
- for (i = 0; i < MAX_ECARDS; i++) {
- if (e_dev[i]) {
- unregister_netdev(e_dev[i]);
- release_region(e_dev[i]->base_addr, 128);
- kfree(e_dev[i]);
- e_dev[i] = NULL;
- }
- if (e_card[i]) {
- ecard_release(e_card[i]);
- e_card[i] = NULL;
- }
- }
+ ecard_remove_driver(&ether3_driver);
}
module_init(ether3_init);
diff --git a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c
index 2a36107257dd..4ffe92dd478f 100644
--- a/drivers/acorn/net/etherh.c
+++ b/drivers/acorn/net/etherh.c
@@ -42,6 +42,7 @@
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include <linux/init.h>
#include <asm/system.h>
@@ -57,14 +58,6 @@
static unsigned int net_debug = NET_DEBUG;
-static const card_ids __init etherh_cids[] = {
- { MANU_ANT, PROD_ANT_ETHERM },
- { MANU_I3, PROD_I3_ETHERLAN500 },
- { MANU_I3, PROD_I3_ETHERLAN600 },
- { MANU_I3, PROD_I3_ETHERLAN600A },
- { 0xffff, 0xffff }
-};
-
struct etherh_priv {
struct ei_device eidev;
unsigned int id;
@@ -441,6 +434,12 @@ etherh_open(struct net_device *dev)
{
struct ei_device *ei_local = (struct ei_device *) dev->priv;
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+ printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
+ dev->name);
+ return -EINVAL;
+ }
+
if (request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))
return -EAGAIN;
@@ -483,6 +482,23 @@ etherh_close(struct net_device *dev)
return 0;
}
+static int
+etherh_set_mac_address(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+ /*
+ * We'll set the MAC address on the chip when we open it.
+ */
+
+ return 0;
+}
+
/*
* Initialisation
*/
@@ -541,21 +557,24 @@ static int __init etherm_addr(char *addr)
static u32 etherh_regoffsets[16];
static u32 etherm_regoffsets[16];
-static struct net_device * __init etherh_init_one(struct expansion_card *ec)
+static int __init
+etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct ei_device *ei_local;
struct net_device *dev;
struct etherh_priv *eh;
const char *dev_type;
- int i, size;
+ int i, size, ret;
etherh_banner();
ecard_claim(ec);
dev = init_etherdev(NULL, sizeof(struct etherh_priv));
- if (!dev)
+ if (!dev) {
+ ret = -ENOMEM;
goto out;
+ }
/*
* init_etherdev allocs and zeros dev->priv
@@ -566,33 +585,33 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
SET_MODULE_OWNER(dev);
- dev->open = etherh_open;
- dev->stop = etherh_close;
- dev->set_config = etherh_set_config;
- dev->irq = ec->irq;
- dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
- dev->priv = eh;
+ dev->open = etherh_open;
+ dev->stop = etherh_close;
+ dev->set_mac_address = etherh_set_mac_address;
+ dev->set_config = etherh_set_config;
+ dev->irq = ec->irq;
+ dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
/*
* IRQ and control port handling
*/
- ec->ops = &etherh_ops;
- ec->irq_data = eh;
- eh->ctrl = 0;
- eh->id = ec->cid.product;
+ if (ec->irq != 11) {
+ ec->ops = &etherh_ops;
+ ec->irq_data = eh;
+ }
+ eh->ctrl = 0;
+ eh->id = ec->cid.product;
switch (ec->cid.product) {
case PROD_ANT_ETHERM:
- if (etherm_addr(dev->dev_addr))
- goto free;
+ etherm_addr(dev->dev_addr);
dev->base_addr += ETHERM_NS8390;
dev->mem_start = dev->base_addr + ETHERM_DATAPORT;
eh->ctrl_port = dev->base_addr + ETHERM_CTRLPORT;
break;
case PROD_I3_ETHERLAN500:
- if (etherh_addr(dev->dev_addr, ec))
- goto free;
+ etherh_addr(dev->dev_addr, ec);
dev->base_addr += ETHERH500_NS8390;
dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
eh->ctrl_port = ecard_address (ec, ECARD_IOC, ECARD_FAST)
@@ -601,8 +620,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
- if (etherh_addr(dev->dev_addr, ec))
- goto free;
+ etherh_addr(dev->dev_addr, ec);
dev->base_addr += ETHERH600_NS8390;
dev->mem_start = dev->base_addr + ETHERH600_DATAPORT;
eh->ctrl_port = dev->base_addr + ETHERH600_CTRLPORT;
@@ -611,6 +629,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
default:
printk(KERN_ERR "%s: unknown card type %x\n",
dev->name, ec->cid.product);
+ ret = -ENODEV;
goto free;
}
@@ -618,11 +637,15 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (ec->cid.product == PROD_ANT_ETHERM)
size <<= 3;
- if (!request_region(dev->base_addr, size, dev->name))
+ if (!request_region(dev->base_addr, size, dev->name)) {
+ ret = -EBUSY;
goto free;
+ }
- if (ethdev_init(dev))
+ if (ethdev_init(dev)) {
+ ret = -ENODEV;
goto release;
+ }
/*
* If we're in the NIC slot, make sure the IRQ is enabled
@@ -690,7 +713,10 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
etherh_reset(dev);
NS8390_init(dev, 0);
- return dev;
+
+ ecard_set_drvdata(ec, dev);
+
+ return 0;
release:
release_region(dev->base_addr, 16);
@@ -700,67 +726,59 @@ free:
kfree(dev);
out:
ecard_release(ec);
- return NULL;
+ return ret;
+}
+
+static void __devexit etherh_remove(struct expansion_card *ec)
+{
+ struct net_device *dev = ecard_get_drvdata(ec);
+ int size = 16;
+
+ ecard_set_drvdata(ec, NULL);
+
+ unregister_netdev(dev);
+ if (ec->cid.product == PROD_ANT_ETHERM)
+ size <<= 3;
+ release_region(dev->base_addr, size);
+ kfree(dev);
+
+ ec->ops = NULL;
+ kfree(ec->irq_data);
+ ecard_release(ec);
}
-#define MAX_ETHERH_CARDS 2
+static const struct ecard_id etherh_ids[] = {
+ { MANU_ANT, PROD_ANT_ETHERM },
+ { MANU_I3, PROD_I3_ETHERLAN500 },
+ { MANU_I3, PROD_I3_ETHERLAN600 },
+ { MANU_I3, PROD_I3_ETHERLAN600A },
+ { 0xffff, 0xffff }
+};
-static struct net_device *e_dev[MAX_ETHERH_CARDS];
-static struct expansion_card *e_card[MAX_ETHERH_CARDS];
+static struct ecard_driver etherh_driver = {
+ .probe = etherh_probe,
+ .remove = __devexit_p(etherh_remove),
+ .id_table = etherh_ids,
+ .drv = {
+ .name = "etherh",
+ },
+};
static int __init etherh_init(void)
{
- int i, ret = -ENODEV;
+ int i;
for (i = 0; i < 16; i++) {
etherh_regoffsets[i] = i;
etherm_regoffsets[i] = i << 3;
}
- ecard_startfind();
-
- for (i = 0; i < MAX_ECARDS; i++) {
- struct expansion_card *ec;
- struct net_device *dev;
-
- ec = ecard_find(0, etherh_cids);
- if (!ec)
- break;
-
- dev = etherh_init_one(ec);
- if (!dev)
- break;
-
- e_card[i] = ec;
- e_dev[i] = dev;
- ret = 0;
- }
-
- return ret;
+ return ecard_register_driver(&etherh_driver);
}
static void __exit etherh_exit(void)
{
- int i;
-
- for (i = 0; i < MAX_ETHERH_CARDS; i++) {
- if (e_dev[i]) {
- int size;
- unregister_netdev(e_dev[i]);
- size = 16;
- if (e_card[i]->cid.product == PROD_ANT_ETHERM)
- size <<= 3;
- release_region(e_dev[i]->base_addr, size);
- kfree(e_dev[i]);
- e_dev[i] = NULL;
- }
- if (e_card[i]) {
- e_card[i]->ops = NULL;
- kfree(e_card[i]->irq_data);
- ecard_release(e_card[i]);
- e_card[i] = NULL;
- }
- }
+ ecard_remove_driver(&etherh_driver);
}
module_init(etherh_init);
diff --git a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c
index ba98aa489f5c..b0b8a490a214 100644
--- a/drivers/acorn/scsi/acornscsi.c
+++ b/drivers/acorn/scsi/acornscsi.c
@@ -319,12 +319,12 @@ acornscsi_csdelay(unsigned int cs)
target_jiffies = jiffies + 1 + cs * HZ / 100;
- save_flags(flags);
- sti();
+ local_save_flags(flags);
+ local_irq_enable();
while (time_before(jiffies, target_jiffies)) barrier();
- restore_flags(flags);
+ local_irq_restore(flags);
}
static
@@ -403,8 +403,9 @@ void acornscsi_resetcard(AS_Host *host)
host->scsi.phase = PHASE_IDLE;
host->scsi.disconnectable = 0;
+ memset(host->busyluns, 0, sizeof(host->busyluns));
+
for (i = 0; i < 8; i++) {
- host->busyluns[i] = 0;
host->device[i].sync_state = SYNC_NEGOCIATE;
host->device[i].disconnect_ok = 1;
}
@@ -1593,7 +1594,7 @@ void acornscsi_message(AS_Host *host)
printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n",
host->host->host_no, acornscsi_target(host));
host->SCpnt->device->tagged_queue = 0;
- set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns);
+ set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, host->busyluns);
break;
#endif
case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8):
@@ -2637,8 +2638,7 @@ acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt)
printk("executing ");
//#endif
- save_flags(flags);
- cli();
+ local_irq_save(flags);
switch (host->scsi.phase) {
/*
* If the interface is idle, and the command is 'disconnectable',
@@ -2671,7 +2671,7 @@ acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt)
acornscsi_abortcmd(host, host->SCpnt->tag);
res = res_snooze;
}
- restore_flags(flags);
+ local_irq_restore(flags);
} else if (host->origSCpnt == SCpnt) {
/*
* The command will be executed next, but a command
diff --git a/drivers/acorn/scsi/acornscsi.h b/drivers/acorn/scsi/acornscsi.h
index 191d16af8c45..457929b24925 100644
--- a/drivers/acorn/scsi/acornscsi.h
+++ b/drivers/acorn/scsi/acornscsi.h
@@ -326,7 +326,7 @@ typedef struct acornscsi_hostdata {
syncxfer_t sync_state; /* sync xfer negociation state */
unsigned char disconnect_ok:1; /* device can disconnect */
} device[8];
- unsigned char busyluns[8]; /* array of bits indicating LUNs busy */
+ unsigned long busyluns[64 / sizeof(unsigned long)];/* array of bits indicating LUNs busy */
/* DMA info */
struct {
diff --git a/drivers/acorn/scsi/cumana_1.c b/drivers/acorn/scsi/cumana_1.c
index 4e9e68960782..bb9e6d66daaf 100644
--- a/drivers/acorn/scsi/cumana_1.c
+++ b/drivers/acorn/scsi/cumana_1.c
@@ -83,11 +83,9 @@ static const card_ids cumanascsi_cids[] = {
#define NCR5380_read(reg) cumanascsi_read(_instance, reg)
#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
-#define do_NCR5380_intr do_cumanascsi_intr
-#define NCR5380_queue_command cumanascsi_queue_command
-#define NCR5380_abort cumanascsi_abort
-#define NCR5380_reset cumanascsi_reset
-#define NCR5380_proc_info cumanascsi_proc_info
+#define NCR5380_intr cumanascsi_intr
+#define NCR5380_queue_command cumanascsi_queue_command
+#define NCR5380_proc_info cumanascsi_proc_info
int NCR5380_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int inout);
@@ -159,7 +157,7 @@ int cumanascsi_detect(Scsi_Host_Template * tpnt)
outb(0x00, instance->io_port - 577);
if (instance->irq != IRQ_NONE)
- if (request_irq(instance->irq, do_cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
+ if (request_irq(instance->irq, cumanascsi_intr, SA_INTERRUPT, "CumanaSCSI-1", NULL)) {
printk("scsi%d: IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
instance->irq = IRQ_NONE;
@@ -401,8 +399,10 @@ static Scsi_Host_Template cumanascsi_template = {
.release = cumanascsi_release,
.info = cumanascsi_info,
.queuecommand = cumanascsi_queue_command,
- .abort = cumanascsi_abort,
- .reset = cumanascsi_reset,
+ .eh_abort_handler = NCR5380_abort,
+ .eh_device_reset_handler= NCR5380_device_reset,
+ .eh_bus_reset_handler = NCR5380_bus_reset,
+ .eh_host_reset_handler = NCR5380_host_reset,
.bios_param = scsicam_bios_param,
.can_queue = 16,
.this_id = 7,
diff --git a/drivers/acorn/scsi/ecoscsi.c b/drivers/acorn/scsi/ecoscsi.c
index 93c2fe570177..9a8e70376295 100644
--- a/drivers/acorn/scsi/ecoscsi.c
+++ b/drivers/acorn/scsi/ecoscsi.c
@@ -248,11 +248,9 @@ printk("reading %p len %d\n",addr, len);
#define NCR5380_read(reg) ecoscsi_read(_instance, reg)
#define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value)
-#define do_NCR5380_intr do_ecoscsi_intr
-#define NCR5380_queue_command ecoscsi_queue_command
-#define NCR5380_abort ecoscsi_abort
-#define NCR5380_reset ecoscsi_reset
-#define NCR5380_proc_info ecoscsi_proc_info
+#define NCR5380_intr ecoscsi_intr
+#define NCR5380_queue_command ecoscsi_queue_command
+#define NCR5380_proc_info ecoscsi_proc_info
int NCR5380_proc_info(char *buffer, char **start, off_t offset,
int length, int hostno, int inout);
@@ -269,8 +267,10 @@ static Scsi_Host_Template ecoscsi_template = {
.release = ecoscsi_release,
.info = ecoscsi_info,
.queuecommand = ecoscsi_queue_command,
- .abort = ecoscsi_abort,
- .reset = ecoscsi_reset,
+ .eh_abort_handler = NCR5380_abort,
+ .eh_device_reset_handler= NCR5380_device_reset,
+ .eh_bus_reset_handler = NCR5380_bus_reset,
+ .eh_host_reset_handler = NCR5380_host_reset,
.can_queue = 16,
.this_id = 7,
.sg_tablesize = SG_ALL,
diff --git a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c
index 445c1574453d..77bd624a7b95 100644
--- a/drivers/acorn/scsi/fas216.c
+++ b/drivers/acorn/scsi/fas216.c
@@ -603,7 +603,7 @@ fas216_updateptrs(FAS216_Info *info, int bytes_transferred)
* next buffer.
*/
bytes_transferred -= SCp->this_residual;
- if (!next_SCp(&info->scsi.SCp)) {
+ if (!next_SCp(&info->scsi.SCp) && bytes_transferred) {
printk(KERN_WARNING "scsi%d.%c: out of buffers\n",
info->host->host_no, '0' + info->SCpnt->target);
return;
@@ -2300,8 +2300,8 @@ int fas216_eh_device_reset(Scsi_Cmnd *SCpnt)
{
FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;
- printk("scsi%d.%c: "__FUNCTION__": called\n",
- info->host->host_no, '0' + SCpnt->target);
+ printk("scsi%d.%c: %s: called\n",
+ info->host->host_no, '0' + SCpnt->target, __FUNCTION__);
return FAILED;
}
@@ -2320,8 +2320,8 @@ int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt)
info->stats.bus_resets += 1;
- printk("scsi%d.%c: "__FUNCTION__": resetting bus\n",
- info->host->host_no, '0' + SCpnt->target);
+ printk("scsi%d.%c: %s: resetting bus\n",
+ info->host->host_no, '0' + SCpnt->target, __FUNCTION__);
/*
* Attempt to stop all activity on this interface.
@@ -2381,8 +2381,8 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
fas216_checkmagic(info);
- printk("scsi%d.%c: "__FUNCTION__": resetting host\n",
- info->host->host_no, '0' + SCpnt->target);
+ printk("scsi%d.%c: %s: resetting host\n",
+ info->host->host_no, '0' + SCpnt->target, __FUNCTION__);
/*
* Reset the SCSI chip.
diff --git a/drivers/acorn/scsi/fas216.h b/drivers/acorn/scsi/fas216.h
index a5b107182873..7d11ef613dc2 100644
--- a/drivers/acorn/scsi/fas216.h
+++ b/drivers/acorn/scsi/fas216.h
@@ -288,7 +288,7 @@ typedef struct {
neg_t sync_state; /* synchronous transfer mode */
neg_t wide_state; /* wide transfer mode */
} device[8];
- unsigned char busyluns[8]; /* array of bits indicating LUNs busy */
+ unsigned long busyluns[64/sizeof(unsigned long)];/* array of bits indicating LUNs busy */
/* dma */
struct {
diff --git a/drivers/acorn/scsi/oak.c b/drivers/acorn/scsi/oak.c
index 409efb4084c0..922deb68a7cf 100644
--- a/drivers/acorn/scsi/oak.c
+++ b/drivers/acorn/scsi/oak.c
@@ -64,10 +64,8 @@
#define NCR5380_read(reg) oakscsi_read(_instance, reg)
#define NCR5380_write(reg, value) oakscsi_write(_instance, reg, value)
-#define do_NCR5380_intr do_oakscsi_intr
+#define NCR5380_intr oakscsi_intr
#define NCR5380_queue_command oakscsi_queue_command
-#define NCR5380_abort oakscsi_abort
-#define NCR5380_reset oakscsi_reset
#define NCR5380_proc_info oakscsi_proc_info
int NCR5380_proc_info(char *buffer, char **start, off_t offset,
@@ -142,7 +140,7 @@ int oakscsi_detect(Scsi_Host_Template * tpnt)
}
if (instance->irq != IRQ_NONE)
- if (request_irq(instance->irq, do_oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
+ if (request_irq(instance->irq, oakscsi_intr, SA_INTERRUPT, "Oak SCSI", NULL)) {
printk("scsi%d: IRQ%d not free, interrupts disabled\n",
instance->host_no, instance->irq);
instance->irq = IRQ_NONE;
@@ -264,8 +262,10 @@ static Scsi_Host_Template oakscsi_template = {
.release = oakscsi_release,
.info = oakscsi_info,
.queuecommand = oakscsi_queue_command,
- .abort = oakscsi_abort,
- .reset = oakscsi_reset,
+ .eh_abort_handler = NCR5380_abort,
+ .eh_device_reset_handler= NCR5380_device_reset,
+ .eh_bus_reset_handler = NCR5380_bus_reset,
+ .eh_host_reset_handler = NCR5380_host_reset,
.can_queue = 16,
.this_id = 7,
.sg_tablesize = SG_ALL,
diff --git a/drivers/acorn/scsi/queue.c b/drivers/acorn/scsi/queue.c
index 127bbb59f9fa..82e247e1fb16 100644
--- a/drivers/acorn/scsi/queue.c
+++ b/drivers/acorn/scsi/queue.c
@@ -161,7 +161,7 @@ static Scsi_Cmnd *__queue_remove(Queue_t *queue, struct list_head *ent)
* exclude - bit array of target&lun which is busy
* Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
*/
-Scsi_Cmnd *queue_remove_exclude(Queue_t *queue, void *exclude)
+Scsi_Cmnd *queue_remove_exclude(Queue_t *queue, unsigned long *exclude)
{
unsigned long flags;
struct list_head *l;
diff --git a/drivers/acorn/scsi/queue.h b/drivers/acorn/scsi/queue.h
index 08f5c4697d75..508b42ec7a1e 100644
--- a/drivers/acorn/scsi/queue.h
+++ b/drivers/acorn/scsi/queue.h
@@ -46,7 +46,7 @@ extern Scsi_Cmnd *queue_remove (Queue_t *queue);
* exclude - array of busy LUNs
* Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
*/
-extern Scsi_Cmnd *queue_remove_exclude (Queue_t *queue, void *exclude);
+extern Scsi_Cmnd *queue_remove_exclude (Queue_t *queue, unsigned long *exclude);
#define queue_add_cmd_ordered(queue,SCpnt) \
__queue_add(queue,SCpnt,(SCpnt)->cmnd[0] == REQUEST_SENSE)
diff --git a/drivers/acorn/scsi/scsi.h b/drivers/acorn/scsi/scsi.h
index fe4e8c80a04a..f9c6c5869a6c 100644
--- a/drivers/acorn/scsi/scsi.h
+++ b/drivers/acorn/scsi/scsi.h
@@ -51,7 +51,7 @@ static inline int next_SCp(Scsi_Pointer *SCp)
static inline unsigned char get_next_SCp_byte(Scsi_Pointer *SCp)
{
- char c = SCp->ptr;
+ char c = *SCp->ptr;
SCp->ptr += 1;
SCp->this_residual -= 1;
@@ -63,7 +63,7 @@ static inline unsigned char get_next_SCp_byte(Scsi_Pointer *SCp)
static inline void put_next_SCp_byte(Scsi_Pointer *SCp, unsigned char c)
{
- SCp->ptr = c;
+ *SCp->ptr = c;
SCp->ptr += 1;
SCp->this_residual -= 1;
if (SCp->this_residual == 0)
diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c
index 0bd163307af9..23d980122df3 100644
--- a/drivers/mtd/afs.c
+++ b/drivers/mtd/afs.c
@@ -21,7 +21,7 @@
This is access code for flashes using ARM's flash partitioning
standards.
- $Id: afs.c,v 1.6 2001/10/02 10:04:51 rmk Exp $
+ $Id: afs.c,v 1.8 2002/05/04 08:49:09 rmk Exp $
======================================================================*/
@@ -82,6 +82,12 @@ afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start,
if (fs.signature != 0xa0ffff9f)
ret = 1;
+ /*
+ * Don't touch the SIB.
+ */
+ if (fs.type == 2)
+ ret = 1;
+
*iis_start = fs.image_info_base & mask;
*img_start = fs.image_start & mask;
@@ -163,6 +169,7 @@ int parse_afs_partitions(struct mtd_info *mtd, struct mtd_partition **pparts)
if (!parts)
return -ENOMEM;
+ memset(parts, 0, sz);
str = (char *)(parts + idx);
/*
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
index 0b22c6e60417..cd58f8fae012 100644
--- a/drivers/mtd/maps/integrator-flash.c
+++ b/drivers/mtd/maps/integrator-flash.c
@@ -21,7 +21,7 @@
This is access code for flashes using ARM's flash partitioning
standards.
- $Id: integrator-flash.c,v 1.6 2001/10/02 16:00:01 dwmw2 Exp $
+ $Id: integrator-flash.c,v 1.7 2001/11/01 20:55:47 rmk Exp $
======================================================================*/
@@ -208,10 +208,10 @@ static struct map_info armflash_map =
};
static struct mtd_info *mtd;
+static struct mtd_partition *parts;
static int __init armflash_cfi_init(void *base, u_int size)
{
- struct mtd_partition *parts;
int ret;
armflash_flash_init();
@@ -238,8 +238,6 @@ static int __init armflash_cfi_init(void *base, u_int size)
ret = parse_afs_partitions(mtd, &parts);
if (ret > 0) {
ret = add_mtd_partitions(mtd, parts, ret);
- /* we don't need the partition info any longer */
- kfree(parts);
if (ret)
printk(KERN_ERR "mtd partition registration "
"failed: %d\n", ret);
@@ -262,6 +260,8 @@ static void armflash_cfi_exit(void)
del_mtd_partitions(mtd);
map_destroy(mtd);
}
+ if (parts)
+ kfree(parts);
}
static int __init armflash_init(void)
diff --git a/drivers/pcmcia/sa1100_adsbitsy.c b/drivers/pcmcia/sa1100_adsbitsy.c
index 202524e4c354..a7f533ca5c05 100644
--- a/drivers/pcmcia/sa1100_adsbitsy.c
+++ b/drivers/pcmcia/sa1100_adsbitsy.c
@@ -84,14 +84,14 @@ adsbitsy_pcmcia_configure_socket(const struct pcmcia_configure *conf)
}
static struct pcmcia_low_level adsbitsy_pcmcia_ops = {
- init: adsbitsy_pcmcia_init,
- shutdown: sa1111_pcmcia_shutdown,
- socket_state: sa1111_pcmcia_socket_state,
- get_irq_info: sa1111_pcmcia_get_irq_info,
- configure_socket: adsbitsy_pcmcia_configure_socket,
-
- socket_init: sa1111_pcmcia_socket_init,
- socket_suspend: sa1111_pcmcia_socket_suspend,
+ .init = adsbitsy_pcmcia_init,
+ .shutdown = sa1111_pcmcia_shutdown,
+ .socket_state = sa1111_pcmcia_socket_state,
+ .get_irq_info = sa1111_pcmcia_get_irq_info,
+ .configure_socket = adsbitsy_pcmcia_configure_socket,
+
+ .socket_init = sa1111_pcmcia_socket_init,
+ .socket_suspend = sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_adsbitsy_init(void)
diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c
index eb883f64e239..494f6b625ee7 100644
--- a/drivers/pcmcia/sa1100_assabet.c
+++ b/drivers/pcmcia/sa1100_assabet.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include <asm/arch/assabet.h>
@@ -192,14 +193,14 @@ static int assabet_pcmcia_socket_suspend(int sock)
}
static struct pcmcia_low_level assabet_pcmcia_ops = {
- init: assabet_pcmcia_init,
- shutdown: assabet_pcmcia_shutdown,
- socket_state: assabet_pcmcia_socket_state,
- get_irq_info: assabet_pcmcia_get_irq_info,
- configure_socket: assabet_pcmcia_configure_socket,
-
- socket_init: assabet_pcmcia_socket_init,
- socket_suspend: assabet_pcmcia_socket_suspend,
+ .init = assabet_pcmcia_init,
+ .shutdown = assabet_pcmcia_shutdown,
+ .socket_state = assabet_pcmcia_socket_state,
+ .get_irq_info = assabet_pcmcia_get_irq_info,
+ .configure_socket = assabet_pcmcia_configure_socket,
+
+ .socket_init = assabet_pcmcia_socket_init,
+ .socket_suspend = assabet_pcmcia_socket_suspend,
};
int __init pcmcia_assabet_init(void)
diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c
index 77174645d6c1..255872d64f10 100644
--- a/drivers/pcmcia/sa1100_badge4.c
+++ b/drivers/pcmcia/sa1100_badge4.c
@@ -146,14 +146,14 @@ badge4_pcmcia_configure_socket(const struct pcmcia_configure *conf)
}
static struct pcmcia_low_level badge4_pcmcia_ops = {
- init: badge4_pcmcia_init,
- shutdown: badge4_pcmcia_shutdown,
- socket_state: sa1111_pcmcia_socket_state,
- get_irq_info: sa1111_pcmcia_get_irq_info,
- configure_socket: badge4_pcmcia_configure_socket,
-
- socket_init: sa1111_pcmcia_socket_init,
- socket_suspend: sa1111_pcmcia_socket_suspend,
+ .init = badge4_pcmcia_init,
+ .shutdown = badge4_pcmcia_shutdown,
+ .socket_state = sa1111_pcmcia_socket_state,
+ .get_irq_info = sa1111_pcmcia_get_irq_info,
+ .configure_socket = badge4_pcmcia_configure_socket,
+
+ .socket_init = sa1111_pcmcia_socket_init,
+ .socket_suspend = sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_badge4_init(void)
diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c
index f3142cea6deb..28c808f95d1e 100644
--- a/drivers/pcmcia/sa1100_cerf.c
+++ b/drivers/pcmcia/sa1100_cerf.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
@@ -160,14 +161,14 @@ static int cerf_pcmcia_socket_suspend(int sock)
}
static struct pcmcia_low_level cerf_pcmcia_ops = {
- init: cerf_pcmcia_init,
- shutdown: cerf_pcmcia_shutdown,
- socket_state: cerf_pcmcia_socket_state,
- get_irq_info: cerf_pcmcia_get_irq_info,
- configure_socket: cerf_pcmcia_configure_socket,
-
- socket_init: cerf_pcmcia_socket_init,
- socket_suspend: cerf_pcmcia_socket_suspend,
+ .init = cerf_pcmcia_init,
+ .shutdown = cerf_pcmcia_shutdown,
+ .socket_state = cerf_pcmcia_socket_state,
+ .get_irq_info = cerf_pcmcia_get_irq_info,
+ .configure_socket = cerf_pcmcia_configure_socket,
+
+ .socket_init = cerf_pcmcia_socket_init,
+ .socket_suspend = cerf_pcmcia_socket_suspend,
};
int __init pcmcia_cerf_init(void)
diff --git a/drivers/pcmcia/sa1100_flexanet.c b/drivers/pcmcia/sa1100_flexanet.c
index edb8c9c029cf..3d4e35efa8b5 100644
--- a/drivers/pcmcia/sa1100_flexanet.c
+++ b/drivers/pcmcia/sa1100_flexanet.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
@@ -221,14 +222,14 @@ static int flexanet_pcmcia_socket_suspend(int sock)
*
*/
static struct pcmcia_low_level flexanet_pcmcia_ops = {
- init: flexanet_pcmcia_init,
- shutdown: flexanet_pcmcia_shutdown,
- socket_state: flexanet_pcmcia_socket_state,
- get_irq_info: flexanet_pcmcia_get_irq_info,
- configure_socket: flexanet_pcmcia_configure_socket,
-
- socket_init: flexanet_pcmcia_socket_init,
- socket_suspend: flexanet_pcmcia_socket_suspend,
+ .init = flexanet_pcmcia_init,
+ .shutdown = flexanet_pcmcia_shutdown,
+ .socket_state = flexanet_pcmcia_socket_state,
+ .get_irq_info = flexanet_pcmcia_get_irq_info,
+ .configure_socket = flexanet_pcmcia_configure_socket,
+
+ .socket_init = flexanet_pcmcia_socket_init,
+ .socket_suspend = flexanet_pcmcia_socket_suspend,
};
int __init pcmcia_flexanet_init(void)
diff --git a/drivers/pcmcia/sa1100_freebird.c b/drivers/pcmcia/sa1100_freebird.c
index 99cbb28a0e66..dc8fc02839db 100644
--- a/drivers/pcmcia/sa1100_freebird.c
+++ b/drivers/pcmcia/sa1100_freebird.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
@@ -178,14 +179,14 @@ static int freebird_pcmcia_socket_suspend(int sock)
}
static struct pcmcia_low_level freebird_pcmcia_ops = {
- init: freebird_pcmcia_init,
- shutdown: freebird_pcmcia_shutdown,
- socket_state: freebird_pcmcia_socket_state,
- get_irq_info: freebird_pcmcia_get_irq_info,
- configure_socket: freebird_pcmcia_configure_socket,
-
- socket_init: freebird_pcmcia_socket_init,
- socket_suspend: freebird_pcmcia_socket_suspend,
+ .init = freebird_pcmcia_init,
+ .shutdown = freebird_pcmcia_shutdown,
+ .socket_state = freebird_pcmcia_socket_state,
+ .get_irq_info = freebird_pcmcia_get_irq_info,
+ .configure_socket = freebird_pcmcia_configure_socket,
+
+ .socket_init = freebird_pcmcia_socket_init,
+ .socket_suspend = freebird_pcmcia_socket_suspend,
};
int __init pcmcia_freebird_init(void)
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index a31365bb73fe..4083ae37cfb2 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -719,7 +719,7 @@ sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
(map->flags&MAP_ATTRIB)?"ATTRIB ":"",
(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
- if (map->map >= MAX_WIN){
+ if (map->map >= MAX_WIN) {
printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
map->map);
return -1;
@@ -853,19 +853,19 @@ sa1100_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base)
#endif /* defined(CONFIG_PROC_FS) */
static struct pccard_operations sa1100_pcmcia_operations = {
- init: sa1100_pcmcia_sock_init,
- suspend: sa1100_pcmcia_suspend,
- register_callback: sa1100_pcmcia_register_callback,
- inquire_socket: sa1100_pcmcia_inquire_socket,
- get_status: sa1100_pcmcia_get_status,
- get_socket: sa1100_pcmcia_get_socket,
- set_socket: sa1100_pcmcia_set_socket,
- get_io_map: sa1100_pcmcia_get_io_map,
- set_io_map: sa1100_pcmcia_set_io_map,
- get_mem_map: sa1100_pcmcia_get_mem_map,
- set_mem_map: sa1100_pcmcia_set_mem_map,
+ .init = sa1100_pcmcia_sock_init,
+ .suspend = sa1100_pcmcia_suspend,
+ .register_callback = sa1100_pcmcia_register_callback,
+ .inquire_socket = sa1100_pcmcia_inquire_socket,
+ .get_status = sa1100_pcmcia_get_status,
+ .get_socket = sa1100_pcmcia_get_socket,
+ .set_socket = sa1100_pcmcia_set_socket,
+ .get_io_map = sa1100_pcmcia_get_io_map,
+ .set_io_map = sa1100_pcmcia_set_io_map,
+ .get_mem_map = sa1100_pcmcia_get_mem_map,
+ .set_mem_map = sa1100_pcmcia_set_mem_map,
#ifdef CONFIG_PROC_FS
- proc_setup: sa1100_pcmcia_proc_setup
+ .proc_setup = sa1100_pcmcia_proc_setup
#endif
};
@@ -927,7 +927,7 @@ sa1100_pcmcia_notifier(struct notifier_block *nb, unsigned long val,
}
static struct notifier_block sa1100_pcmcia_notifier_block = {
- notifier_call: sa1100_pcmcia_notifier
+ .notifier_call = sa1100_pcmcia_notifier
};
#endif
@@ -1148,6 +1148,9 @@ static int __init sa1100_pcmcia_init(void)
#ifdef CONFIG_SA1100_GRAPHICSCLIENT
pcmcia_gcplus_init();
#endif
+#ifdef CONFIG_SA1100_H3600
+ pcmcia_h3600_init();
+#endif
#ifdef CONFIG_SA1100_PANGOLIN
pcmcia_pangolin_init();
#endif
@@ -1192,6 +1195,9 @@ static void __exit sa1100_pcmcia_exit(void)
#ifdef CONFIG_SA1100_GRAPHICSCLIENT
pcmcia_gcplus_exit();
#endif
+#ifdef CONFIG_SA1100_H3600
+ pcmcia_h3600_exit();
+#endif
#ifdef CONFIG_SA1100_PANGOLIN
pcmcia_pangolin_exit();
#endif
diff --git a/drivers/pcmcia/sa1100_graphicsclient.c b/drivers/pcmcia/sa1100_graphicsclient.c
index 6a3691df82ef..1268e6d88018 100644
--- a/drivers/pcmcia/sa1100_graphicsclient.c
+++ b/drivers/pcmcia/sa1100_graphicsclient.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
@@ -159,14 +160,14 @@ static int gcplus_pcmcia_socket_suspend(int sock)
}
static struct pcmcia_low_level gcplus_pcmcia_ops = {
- init: gcplus_pcmcia_init,
- shutdown: gcplus_pcmcia_shutdown,
- socket_state: gcplus_pcmcia_socket_state,
- get_irq_info: gcplus_pcmcia_get_irq_info,
- configure_socket: gcplus_pcmcia_configure_socket,
-
- socket_init: gcplus_pcmcia_socket_init,
- socket_suspend: gcplus_pcmcia_socket_suspend,
+ .init = gcplus_pcmcia_init,
+ .shutdown = gcplus_pcmcia_shutdown,
+ .socket_state = gcplus_pcmcia_socket_state,
+ .get_irq_info = gcplus_pcmcia_get_irq_info,
+ .configure_socket = gcplus_pcmcia_configure_socket,
+
+ .socket_init = gcplus_pcmcia_socket_init,
+ .socket_suspend = gcplus_pcmcia_socket_suspend,
};
int __init pcmcia_gcplus_init(void)
diff --git a/drivers/pcmcia/sa1100_graphicsmaster.c b/drivers/pcmcia/sa1100_graphicsmaster.c
index 9552dfa55816..34ca7f144201 100644
--- a/drivers/pcmcia/sa1100_graphicsmaster.c
+++ b/drivers/pcmcia/sa1100_graphicsmaster.c
@@ -82,14 +82,14 @@ graphicsmaster_pcmcia_configure_socket(const struct pcmcia_configure *conf)
}
static struct pcmcia_low_level graphicsmaster_pcmcia_ops = {
- init: graphicsmaster_pcmcia_init,
- shutdown: sa1111_pcmcia_shutdown,
- socket_state: sa1111_pcmcia_socket_state,
- get_irq_info: sa1111_pcmcia_get_irq_info,
- configure_socket: graphicsmaster_pcmcia_configure_socket,
-
- socket_init: sa1111_pcmcia_socket_init,
- socket_suspend: sa1111_pcmcia_socket_suspend,
+ .init = graphicsmaster_pcmcia_init,
+ .shutdown = sa1111_pcmcia_shutdown,
+ .socket_state = sa1111_pcmcia_socket_state,
+ .get_irq_info = sa1111_pcmcia_get_irq_info,
+ .configure_socket = graphicsmaster_pcmcia_configure_socket,
+
+ .socket_init = sa1111_pcmcia_socket_init,
+ .socket_suspend = sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_graphicsmaster_init(void)
diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c
index b9310ea18e51..e25fed19f7fb 100644
--- a/drivers/pcmcia/sa1100_h3600.c
+++ b/drivers/pcmcia/sa1100_h3600.c
@@ -10,6 +10,9 @@
#include <asm/hardware.h>
#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/arch/h3600.h>
+
#include "sa1100_generic.h"
static struct irqs {
@@ -185,13 +188,27 @@ static int h3600_pcmcia_socket_suspend(int sock)
}
struct pcmcia_low_level h3600_pcmcia_ops = {
- init: h3600_pcmcia_init,
- shutdown: h3600_pcmcia_shutdown,
- socket_state: h3600_pcmcia_socket_state,
- get_irq_info: h3600_pcmcia_get_irq_info,
- configure_socket: h3600_pcmcia_configure_socket,
-
- socket_init: h3600_pcmcia_socket_init,
- socket_suspend: h3600_pcmcia_socket_suspend,
+ .init = h3600_pcmcia_init,
+ .shutdown = h3600_pcmcia_shutdown,
+ .socket_state = h3600_pcmcia_socket_state,
+ .get_irq_info = h3600_pcmcia_get_irq_info,
+ .configure_socket = h3600_pcmcia_configure_socket,
+
+ .socket_init = h3600_pcmcia_socket_init,
+ .socket_suspend = h3600_pcmcia_socket_suspend,
};
+int __init pcmcia_h3600_init(void)
+{
+ int ret = -ENODEV;
+
+ if (machine_is_h3600())
+ ret = sa1100_register_pcmcia(&h3600_pcmcia_ops);
+
+ return ret;
+}
+
+void __exit pcmcia_h3600_exit(void)
+{
+ sa1100_unregister_pcmcia(&h3600_pcmcia_ops);
+}
diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1100_jornada720.c
index d15f51eedba6..2563902ec01a 100644
--- a/drivers/pcmcia/sa1100_jornada720.c
+++ b/drivers/pcmcia/sa1100_jornada720.c
@@ -97,14 +97,14 @@ printk("%s(): config socket %d vcc %d vpp %d\n", __FUNCTION__,
}
static struct pcmcia_low_level jornada720_pcmcia_ops = {
- init: jornada720_pcmcia_init,
- shutdown: sa1111_pcmcia_shutdown,
- socket_state: sa1111_pcmcia_socket_state,
- get_irq_info: sa1111_pcmcia_get_irq_info,
- configure_socket: jornada720_pcmcia_configure_socket,
-
- socket_init: sa1111_pcmcia_socket_init,
- socket_suspend: sa1111_pcmcia_socket_suspend,
+ .init = jornada720_pcmcia_init,
+ .shutdown = sa1111_pcmcia_shutdown,
+ .socket_state = sa1111_pcmcia_socket_state,
+ .get_irq_info = sa1111_pcmcia_get_irq_info,
+ .configure_socket = jornada720_pcmcia_configure_socket,
+
+ .socket_init = sa1111_pcmcia_socket_init,
+ .socket_suspend = sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_jornada720_init(void)
diff --git a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1100_neponset.c
index 12d6c5c662f9..c9a37dd4bcce 100644
--- a/drivers/pcmcia/sa1100_neponset.c
+++ b/drivers/pcmcia/sa1100_neponset.c
@@ -127,14 +127,14 @@ neponset_pcmcia_configure_socket(const struct pcmcia_configure *conf)
}
static struct pcmcia_low_level neponset_pcmcia_ops = {
- init: neponset_pcmcia_init,
- shutdown: sa1111_pcmcia_shutdown,
- socket_state: sa1111_pcmcia_socket_state,
- get_irq_info: sa1111_pcmcia_get_irq_info,
- configure_socket: neponset_pcmcia_configure_socket,
-
- socket_init: sa1111_pcmcia_socket_init,
- socket_suspend: sa1111_pcmcia_socket_suspend,
+ .init = neponset_pcmcia_init,
+ .shutdown = sa1111_pcmcia_shutdown,
+ .socket_state = sa1111_pcmcia_socket_state,
+ .get_irq_info = sa1111_pcmcia_get_irq_info,
+ .configure_socket = neponset_pcmcia_configure_socket,
+
+ .socket_init = sa1111_pcmcia_socket_init,
+ .socket_suspend = sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_neponset_init(void)
diff --git a/drivers/pcmcia/sa1100_pangolin.c b/drivers/pcmcia/sa1100_pangolin.c
index 35455466f8f7..6221fa149cae 100644
--- a/drivers/pcmcia/sa1100_pangolin.c
+++ b/drivers/pcmcia/sa1100_pangolin.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
@@ -159,13 +160,13 @@ static int pangolin_pcmcia_socket_suspend(int sock)
}
static struct pcmcia_low_level pangolin_pcmcia_ops = {
- init: pangolin_pcmcia_init,
- shutdown: pangolin_pcmcia_shutdown,
- socket_state: pangolin_pcmcia_socket_state,
- get_irq_info: pangolin_pcmcia_get_irq_info,
- configure_socket: pangolin_pcmcia_configure_socket,
+ .init = pangolin_pcmcia_init,
+ .shutdown = pangolin_pcmcia_shutdown,
+ .socket_state = pangolin_pcmcia_socket_state,
+ .get_irq_info = pangolin_pcmcia_get_irq_info,
+ .configure_socket = pangolin_pcmcia_configure_socket,
- socket_init: pangolin_pcmcia_socket_init,
+ .socket_init = pangolin_pcmcia_socket_init,
socket_suspend, pangolin_pcmcia_socket_suspend,
};
diff --git a/drivers/pcmcia/sa1100_pfs168.c b/drivers/pcmcia/sa1100_pfs168.c
index 511afebb38a3..770132ee9fc2 100644
--- a/drivers/pcmcia/sa1100_pfs168.c
+++ b/drivers/pcmcia/sa1100_pfs168.c
@@ -119,14 +119,14 @@ pfs168_pcmcia_configure_socket(const struct pcmcia_configure *conf)
}
static struct pcmcia_low_level pfs168_pcmcia_ops = {
- init: pfs168_pcmcia_init,
- shutdown: sa1111_pcmcia_shutdown,
- socket_state: sa1111_pcmcia_socket_state,
- get_irq_info: sa1111_pcmcia_get_irq_info,
- configure_socket: pfs168_pcmcia_configure_socket,
-
- socket_init: sa1111_pcmcia_socket_init,
- socket_suspend: sa1111_pcmcia_socket_suspend,
+ .init = pfs168_pcmcia_init,
+ .shutdown = sa1111_pcmcia_shutdown,
+ .socket_state = sa1111_pcmcia_socket_state,
+ .get_irq_info = sa1111_pcmcia_get_irq_info,
+ .configure_socket = pfs168_pcmcia_configure_socket,
+
+ .socket_init = sa1111_pcmcia_socket_init,
+ .socket_suspend = sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_pfs168_init(void)
diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c
index 7cfe0105a225..41e25ddaa461 100644
--- a/drivers/pcmcia/sa1100_shannon.c
+++ b/drivers/pcmcia/sa1100_shannon.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/arch/shannon.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
@@ -151,14 +152,14 @@ static int shannon_pcmcia_socket_suspend(int sock)
}
static struct pcmcia_low_level shannon_pcmcia_ops = {
- init: shannon_pcmcia_init,
- shutdown: shannon_pcmcia_shutdown,
- socket_state: shannon_pcmcia_socket_state,
- get_irq_info: shannon_pcmcia_get_irq_info,
- configure_socket: shannon_pcmcia_configure_socket,
-
- socket_init: shannon_pcmcia_socket_init,
- socket_suspend: shannon_pcmcia_socket_suspend,
+ .init = shannon_pcmcia_init,
+ .shutdown = shannon_pcmcia_shutdown,
+ .socket_state = shannon_pcmcia_socket_state,
+ .get_irq_info = shannon_pcmcia_get_irq_info,
+ .configure_socket = shannon_pcmcia_configure_socket,
+
+ .socket_init = shannon_pcmcia_socket_init,
+ .socket_suspend = shannon_pcmcia_socket_suspend,
};
int __init pcmcia_shannon_init(void)
diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c
index bbe79bdf8fc1..7d699fc475f5 100644
--- a/drivers/pcmcia/sa1100_simpad.c
+++ b/drivers/pcmcia/sa1100_simpad.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
@@ -158,14 +159,14 @@ static int simpad_pcmcia_socket_suspend(int sock)
}
static struct pcmcia_low_level simpad_pcmcia_ops = {
- init: simpad_pcmcia_init,
- shutdown: simpad_pcmcia_shutdown,
- socket_state: simpad_pcmcia_socket_state,
- get_irq_info: simpad_pcmcia_get_irq_info,
- configure_socket: simpad_pcmcia_configure_socket,
-
- socket_init: simpad_pcmcia_socket_init,
- socket_suspend: simpad_pcmcia_socket_suspend,
+ .init = simpad_pcmcia_init,
+ .shutdown = simpad_pcmcia_shutdown,
+ .socket_state = simpad_pcmcia_socket_state,
+ .get_irq_info = simpad_pcmcia_get_irq_info,
+ .configure_socket = simpad_pcmcia_configure_socket,
+
+ .socket_init = simpad_pcmcia_socket_init,
+ .socket_suspend = simpad_pcmcia_socket_suspend,
};
int __init pcmcia_simpad_init(void)
diff --git a/drivers/pcmcia/sa1100_stork.c b/drivers/pcmcia/sa1100_stork.c
index c172acce8305..597d164ea0f7 100644
--- a/drivers/pcmcia/sa1100_stork.c
+++ b/drivers/pcmcia/sa1100_stork.c
@@ -25,6 +25,7 @@
#include <linux/i2c.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
@@ -227,14 +228,14 @@ static int stork_pcmcia_socket_suspend(int sock)
}
static struct pcmcia_low_level stork_pcmcia_ops = {
- init: stork_pcmcia_init,
- shutdown: stork_pcmcia_shutdown,
- socket_state: stork_pcmcia_socket_state,
- get_irq_info: stork_pcmcia_get_irq_info,
- configure_socket: stork_pcmcia_configure_socket,
-
- socket_init: stork_pcmcia_socket_init,
- socket_suspend: stork_pcmcia_socket_suspend,
+ .init = stork_pcmcia_init,
+ .shutdown = stork_pcmcia_shutdown,
+ .socket_state = stork_pcmcia_socket_state,
+ .get_irq_info = stork_pcmcia_get_irq_info,
+ .configure_socket = stork_pcmcia_configure_socket,
+
+ .socket_init = stork_pcmcia_socket_init,
+ .socket_suspend = stork_pcmcia_socket_suspend,
};
int __init pcmcia_stork_init(void)
diff --git a/drivers/pcmcia/sa1100_system3.c b/drivers/pcmcia/sa1100_system3.c
index 2ab0d4537d0d..c6076fee5bcb 100644
--- a/drivers/pcmcia/sa1100_system3.c
+++ b/drivers/pcmcia/sa1100_system3.c
@@ -106,14 +106,14 @@ static int system3_pcmcia_socket_state(struct pcmcia_state_array
}
struct pcmcia_low_level system3_pcmcia_ops = {
- init: system3_pcmcia_init,
- shutdown: system3_pcmcia_shutdown,
- socket_state: system3_pcmcia_socket_state,
- get_irq_info: sa1111_pcmcia_get_irq_info,
- configure_socket: system3_pcmcia_configure_socket,
-
- socket_init: sa1111_pcmcia_socket_init,
- socket_suspend: sa1111_pcmcia_socket_suspend,
+ .init = system3_pcmcia_init,
+ .shutdown = system3_pcmcia_shutdown,
+ .socket_state = system3_pcmcia_socket_state,
+ .get_irq_info = sa1111_pcmcia_get_irq_info,
+ .configure_socket = system3_pcmcia_configure_socket,
+
+ .socket_init = sa1111_pcmcia_socket_init,
+ .socket_suspend = sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_system3_init(void)
diff --git a/drivers/pcmcia/sa1100_trizeps.c b/drivers/pcmcia/sa1100_trizeps.c
index c06a041bac8c..07660b5e77af 100644
--- a/drivers/pcmcia/sa1100_trizeps.c
+++ b/drivers/pcmcia/sa1100_trizeps.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <asm/hardware.h> // included trizeps.h
+#include <asm/mach-types.h>
#include <asm/system.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
@@ -191,13 +192,13 @@ static int trizeps_pcmcia_socket_suspend(int sock)
*
******************************************************/
struct pcmcia_low_level trizeps_pcmcia_ops = {
- init: trizeps_pcmcia_init,
- shutdown: trizeps_pcmcia_shutdown,
- socket_state: trizeps_pcmcia_socket_state,
- get_irq_info: trizeps_pcmcia_get_irq_info,
- configure_socket: trizeps_pcmcia_configure_socket,
- socket_init: trizeps_pcmcia_socket_init,
- socket_suspend: trizeps_pcmcia_socket_suspend,
+ .init = trizeps_pcmcia_init,
+ .shutdown = trizeps_pcmcia_shutdown,
+ .socket_state = trizeps_pcmcia_socket_state,
+ .get_irq_info = trizeps_pcmcia_get_irq_info,
+ .configure_socket = trizeps_pcmcia_configure_socket,
+ .socket_init = trizeps_pcmcia_socket_init,
+ .socket_suspend = trizeps_pcmcia_socket_suspend,
};
int __init pcmcia_trizeps_init(void)
diff --git a/drivers/pcmcia/sa1100_xp860.c b/drivers/pcmcia/sa1100_xp860.c
index 69d3f3ddaacc..c1eb6ae18249 100644
--- a/drivers/pcmcia/sa1100_xp860.c
+++ b/drivers/pcmcia/sa1100_xp860.c
@@ -132,14 +132,14 @@ xp860_pcmcia_configure_socket(const struct pcmcia_configure *conf)
}
static struct pcmcia_low_level xp860_pcmcia_ops = {
- init: xp860_pcmcia_init,
- shutdown: sa1111_pcmcia_shutdown,
- socket_state: sa1111_pcmcia_socket_state,
- get_irq_info: sa1111_pcmcia_get_irq_info,
- configure_socket: xp860_pcmcia_configure_socket,
-
- socket_init: sa1111_pcmcia_socket_init,
- socket_suspend: sa1111_pcmcia_socket_suspend,
+ .init = xp860_pcmcia_init,
+ .shutdown = sa1111_pcmcia_shutdown,
+ .socket_state = sa1111_pcmcia_socket_state,
+ .get_irq_info = sa1111_pcmcia_get_irq_info,
+ .configure_socket = xp860_pcmcia_configure_socket,
+
+ .socket_init = sa1111_pcmcia_socket_init,
+ .socket_suspend = sa1111_pcmcia_socket_suspend,
};
int __init pcmcia_xp860_init(void)
diff --git a/drivers/pcmcia/sa1100_yopy.c b/drivers/pcmcia/sa1100_yopy.c
index 4bdb837cd6f1..138f2b07f067 100644
--- a/drivers/pcmcia/sa1100_yopy.c
+++ b/drivers/pcmcia/sa1100_yopy.c
@@ -9,6 +9,7 @@
#include <linux/init.h>
#include <asm/hardware.h>
+#include <asm/mach-types.h>
#include <asm/irq.h>
#include "sa1100_generic.h"
@@ -160,14 +161,14 @@ static int yopy_pcmcia_socket_suspend(int sock)
}
static struct pcmcia_low_level yopy_pcmcia_ops = {
- init: yopy_pcmcia_init,
- shutdown: yopy_pcmcia_shutdown,
- socket_state: yopy_pcmcia_socket_state,
- get_irq_info: yopy_pcmcia_get_irq_info,
- configure_socket: yopy_pcmcia_configure_socket,
-
- socket_init: yopy_pcmcia_socket_init,
- socket_suspend: yopy_pcmcia_socket_suspend,
+ .init = yopy_pcmcia_init,
+ .shutdown = yopy_pcmcia_shutdown,
+ .socket_state = yopy_pcmcia_socket_state,
+ .get_irq_info = yopy_pcmcia_get_irq_info,
+ .configure_socket = yopy_pcmcia_configure_socket,
+
+ .socket_init = yopy_pcmcia_socket_init,
+ .socket_suspend = yopy_pcmcia_socket_suspend,
};
int __init pcmcia_yopy_init(void)
diff --git a/drivers/serial/8250_acorn.c b/drivers/serial/8250_acorn.c
new file mode 100644
index 000000000000..80160e093967
--- /dev/null
+++ b/drivers/serial/8250_acorn.c
@@ -0,0 +1,150 @@
+/*
+ * linux/drivers/serial/acorn.c
+ *
+ * Copyright (C) 1996-2002 Russell King.
+ *
+ * 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/serial.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/init.h>
+
+#include <asm/ecard.h>
+#include <asm/string.h>
+
+#define MAX_PORTS 3
+
+struct serial_card_type {
+ unsigned int num_ports;
+ unsigned int baud_base;
+ int type;
+ int speed;
+ int offset[MAX_PORTS];
+};
+
+struct serial_card_info {
+ unsigned int num_ports;
+ int ports[MAX_PORTS];
+ unsigned long base[MAX_PORTS];
+};
+
+static inline int serial_register_onedev(unsigned long port, int irq, unsigned int baud_base)
+{
+ struct serial_struct req;
+
+ memset(&req, 0, sizeof(req));
+ req.baud_base = baud_base;
+ req.irq = irq;
+ req.port = port;
+ req.flags = 0;
+
+ return register_serial(&req);
+}
+
+static int __devinit serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
+{
+ struct serial_card_info *info;
+ struct serial_card_type *type = id->data;
+ unsigned long cardaddr, address;
+ int port;
+
+ ecard_claim (ec);
+
+ info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ memset(info, 0, sizeof(struct serial_card_info));
+ info->num_ports = type->num_ports;
+
+ cardaddr = ecard_address(ec, type->type, type->speed);
+
+ for (port = 0; port < info->num_ports; port ++) {
+ address = cardaddr + type->offset[port];
+
+ info->ports[port] = -1;
+ info->base[port] = address;
+
+ if (!request_region(address, 8, "acornserial"))
+ continue;
+
+ info->ports[port] = serial_register_onedev(address, ec->irq, type->baud_base);
+ if (info->ports[port] < 0)
+ break;
+ }
+
+ return 0;
+}
+
+static void __devexit serial_card_remove(struct expansion_card *ec)
+{
+ struct serial_card_info *info = ecard_get_drvdata(ec);
+ int i;
+
+ ecard_set_drvdata(ec, NULL);
+
+ for (i = 0; i < info->num_ports; i++) {
+ if (info->ports[i] > 0) {
+ unregister_serial(info->ports[i]);
+ release_region(info->base[i], 8);
+ }
+ }
+
+ kfree(info);
+
+ ecard_release(ec);
+}
+
+static struct serial_card_type atomwide_type = {
+ .num_ports = 3,
+ .baud_base = 7372800 / 16,
+ .type = ECARD_IOC,
+ .speed = ECARD_SLOW,
+ .offset = { 0xa00, 0x900, 0x800 },
+};
+
+static struct serial_card_type serport_type = {
+ .num_ports = 2,
+ .baud_base = 3686400 / 16,
+ .type = ECARD_IOC,
+ .speed = ECARD_SLOW,
+ .offset = { 0x800, 0x808 },
+};
+
+static const struct ecard_id serial_cids[] = {
+ { MANU_ATOMWIDE, PROD_ATOMWIDE_3PSERIAL, &atomwide_type },
+ { MANU_SERPORT, PROD_SERPORT_DSPORT, &serport_type },
+ { 0xffff, 0xffff }
+};
+
+static struct ecard_driver serial_card_driver = {
+ .probe = serial_card_probe,
+ .remove = __devexit_p(serial_card_remove),
+ .id_table = serial_cids,
+ .drv = {
+ .name = "acornserial",
+ },
+};
+
+static int __init serial_card_init(void)
+{
+ return ecard_register_driver(&serial_card_driver);
+}
+
+static void __exit serial_card_exit(void)
+{
+ ecard_remove_driver(&serial_card_driver);
+}
+
+MODULE_AUTHOR("Russell King");
+MODULE_LICENSE("GPL");
+
+module_init(serial_card_init);
+module_exit(serial_card_exit);
diff --git a/drivers/serial/Config.help b/drivers/serial/Config.help
index c5907d78e1b2..fccf27c710f9 100644
--- a/drivers/serial/Config.help
+++ b/drivers/serial/Config.help
@@ -103,20 +103,15 @@ CONFIG_SERIAL_8250_MULTIPORT
CONFIG_SERIAL_8250_RSA
::: To be written :::
-CONFIG_ATOMWIDE_SERIAL
- If you have an Atomwide Serial card for an Acorn system, say Y to
- this option. The driver can handle 1, 2, or 3 port cards.
- If unsure, say N.
-
-CONFIG_DUALSP_SERIAL
- If you have the Serial Port's dual serial card for an Acorn system,
- say Y to this option. If unsure, say N.
+CONFIG_SERIAL_8250_ACORN
+ If you have an Atomwide Serial card or Serial Port card for an Acorn
+ system, say Y to this option. The driver can handle 1, 2, or 3 port
+ cards. If unsure, say N.
CONFIG_SERIAL_ANAKIN
::: To be written :::
-CONFIG_SERIAL_ANAKIN_CONSOLE
- ::: To be written :::
+CONFIG_SERIAL_ANAKIN_CONSOLE
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
@@ -149,8 +144,6 @@ CONFIG_SERIAL_CLPS711X
::: To be written :::
CONFIG_SERIAL_CLPS711X_CONSOLE
- ::: To be written :::
-
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
diff --git a/drivers/serial/Config.in b/drivers/serial/Config.in
index 5a7841d7deeb..71637638d4d8 100644
--- a/drivers/serial/Config.in
+++ b/drivers/serial/Config.in
@@ -22,8 +22,7 @@ dep_bool ' Support RSA serial ports' CONFIG_SERIAL_8250_RSA $CONFIG_SERIAL_8250
comment 'Non-8250 serial port support'
if [ "$CONFIG_ARM" = "y" ]; then
- dep_tristate 'Acorn Atomwide 16550 serial port support' CONFIG_ATOMWIDE_SERIAL $CONFIG_ARCH_ACORN $CONFIG_SERIAL_8250
- dep_tristate 'Acorn Dual 16550 serial port support' CONFIG_DUALSP_SERIAL $CONFIG_ARCH_ACORN $CONFIG_SERIAL_8250
+ dep_tristate 'Acorn expansion card serial port support' CONFIG_SERIAL_8250_ACORN $CONFIG_ARCH_ACORN $CONFIG_SERIAL_8250
dep_bool 'Anakin serial port support' CONFIG_SERIAL_ANAKIN $CONFIG_ARCH_ANAKIN
dep_bool ' Console on Anakin serial port' CONFIG_SERIAL_ANAKIN_CONSOLE $CONFIG_SERIAL_ANAKIN
if [ "$CONFIG_SERIAL_ANAKIN" = "y" ]; then
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 6b7a12d08bf7..bbf7e26cf521 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SERIAL_CORE) += core.o
obj-$(CONFIG_SERIAL_21285) += 21285.o
obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y)
obj-$(CONFIG_SERIAL_8250_CS) += 8250_cs.o
+obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o
obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o
obj-$(CONFIG_SERIAL_AMBA) += amba.o
obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 096014df8eaa..8271d0bbcbb1 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -380,7 +380,7 @@ acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
* vder : >= vdsr
*/
static void
-acornfb_set_timing(struct fb_var_screeninfo *var)
+acornfb_set_timing(struct fb_info *info, struct fb_var_screeninfo *var)
{
struct vidc_timing vidc;
u_int vcr, fsize;
@@ -470,7 +470,7 @@ acornfb_set_timing(struct fb_var_screeninfo *var)
words_per_line = var->xres * var->bits_per_pixel / 32;
- if (current_par.using_vram && current_par.screen_size == 2048*1024)
+ if (current_par.using_vram && info->fix.smem_len == 2048*1024)
words_per_line /= 2;
/* RiscPC doesn't use the VIDC's VRAM control. */
@@ -549,7 +549,7 @@ acornfb_palette_decode(u_int regno, u_int *red, u_int *green, u_int *blue,
* the resolution to fit the rules.
*/
static int
-acornfb_adjust_timing(struct fb_var_screeninfo *var, int con)
+acornfb_adjust_timing(struct fb_info *info, struct fb_var_screeninfo *var, int con)
{
u_int font_line_len;
u_int fontht;
@@ -595,13 +595,13 @@ acornfb_adjust_timing(struct fb_var_screeninfo *var, int con)
* If minimum screen size is greater than that we have
* available, reject it.
*/
- if (min_size > current_par.screen_size)
+ if (min_size > info->fix.smem_len)
return -EINVAL;
/* Find int 'y', such that y * fll == s * sam < maxsize
* y = s * sam / fll; s = maxsize / sam
*/
- for (size = current_par.screen_size;
+ for (size = info->fix.smem_len;
nr_y = size / font_line_len, min_size <= size;
size -= sam_size) {
if (nr_y * font_line_len == size)
@@ -614,14 +614,14 @@ acornfb_adjust_timing(struct fb_var_screeninfo *var, int con)
/*
* failed, use ypan
*/
- size = current_par.screen_size;
+ size = info->fix.smem_len;
var->yres_virtual = size / (font_line_len / fontht);
} else
var->yres_virtual = nr_y;
} else if (var->yres_virtual > nr_y)
var->yres_virtual = nr_y;
- current_par.screen_end = current_par.screen_base_p + size;
+ current_par.screen_end = info->fix.smem_start + size;
/*
* Fix yres & yoffset if needed.
@@ -691,7 +691,7 @@ acornfb_validate_timing(struct fb_var_screeninfo *var,
}
static inline void
-acornfb_update_dma(struct fb_var_screeninfo *var)
+acornfb_update_dma(struct fb_info *info, struct fb_var_screeninfo *var)
{
int off = (var->yoffset * var->xres_virtual *
var->bits_per_pixel) >> 3;
@@ -699,7 +699,7 @@ acornfb_update_dma(struct fb_var_screeninfo *var)
#if defined(HAS_MEMC)
memc_write(VDMA_INIT, off >> 2);
#elif defined(HAS_IOMD)
- iomd_writel(current_par.screen_base_p + off, IOMD_VIDINIT);
+ iomd_writel(info->fix.smem_start + off, IOMD_VIDINIT);
#endif
}
@@ -792,7 +792,7 @@ acornfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
}
static int
-acornfb_decode_var(struct fb_var_screeninfo *var, int con)
+acornfb_decode_var(struct fb_info *info, struct fb_var_screeninfo *var, int con)
{
int err;
@@ -865,7 +865,7 @@ acornfb_decode_var(struct fb_var_screeninfo *var, int con)
* Validate and adjust the resolution to
* match the video generator hardware.
*/
- err = acornfb_adjust_timing(var, con);
+ err = acornfb_adjust_timing(info, var, con);
if (err)
return err;
@@ -877,55 +877,18 @@ acornfb_decode_var(struct fb_var_screeninfo *var, int con)
}
static int
-acornfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
-{
- struct display *display;
-
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
- strcpy(fix->id, "Acorn");
-
- if (con >= 0)
- display = fb_display + con;
- else
- display = &global_disp;
-
- fix->smem_start = current_par.screen_base_p;
- fix->smem_len = current_par.screen_size;
- fix->type = display->type;
- fix->type_aux = display->type_aux;
- fix->xpanstep = 0;
- fix->ypanstep = display->ypanstep;
- fix->ywrapstep = display->ywrapstep;
- fix->visual = display->visual;
- fix->line_length = display->line_length;
- fix->accel = FB_ACCEL_NONE;
-
- return 0;
-}
-
-static int
-acornfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
-{
- if (con == -1) {
- *var = global_disp.var;
- } else
- *var = fb_display[con].var;
-
- return 0;
-}
-
-static int
acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
{
struct display *display;
- int err, chgvar = 0;
+ unsigned int visual, chgvar = 0;
+ int err;
if (con >= 0)
display = fb_display + con;
else
display = &global_disp;
- err = acornfb_decode_var(var, con);
+ err = acornfb_decode_var(info, var, con);
if (err)
return err;
@@ -969,21 +932,21 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
case 1:
current_par.palette_size = 2;
display->dispsw = &fbcon_mfb;
- display->visual = FB_VISUAL_MONO10;
+ visual = FB_VISUAL_MONO10;
break;
#endif
#ifdef FBCON_HAS_CFB2
case 2:
current_par.palette_size = 4;
display->dispsw = &fbcon_cfb2;
- display->visual = FB_VISUAL_PSEUDOCOLOR;
+ visual = FB_VISUAL_PSEUDOCOLOR;
break;
#endif
#ifdef FBCON_HAS_CFB4
case 4:
current_par.palette_size = 16;
display->dispsw = &fbcon_cfb4;
- display->visual = FB_VISUAL_PSEUDOCOLOR;
+ visual = FB_VISUAL_PSEUDOCOLOR;
break;
#endif
#ifdef FBCON_HAS_CFB8
@@ -991,9 +954,9 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
current_par.palette_size = VIDC_PALETTE_SIZE;
display->dispsw = &fbcon_cfb8;
#ifdef HAS_VIDC
- display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+ visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
#else
- display->visual = FB_VISUAL_PSEUDOCOLOR;
+ visual = FB_VISUAL_PSEUDOCOLOR;
#endif
break;
#endif
@@ -1002,7 +965,7 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
current_par.palette_size = 32;
display->dispsw = &fbcon_cfb16;
display->dispsw_data = current_par.cmap.cfb16;
- display->visual = FB_VISUAL_DIRECTCOLOR;
+ visual = FB_VISUAL_DIRECTCOLOR;
break;
#endif
#ifdef FBCON_HAS_CFB32
@@ -1010,22 +973,17 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
current_par.palette_size = VIDC_PALETTE_SIZE;
display->dispsw = &fbcon_cfb32;
display->dispsw_data = current_par.cmap.cfb32;
- display->visual = FB_VISUAL_TRUECOLOR;
+ visual = FB_VISUAL_TRUECOLOR;
break;
#endif
default:
display->dispsw = &fbcon_dummy;
+ visual = FB_VISUAL_MONO10;
break;
}
- info->screen_base = (char *)current_par.screen_base;
- display->type = FB_TYPE_PACKED_PIXELS;
- display->type_aux = 0;
- display->ypanstep = 1;
- display->ywrapstep = 1;
- display->line_length =
display->next_line = (var->xres * var->bits_per_pixel) / 8;
- display->can_soft_blank = display->visual == FB_VISUAL_PSEUDOCOLOR ? 1 : 0;
+ display->can_soft_blank = visual == FB_VISUAL_PSEUDOCOLOR ? 1 : 0;
display->inverse = 0;
if (chgvar && info && info->changevar)
@@ -1036,16 +994,18 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
unsigned long start, size;
int control;
+ info->fix.visual = visual;
+
#if defined(HAS_MEMC)
start = 0;
- size = current_par.screen_size - VDMA_XFERSIZE;
+ size = info->fix.smem_len - VDMA_XFERSIZE;
control = 0;
memc_write(VDMA_START, start);
memc_write(VDMA_END, size >> 2);
#elif defined(HAS_IOMD)
- start = current_par.screen_base_p;
+ start = info->fix.smem_start;
size = current_par.screen_end;
if (current_par.using_vram) {
@@ -1060,8 +1020,8 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
iomd_writel(size, IOMD_VIDEND);
iomd_writel(control, IOMD_VIDCR);
#endif
- acornfb_update_dma(var);
- acornfb_set_timing(var);
+ acornfb_update_dma(info, var);
+ acornfb_set_timing(info, var);
if (display->cmap.len)
cmap = &display->cmap;
@@ -1090,7 +1050,7 @@ acornfb_pan_display(struct fb_var_screeninfo *var, int con,
if (y_bottom > fb_display[con].var.yres_virtual)
return -EINVAL;
- acornfb_update_dma(var);
+ acornfb_update_dma(info, var);
fb_display[con].var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
@@ -1147,8 +1107,8 @@ acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma
off = vma->vm_pgoff << PAGE_SHIFT;
- start = current_par.screen_base_p;
- len = PAGE_ALIGN(start & ~PAGE_MASK) + current_par.screen_size;
+ start = info->fix.smem_start;
+ len = PAGE_ALIGN(start & ~PAGE_MASK) + info->fix.smem_len;
start &= PAGE_MASK;
if ((vma->vm_end - vma->vm_start + off) > len)
return -EINVAL;
@@ -1176,23 +1136,21 @@ acornfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma
}
static struct fb_ops acornfb_ops = {
- .owner = THIS_MODULE,
- .fb_get_fix = acornfb_get_fix,
- .fb_get_var = acornfb_get_var,
- .fb_set_var = acornfb_set_var,
- .fb_get_cmap = acornfb_get_cmap,
- .fb_set_cmap = gen_set_cmap,
- .fb_setcolreg = acornfb_setcolreg,
- .fb_pan_display =acornfb_pan_display,
- .fb_blank = acornfb_blank,
- .fb_mmap = acornfb_mmap,
+ .owner = THIS_MODULE,
+ .fb_set_var = acornfb_set_var,
+ .fb_get_cmap = acornfb_get_cmap,
+ .fb_set_cmap = gen_set_cmap,
+ .fb_setcolreg = acornfb_setcolreg,
+ .fb_pan_display = acornfb_pan_display,
+ .fb_blank = acornfb_blank,
+ .fb_mmap = acornfb_mmap,
};
static int
acornfb_updatevar(int con, struct fb_info *info)
{
if (con == info->currcon)
- acornfb_update_dma(&fb_display[con].var);
+ acornfb_update_dma(info, &fb_display[con].var);
return 0;
}
@@ -1302,15 +1260,24 @@ acornfb_init_fbinfo(void)
strcpy(fb_info.modename, "Acorn");
strcpy(fb_info.fontname, "Acorn8x8");
- fb_info.node = NODEV;
- fb_info.fbops = &acornfb_ops;
- fb_info.disp = &global_disp;
- fb_info.changevar = NULL;
- fb_info.switch_con = acornfb_switch;
- fb_info.updatevar = acornfb_updatevar;
- fb_info.flags = FBINFO_FLAG_DEFAULT;
-
- global_disp.dispsw = &fbcon_dummy;
+ fb_info.node = NODEV;
+ fb_info.fbops = &acornfb_ops;
+ fb_info.disp = &global_disp;
+ fb_info.changevar = NULL;
+ fb_info.switch_con = acornfb_switch;
+ fb_info.updatevar = acornfb_updatevar;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+ strcpy(fb_info.fix.id, "Acorn");
+ fb_info.fix.type = FB_TYPE_PACKED_PIXELS;
+ fb_info.fix.type_aux = 0;
+ fb_info.fix.xpanstep = 0;
+ fb_info.fix.ypanstep = 1;
+ fb_info.fix.ywrapstep = 1;
+ fb_info.fix.line_length = 0;
+ fb_info.fix.accel = FB_ACCEL_NONE;
+
+ global_disp.dispsw = &fbcon_dummy;
/*
* setup initial parameters
@@ -1618,10 +1585,10 @@ acornfb_init(void)
}
}
- fb_info.currcon = -1;
- current_par.screen_base = SCREEN_BASE;
- current_par.screen_base_p = SCREEN_START;
- current_par.using_vram = 0;
+ fb_info.currcon = -1;
+ fb_info.screen_base = (char *)SCREEN_BASE;
+ fb_info.fix.smem_start = SCREEN_START;
+ current_par.using_vram = 0;
/*
* If vram_size is set, we are using VRAM in
@@ -1653,27 +1620,26 @@ acornfb_init(void)
* VRAM. Archimedes/A5000 machines use a
* fixed address for their framebuffers.
*/
- int order = 0;
- unsigned long page, top;
- while (size > (PAGE_SIZE * (1 << order)))
- order++;
- current_par.screen_base = __get_free_pages(GFP_KERNEL, order);
- if (current_par.screen_base == 0) {
+ unsigned long page, top, base;
+ int order = get_order(size);
+
+ base = __get_free_pages(GFP_KERNEL, order);
+ if (base == 0) {
printk(KERN_ERR "acornfb: unable to allocate screen "
"memory\n");
return -ENOMEM;
}
- top = current_par.screen_base + (PAGE_SIZE * (1 << order));
+ top = base + (PAGE_SIZE << order);
+
/* Mark the framebuffer pages as reserved so mmap will work. */
- for (page = current_par.screen_base;
- page < PAGE_ALIGN(current_par.screen_base + size);
- page += PAGE_SIZE)
+ for (page = base; page < PAGE_ALIGN(base + size); page += PAGE_SIZE)
SetPageReserved(virt_to_page(page));
/* Hand back any excess pages that we allocated. */
- for (page = current_par.screen_base + size; page < top; page += PAGE_SIZE)
+ for (page = base + size; page < top; page += PAGE_SIZE)
free_page(page);
- current_par.screen_base_p =
- virt_to_phys((void *)current_par.screen_base);
+
+ fb_info.screen_base = (char *)base;
+ fb_info.fix.smem_start = virt_to_phys(fb_info.screen_base);
}
#endif
#if defined(HAS_VIDC)
@@ -1683,7 +1649,7 @@ acornfb_init(void)
free_unused_pages(PAGE_OFFSET + size, PAGE_OFFSET + MAX_SIZE);
#endif
- current_par.screen_size = size;
+ fb_info.fix.smem_len = size;
current_par.palette_size = VIDC_PALETTE_SIZE;
/*
@@ -1734,9 +1700,9 @@ acornfb_init(void)
v_sync = h_sync / (init_var.yres + init_var.upper_margin +
init_var.lower_margin + init_var.vsync_len);
- printk(KERN_INFO "Acornfb: %ldkB %cRAM, %s, using %dx%d, "
+ printk(KERN_INFO "Acornfb: %dkB %cRAM, %s, using %dx%d, "
"%d.%03dkHz, %dHz\n",
- current_par.screen_size / 1024,
+ fb_info.fix.smem_len / 1024,
current_par.using_vram ? 'V' : 'D',
VIDC_NAME, init_var.xres, init_var.yres,
h_sync / 1000, h_sync % 1000, v_sync);
diff --git a/drivers/video/acornfb.h b/drivers/video/acornfb.h
index c0e45dcecfab..fd08ae82bffa 100644
--- a/drivers/video/acornfb.h
+++ b/drivers/video/acornfb.h
@@ -47,10 +47,7 @@ union palette {
};
struct acornfb_par {
- unsigned long screen_base;
- unsigned long screen_base_p;
unsigned long screen_end;
- unsigned long screen_size;
unsigned int dram_size;
unsigned int vram_half_sam;
unsigned int palette_size;
diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c
index d00c96dccb1e..14a67d332255 100644
--- a/drivers/video/clps711xfb.c
+++ b/drivers/video/clps711xfb.c
@@ -25,6 +25,7 @@
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
+#include <linux/delay.h>
#include <video/fbcon.h>
@@ -37,7 +38,7 @@
struct fb_info *cfb;
-#define CMAP_SIZE 16
+#define CMAP_MAX_SIZE 16
/* The /proc entry for the backlight. */
static struct proc_dir_entry *clps7111fb_backlight_proc_entry = NULL;
@@ -48,6 +49,13 @@ static int clps7111fb_proc_backlight_write(struct file *file,
const char *buffer, unsigned long count, void *data);
/*
+ * LCD AC Prescale. This comes from the LCD panel manufacturers specifications.
+ * This determines how many clocks + 1 of CL1 before the M signal toggles.
+ * The number of lines on the display must not be divisible by this number.
+ */
+static unsigned int lcd_ac_prescale = 13;
+
+/*
* Set a single color register. Return != 0 for invalid regno.
*/
static int
@@ -56,7 +64,7 @@ clps7111fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
{
unsigned int level, mask, shift, pal;
- if (regno >= CMAP_SIZE)
+ if (regno >= (1 << info->var.bits_per_pixel))
return 1;
/* gray = 0.30*R + 0.58*G + 0.11*B */
@@ -104,6 +112,8 @@ clps7111fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
if (var->bits_per_pixel > 4)
return -EINVAL;
+
+ return 0;
}
/*
@@ -112,32 +122,46 @@ clps7111fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
static int
clps7111fb_set_par(struct fb_info *info)
{
- unsigned int lcdcon, syscon;
+ unsigned int lcdcon, syscon, pixclock;
- switch (var->bits_per_pixel) {
+ switch (info->var.bits_per_pixel) {
case 1:
- info->fix.visual = FB_VISUAL_MONO01;
+ info->fix.visual = FB_VISUAL_MONO01;
break;
case 2:
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
case 4:
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
break;
}
info->fix.line_length = info->var.xres_virtual * info->var.bits_per_pixel / 8;
- /*
- * LCDCON must only be changed while the LCD is disabled
- */
lcdcon = (info->var.xres_virtual * info->var.yres_virtual * info->var.bits_per_pixel) / 128 - 1;
lcdcon |= ((info->var.xres_virtual / 16) - 1) << 13;
- lcdcon |= 2 << 19;
- lcdcon |= 13 << 25;
- lcdcon |= LCDCON_GSEN;
- lcdcon |= LCDCON_GSMD;
+ lcdcon |= lcd_ac_prescale << 25;
+
+ /*
+ * Calculate pixel prescale value from the pixclock. This is:
+ * 36.864MHz / pixclock_mhz - 1.
+ * However, pixclock is in picoseconds, so this ends up being:
+ * 36864000 * pixclock_ps / 10^12 - 1
+ * and this will overflow the 32-bit math. We perform this as
+ * (9 * 4096000 == 36864000):
+ * pixclock_ps * 9 * (4096000 / 10^12) - 1
+ */
+ pixclock = 9 * info->var.pixclock / 244140 - 1;
+ lcdcon |= pixclock << 19;
+
+ if (info->var.bits_per_pixel == 4)
+ lcdcon |= LCDCON_GSMD;
+ if (info->var.bits_per_pixel >= 2)
+ lcdcon |= LCDCON_GSEN;
+ /*
+ * LCDCON must only be changed while the LCD is disabled
+ */
syscon = clps_readl(SYSCON1);
clps_writel(syscon & ~SYSCON1_LCDEN, SYSCON1);
clps_writel(lcdcon, LCDCON);
@@ -149,8 +173,6 @@ static int clps7111fb_blank(int blank, struct fb_info *info)
{
if (blank) {
if (machine_is_edb7211()) {
- int i;
-
/* Turn off the LCD backlight. */
clps_writeb(clps_readb(PDDR) & ~EDB_PD3_LCDBL, PDDR);
@@ -169,8 +191,6 @@ static int clps7111fb_blank(int blank, struct fb_info *info)
}
} else {
if (machine_is_edb7211()) {
- int i;
-
/* Power up the LCD controller. */
clps_writel(clps_readl(SYSCON1) | SYSCON1_LCDEN,
SYSCON1);
@@ -256,6 +276,93 @@ clps7111fb_proc_backlight_write(struct file *file, const char *buffer,
return count;
}
+static void __init clps711x_guess_lcd_params(struct fb_info *info)
+{
+ unsigned int lcdcon, syscon, size;
+ unsigned long phys_base = PAGE_OFFSET;
+ void *virt_base = (void *)PAGE_OFFSET;
+
+ info->var.xres_virtual = 640;
+ info->var.yres_virtual = 240;
+ info->var.bits_per_pixel = 4;
+ info->var.activate = FB_ACTIVATE_NOW;
+ info->var.height = -1;
+ info->var.width = -1;
+ info->var.pixclock = 93006; /* 10.752MHz pixel clock */
+
+ /*
+ * If the LCD controller is already running, decode the values
+ * in LCDCON to xres/yres/bpp/pixclock/acprescale
+ */
+ syscon = clps_readl(SYSCON1);
+ if (syscon & SYSCON1_LCDEN) {
+ lcdcon = clps_readl(LCDCON);
+
+ /*
+ * Decode GSMD and GSEN bits to bits per pixel
+ */
+ switch (lcdcon & (LCDCON_GSMD | LCDCON_GSEN)) {
+ case LCDCON_GSMD | LCDCON_GSEN:
+ info->var.bits_per_pixel = 4;
+ break;
+
+ case LCDCON_GSEN:
+ info->var.bits_per_pixel = 2;
+ break;
+
+ default:
+ info->var.bits_per_pixel = 1;
+ break;
+ }
+
+ /*
+ * Decode xres/yres
+ */
+ info->var.xres_virtual = (((lcdcon >> 13) & 0x3f) + 1) * 16;
+ info->var.yres_virtual = (((lcdcon & 0x1fff) + 1) * 128) /
+ (info->var.xres_virtual *
+ info->var.bits_per_pixel);
+
+ /*
+ * Calculate pixclock
+ */
+ info->var.pixclock = (((lcdcon >> 19) & 0x3f) + 1) * 244140 / 9;
+
+ /*
+ * Grab AC prescale
+ */
+ lcd_ac_prescale = (lcdcon >> 25) & 0x1f;
+ }
+
+ info->var.xres = info->var.xres_virtual;
+ info->var.yres = info->var.yres_virtual;
+ info->var.grayscale = info->var.bits_per_pixel > 1;
+
+ size = info->var.xres * info->var.yres * info->var.bits_per_pixel / 8;
+
+ /*
+ * Might be worth checking to see if we can use the on-board
+ * RAM if size here...
+ * CLPS7110 - no on-board SRAM
+ * EP7212 - 38400 bytes
+ */
+ if (size < 38400) {
+ printk(KERN_INFO "CLPS711xFB: could use on-board SRAM?\n");
+ }
+
+ if ((syscon & SYSCON1_LCDEN) == 0) {
+ /*
+ * The display isn't running. Ensure that
+ * the display memory is empty.
+ */
+ memset(virt_base, 0, size);
+ }
+
+ info->screen_base = virt_base;
+ info->fix.smem_start = phys_base;
+ info->fix.smem_len = PAGE_ALIGN(size);
+ info->fix.type = FB_TYPE_PACKED_PIXELS;
+}
int __init clps711xfb_init(void)
{
@@ -266,34 +373,19 @@ int __init clps711xfb_init(void)
goto out;
memset(cfb, 0, sizeof(*cfb) + sizeof(struct display));
- memset((void *)PAGE_OFFSET, 0, 0x14000);
+ strcpy(cfb->fix.id, "clps711x");
cfb->currcon = -1;
-
- strcpy(cfb->fix.id, "clps7111");
- cfb->screen_base = (void *)PAGE_OFFSET;
- cfb->fix.smem_start = PAGE_OFFSET;
- cfb->fix.smem_len = 0x14000;
- cfb->fix.type = FB_TYPE_PACKED_PIXELS;
-
- cfb->var.xres = 640;
- cfb->var.xres_virtual = 640;
- cfb->var.yres = 240;
- cfb->var.yres_virtual = 240;
- cfb->var.bits_per_pixel = 4;
- cfb->var.grayscale = 1;
- cfb->var.activate = FB_ACTIVATE_NOW;
- cfb->var.height = -1;
- cfb->var.width = -1;
-
cfb->fbops = &clps7111fb_ops;
- cfb->changevar = NULL;
- cfb->switch_con = gen_switch;
- cfb->updatevar = gen_update_var;
+ cfb->changevar = NULL;
+ cfb->switch_con = gen_switch;
+ cfb->updatevar = gen_update_var;
cfb->flags = FBINFO_FLAG_DEFAULT;
cfb->disp = (struct display *)(cfb + 1);
- fb_alloc_cmap(&cfb->cmap, CMAP_SIZE, 0);
+ clps711x_guess_lcd_params(cfb);
+
+ fb_alloc_cmap(&cfb->cmap, CMAP_MAX_SIZE, 0);
/* Register the /proc entries. */
clps7111fb_backlight_proc_entry = create_proc_entry("backlight", 0444,
@@ -317,8 +409,6 @@ int __init clps711xfb_init(void)
}
if (machine_is_edb7211()) {
- int i;
-
/* Power up the LCD panel. */
clps_writeb(clps_readb(PDDR) | EDB_PD2_LCDEN, PDDR);
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
index a090625f0483..e21e8e38e931 100644
--- a/drivers/video/cyber2000fb.c
+++ b/drivers/video/cyber2000fb.c
@@ -1,11 +1,14 @@
/*
* linux/drivers/video/cyber2000fb.c
*
- * Copyright (C) 1998-2000 Russell King
+ * Copyright (C) 1998-2002 Russell King
*
* MIPS and 50xx clock support
* Copyright (C) 2001 Bradley D. LaRonde <brad@ltc.com>
*
+ * 32 bit support, text color and panning fixes for modes != 8 bit
+ * Copyright (C) 2002 Denis Oliver Kropp <dok@directfb.org>
+ *
* 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.
@@ -14,17 +17,24 @@
*
* Based on cyberfb.c.
*
- * Note that we now use the new fbcon fix, var and cmap scheme. We do still
- * have to check which console is the currently displayed one however, since
- * especially for the colourmap stuff.
+ * Note that we now use the new fbcon fix, var and cmap scheme. We do
+ * still have to check which console is the currently displayed one
+ * however, especially for the colourmap stuff.
+ *
+ * We also use the new hotplug PCI subsystem. I'm not sure if there
+ * are any such cards, but I'm erring on the side of caution. We don't
+ * want to go pop just because someone does have one.
*
- * We also use the new hotplug PCI subsystem. I'm not sure if there are any
- * such cards, but I'm erring on the side of caution. We don't want to go
- * pop just because someone does have one.
+ * Note that this doesn't work fully in the case of multiple CyberPro
+ * cards with grabbers. We currently can only attach to the first
+ * CyberPro card found.
*
- * Note that this doesn't work fully in the case of multiple CyberPro cards
- * with grabbers. We currently can only attach to the first CyberPro card
- * found.
+ * When we're in truecolour mode, we power down the LUT RAM as a power
+ * saving feature. Also, when we enter any of the powersaving modes
+ * (except soft blanking) we power down the RAMDACs. This saves about
+ * 1W, which is roughly 8% of the power consumption of a NetWinder
+ * (which, incidentally, is about the same saving as a 2.5in hard disk
+ * entering standby mode.)
*/
#include <linux/config.h>
#include <linux/module.h>
@@ -49,11 +59,7 @@
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb24.h>
-
-/*
- * Define this if you don't want RGB565, but RGB555 for 16bpp displays.
- */
-/*#define CFB16_IS_CFB15*/
+#include <video/fbcon-cfb32.h>
#include "cyber2000fb.h"
@@ -64,6 +70,7 @@ struct cfb_info {
struct pci_dev *dev;
unsigned char *region;
unsigned char *regs;
+ u_int id;
int func_use_count;
u_long ref_ps;
@@ -80,6 +87,11 @@ struct cfb_info {
u_char mem_ctl2;
u_char mclk_mult;
u_char mclk_div;
+ /*
+ * RAMDAC control register is both of these or'ed together
+ */
+ u_char ramdac_ctrl;
+ u_char ramdac_powerdown;
};
static char default_font_storage[40];
@@ -139,7 +151,7 @@ static void cyber2000_accel_wait(struct cfb_info *cfb)
{
int count = 100000;
- while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & 0x80) {
+ while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & CO_CTRL_BUSY) {
if (!count--) {
debug_printf("accel_wait timed out\n");
cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
@@ -163,8 +175,7 @@ cyber2000_accel_bmove(struct display *display, int sy, int sx, int dy, int dx,
struct cfb_info *cfb = (struct cfb_info *)display->fb_info;
struct fb_var_screeninfo *var = &display->var;
u_long src, dst;
- u_int fh, fw;
- int cmd = CO_CMD_L_PATTERN_FGCOL;
+ u_int fh, fw, cmd = CO_CMD_L_PATTERN_FGCOL;
fw = fontwidth(display);
sx *= fw;
@@ -194,22 +205,21 @@ cyber2000_accel_bmove(struct display *display, int sy, int sx, int dy, int dx,
dst = dx + dy * var->xres_virtual;
cyber2000_accel_wait(cfb);
- cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
- cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
- cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
+ cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
+ cyber2000fb_writew(width, CO_REG_PIXWIDTH, cfb);
+ cyber2000fb_writew(height, CO_REG_PIXHEIGHT, cfb);
- if (var->bits_per_pixel != 24) {
- cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
- cyber2000fb_writel(src, CO_REG_SRC_PTR, cfb);
- } else {
- cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
- cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
- cyber2000fb_writel(src * 3, CO_REG_SRC_PTR, cfb);
+ if (var->bits_per_pixel == 24) {
+ cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
+ dst *= 3;
+ src *= 3;
}
- cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
- cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
- cyber2000fb_writew(0x2800, CO_REG_CMD_H, cfb);
+ cyber2000fb_writel(src, CO_REG_SRC1_PTR, cfb);
+ cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
+ cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
+ cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
+ cyber2000fb_writew(CO_CMD_H_FGSRCMAP|CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
}
static void
@@ -230,28 +240,25 @@ cyber2000_accel_clear(struct vc_data *conp, struct display *display, int sy,
height = height * fh - 1;
cyber2000_accel_wait(cfb);
- cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
- cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
- cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
- cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
+ cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
+ cyber2000fb_writew(width, CO_REG_PIXWIDTH, cfb);
+ cyber2000fb_writew(height, CO_REG_PIXHEIGHT, cfb);
- switch (var->bits_per_pixel) {
- case 16:
- bgx = ((u16 *)display->dispsw_data)[bgx];
- case 8:
- cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
- break;
-
- case 24:
- cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
+ if (var->bits_per_pixel == 24) {
cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
- bgx = ((u32 *)display->dispsw_data)[bgx];
- break;
+ dst *= 3;
}
- cyber2000fb_writel(bgx, CO_REG_FOREGROUND, cfb);
+ if (var->bits_per_pixel == 16)
+ bgx = ((u16 *)display->dispsw_data)[bgx];
+ else if (var->bits_per_pixel >= 24)
+ bgx = ((u32 *)display->dispsw_data)[bgx];
+
+ cyber2000fb_writel(bgx, CO_REG_FGCOLOUR, cfb);
+ cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
+ cyber2000fb_writeb(CO_FG_MIX_SRC, CO_REG_FGMIX, cfb);
cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
- cyber2000fb_writew(0x0800, CO_REG_CMD_H, cfb);
+ cyber2000fb_writew(CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
}
static void
@@ -292,16 +299,23 @@ cyber2000_accel_clear_margins(struct vc_data *conp, struct display *display,
}
static struct display_switch fbcon_cyber_accel = {
- .setup = cyber2000_accel_setup,
- .bmove = cyber2000_accel_bmove,
- .clear = cyber2000_accel_clear,
- .putc = cyber2000_accel_putc,
- .putcs = cyber2000_accel_putcs,
- .revc = cyber2000_accel_revc,
- .clear_margins =cyber2000_accel_clear_margins,
- .fontwidthmask =FONTWIDTH(8)|FONTWIDTH(16)
+ .setup = cyber2000_accel_setup,
+ .bmove = cyber2000_accel_bmove,
+ .clear = cyber2000_accel_clear,
+ .putc = cyber2000_accel_putc,
+ .putcs = cyber2000_accel_putcs,
+ .revc = cyber2000_accel_revc,
+ .clear_margins = cyber2000_accel_clear_margins,
+ .fontwidthmask = FONTWIDTH(8)|FONTWIDTH(16)
};
+static inline u32 convert_bitfield(u_int val, struct fb_bitfield *bf)
+{
+ u_int mask = (1 << bf->length) - 1;
+
+ return (val >> (16 - bf->length) & mask) << bf->offset;
+}
+
/*
* Set a single color register. Return != 0 for invalid regno.
*/
@@ -311,85 +325,145 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
{
struct cfb_info *cfb = (struct cfb_info *)info;
struct fb_var_screeninfo *var = &cfb->display->var;
+ u32 pseudo_val;
+ int ret = 1;
- if (regno >= NR_PALETTE)
+ switch (cfb->fb.fix.visual) {
+ default:
return 1;
- red >>= 8;
- green >>= 8;
- blue >>= 8;
+#ifdef FBCON_HAS_CFB8
+ /*
+ * Pseudocolour:
+ * 8 8
+ * pixel --/--+--/--> red lut --> red dac
+ * | 8
+ * +--/--> green lut --> green dac
+ * | 8
+ * +--/--> blue lut --> blue dac
+ */
+ case FB_VISUAL_PSEUDOCOLOR:
+ if (regno >= NR_PALETTE)
+ return 1;
- cfb->palette[regno].red = red;
- cfb->palette[regno].green = green;
- cfb->palette[regno].blue = blue;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ cfb->palette[regno].red = red;
+ cfb->palette[regno].green = green;
+ cfb->palette[regno].blue = blue;
- switch (var->bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
- case 8:
cyber2000fb_writeb(regno, 0x3c8, cfb);
- cyber2000fb_writeb(red, 0x3c9, cfb);
+ cyber2000fb_writeb(red, 0x3c9, cfb);
cyber2000fb_writeb(green, 0x3c9, cfb);
- cyber2000fb_writeb(blue, 0x3c9, cfb);
- break;
+ cyber2000fb_writeb(blue, 0x3c9, cfb);
+ return 0;
#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
-#ifndef CFB16_IS_CFB15
- if (var->green.length == 6) {
- if (regno < 64) {
- /* write green */
- cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
- cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
- cyber2000fb_writeb(green, 0x3c9, cfb);
- cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
- }
-
- if (regno < 32) {
- /* write red,blue */
- cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
- cyber2000fb_writeb(red, 0x3c9, cfb);
- cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
- cyber2000fb_writeb(blue, 0x3c9, cfb);
- }
-
- if (regno < 16)
- ((u16 *)cfb->fb.pseudo_palette)[regno] =
- regno | regno << 5 | regno << 11;
- break;
+ /*
+ * Direct colour:
+ * n rl
+ * pixel --/--+--/--> red lut --> red dac
+ * | gl
+ * +--/--> green lut --> green dac
+ * | bl
+ * +--/--> blue lut --> blue dac
+ * n = bpp, rl = red length, gl = green length, bl = blue length
+ */
+ case FB_VISUAL_DIRECTCOLOR:
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ if (var->green.length == 6 && regno < 64) {
+ cfb->palette[regno << 2].green = green;
+
+ /*
+ * The 6 bits of the green component are applied
+ * to the high 6 bits of the LUT.
+ */
+ cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
+ cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
+ cyber2000fb_writeb(green, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
+
+ green = cfb->palette[regno << 3].green;
+
+ ret = 0;
}
-#endif
- if (regno < 32) {
+
+ if (var->green.length >= 5 && regno < 32) {
+ cfb->palette[regno << 3].red = red;
+ cfb->palette[regno << 3].green = green;
+ cfb->palette[regno << 3].blue = blue;
+
+ /*
+ * The 5 bits of each colour component are
+ * applied to the high 5 bits of the LUT.
+ */
cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
cyber2000fb_writeb(red, 0x3c9, cfb);
cyber2000fb_writeb(green, 0x3c9, cfb);
cyber2000fb_writeb(blue, 0x3c9, cfb);
+ ret = 0;
}
- if (regno < 16)
- ((u16 *)cfb->fb.pseudo_palette)[regno] =
- regno | regno << 5 | regno << 10;
- break;
-#endif
+ if (var->green.length == 4 && regno < 16) {
+ cfb->palette[regno << 4].red = red;
+ cfb->palette[regno << 4].green = green;
+ cfb->palette[regno << 4].blue = blue;
-#ifdef FBCON_HAS_CFB24
- case 24:
- cyber2000fb_writeb(regno, 0x3c8, cfb);
- cyber2000fb_writeb(red, 0x3c9, cfb);
- cyber2000fb_writeb(green, 0x3c9, cfb);
- cyber2000fb_writeb(blue, 0x3c9, cfb);
+ /*
+ * The 5 bits of each colour component are
+ * applied to the high 5 bits of the LUT.
+ */
+ cyber2000fb_writeb(regno << 4, 0x3c8, cfb);
+ cyber2000fb_writeb(red, 0x3c9, cfb);
+ cyber2000fb_writeb(green, 0x3c9, cfb);
+ cyber2000fb_writeb(blue, 0x3c9, cfb);
+ ret = 0;
+ }
- if (regno < 16)
- ((u32 *)cfb->fb.pseudo_palette)[regno] =
- regno | regno << 8 | regno << 16;
+ /*
+ * Since this is only used for the first 16 colours, we
+ * don't have to care about overflowing for regno >= 32
+ */
+ pseudo_val = regno << var->red.offset |
+ regno << var->green.offset |
+ regno << var->blue.offset;
break;
-#endif
- default:
- return 1;
+ /*
+ * True colour:
+ * n rl
+ * pixel --/--+--/--> red dac
+ * | gl
+ * +--/--> green dac
+ * | bl
+ * +--/--> blue dac
+ * n = bpp, rl = red length, gl = green length, bl = blue length
+ */
+ case FB_VISUAL_TRUECOLOR:
+ pseudo_val = convert_bitfield(transp ^ 0xffff, &var->transp);
+ pseudo_val |= convert_bitfield(red, &var->red);
+ pseudo_val |= convert_bitfield(green, &var->green);
+ pseudo_val |= convert_bitfield(blue, &var->blue);
+ break;
}
- return 0;
+ /*
+ * Now set our pseudo palette for the CFB16/24/32 drivers.
+ */
+ if (regno < 16) {
+ if (var->bits_per_pixel == 16)
+ ((u16 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
+ else
+ ((u32 *)cfb->fb.pseudo_palette)[regno] = pseudo_val;
+ ret = 0;
+ }
+
+ return ret;
}
struct par_info {
@@ -399,7 +473,7 @@ struct par_info {
u_char clock_mult;
u_char clock_div;
u_char extseqmisc;
- u_char pixformat;
+ u_char co_pixfmt;
u_char crtc_ofl;
u_char crtc[19];
u_int width;
@@ -409,8 +483,7 @@ struct par_info {
/*
* Other
*/
- u_char palette_ctrl;
- u_int vmode;
+ u_char ramdac;
};
static const u_char crtc_idx[] = {
@@ -419,6 +492,18 @@ static const u_char crtc_idx[] = {
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
};
+static void cyber2000fb_write_ramdac_ctrl(struct cfb_info *cfb)
+{
+ unsigned int i;
+ unsigned int val = cfb->ramdac_ctrl | cfb->ramdac_powerdown;
+
+ cyber2000fb_writeb(0x56, 0x3ce, cfb);
+ i = cyber2000fb_readb(0x3cf, cfb);
+ cyber2000fb_writeb(i | 4, 0x3cf, cfb);
+ cyber2000fb_writeb(val, 0x3c6, cfb);
+ cyber2000fb_writeb(i, 0x3cf, cfb);
+}
+
static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
{
u_int i;
@@ -450,7 +535,7 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
for (i = 0x0a; i < 0x10; i++)
cyber2000_crtcw(i, 0, cfb);
- cyber2000_grphw(0x11, hw->crtc_ofl, cfb);
+ cyber2000_grphw(EXT_CRT_VRTOFL, hw->crtc_ofl, cfb);
cyber2000_grphw(0x00, 0x00, cfb);
cyber2000_grphw(0x01, 0x00, cfb);
cyber2000_grphw(0x02, 0x00, cfb);
@@ -471,16 +556,6 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
cyber2000_attrw(0x13, 0x00, cfb);
cyber2000_attrw(0x14, 0x00, cfb);
- /* woody: set the interlaced bit... */
- /* FIXME: what about doublescan? */
- cyber2000fb_writeb(0x11, 0x3ce, cfb);
- i = cyber2000fb_readb(0x3cf, cfb);
- if (hw->vmode == FB_VMODE_INTERLACED)
- i |= 0x20;
- else
- i &= ~0x20;
- cyber2000fb_writeb(i, 0x3cf, cfb);
-
/* PLL registers */
cyber2000_grphw(EXT_DCLK_MULT, hw->clock_mult, cfb);
cyber2000_grphw(EXT_DCLK_DIV, hw->clock_div, cfb);
@@ -490,11 +565,8 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
cyber2000_grphw(0xb9, 0x80, cfb);
cyber2000_grphw(0xb9, 0x00, cfb);
- cyber2000fb_writeb(0x56, 0x3ce, cfb);
- i = cyber2000fb_readb(0x3cf, cfb);
- cyber2000fb_writeb(i | 4, 0x3cf, cfb);
- cyber2000fb_writeb(hw->palette_ctrl, 0x3c6, cfb);
- cyber2000fb_writeb(i, 0x3cf, cfb);
+ cfb->ramdac_ctrl = hw->ramdac;
+ cyber2000fb_write_ramdac_ctrl(cfb);
cyber2000fb_writeb(0x20, 0x3c0, cfb);
cyber2000fb_writeb(0xff, 0x3c6, cfb);
@@ -504,25 +576,20 @@ static void cyber2000fb_set_timing(struct cfb_info *cfb, struct par_info *hw)
((hw->pitch >> 4) & 0x30), cfb);
cyber2000_grphw(EXT_SEQ_MISC, hw->extseqmisc, cfb);
- cyber2000_grphw(EXT_BIU_MISC, EXT_BIU_MISC_LIN_ENABLE |
- EXT_BIU_MISC_COP_ENABLE |
- EXT_BIU_MISC_COP_BFC, cfb);
-
/*
* Set up accelerator registers
*/
cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
- cyber2000fb_writeb(hw->pixformat, CO_REG_PIX_FORMAT, cfb);
+ cyber2000fb_writeb(hw->co_pixfmt, CO_REG_PIXFMT, cfb);
}
static inline int
cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var)
{
- u_int base;
+ u_int base = var->yoffset * var->xres_virtual + var->xoffset;
- base = var->yoffset * var->xres_virtual * var->bits_per_pixel +
- var->xoffset * var->bits_per_pixel;
+ base *= var->bits_per_pixel;
/*
* Convert to bytes and shift two extra bits because DAC
@@ -606,8 +673,9 @@ cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb,
hw->crtc[16] = Vblankend;
hw->crtc[18] = 0xff;
- /* overflow - graphics reg 0x11 */
- /* 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
+ /*
+ * overflow - graphics reg 0x11
+ * 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10
* 4=LINECOMP:10 5-IVIDEO 6=FIXCNT
*/
hw->crtc_ofl =
@@ -615,7 +683,12 @@ cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb,
BIT(Vdispend, 10, 0x01, 1) |
BIT(Vsyncstart, 10, 0x01, 2) |
BIT(Vblankstart,10, 0x01, 3) |
- 1 << 4;
+ EXT_CRT_VRTOFL_LINECOMP10;
+
+ /* woody: set the interlaced bit... */
+ /* FIXME: what about doublescan? */
+ if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
+ hw->crtc_ofl |= EXT_CRT_VRTOFL_INTERLACE;
return 0;
}
@@ -735,51 +808,131 @@ static int
cyber2000fb_decode_var(struct fb_var_screeninfo *var, struct cfb_info *cfb,
struct par_info *hw)
{
+ unsigned int mem;
int err;
hw->width = var->xres_virtual;
- hw->palette_ctrl = 0x06;
- hw->vmode = var->vmode;
+ hw->ramdac = RAMDAC_VREFEN | RAMDAC_DAC8BIT;
+
+ var->transp.msb_right = 0;
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8: /* PSEUDOCOLOUR, 256 */
- hw->pixformat = PIXFORMAT_8BPP;
- hw->extseqmisc = EXT_SEQ_MISC_8;
+ hw->co_pixfmt = CO_PIXFMT_8BPP;
hw->pitch = hw->width >> 3;
+ hw->extseqmisc = EXT_SEQ_MISC_8;
+
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 0;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
break;
#endif
#ifdef FBCON_HAS_CFB16
- case 16:
- hw->pixformat = PIXFORMAT_16BPP;
+ case 16:/* DIRECTCOLOUR, 64k or 32k */
+ hw->co_pixfmt = CO_PIXFMT_16BPP;
hw->pitch = hw->width >> 2;
- hw->palette_ctrl |= 0x10;
-#ifndef CFB16_IS_CFB15
- /* DIRECTCOLOUR, 64k */
- if (var->green.length == 6) {
+ switch (var->green.length) {
+ case 6: /* RGB565, 64k */
hw->extseqmisc = EXT_SEQ_MISC_16_RGB565;
+
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->red.offset = 11;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 6;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ break;
+
+ default:
+ case 5: /* RGB555, 32k */
+ hw->extseqmisc = EXT_SEQ_MISC_16_RGB555;
+
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->red.offset = 10;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 5;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ break;
+
+ case 4: /* RGB444, 4k + transparency? */
+ hw->extseqmisc = EXT_SEQ_MISC_16_RGB444;
+
+ var->transp.offset = 12;
+ var->transp.length = 4;
+ var->red.offset = 8;
+ var->red.length = 4;
+ var->green.offset = 4;
+ var->green.length = 4;
+ var->blue.offset = 0;
+ var->blue.length = 4;
break;
}
-#endif
- /* DIRECTCOLOUR, 32k */
- hw->extseqmisc = EXT_SEQ_MISC_16_RGB555;
break;
-
#endif
#ifdef FBCON_HAS_CFB24
case 24:/* TRUECOLOUR, 16m */
- hw->pixformat = PIXFORMAT_24BPP;
- hw->extseqmisc = EXT_SEQ_MISC_24_RGB888;
+ hw->co_pixfmt = CO_PIXFMT_24BPP;
hw->width *= 3;
hw->pitch = hw->width >> 3;
- hw->palette_ctrl |= 0x10;
+ hw->ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
+ hw->extseqmisc = EXT_SEQ_MISC_24_RGB888;
+
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:/* TRUECOLOUR, 16m */
+ hw->co_pixfmt = CO_PIXFMT_32BPP;
+ hw->pitch = hw->width >> 1;
+ hw->ramdac |= (RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
+ hw->extseqmisc = EXT_SEQ_MISC_32;
+
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
break;
#endif
default:
return -EINVAL;
}
+ mem = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel / 8);
+ if (mem > cfb->fb.fix.smem_len)
+ var->yres_virtual = cfb->fb.fix.smem_len * 8 /
+ (var->bits_per_pixel * var->xres_virtual);
+
+ if (var->yres > var->yres_virtual)
+ var->yres = var->yres_virtual;
+ if (var->xres > var->xres_virtual)
+ var->xres = var->xres_virtual;
+
err = cyber2000fb_decode_clock(hw, cfb, var);
if (err)
return err;
@@ -807,7 +960,7 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con,
struct cfb_info *cfb = (struct cfb_info *)info;
struct display *display;
struct par_info hw;
- int err, chgvar = 0;
+ int err, chgvar;
/*
* CONUPDATE and SMOOTH_XPAN are equal. However,
@@ -819,7 +972,7 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con,
var->yoffset = cfb->display->var.yoffset;
}
- err = cyber2000fb_decode_var(var, (struct cfb_info *)info, &hw);
+ err = cyber2000fb_decode_var(var, cfb, &hw);
if (err)
return err;
@@ -831,84 +984,62 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con,
if (con < 0) {
display = cfb->fb.disp;
- chgvar = 0;
} else {
display = fb_display + con;
}
- if (display->var.xres != var->xres)
- chgvar = 1;
- if (display->var.yres != var->yres)
- chgvar = 1;
- if (display->var.xres_virtual != var->xres_virtual)
- chgvar = 1;
- if (display->var.yres_virtual != var->yres_virtual)
- chgvar = 1;
- if (display->var.bits_per_pixel != var->bits_per_pixel)
+ chgvar = cfb->fb.var.xres != var->xres ||
+ cfb->fb.var.yres != var->yres ||
+ cfb->fb.var.xres_virtual != var->xres_virtual ||
+ cfb->fb.var.yres_virtual != var->yres_virtual ||
+ cfb->fb.var.bits_per_pixel != var->bits_per_pixel;
+
+ if (memcmp(&cfb->fb.var.red, &var->red, sizeof(var->red)) ||
+ memcmp(&cfb->fb.var.green, &var->green, sizeof(var->green)) ||
+ memcmp(&cfb->fb.var.blue, &var->blue, sizeof(var->blue)))
chgvar = 1;
+ if (con >= 0 && chgvar == 0)
+ return 0;
+
if (con < 0)
chgvar = 0;
- var->red.msb_right = 0;
- var->green.msb_right = 0;
- var->blue.msb_right = 0;
+ /*
+ * If we are setting all the virtual consoles, also set the
+ * defaults used to create new consoles.
+ */
+ err = var->activate;
+ var->activate = FB_ACTIVATE_NOW;
+ if (err & FB_ACTIVATE_ALL)
+ cfb->fb.disp->var = *var;
+
+ cfb->fb.var = *var;
+ cfb->fb.fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8: /* PSEUDOCOLOUR, 256 */
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 0;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
-
- cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
cfb->dispsw = &fbcon_cfb8;
display->dispsw_data = NULL;
- display->next_line = var->xres_virtual;
break;
#endif
#ifdef FBCON_HAS_CFB16
- case 16:
- var->bits_per_pixel = 16;
- var->red.length = 5;
- var->green.offset = 5;
- var->blue.offset = 0;
- var->blue.length = 5;
-
- cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
+ case 16:/* DIRECTCOLOUR */
cfb->dispsw = &fbcon_cfb16;
display->dispsw_data = cfb->fb.pseudo_palette;
- display->next_line = var->xres_virtual * 2;
-
-#ifndef CFB16_IS_CFB15
- /* DIRECTCOLOUR, 64k */
- if (var->green.length == 6) {
- var->red.offset = 11;
- var->green.length = 6;
- break;
- }
-#endif
- /* DIRECTCOLOUR, 32k */
- var->red.offset = 10;
- var->green.length = 5;
break;
#endif
#ifdef FBCON_HAS_CFB24
case 24:/* TRUECOLOUR, 16m */
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
-
- cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
cfb->dispsw = &fbcon_cfb24;
display->dispsw_data = cfb->fb.pseudo_palette;
- display->next_line = var->xres_virtual * 3;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:/* TRUECOLOUR, 16m */
+ cfb->dispsw = &fbcon_cfb32;
+ display->dispsw_data = cfb->fb.pseudo_palette;
break;
#endif
default:/* in theory this should never happen */
@@ -918,40 +1049,34 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con,
break;
}
+ /*
+ * 8bpp displays are always pseudo colour.
+ * 16bpp and above are direct colour or true colour, depending
+ * on whether the RAMDAC palettes are bypassed. (Direct colour
+ * has palettes, true colour does not.)
+ */
+ if (var->bits_per_pixel == 8)
+ cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
+ else if (hw.ramdac & RAMDAC_BYPASS)
+ cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR;
+ else
+ cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR;
+
if (var->accel_flags & FB_ACCELF_TEXT && cfb->dispsw != &fbcon_dummy)
display->dispsw = &fbcon_cyber_accel;
else
display->dispsw = cfb->dispsw;
- cfb->fb.fix.line_length = display->next_line;
-
- display->line_length = cfb->fb.fix.line_length;
- display->visual = cfb->fb.fix.visual;
- display->type = cfb->fb.fix.type;
- display->type_aux = cfb->fb.fix.type_aux;
- display->ypanstep = cfb->fb.fix.ypanstep;
- display->ywrapstep = cfb->fb.fix.ywrapstep;
display->can_soft_blank = 1;
display->inverse = 0;
- display->var = *var;
- display->var.activate &= ~FB_ACTIVATE_ALL;
-
- cfb->fb.var = display->var;
-
- /*
- * If we are setting all the virtual consoles, also set the
- * defaults used to create new consoles.
- */
- if (var->activate & FB_ACTIVATE_ALL)
- cfb->fb.disp->var = display->var;
-
- if (chgvar && info && cfb->fb.changevar)
- cfb->fb.changevar(con);
- cyber2000fb_update_start(cfb, var);
cyber2000fb_set_timing(cfb, &hw);
+ cyber2000fb_update_start(cfb, var);
fb_set_cmap(&cfb->fb.cmap, 1, &cfb->fb);
+ if (chgvar && cfb->fb.changevar)
+ cfb->fb.changevar(con);
+
return 0;
}
@@ -1044,6 +1169,20 @@ static int cyber2000fb_switch(int con, struct fb_info *info)
/*
* (Un)Blank the display.
+ *
+ * Blank the screen if blank_mode != 0, else unblank. If
+ * blank == NULL then the caller blanks by setting the CLUT
+ * (Color Look Up Table) to all black. 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
+ *
+ * wms...Enable VESA DMPS compatible powerdown mode
+ * run "setterm -powersave powerdown" to take advantage
*/
static int cyber2000fb_blank(int blank, struct fb_info *info)
{
@@ -1051,22 +1190,6 @@ static int cyber2000fb_blank(int blank, struct fb_info *info)
unsigned int sync = 0;
int i;
- /*
- * Blank the screen if blank_mode != 0, else unblank. If
- * blank == NULL then the caller blanks by setting the CLUT
- * (Color Look Up Table) to all black. 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
- *
- * wms...Enable VESA DMPS compatible powerdown mode
- * run "setterm -powersave powerdown" to take advantage
- */
-
switch (blank) {
case 4: /* powerdown - both sync lines down */
sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_0;
@@ -1078,44 +1201,54 @@ static int cyber2000fb_blank(int blank, struct fb_info *info)
sync = EXT_SYNC_CTL_VS_0 | EXT_SYNC_CTL_HS_NORMAL;
break;
case 1: /* soft blank */
- break;
default: /* unblank */
break;
}
+
cyber2000_grphw(EXT_SYNC_CTL, sync, cfb);
- switch (blank) {
- case 4:
- case 3:
- case 2:
- case 1: /* soft blank */
+ if (blank <= 1) {
+ /* turn on ramdacs */
+ cfb->ramdac_powerdown &= ~(RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN);
+ cyber2000fb_write_ramdac_ctrl(cfb);
+ }
+
+ /*
+ * Soft blank/unblank the display.
+ */
+ if (blank) { /* soft blank */
for (i = 0; i < NR_PALETTE; i++) {
cyber2000fb_writeb(i, 0x3c8, cfb);
cyber2000fb_writeb(0, 0x3c9, cfb);
cyber2000fb_writeb(0, 0x3c9, cfb);
cyber2000fb_writeb(0, 0x3c9, cfb);
}
- break;
- default: /* unblank */
+ } else { /* unblank */
for (i = 0; i < NR_PALETTE; i++) {
cyber2000fb_writeb(i, 0x3c8, cfb);
cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
}
- break;
}
+
+ if (blank >= 2) {
+ /* turn off ramdacs */
+ cfb->ramdac_powerdown |= RAMDAC_DACPWRDN | RAMDAC_BYPASS | RAMDAC_RAMPWRDN;
+ cyber2000fb_write_ramdac_ctrl(cfb);
+ }
+
return 0;
}
static struct fb_ops cyber2000fb_ops = {
.owner = THIS_MODULE,
.fb_set_var = cyber2000fb_set_var,
+ .fb_get_cmap = gen_get_cmap,
+ .fb_set_cmap = gen_set_cmap,
.fb_setcolreg = cyber2000fb_setcolreg,
.fb_pan_display = cyber2000fb_pan_display,
.fb_blank = cyber2000fb_blank,
- .fb_get_cmap = gen_get_cmap,
- .fb_set_cmap = gen_set_cmap,
};
/*
@@ -1206,18 +1339,18 @@ EXPORT_SYMBOL(cyber2000fb_get_fb_var);
* 640x480, hsync 31.5kHz, vsync 60Hz
*/
static struct fb_videomode __devinitdata cyber2000fb_default_mode = {
- .refresh = 60,
- .xres = 640,
- .yres = 480,
- .pixclock = 39722,
- .left_margin = 56,
- .right_margin = 16,
- .upper_margin = 34,
- .lower_margin = 9,
- .hsync_len = 88,
- .vsync_len = 2,
- .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- .vmode = FB_VMODE_NONINTERLACED
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 39722,
+ .left_margin = 56,
+ .right_margin = 16,
+ .upper_margin = 34,
+ .lower_margin = 9,
+ .hsync_len = 88,
+ .vsync_len = 2,
+ .sync = FB_SYNC_COMP_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ .vmode = FB_VMODE_NONINTERLACED
};
static char igs_regs[] __devinitdata = {
@@ -1265,7 +1398,7 @@ static void cyberpro_init_hw(struct cfb_info *cfb)
for (i = 0; i < sizeof(igs_regs); i += 2)
cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);
- if (cfb->fb.fix.accel == FB_ACCEL_IGS_CYBER5000) {
+ if (cfb->id == ID_CYBERPRO_5000) {
unsigned char val;
cyber2000fb_writeb(0xba, 0x3ce, cfb);
val = cyber2000fb_readb(0x3cf, cfb) & 0x80;
@@ -1286,6 +1419,8 @@ cyberpro_alloc_fb_info(unsigned int id, char *name)
memset(cfb, 0, sizeof(struct cfb_info) + sizeof(struct display));
+ cfb->id = id;
+
if (id == ID_CYBERPRO_5000)
cfb->ref_ps = 40690; // 24.576 MHz
else
@@ -1403,6 +1538,8 @@ static int __devinit cyberpro_common_probe(struct cfb_info *cfb)
u_int h_sync, v_sync;
int err;
+ cyberpro_init_hw(cfb);
+
/*
* Get the video RAM size and width from the VGA register.
* This should have been already initialised by the BIOS,
@@ -1521,8 +1658,6 @@ cyberpro_vl_probe(void)
cfb->mclk_mult = 0xdb;
cfb->mclk_div = 0x54;
- cyberpro_init_hw(cfb);
-
err = cyberpro_common_probe(cfb);
if (err)
goto failed;
@@ -1559,6 +1694,8 @@ failed_release:
*/
static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
{
+ unsigned char val;
+
#if defined(__sparc_v9__)
#error "You loose, consult DaveM."
#elif defined(__sparc__)
@@ -1593,6 +1730,22 @@ static int cyberpro_pci_enable_mmio(struct cfb_info *cfb)
outb(EXT_BIU_MISC, 0x3ce);
outb(EXT_BIU_MISC_LIN_ENABLE, 0x3cf);
#endif
+
+ /*
+ * Allow the CyberPro to accept PCI burst accesses
+ */
+ val = cyber2000_grphr(EXT_BUS_CTL, cfb);
+ if (!(val & EXT_BUS_CTL_PCIBURST_WRITE)) {
+ printk(KERN_INFO "%s: enabling PCI bursts\n", cfb->fb.fix.id);
+
+ val |= EXT_BUS_CTL_PCIBURST_WRITE;
+
+ if (cfb->id == ID_CYBERPRO_5000)
+ val |= EXT_BUS_CTL_PCIBURST_READ;
+
+ cyber2000_grphw(EXT_BUS_CTL, val, cfb);
+ }
+
return 0;
}
@@ -1652,8 +1805,6 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
cfb->mclk_div = 0x54;
#endif
- cyberpro_init_hw(cfb);
-
err = cyberpro_common_probe(cfb);
if (err)
goto failed;
@@ -1742,12 +1893,12 @@ static struct pci_device_id cyberpro_pci_table[] __devinitdata = {
MODULE_DEVICE_TABLE(pci,cyberpro_pci_table);
static struct pci_driver cyberpro_driver = {
- .name = "CyberPro",
- .probe = cyberpro_pci_probe,
- .remove = __devexit_p(cyberpro_pci_remove),
- .suspend = cyberpro_pci_suspend,
- .resume = cyberpro_pci_resume,
- .id_table = cyberpro_pci_table
+ .name = "CyberPro",
+ .probe = cyberpro_pci_probe,
+ .remove = __devexit_p(cyberpro_pci_remove),
+ .suspend = cyberpro_pci_suspend,
+ .resume = cyberpro_pci_resume,
+ .id_table = cyberpro_pci_table
};
#endif
@@ -1758,17 +1909,20 @@ static struct pci_driver cyberpro_driver = {
*/
int __init cyber2000fb_init(void)
{
- int ret = -1, err = -ENODEV;
+ int ret = -1, err;
+
#ifdef CONFIG_ARCH_SHARK
err = cyberpro_vl_probe();
if (!err) {
- ret = err;
+ ret = 0;
MOD_INC_USE_COUNT;
}
#endif
+#ifdef CONFIG_PCI
err = pci_module_init(&cyberpro_driver);
if (!err)
- ret = err;
+ ret = 0;
+#endif
return ret ? err : 0;
}
diff --git a/drivers/video/cyber2000fb.h b/drivers/video/cyber2000fb.h
index 2f0eb757c1a4..261d157ccee0 100644
--- a/drivers/video/cyber2000fb.h
+++ b/drivers/video/cyber2000fb.h
@@ -36,9 +36,15 @@ static void debug_printf(char *fmt, ...)
#define debug_printf(x...) do { } while (0)
#endif
-#define PIXFORMAT_8BPP 0
-#define PIXFORMAT_16BPP 1
-#define PIXFORMAT_24BPP 2
+#define RAMDAC_RAMPWRDN 0x01
+#define RAMDAC_DAC8BIT 0x02
+#define RAMDAC_VREFEN 0x04
+#define RAMDAC_BYPASS 0x10
+#define RAMDAC_DACPWRDN 0x40
+
+#define EXT_CRT_VRTOFL 0x11
+#define EXT_CRT_VRTOFL_LINECOMP10 0x10
+#define EXT_CRT_VRTOFL_INTERLACE 0x20
#define EXT_CRT_IRQ 0x12
#define EXT_CRT_IRQ_ENABLE 0x01
@@ -61,7 +67,8 @@ static void debug_printf(char *fmt, ...)
#define EXT_BUS_CTL_LIN_2MB 0x01
#define EXT_BUS_CTL_LIN_4MB 0x02
#define EXT_BUS_CTL_ZEROWAIT 0x04
-#define EXT_BUS_CTL_PCIBURST 0x20
+#define EXT_BUS_CTL_PCIBURST_WRITE 0x20
+#define EXT_BUS_CTL_PCIBURST_READ 0x80 /* CyberPro 5000 only */
#define EXT_SEG_WRITE_PTR 0x31
#define EXT_SEG_READ_PTR 0x32
@@ -401,24 +408,54 @@ static void debug_printf(char *fmt, ...)
/*
* Graphics Co-processor
*/
-#define CO_CMD_L_PATTERN_FGCOL 0x8000
-#define CO_CMD_L_INC_LEFT 0x0004
-#define CO_CMD_L_INC_UP 0x0002
-
-#define CO_CMD_H_SRC_PIXMAP 0x2000
-#define CO_CMD_H_BLITTER 0x0800
-
#define CO_REG_CONTROL 0xbf011
+#define CO_CTRL_BUSY 0x80
+#define CO_CTRL_CMDFULL 0x04
+#define CO_CTRL_FIFOEMPTY 0x02
+#define CO_CTRL_READY 0x01
+
#define CO_REG_SRC_WIDTH 0xbf018
-#define CO_REG_PIX_FORMAT 0xbf01c
-#define CO_REG_FORE_MIX 0xbf048
-#define CO_REG_FOREGROUND 0xbf058
-#define CO_REG_WIDTH 0xbf060
-#define CO_REG_HEIGHT 0xbf062
+#define CO_REG_PIXFMT 0xbf01c
+#define CO_PIXFMT_32BPP 0x03
+#define CO_PIXFMT_24BPP 0x02
+#define CO_PIXFMT_16BPP 0x01
+#define CO_PIXFMT_8BPP 0x00
+
+#define CO_REG_FGMIX 0xbf048
+#define CO_FG_MIX_ZERO 0x00
+#define CO_FG_MIX_SRC_AND_DST 0x01
+#define CO_FG_MIX_SRC_AND_NDST 0x02
+#define CO_FG_MIX_SRC 0x03
+#define CO_FG_MIX_NSRC_AND_DST 0x04
+#define CO_FG_MIX_DST 0x05
+#define CO_FG_MIX_SRC_XOR_DST 0x06
+#define CO_FG_MIX_SRC_OR_DST 0x07
+#define CO_FG_MIX_NSRC_AND_NDST 0x08
+#define CO_FG_MIX_SRC_XOR_NDST 0x09
+#define CO_FG_MIX_NDST 0x0a
+#define CO_FG_MIX_SRC_OR_NDST 0x0b
+#define CO_FG_MIX_NSRC 0x0c
+#define CO_FG_MIX_NSRC_OR_DST 0x0d
+#define CO_FG_MIX_NSRC_OR_NDST 0x0e
+#define CO_FG_MIX_ONES 0x0f
+
+#define CO_REG_FGCOLOUR 0xbf058
+#define CO_REG_BGCOLOUR 0xbf05c
+#define CO_REG_PIXWIDTH 0xbf060
+#define CO_REG_PIXHEIGHT 0xbf062
#define CO_REG_X_PHASE 0xbf078
#define CO_REG_CMD_L 0xbf07c
+#define CO_CMD_L_PATTERN_FGCOL 0x8000
+#define CO_CMD_L_INC_LEFT 0x0004
+#define CO_CMD_L_INC_UP 0x0002
+
#define CO_REG_CMD_H 0xbf07e
-#define CO_REG_SRC_PTR 0xbf170
+#define CO_CMD_H_BGSRCMAP 0x8000 /* otherwise bg colour */
+#define CO_CMD_H_FGSRCMAP 0x2000 /* otherwise fg colour */
+#define CO_CMD_H_BLITTER 0x0800
+
+#define CO_REG_SRC1_PTR 0xbf170
+#define CO_REG_SRC2_PTR 0xbf174
#define CO_REG_DEST_PTR 0xbf178
#define CO_REG_DEST_WIDTH 0xbf218
diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c
index 0e1775bb9a7c..7560c6cfd800 100644
--- a/fs/adfs/dir_f.c
+++ b/fs/adfs/dir_f.c
@@ -469,9 +469,9 @@ adfs_f_free(struct adfs_dir *dir)
}
struct adfs_dir_ops adfs_f_dir_ops = {
- read: adfs_f_read,
- setpos: adfs_f_setpos,
- getnext: adfs_f_getnext,
- update: adfs_f_update,
- free: adfs_f_free
+ .read = adfs_f_read,
+ .setpos = adfs_f_setpos,
+ .getnext = adfs_f_getnext,
+ .update = adfs_f_update,
+ .free = adfs_f_free
};
diff --git a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c
index 372485ee4a9c..fc2ad89a10b1 100644
--- a/fs/adfs/dir_fplus.c
+++ b/fs/adfs/dir_fplus.c
@@ -172,8 +172,8 @@ adfs_fplus_free(struct adfs_dir *dir)
}
struct adfs_dir_ops adfs_fplus_dir_ops = {
- read: adfs_fplus_read,
- setpos: adfs_fplus_setpos,
- getnext: adfs_fplus_getnext,
- free: adfs_fplus_free
+ .read = adfs_fplus_read,
+ .setpos = adfs_fplus_setpos,
+ .getnext = adfs_fplus_getnext,
+ .free = adfs_fplus_free
};
diff --git a/include/asm-arm/arch-ebsa285/time.h b/include/asm-arm/arch-ebsa285/time.h
index 7b40c671daad..a500b9c08b8b 100644
--- a/include/asm-arm/arch-ebsa285/time.h
+++ b/include/asm-arm/arch-ebsa285/time.h
@@ -62,7 +62,7 @@ static unsigned long isa_gettimeoffset(void)
count_p = count;
- count = (((mSEC_10_from_14/6)-1) - count) * tick;
+ count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
return count;
@@ -182,7 +182,7 @@ static unsigned long timer1_gettimeoffset (void)
{
unsigned long value = LATCH - *CSR_TIMER1_VALUE;
- return (tick * value) / LATCH;
+ return ((tick_nsec / 1000) * value) / LATCH;
}
static void timer1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
diff --git a/include/asm-arm/arch-rpc/ide.h b/include/asm-arm/arch-rpc/ide.h
index aaf49b1be75c..15fecab1f7b8 100644
--- a/include/asm-arm/arch-rpc/ide.h
+++ b/include/asm-arm/arch-rpc/ide.h
@@ -44,5 +44,5 @@ ide_init_default_hwifs(void)
ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
hw.irq = IRQ_HARDDISK;
- ide_register_hw(&hw);
+ ide_register_hw(&hw, NULL);
}
diff --git a/include/asm-arm/arch-rpc/serial.h b/include/asm-arm/arch-rpc/serial.h
index 1497fc6fec8c..2f12e6da9bf6 100644
--- a/include/asm-arm/arch-rpc/serial.h
+++ b/include/asm-arm/arch-rpc/serial.h
@@ -29,7 +29,7 @@
/* UART CLK PORT IRQ FLAGS */
#define STD_SERIAL_PORT_DEFNS \
{ 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS }, /* ttyS0 */ \
- { 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS }, /* ttyS1 */ \
+ { 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS1 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS2 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS3 */ \
{ 0, BASE_BAUD, 0 , 0, STD_COM_FLAGS }, /* ttyS4 */ \
diff --git a/include/asm-arm/arch-rpc/uncompress.h b/include/asm-arm/arch-rpc/uncompress.h
index dde1bfc7af20..4a3036dad1f2 100644
--- a/include/asm-arm/arch-rpc/uncompress.h
+++ b/include/asm-arm/arch-rpc/uncompress.h
@@ -56,7 +56,7 @@ static const unsigned long palette_4[16] = {
#define palette_setpixel(p) *(unsigned long *)(IO_START+0x00400000) = 0x10000000|((p) & 255)
#define palette_write(v) *(unsigned long *)(IO_START+0x00400000) = 0x00000000|((v) & 0x00ffffff)
-extern struct param_struct params;
+static struct param_struct *params = (struct param_struct *)PARAMS_PHYS;
#ifndef STANDALONE_DEBUG
/*
@@ -64,13 +64,13 @@ extern struct param_struct params;
*/
static void puts(const char *s)
{
- extern void ll_write_char(char *, unsigned long);
+ extern void ll_write_char(char *, char c, char white);
int x,y;
unsigned char c;
char *ptr;
- x = params.video_x;
- y = params.video_y;
+ x = params->video_x;
+ y = params->video_y;
while ( ( c = *(unsigned char *)s++ ) != '\0' ) {
if ( c == '\n' ) {
@@ -79,8 +79,8 @@ static void puts(const char *s)
y--;
}
} else {
- ptr = VIDMEM + ((y*video_num_columns*params.bytes_per_char_v+x)*bytes_per_char_h);
- ll_write_char(ptr, c|(white<<16));
+ ptr = VIDMEM + ((y*video_num_columns*params->bytes_per_char_v+x)*bytes_per_char_h);
+ ll_write_char(ptr, c, white);
if ( ++x >= video_num_columns ) {
x = 0;
if ( ++y >= video_num_lines ) {
@@ -90,8 +90,8 @@ static void puts(const char *s)
}
}
- params.video_x = x;
- params.video_y = y;
+ params->video_x = x;
+ params->video_y = y;
}
static void error(char *x);
@@ -103,9 +103,9 @@ static void arch_decomp_setup(void)
{
int i;
- video_num_lines = params.video_num_rows;
- video_num_columns = params.video_num_cols;
- bytes_per_char_h = params.bytes_per_char_h;
+ video_num_lines = params->video_num_rows;
+ video_num_columns = params->video_num_cols;
+ bytes_per_char_h = params->bytes_per_char_h;
video_size_row = video_num_columns * bytes_per_char_h;
if (bytes_per_char_h == 4)
for (i = 0; i < 256; i++)
@@ -140,7 +140,7 @@ static void arch_decomp_setup(void)
white = 7;
}
- if (params.nr_pages * params.page_size < 4096*1024) error("<4M of mem\n");
+ if (params->nr_pages * params->page_size < 4096*1024) error("<4M of mem\n");
}
#endif
diff --git a/include/asm-arm/arch-sa1100/irqs.h b/include/asm-arm/arch-sa1100/irqs.h
index 66e4f596c739..4d906d33a78e 100644
--- a/include/asm-arm/arch-sa1100/irqs.h
+++ b/include/asm-arm/arch-sa1100/irqs.h
@@ -109,7 +109,7 @@
#define AUDRDD (IRQ_BOARD_END + 41)
#define AUDSTO (IRQ_BOARD_END + 42)
#define IRQ_USBPWR (IRQ_BOARD_END + 43)
-#define IRQ_NHCIM (IRQ_BOARD_END + 44)
+#define IRQ_HCIM (IRQ_BOARD_END + 44)
#define IRQ_HCIBUFFACC (IRQ_BOARD_END + 45)
#define IRQ_HCIRMTWKP (IRQ_BOARD_END + 46)
#define IRQ_NHCIMFCIR (IRQ_BOARD_END + 47)
diff --git a/include/asm-arm/arch-sa1100/time.h b/include/asm-arm/arch-sa1100/time.h
index 5e459a32e8f8..c52eb9588c3c 100644
--- a/include/asm-arm/arch-sa1100/time.h
+++ b/include/asm-arm/arch-sa1100/time.h
@@ -58,7 +58,7 @@ static unsigned long sa1100_gettimeoffset (void)
elapsed = LATCH - ticks_to_match;
/* Now convert them to usec */
- usec = (unsigned long)(elapsed*tick)/LATCH;
+ usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
return usec;
}
diff --git a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h
index fa0adbaeb12d..7c719a206399 100644
--- a/include/asm-arm/ecard.h
+++ b/include/asm-arm/ecard.h
@@ -95,9 +95,10 @@ typedef enum { /* Speed for ECARD_IOC space */
ECARD_SYNC = 3
} card_speed_t;
-typedef struct { /* Card ID structure */
- unsigned short manufacturer;
- unsigned short product;
+typedef struct ecard_id { /* Card ID structure */
+ unsigned short manufacturer;
+ unsigned short product;
+ void *data;
} card_ids;
struct in_ecid { /* Packed card ID information */
@@ -132,6 +133,8 @@ typedef struct { /* Card handler routines */
struct expansion_card {
struct expansion_card *next;
+ struct device dev;
+
/* Public data */
volatile unsigned char *irqaddr; /* address of IRQ register */
volatile unsigned char *fiqaddr; /* address of FIQ register */
@@ -248,4 +251,24 @@ struct ex_chunk_dir {
#endif
+extern struct bus_type ecard_bus_type;
+
+#define ECARD_DEV(_d) container_of((_d), struct expansion_card, dev)
+
+struct ecard_driver {
+ int (*probe)(struct expansion_card *, const struct ecard_id *id);
+ void (*remove)(struct expansion_card *);
+ const struct ecard_id *id_table;
+ unsigned int id;
+ struct device_driver drv;
+};
+
+#define ECARD_DRV(_d) container_of((_d), struct ecard_driver, drv)
+
+#define ecard_set_drvdata(ec,data) dev_set_drvdata(&(ec)->dev, (data))
+#define ecard_get_drvdata(ec) dev_get_drvdata(&(ec)->dev)
+
+int ecard_register_driver(struct ecard_driver *);
+void ecard_remove_driver(struct ecard_driver *);
+
#endif
diff --git a/include/asm-arm/glue.h b/include/asm-arm/glue.h
index 84b5d77c7562..a29d70176c75 100644
--- a/include/asm-arm/glue.h
+++ b/include/asm-arm/glue.h
@@ -27,59 +27,6 @@
/*
- * MMU TLB Model
- * =============
- *
- * We have the following to choose from:
- * v3 - ARMv3
- * v4 - ARMv4 without write buffer
- * v4wb - ARMv4 with write buffer without I TLB flush entry instruction
- * v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
- */
-#undef _TLB
-#undef MULTI_TLB
-
-#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
-# ifdef _TLB
-# define MULTI_TLB 1
-# else
-# define _TLB v3
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM720T)
-# ifdef _TLB
-# define MULTI_TLB 1
-# else
-# define _TLB v4
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
- defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \
- defined(CONFIG_CPU_XSCALE)
-# ifdef _TLB
-# define MULTI_TLB 1
-# else
-# define _TLB v4wbi
-# endif
-#endif
-
-#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
-# ifdef _TLB
-# define MULTI_TLB 1
-# else
-# define _TLB v4wb
-# endif
-#endif
-
-#ifndef _TLB
-#error Unknown TLB model
-#endif
-
-
-
-/*
* Data Abort Model
* ================
*
@@ -156,69 +103,4 @@
#error Unknown data abort handler type
#endif
-
-/*
- * User Space Model
- * ================
- *
- * This section selects the correct set of functions for dealing with
- * page-based copying and clearing for user space for the particular
- * processor(s) we're building for.
- *
- * We have the following to choose from:
- * v3 - ARMv3
- * v4wt - ARMv4 with writethrough cache, without minicache
- * v4wb - ARMv4 with writeback cache, without minicache
- * v4_mc - ARMv4 with minicache
- * xscale - Xscale
- */
-#undef _USER
-#undef MULTI_USER
-
-#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
-# ifdef _USER
-# define MULTI_USER 1
-# else
-# define _USER v3
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM720T)
-# ifdef _USER
-# define MULTI_USER 1
-# else
-# define _USER v4wt
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
- defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_SA110) || \
- defined(CONFIG_CPU_ARM1020)
-# ifdef _USER
-# define MULTI_USER 1
-# else
-# define _USER v4wb
-# endif
-#endif
-
-#if defined(CONFIG_CPU_SA1100)
-# ifdef _USER
-# define MULTI_USER 1
-# else
-# define _USER v4_mc
-# endif
-#endif
-
-#if defined(CONFIG_CPU_XSCALE)
-# ifdef _USER
-# define MULTI_USER 1
-# else
-# define _USER xscale_mc
-# endif
-#endif
-
-#ifndef _USER
-#error Unknown user operations model
-#endif
-
#endif
diff --git a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h
index 0e6a5492e1e4..3f164e01f7a1 100644
--- a/include/asm-arm/hardirq.h
+++ b/include/asm-arm/hardirq.h
@@ -69,10 +69,18 @@ typedef struct {
#define irq_enter() (preempt_count() += HARDIRQ_OFFSET)
+#ifdef CONFIG_PREEMPT
+# define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
+# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
+#else
+# define in_atomic() (preempt_count() != 0)
+# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#endif
+
#ifndef CONFIG_SMP
#define irq_exit() \
do { \
- preempt_count() -= HARDIRQ_OFFSET; \
+ preempt_count() -= IRQ_EXIT_OFFSET; \
if (!in_interrupt() && softirq_pending(smp_processor_id())) \
__asm__("bl%? __do_softirq": : : "lr");/* out of line */\
preempt_enable_no_resched(); \
@@ -80,7 +88,7 @@ typedef struct {
#define synchronize_irq(irq) barrier()
#else
-#error SMP not supported
+extern void synchronize_irq(unsigned int irq);
#endif
#endif /* __ASM_HARDIRQ_H */
diff --git a/include/asm-arm/hardware/sa1111.h b/include/asm-arm/hardware/sa1111.h
index 311e4832eb2f..30e1f8141633 100644
--- a/include/asm-arm/hardware/sa1111.h
+++ b/include/asm-arm/hardware/sa1111.h
@@ -64,10 +64,6 @@
#define SA1111_SMCR 0x0004
#define SA1111_SKID 0x0008
-#define SBI_SKCR __CCREG(SA1111_SKCR)
-#define SBI_SMCR __CCREG(SA1111_SMCR)
-#define SBI_SKID __CCREG(SA1111_SKID)
-
#define SKCR_PLL_BYPASS (1<<0)
#define SKCR_RCLKEN (1<<1)
#define SKCR_SLEEP (1<<2)
@@ -131,16 +127,6 @@
#define SA1111_SKPEN1 0x021c
#define SA1111_SKPWM1 0x0220
-#define SKPCR __CCREG(SA1111_SKPCR)
-#define SKCDR __CCREG(SA1111_SKCDR)
-#define SKAUD __CCREG(SA1111_SKAUD)
-#define SKPMC __CCREG(SA1111_SKPMC)
-#define SKPTC __CCREG(SA1111_SKPTC)
-#define SKPEN0 __CCREG(SA1111_SKPEN0)
-#define SKPWM0 __CCREG(SA1111_SKPWM0)
-#define SKPEN1 __CCREG(SA1111_SKPEN1)
-#define SKPWM1 __CCREG(SA1111_SKPWM1)
-
#define SKPCR_UCLKEN (1<<0)
#define SKPCR_ACCLKEN (1<<1)
#define SKPCR_I2SCLKEN (1<<2)
diff --git a/include/asm-arm/ide.h b/include/asm-arm/ide.h
index 3b9c4c18c6af..e872974aa009 100644
--- a/include/asm-arm/ide.h
+++ b/include/asm-arm/ide.h
@@ -36,7 +36,6 @@
* The following are not needed for the non-m68k ports
*/
#define ide_ack_intr(hwif) (1)
-#define ide_fix_driveid(id) do {} while (0)
#define ide_release_lock(lock) do {} while (0)
#define ide_get_lock(lock, hdlr, data) do {} while (0)
diff --git a/include/asm-arm/numnodes.h b/include/asm-arm/numnodes.h
new file mode 100644
index 000000000000..4c12812f73dc
--- /dev/null
+++ b/include/asm-arm/numnodes.h
@@ -0,0 +1,17 @@
+/*
+ * linux/include/asm-arm/numnodes.h
+ *
+ * Copyright (C) 2002 Russell King
+ *
+ * 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 __ASM_ARM_NUMNODES_H
+#define __ASM_ARM_NUMNODES_H
+
+#include <asm/memory.h>
+
+#define MAX_NUMNODES NR_NODES
+
+#endif
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index 84b1f5970586..0b1a26ed991d 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -8,6 +8,70 @@
#include <asm/glue.h>
+/*
+ * User Space Model
+ * ================
+ *
+ * This section selects the correct set of functions for dealing with
+ * page-based copying and clearing for user space for the particular
+ * processor(s) we're building for.
+ *
+ * We have the following to choose from:
+ * v3 - ARMv3
+ * v4wt - ARMv4 with writethrough cache, without minicache
+ * v4wb - ARMv4 with writeback cache, without minicache
+ * v4_mc - ARMv4 with minicache
+ * xscale - Xscale
+ */
+#undef _USER
+#undef MULTI_USER
+
+#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER v3
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM720T)
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER v4wt
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
+ defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_SA110) || \
+ defined(CONFIG_CPU_ARM1020)
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER v4wb
+# endif
+#endif
+
+#if defined(CONFIG_CPU_SA1100)
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER v4_mc
+# endif
+#endif
+
+#if defined(CONFIG_CPU_XSCALE)
+# ifdef _USER
+# define MULTI_USER 1
+# else
+# define _USER xscale_mc
+# endif
+#endif
+
+#ifndef _USER
+#error Unknown user operations model
+#endif
+
struct cpu_user_fns {
void (*cpu_clear_user_page)(void *p, unsigned long user);
void (*cpu_copy_user_page)(void *to, const void *from,
diff --git a/include/asm-arm/pci.h b/include/asm-arm/pci.h
index 3a7310558dd2..cd074e0daf51 100644
--- a/include/asm-arm/pci.h
+++ b/include/asm-arm/pci.h
@@ -248,6 +248,10 @@ void *pci_pool_alloc (struct pci_pool *pool, int flags, dma_addr_t *handle);
void pci_pool_free (struct pci_pool *pool, void *vaddr, dma_addr_t addr);
#endif
+#define HAVE_PCI_MMAP
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine);
+
#endif /* __KERNEL__ */
#endif
diff --git a/include/asm-arm/pgalloc.h b/include/asm-arm/pgalloc.h
index f0e2c9f5393d..81a7eccf2991 100644
--- a/include/asm-arm/pgalloc.h
+++ b/include/asm-arm/pgalloc.h
@@ -11,9 +11,6 @@
#define _ASMARM_PGALLOC_H
#include <asm/processor.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
#include <asm/proc/pgalloc.h>
/*
diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
index ca5bef29d81b..da98e2ee55b8 100644
--- a/include/asm-arm/pgtable.h
+++ b/include/asm-arm/pgtable.h
@@ -12,6 +12,7 @@
#include <linux/config.h>
#include <asm/memory.h>
+#include <asm/proc-fns.h>
#include <asm/arch/vmalloc.h>
/*
diff --git a/include/asm-arm/proc-armo/system.h b/include/asm-arm/proc-armo/system.h
index 23f2b96cb2d0..9e46e58f56e4 100644
--- a/include/asm-arm/proc-armo/system.h
+++ b/include/asm-arm/proc-armo/system.h
@@ -10,8 +10,6 @@
#ifndef __ASM_PROC_SYSTEM_H
#define __ASM_PROC_SYSTEM_H
-#include <asm/proc-fns.h>
-
#define vectors_base() (0)
static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
diff --git a/include/asm-arm/proc-armv/pgalloc.h b/include/asm-arm/proc-armv/pgalloc.h
index 99546c6fc1c8..53e760417601 100644
--- a/include/asm-arm/proc-armv/pgalloc.h
+++ b/include/asm-arm/proc-armv/pgalloc.h
@@ -5,6 +5,7 @@
*
* Page table allocation/freeing primitives for 32-bit ARM processors.
*/
+#include <asm/cacheflush.h>
#include "pgtable.h"
/*
diff --git a/include/asm-arm/proc-armv/tlbflush.h b/include/asm-arm/proc-armv/tlbflush.h
index d465e954ae13..fd758b2e90f2 100644
--- a/include/asm-arm/proc-armv/tlbflush.h
+++ b/include/asm-arm/proc-armv/tlbflush.h
@@ -7,6 +7,113 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#include <linux/config.h>
+#include <asm/glue.h>
+
+#define TLB_V3_PAGE (1 << 0)
+#define TLB_V4_U_PAGE (1 << 1)
+#define TLB_V4_D_PAGE (1 << 2)
+#define TLB_V4_I_PAGE (1 << 3)
+
+#define TLB_V3_FULL (1 << 8)
+#define TLB_V4_U_FULL (1 << 9)
+#define TLB_V4_D_FULL (1 << 10)
+#define TLB_V4_I_FULL (1 << 11)
+
+#define TLB_WB (1 << 31)
+
+/*
+ * MMU TLB Model
+ * =============
+ *
+ * We have the following to choose from:
+ * v3 - ARMv3
+ * v4 - ARMv4 without write buffer
+ * v4wb - ARMv4 with write buffer without I TLB flush entry instruction
+ * v4wbi - ARMv4 with write buffer with I TLB flush entry instruction
+ */
+#undef _TLB
+#undef MULTI_TLB
+
+#define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE)
+
+#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710)
+# ifdef _TLB
+# define MULTI_TLB 1
+# else
+# define _TLB v3
+# endif
+#endif
+
+#define v4_tlb_flags (TLB_V4_U_FULL | TLB_V4_U_PAGE)
+
+#if defined(CONFIG_CPU_ARM720T)
+# ifdef _TLB
+# define MULTI_TLB 1
+# else
+# define _TLB v4
+# endif
+#endif
+
+#define v4wbi_tlb_flags (TLB_WB | \
+ TLB_V4_I_FULL | TLB_V4_D_FULL | \
+ TLB_V4_I_PAGE | TLB_V4_D_PAGE)
+
+#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
+ defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \
+ defined(CONFIG_CPU_XSCALE)
+# ifdef _TLB
+# define MULTI_TLB 1
+# else
+# define _TLB v4wbi
+# endif
+#endif
+
+#define v4wb_tlb_flags (TLB_WB | \
+ TLB_V4_I_FULL | TLB_V4_D_FULL | \
+ TLB_V4_D_PAGE)
+
+#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
+# ifdef _TLB
+# define MULTI_TLB 1
+# else
+# define _TLB v4wb
+# endif
+#endif
+
+#ifndef _TLB
+#error Unknown TLB model
+#endif
+
+#ifndef __ASSEMBLY__
+
+struct cpu_tlb_fns {
+ void (*flush_user_range)(unsigned long, unsigned long, struct vm_area_struct *);
+ void (*flush_kern_range)(unsigned long, unsigned long);
+ unsigned long tlb_flags;
+};
+
+/*
+ * Select the calling method
+ */
+#ifdef MULTI_TLB
+
+extern struct cpu_tlb_fns cpu_tlb;
+
+#define __cpu_flush_user_tlb_range cpu_tlb.flush_user_range
+#define __cpu_flush_kern_tlb_range cpu_tlb.flush_kern_range
+#define __cpu_tlb_flags cpu_tlb.tlb_flags
+
+#else
+
+#define __cpu_flush_user_tlb_range __glue(_TLB,_flush_user_tlb_range)
+#define __cpu_flush_kern_tlb_range __glue(_TLB,_flush_kern_tlb_range)
+#define __cpu_tlb_flags __glue(_TLB,_tlb_flags)
+
+extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
+extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
+
+#endif
/*
* TLB Management
@@ -51,56 +158,94 @@
* - kaddr - Kernel virtual memory address
*/
-struct cpu_tlb_fns {
- void (*flush_kern_all)(void);
- void (*flush_user_mm)(struct mm_struct *);
- void (*flush_user_range)(unsigned long, unsigned long, struct vm_area_struct *);
- void (*flush_user_page)(unsigned long, struct vm_area_struct *);
- void (*flush_kern_range)(unsigned long, unsigned long);
- void (*flush_kern_page)(unsigned long);
-};
+#define tlb_flag(f) (__cpu_tlb_flags & (f))
-/*
- * Convert calls to our calling convention.
- */
-#define flush_tlb_all() __cpu_flush_kern_tlb_all()
-#define flush_tlb_mm(mm) __cpu_flush_user_tlb_mm(mm)
-#define flush_tlb_range(vma,start,end) __cpu_flush_user_tlb_range(start,end,vma)
-#define flush_tlb_page(vma,vaddr) __cpu_flush_user_tlb_page(vaddr,vma)
-#define flush_tlb_kernel_range(s,e) __cpu_flush_kern_tlb_range(s,e)
-#define flush_tlb_kernel_page(kaddr) __cpu_flush_kern_tlb_page(kaddr)
+static inline void flush_tlb_all(void)
+{
+ const int zero = 0;
-/*
- * Now select the calling method
- */
-#ifdef MULTI_TLB
+ if (tlb_flag(TLB_WB))
+ asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
-extern struct cpu_tlb_fns cpu_tlb;
+ if (tlb_flag(TLB_V3_FULL))
+ asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero));
+ if (tlb_flag(TLB_V4_U_FULL))
+ asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero));
+ if (tlb_flag(TLB_V4_D_FULL))
+ asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero));
+ if (tlb_flag(TLB_V4_I_FULL))
+ asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+}
-#define __cpu_flush_kern_tlb_all cpu_tlb.flush_kern_all
-#define __cpu_flush_user_tlb_mm cpu_tlb.flush_user_mm
-#define __cpu_flush_user_tlb_range cpu_tlb.flush_user_range
-#define __cpu_flush_user_tlb_page cpu_tlb.flush_user_page
-#define __cpu_flush_kern_tlb_range cpu_tlb.flush_kern_range
-#define __cpu_flush_kern_tlb_page cpu_tlb.flush_kern_page
+static inline void flush_tlb_mm(struct mm_struct *mm)
+{
+ const int zero = 0;
-#else
+ if (tlb_flag(TLB_WB))
+ asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
-#define __cpu_flush_kern_tlb_all __glue(_TLB,_flush_kern_tlb_all)
-#define __cpu_flush_user_tlb_mm __glue(_TLB,_flush_user_tlb_mm)
-#define __cpu_flush_user_tlb_range __glue(_TLB,_flush_user_tlb_range)
-#define __cpu_flush_user_tlb_page __glue(_TLB,_flush_user_tlb_page)
-#define __cpu_flush_kern_tlb_range __glue(_TLB,_flush_kern_tlb_range)
-#define __cpu_flush_kern_tlb_page __glue(_TLB,_flush_kern_tlb_page)
+ if (mm == current->active_mm) {
+ if (tlb_flag(TLB_V3_FULL))
+ asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (zero));
+ if (tlb_flag(TLB_V4_U_FULL))
+ asm("mcr%? p15, 0, %0, c8, c7, 0" : : "r" (zero));
+ if (tlb_flag(TLB_V4_D_FULL))
+ asm("mcr%? p15, 0, %0, c8, c6, 0" : : "r" (zero));
+ if (tlb_flag(TLB_V4_I_FULL))
+ asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+ }
+}
-extern void __cpu_flush_kern_tlb_all(void);
-extern void __cpu_flush_user_tlb_mm(struct mm_struct *);
-extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
-extern void __cpu_flush_user_tlb_page(unsigned long, struct vm_area_struct *);
-extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
-extern void __cpu_flush_kern_tlb_page(unsigned long);
+static inline void
+flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
+{
+ const int zero = 0;
-#endif
+ uaddr &= PAGE_MASK;
+
+ if (tlb_flag(TLB_WB))
+ asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+
+ if (vma->vm_mm == current->active_mm) {
+ if (tlb_flag(TLB_V3_PAGE))
+ asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (uaddr));
+ if (tlb_flag(TLB_V4_U_PAGE))
+ asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (uaddr));
+ if (tlb_flag(TLB_V4_D_PAGE))
+ asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (uaddr));
+ if (tlb_flag(TLB_V4_I_PAGE))
+ asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr));
+ if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
+ asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+ }
+}
+
+static inline void flush_tlb_kernel_page(unsigned long kaddr)
+{
+ const int zero = 0;
+
+ kaddr &= PAGE_MASK;
+
+ if (tlb_flag(TLB_WB))
+ asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero));
+
+ if (tlb_flag(TLB_V3_PAGE))
+ asm("mcr%? p15, 0, %0, c6, c0, 0" : : "r" (kaddr));
+ if (tlb_flag(TLB_V4_U_PAGE))
+ asm("mcr%? p15, 0, %0, c8, c7, 1" : : "r" (kaddr));
+ if (tlb_flag(TLB_V4_D_PAGE))
+ asm("mcr%? p15, 0, %0, c8, c6, 1" : : "r" (kaddr));
+ if (tlb_flag(TLB_V4_I_PAGE))
+ asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (kaddr));
+ if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
+ asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
+}
+
+/*
+ * Convert calls to our calling convention.
+ */
+#define flush_tlb_range(vma,start,end) __cpu_flush_user_tlb_range(start,end,vma)
+#define flush_tlb_kernel_range(s,e) __cpu_flush_kern_tlb_range(s,e)
/*
* if PG_dcache_dirty is set for the page, we need to ensure that any
@@ -123,3 +268,4 @@ extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte
#define memc_update_addr(mm,pte,log) do { } while (0)
#define memc_clear(mm,physaddr) do { } while (0)
+#endif
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h
index 7f3bed11ebd1..b13e4e54282c 100644
--- a/include/asm-arm/processor.h
+++ b/include/asm-arm/processor.h
@@ -28,22 +28,30 @@
#include <asm/procinfo.h>
#include <asm/arch/memory.h>
#include <asm/proc/processor.h>
+#include <asm/types.h>
+
+union debug_insn {
+ u32 arm;
+ u16 thumb;
+};
+
+struct debug_entry {
+ u32 address;
+ union debug_insn insn;
+};
struct debug_info {
- int nsaved;
- struct {
- unsigned long address;
- unsigned long insn;
- } bp[2];
+ int nsaved;
+ struct debug_entry bp[2];
};
struct thread_struct {
/* fault info */
- unsigned long address;
- unsigned long trap_no;
- unsigned long error_code;
+ unsigned long address;
+ unsigned long trap_no;
+ unsigned long error_code;
/* debugging */
- struct debug_info debug;
+ struct debug_info debug;
};
#define INIT_THREAD { }
diff --git a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h
index c143ffa712de..fced718b32be 100644
--- a/include/asm-arm/procinfo.h
+++ b/include/asm-arm/procinfo.h
@@ -12,8 +12,6 @@
#ifndef __ASSEMBLY__
-#include <asm/proc-fns.h>
-
struct cpu_tlb_fns;
struct cpu_user_fns;
struct processor;
diff --git a/include/asm-arm/tlb.h b/include/asm-arm/tlb.h
index 318357c01183..3aa4ee0feb67 100644
--- a/include/asm-arm/tlb.h
+++ b/include/asm-arm/tlb.h
@@ -1,21 +1,76 @@
+/*
+ * linux/include/asm-arm/tlb.h
+ *
+ * Copyright (C) 2002 Russell King
+ *
+ * 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.
+ *
+ * Experimentation shows that on a StrongARM, it appears to be faster
+ * to use the "invalidate whole tlb" rather than "invalidate single
+ * tlb" for this.
+ *
+ * This appears true for both the process fork+exit case, as well as
+ * the munmap-large-area case.
+ */
#ifndef __ASMARM_TLB_H
#define __ASMARM_TLB_H
-#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
-#define tlb_flush(tlb) \
- flush_tlb_mm((tlb)->mm)
-#define tlb_start_vma(tlb,vma) \
- flush_cache_range(vma, vma->vm_start, vma->vm_end)
-#define tlb_end_vma(tlb,vma) \
- flush_tlb_range(vma, vma->vm_start, vma->vm_end)
+/*
+ * TLB handling. This allows us to remove pages from the page
+ * tables, and efficiently handle the TLB issues.
+ */
+typedef struct free_pte_ctx {
+ struct mm_struct *mm;
+ unsigned int freed;
-#define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
+ unsigned int flushes;
+ unsigned int avoided_flushes;
+} mmu_gather_t;
-#include <asm-generic/tlb.h>
+extern mmu_gather_t mmu_gathers[NR_CPUS];
-#define __pmd_free_tlb(tlb, pmd) pmd_free(pmd)
-#define __pte_free_tlb(tlb, pte) pte_free(pte)
+static inline mmu_gather_t *tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
+{
+ int cpu = smp_processor_id();
+ mmu_gather_t *tlb = &mmu_gathers[cpu];
+
+ tlb->mm = mm;
+ tlb->freed = 0;
+
+ return tlb;
+}
+
+static inline void tlb_finish_mmu(mmu_gather_t *tlb, unsigned long start, unsigned long end)
+{
+ struct mm_struct *mm = tlb->mm;
+ unsigned long freed = tlb->freed;
+ int rss = mm->rss;
+
+ if (rss < freed)
+ freed = rss;
+ mm->rss = rss - freed;
+
+ if (freed) {
+ flush_tlb_mm(mm);
+ tlb->flushes++;
+ } else {
+ tlb->avoided_flushes++;
+ }
+
+ /* keep the page table cache within bounds */
+ check_pgt_cache();
+}
+
+#define tlb_remove_tlb_entry(tlb,ptep,address) do { } while (0)
+#define tlb_start_vma(tlb,vma) do { } while (0)
+#define tlb_end_vma(tlb,vma) do { } while (0)
+
+#define tlb_remove_page(tlb,page) free_page_and_swap_cache(page)
+#define pte_free_tlb(tlb,ptep) pte_free(ptep)
+#define pmd_free_tlb(tlb,pmdp) pmd_free(pmdp)
#endif