diff options
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(¤t->sigmask_lock); + spin_lock_irq(¤t->sig->siglock); saveset = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->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(¤t->sigmask_lock); + spin_lock_irq(¤t->sig->siglock); saveset = current->blocked; current->blocked = newset; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->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(¤t->sigmask_lock); + spin_lock_irq(¤t->sig->siglock); current->blocked = set; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->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(¤t->sigmask_lock); + spin_lock_irq(¤t->sig->siglock); current->blocked = set; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->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 = ¤t->blocked; - local_irq_disable(); - if (current->sig->shared_pending.head) { - spin_lock(¤t->sig->siglock); - signr = dequeue_signal(¤t->sig->shared_pending, mask, &info); - spin_unlock(¤t->sig->siglock); - } - if (!signr) { - spin_lock(¤t->sigmask_lock); - signr = dequeue_signal(¤t->pending, mask, &info); - spin_unlock(¤t->sigmask_lock); - } - local_irq_enable(); + spin_lock_irq(¤t->sig->siglock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->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(ðer1_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(ðer1_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(ðer3_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(ðer3_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 = ðerh_ops; - ec->irq_data = eh; - eh->ctrl = 0; - eh->id = ec->cid.product; + if (ec->irq != 11) { + ec->ops = ðerh_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(ðerh_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(ðerh_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 |
