Commit e0970dce authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 6e8b5dcf 4c515af5
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
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.
......@@ -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/
......
......@@ -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)
......
......@@ -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
......
......@@ -21,78 +21,59 @@
#include <asm/assembler.h>
.text
#define BOLD 0x01
#define ITALIC 0x02
#define UNDERLINE 0x04
#define FLASH 0x08
#define INVERSE 0x10
LC0: .word bytes_per_char_h
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}
@
@ 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.
mov r1, r1, lsl #3
/*
* calculate offset required for each row.
*/
adr r4, LC0
ldmia r4, {r4, r5, r6, lr}
ldr r4, [r4]
ldr r5, [r5]
/*
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
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
orr r1, r1, #7
ldrb r7, [r6, r1]
tst ip, #UNDERLINE << 9
eoreq r7, r7, #255
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]
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
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
eor ip, r3, r7
str ip, [r0, -r5]!
str r7, [r0, -r5]!
subne r1, r1, #1
ldrneb r7, [r6, r1]
bne Lrow4bpplp
......@@ -101,19 +82,16 @@ Lrow4bpplp: ldr r7, [lr, r7, lsl #2]
@
@ Smashable regs: {r0 - r3}, [r4], {r5 - r7}, (r8 - fp), [ip], (sp), {lr}, (pc)
@
Lrow8bpplp: mov ip, r7, lsr #4
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 r1, r1, #1 @ 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]
......@@ -121,10 +99,8 @@ Lrow8bpplp: mov ip, r7, lsr #4
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]
......@@ -134,11 +110,9 @@ Lrow8bpplp: mov ip, r7, lsr #4
@
@ Smashable regs: {r0 - r3}, [r4], {r5, r6}, [r7], (r8 - fp), [ip], (sp), [lr], (pc)
@
Lrow1bpp: add r6, r6, r1
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
......@@ -152,8 +126,6 @@ Lrow1bpp: add r6, r6, r1
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})
......
......@@ -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
......
......@@ -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>
......
......@@ -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;
}
......@@ -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;
const struct ecard_id *id;
for (i = 0; cids[i].manufacturer != 65535; i++)
if (manufacturer == cids[i].manufacturer &&
product == cids[i].product)
break;
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);
......@@ -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
......
......@@ -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)
......
......@@ -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;
res = swap_insn(task, addr, &dbg->bp[nr].insn, &new_insn, 4);
if (res == 0) {
if (res == 4) {
dbg->bp[nr].address = addr;
dbg->nsaved += 1;
}
} else
printk(KERN_ERR "ptrace: too many breakpoints\n");
}
return res;
/*
* 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);
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:
......
......@@ -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;
asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (cache_info));
unsigned int info;
if (cache_info == processor_id)
return;
asm("mrc p15, 0, %0, c0, c0, 1" : "=r" (info));
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));
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(cache_info));
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);
......
......@@ -59,11 +59,11 @@ asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t m
sigset_t saveset;
mask &= _BLOCKABLE;
spin_lock_irq(&current->sigmask_lock);
spin_lock_irq(&current->sig->siglock);
saveset = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock);
spin_unlock_irq(&current->sig->siglock);
regs->ARM_r0 = -EINTR;
while (1) {
......@@ -87,11 +87,11 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs)
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sigmask_lock);
spin_lock_irq(&current->sig->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock);
spin_unlock_irq(&current->sig->siglock);
regs->ARM_r0 = -EINTR;
while (1) {
......@@ -207,10 +207,10 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sigmask_lock);
spin_lock_irq(&current->sig->siglock);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock);
spin_unlock_irq(&current->sig->siglock);
if (restore_sigcontext(regs, &frame->sc))
goto badframe;
......@@ -247,10 +247,10 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sigmask_lock);
spin_lock_irq(&current->sig->siglock);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock);
spin_unlock_irq(&current->sig->siglock);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
......@@ -477,12 +477,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
ka->sa.sa_handler = SIG_DFL;
if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&tsk->sigmask_lock);
spin_lock_irq(&tsk->sig->siglock);
sigorsets(&tsk->blocked, &tsk->blocked,
&ka->sa.sa_mask);
sigaddset(&tsk->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&tsk->sigmask_lock);
spin_unlock_irq(&tsk->sig->siglock);
}
return;
}
......@@ -520,20 +520,10 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
for (;;) {
unsigned long signr = 0;
struct k_sigaction *ka;
sigset_t *mask = &current->blocked;
local_irq_disable();
if (current->sig->shared_pending.head) {
spin_lock(&current->sig->siglock);
signr = dequeue_signal(&current->sig->shared_pending, mask, &info);
spin_unlock(&current->sig->siglock);
}
if (!signr) {
spin_lock(&current->sigmask_lock);
signr = dequeue_signal(&current->pending, mask, &info);
spin_unlock(&current->sigmask_lock);
}
local_irq_enable();
spin_lock_irq(&current->sig->siglock);
signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sig->siglock);
if (!signr)
break;
......
......@@ -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)
......
......@@ -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;
......
......@@ -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);
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);
}
......
......@@ -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,
policies = kmalloc(sizeof(struct cpufreq_freqs) * NR_CPUS,
GFP_KERNEL);
if (!freqs) {
printk(KERN_ERR "CPU: unable to allocate cpufreqs structure\n");
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;
......
......@@ -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));
}
......
......@@ -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;
}
......
......@@ -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
......
......@@ -302,21 +302,24 @@ static void __init assabet_map_io(void)
*/
neponset_map_io();
#endif
} else {
sa1100_register_uart_fns(&assabet_port_fns);
}
/*
* 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, 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 */
}
sa1100_register_uart(0, 1);
sa1100_register_uart(2, 3);
}
......
......@@ -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;
......
......@@ -193,20 +193,30 @@ static int neponset_resume(struct device *dev, u32 level)
}
static struct device_driver neponset_device_driver = {
.name = "NEPONSET",
.bus = &system_bus_type,
.suspend = neponset_suspend,
.resume = neponset_resume,
};
static struct device neponset_device = {
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 */
......
......@@ -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;
......@@ -502,84 +611,6 @@ static void __sa1111_remove(struct sa1111 *sachip)
kfree(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
......@@ -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);
}
/*
......
......@@ -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"
......
......@@ -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.
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......@@ -13,31 +13,10 @@
*/
#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)
*
......@@ -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
......@@ -14,31 +14,10 @@
*/
#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)
*
......@@ -64,25 +43,6 @@ ENTRY(v4_flush_user_tlb_range)
blo 1b
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)
*
......@@ -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
......@@ -14,34 +14,10 @@
*/
#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)
*
......@@ -69,28 +45,6 @@ ENTRY(v4wb_flush_user_tlb_range)
blo 1b
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)
*
......@@ -112,20 +66,6 @@ ENTRY(v4wb_flush_kern_tlb_range)
blo 1b
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
......@@ -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
......@@ -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)
......
......@@ -3,17 +3,10 @@
#
# 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-$(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
......
......@@ -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;
......
/*
* 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;
}
/*
* 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");
/*
* 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"
/*
* 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);
......@@ -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 @@ static struct net_device * __init ether1_init_one(struct expansion_card *ec)
kfree(dev);
out:
ecard_release(ec);
return dev;
return ret;
}
static struct expansion_card *e_card[MAX_ECARDS];
static struct net_device *e_dev[MAX_ECARDS];
static int __init ether1_init(void)
static void __devexit ether1_remove(struct expansion_card *ec)
{
int i, ret = -ENODEV;
struct net_device *dev = ecard_get_drvdata(ec);
ecard_startfind();
ecard_set_drvdata(ec, NULL);
for (i = 0; i < MAX_ECARDS; i++) {
struct expansion_card *ec;
struct net_device *dev;
unregister_netdev(dev);
ec = ecard_find(0, ether1_cids);
if (!ec)
break;
release_region(dev->base_addr, 16);
release_region(dev->base_addr + 0x800, 4096);
kfree(dev);
dev = ether1_init_one(ec);
if (!dev)
break;
ecard_release(ec);
}
e_card[i] = ec;
e_dev[i] = dev;
ret = 0;
}
static const struct ecard_id ether1_ids[] = {
{ MANU_ACORN, PROD_ACORN_ETHER1 },
{ 0xffff, 0xffff }
};
return ret;
static struct ecard_driver ether1_driver = {
.probe = ether1_probe,
.remove = __devexit_p(ether1_remove),
.id_table = ether1_ids,
.drv = {
.name = "ether1",
},
};
static int __init ether1_init(void)
{
return ecard_register_driver(&ether1_driver);
}
static void __exit ether1_exit(void)
{
int i;
for (i = 0; i < MAX_ECARDS; i++) {
if (e_dev[i]) {
unregister_netdev(e_dev[i]);
release_region(e_dev[i]->base_addr, 16);
release_region(e_dev[i]->base_addr + 0x800, 4096);
kfree(e_dev[i]);
e_dev[i] = NULL;
}
if (e_card[i]) {
ecard_release(e_card[i]);
e_card[i] = NULL;
}
}
ecard_remove_driver(&ether1_driver);
}
module_init(ether1_init);
......
......@@ -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 @@ static struct net_device * __init ether3_init_one(struct expansion_card *ec)
kfree(dev);
out:
ecard_release(ec);
return NULL;
return ret;
}
static struct expansion_card *e_card[MAX_ECARDS];
static struct net_device *e_dev[MAX_ECARDS];
static int ether3_init(void)
static void __devexit ether3_remove(struct expansion_card *ec)
{
int i, ret = -ENODEV;
struct net_device *dev = ecard_get_drvdata(ec);
ecard_startfind();
ecard_set_drvdata(ec, NULL);
for (i = 0; i < MAX_ECARDS; i++) {
struct net_device *dev;
struct expansion_card *ec;
unregister_netdev(dev);
release_region(dev->base_addr, 128);
kfree(dev);
ec = ecard_find(0, ether3_cids);
if (!ec)
break;
ecard_release(ec);
}
dev = ether3_init_one(ec);
if (!dev)
break;
static const struct ecard_id ether3_ids[] = {
{ MANU_ANT2, PROD_ANT_ETHER3 },
{ MANU_ANT, PROD_ANT_ETHER3 },
{ MANU_ANT, PROD_ANT_ETHERB },
{ 0xffff, 0xffff }
};
e_card[i] = ec;
e_dev[i] = dev;
ret = 0;
}
static struct ecard_driver ether3_driver = {
.probe = ether3_probe,
.remove = __devexit_p(ether3_remove),
.id_table = ether3_ids,
.drv = {
.name = "ether3",
},
};
return ret;
static int __init ether3_init(void)
{
return ecard_register_driver(&ether3_driver);
}
static void ether3_exit(void)
static void __exit ether3_exit(void)
{
int i;
for (i = 0; i < MAX_ECARDS; i++) {
if (e_dev[i]) {
unregister_netdev(e_dev[i]);
release_region(e_dev[i]->base_addr, 128);
kfree(e_dev[i]);
e_dev[i] = NULL;
}
if (e_card[i]) {
ecard_release(e_card[i]);
e_card[i] = NULL;
}
}
ecard_remove_driver(&ether3_driver);
}
module_init(ether3_init);
......
......@@ -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
......@@ -568,31 +587,31 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
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);
dev->priv = eh;
/*
* IRQ and control port handling
*/
if (ec->irq != 11) {
ec->ops = &etherh_ops;
ec->irq_data = eh;
}
eh->ctrl = 0;
eh->id = ec->cid.product;
switch (ec->cid.product) {
case PROD_ANT_ETHERM:
if (etherm_addr(dev->dev_addr))
goto free;
etherm_addr(dev->dev_addr);
dev->base_addr += ETHERM_NS8390;
dev->mem_start = dev->base_addr + ETHERM_DATAPORT;
eh->ctrl_port = dev->base_addr + ETHERM_CTRLPORT;
break;
case PROD_I3_ETHERLAN500:
if (etherh_addr(dev->dev_addr, ec))
goto free;
etherh_addr(dev->dev_addr, ec);
dev->base_addr += ETHERH500_NS8390;
dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
eh->ctrl_port = ecard_address (ec, ECARD_IOC, ECARD_FAST)
......@@ -601,8 +620,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
if (etherh_addr(dev->dev_addr, ec))
goto free;
etherh_addr(dev->dev_addr, ec);
dev->base_addr += ETHERH600_NS8390;
dev->mem_start = dev->base_addr + ETHERH600_DATAPORT;
eh->ctrl_port = dev->base_addr + ETHERH600_CTRLPORT;
......@@ -611,6 +629,7 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
default:
printk(KERN_ERR "%s: unknown card type %x\n",
dev->name, ec->cid.product);
ret = -ENODEV;
goto free;
}
......@@ -618,11 +637,15 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
if (ec->cid.product == PROD_ANT_ETHERM)
size <<= 3;
if (!request_region(dev->base_addr, size, dev->name))
if (!request_region(dev->base_addr, size, dev->name)) {
ret = -EBUSY;
goto free;
}
if (ethdev_init(dev))
if (ethdev_init(dev)) {
ret = -ENODEV;
goto release;
}
/*
* If we're in the NIC slot, make sure the IRQ is enabled
......@@ -690,7 +713,10 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
etherh_reset(dev);
NS8390_init(dev, 0);
return dev;
ecard_set_drvdata(ec, dev);
return 0;
release:
release_region(dev->base_addr, 16);
......@@ -700,67 +726,59 @@ static struct net_device * __init etherh_init_one(struct expansion_card *ec)
kfree(dev);
out:
ecard_release(ec);
return NULL;
return ret;
}
#define MAX_ETHERH_CARDS 2
static void __devexit etherh_remove(struct expansion_card *ec)
{
struct net_device *dev = ecard_get_drvdata(ec);
int size = 16;
static struct net_device *e_dev[MAX_ETHERH_CARDS];
static struct expansion_card *e_card[MAX_ETHERH_CARDS];
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);
}
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 ecard_driver etherh_driver = {
.probe = etherh_probe,
.remove = __devexit_p(etherh_remove),
.id_table = etherh_ids,
.drv = {
.name = "etherh",
},
};
static int __init etherh_init(void)
{
int i, ret = -ENODEV;
int i;
for (i = 0; i < 16; i++) {
etherh_regoffsets[i] = i;
etherm_regoffsets[i] = i << 3;
}
ecard_startfind();
for (i = 0; i < MAX_ECARDS; i++) {
struct expansion_card *ec;
struct net_device *dev;
ec = ecard_find(0, etherh_cids);
if (!ec)
break;
dev = etherh_init_one(ec);
if (!dev)
break;
e_card[i] = ec;
e_dev[i] = dev;
ret = 0;
}
return ret;
return ecard_register_driver(&etherh_driver);
}
static void __exit etherh_exit(void)
{
int i;
for (i = 0; i < MAX_ETHERH_CARDS; i++) {
if (e_dev[i]) {
int size;
unregister_netdev(e_dev[i]);
size = 16;
if (e_card[i]->cid.product == PROD_ANT_ETHERM)
size <<= 3;
release_region(e_dev[i]->base_addr, size);
kfree(e_dev[i]);
e_dev[i] = NULL;
}
if (e_card[i]) {
e_card[i]->ops = NULL;
kfree(e_card[i]->irq_data);
ecard_release(e_card[i]);
e_card[i] = NULL;
}
}
ecard_remove_driver(&etherh_driver);
}
module_init(etherh_init);
......
......@@ -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
......
......@@ -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 {
......
......@@ -83,10 +83,8 @@ 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_intr 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
int NCR5380_proc_info(char *buffer, char **start, off_t offset,
......@@ -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,
......
......@@ -248,10 +248,8 @@ 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_intr 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
int NCR5380_proc_info(char *buffer, char **start, off_t offset,
......@@ -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,
......
......@@ -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.
......
......@@ -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 {
......
......@@ -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,
......
......@@ -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;
......
......@@ -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)
......
......@@ -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)
......
......@@ -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);
/*
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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
......
......@@ -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)
......
......@@ -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)
......
......@@ -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);
}
......@@ -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)
......
......@@ -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)
......
......@@ -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,
};
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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)
......
/*
* 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);
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......@@ -876,56 +876,19 @@ acornfb_decode_var(struct fb_var_screeninfo *var, int con)
return acornfb_validate_timing(var, &fb_info.monspecs);
}
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;
......@@ -1177,13 +1137,11 @@ 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_pan_display = acornfb_pan_display,
.fb_blank = acornfb_blank,
.fb_mmap = acornfb_mmap,
};
......@@ -1192,7 +1150,7 @@ 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;
}
......@@ -1310,6 +1268,15 @@ acornfb_init_fbinfo(void)
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;
/*
......@@ -1619,8 +1586,8 @@ acornfb_init(void)
}
fb_info.currcon = -1;
current_par.screen_base = SCREEN_BASE;
current_par.screen_base_p = SCREEN_START;
fb_info.screen_base = (char *)SCREEN_BASE;
fb_info.fix.smem_start = SCREEN_START;
current_par.using_vram = 0;
/*
......@@ -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);
......
......@@ -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;
......
......@@ -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;
......@@ -47,6 +48,13 @@ static int clps7111fb_proc_backlight_read(char *page, char **start, off_t off,
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.
*/
......@@ -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,9 +122,9 @@ 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;
break;
......@@ -128,16 +138,30 @@ clps7111fb_set_par(struct fb_info *info)
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 |= 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,26 +373,9 @@ 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;
......@@ -293,7 +383,9 @@ int __init clps711xfb_init(void)
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);
......
/*
* 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;
......@@ -195,21 +206,20 @@ cyber2000_accel_bmove(struct display *display, int sy, int sx, int dy, int dx,
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(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);
if (var->bits_per_pixel == 24) {
cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
cyber2000fb_writel(src * 3, CO_REG_SRC_PTR, cfb);
dst *= 3;
src *= 3;
}
cyber2000fb_writew(height, CO_REG_HEIGHT, 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(0x2800, CO_REG_CMD_H, cfb);
cyber2000fb_writew(CO_CMD_H_FGSRCMAP|CO_CMD_H_BLITTER, CO_REG_CMD_H, cfb);
}
static void
......@@ -231,27 +241,24 @@ cyber2000_accel_clear(struct vc_data *conp, struct display *display, int sy,
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_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
......@@ -298,10 +305,17 @@ static struct display_switch fbcon_cyber_accel = {
.putc = cyber2000_accel_putc,
.putcs = cyber2000_accel_putcs,
.revc = cyber2000_accel_revc,
.clear_margins =cyber2000_accel_clear_margins,
.fontwidthmask =FONTWIDTH(8)|FONTWIDTH(16)
.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,7 +325,24 @@ 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;
switch (cfb->fb.fix.visual) {
default:
return 1;
#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;
......@@ -323,73 +354,116 @@ cyber2000fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
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(green, 0x3c9, cfb);
cyber2000fb_writeb(blue, 0x3c9, cfb);
break;
return 0;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
#ifndef CFB16_IS_CFB15
if (var->green.length == 6) {
if (regno < 64) {
/* write green */
/*
* 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);
}
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);
}
green = cfb->palette[regno << 3].green;
if (regno < 16)
((u16 *)cfb->fb.pseudo_palette)[regno] =
regno | regno << 5 | regno << 11;
break;
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);
/*
* 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;
}
#endif
/* DIRECTCOLOUR, 32k */
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;
}
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,14 +1169,7 @@ static int cyber2000fb_switch(int con, struct fb_info *info)
/*
* (Un)Blank the display.
*/
static int cyber2000fb_blank(int blank, struct fb_info *info)
{
struct cfb_info *cfb = (struct cfb_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
......@@ -1066,6 +1184,11 @@ static int cyber2000fb_blank(int blank, struct fb_info *info)
* wms...Enable VESA DMPS compatible powerdown mode
* run "setterm -powersave powerdown" to take advantage
*/
static int cyber2000fb_blank(int blank, struct fb_info *info)
{
struct cfb_info *cfb = (struct cfb_info *)info;
unsigned int sync = 0;
int i;
switch (blank) {
case 4: /* powerdown - both sync lines down */
......@@ -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,
};
/*
......@@ -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 @@ cyberpro_vl_probe(void)
*/
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;
......@@ -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;
}
......
......@@ -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_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_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_CMD_H_SRC_PIXMAP 0x2000
#define CO_REG_CMD_H 0xbf07e
#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_CONTROL 0xbf011
#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_X_PHASE 0xbf078
#define CO_REG_CMD_L 0xbf07c
#define CO_REG_CMD_H 0xbf07e
#define CO_REG_SRC_PTR 0xbf170
#define CO_REG_SRC1_PTR 0xbf170
#define CO_REG_SRC2_PTR 0xbf174
#define CO_REG_DEST_PTR 0xbf178
#define CO_REG_DEST_WIDTH 0xbf218
......
......@@ -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
};
......@@ -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
};
......@@ -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)
......
......@@ -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);
}
......@@ -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 */ \
......
......@@ -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
......
......@@ -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)
......
......@@ -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;
}
......
......@@ -95,9 +95,10 @@ typedef enum { /* Speed for ECARD_IOC space */
ECARD_SYNC = 3
} card_speed_t;
typedef struct { /* Card ID structure */
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
......@@ -26,59 +26,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
......@@ -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 */
......@@ -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)
......
......@@ -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)
......
/*
* linux/drivers/acorn/char/serial-dualsp.c
* linux/include/asm-arm/numnodes.h
*
* Copyright (C) 1996 Russell King.
* 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.
*
* 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)
#ifndef __ASM_ARM_NUMNODES_H
#define __ASM_ARM_NUMNODES_H
#include <asm/memory.h>
#define MAX_NUMNODES NR_NODES
#include "serial-card.c"
#endif
......@@ -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,
......
......@@ -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
......@@ -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>
/*
......
......@@ -12,6 +12,7 @@
#include <linux/config.h>
#include <asm/memory.h>
#include <asm/proc-fns.h>
#include <asm/arch/vmalloc.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)
......
......@@ -5,6 +5,7 @@
*
* Page table allocation/freeing primitives for 32-bit ARM processors.
*/
#include <asm/cacheflush.h>
#include "pgtable.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
......@@ -28,13 +28,21 @@
#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];
struct debug_entry bp[2];
};
struct thread_struct {
......
......@@ -12,8 +12,6 @@
#ifndef __ASSEMBLY__
#include <asm/proc-fns.h>
struct cpu_tlb_fns;
struct cpu_user_fns;
struct processor;
......
/*
* 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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment