mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-04 01:24:12 +08:00
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: powerpc/mm: Lockless get_user_pages_fast() for 64-bit (v3) powerpc: Don't use the wrong thread_struct for ptrace get/set VSX regs powerpc: Fix ptrace buffer size for VSX powerpc: Correctly hookup PTRACE_GET/SETVSRREGS for 32 bit processes ide/powermac: Fix use of uninitialized pointer on media-bay powerpc: Allow non-hcall return values for lparcfg writes ipmi/powerpc: Use linux/of_{device,platform}.h instead of asm powerpc/fsl: proliferate simple-bus compatibility to soc nodes Documentation: remove old sbc8260 board specific information cpm2: Rework baud rate generators configuration to support external clocks. powerpc: rtc_cmos_setup: assign interrupts only if there is i8259 PIC cpm_uart: Add generic clock API support to set baudrates cpm_uart: Modem control lines support powerpc: implement GPIO LIB API on CPM1 Freescale SoC. cpm2: Implement GPIO LIB API on CPM2 Freescale SoC. powerpc: Fix 8xx build failure powerpc: clean up the Book-E HW watchpoint support
This commit is contained in:
commit
660fc1f4d8
@ -20,8 +20,6 @@ mpc52xx-device-tree-bindings.txt
|
|||||||
- MPC5200 Device Tree Bindings
|
- MPC5200 Device Tree Bindings
|
||||||
ppc_htab.txt
|
ppc_htab.txt
|
||||||
- info about the Linux/PPC /proc/ppc_htab entry
|
- info about the Linux/PPC /proc/ppc_htab entry
|
||||||
SBC8260_memory_mapping.txt
|
|
||||||
- EST SBC8260 board info
|
|
||||||
smp.txt
|
smp.txt
|
||||||
- use and state info about Linux/PPC on MP machines
|
- use and state info about Linux/PPC on MP machines
|
||||||
sound.txt
|
sound.txt
|
||||||
|
@ -1,197 +0,0 @@
|
|||||||
Please mail me (Jon Diekema, diekema_jon@si.com or diekema@cideas.com)
|
|
||||||
if you have questions, comments or corrections.
|
|
||||||
|
|
||||||
* EST SBC8260 Linux memory mapping rules
|
|
||||||
|
|
||||||
http://www.estc.com/
|
|
||||||
http://www.estc.com/products/boards/SBC8260-8240_ds.html
|
|
||||||
|
|
||||||
Initial conditions:
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Tasks that need to be perform by the boot ROM before control is
|
|
||||||
transferred to zImage (compressed Linux kernel):
|
|
||||||
|
|
||||||
- Define the IMMR to 0xf0000000
|
|
||||||
|
|
||||||
- Initialize the memory controller so that RAM is available at
|
|
||||||
physical address 0x00000000. On the SBC8260 is this 16M (64M)
|
|
||||||
SDRAM.
|
|
||||||
|
|
||||||
- The boot ROM should only clear the RAM that it is using.
|
|
||||||
|
|
||||||
The reason for doing this is to enhances the chances of a
|
|
||||||
successful post mortem on a Linux panic. One of the first
|
|
||||||
items to examine is the 16k (LOG_BUF_LEN) circular console
|
|
||||||
buffer called log_buf which is defined in kernel/printk.c.
|
|
||||||
|
|
||||||
- To enhance boot ROM performance, the I-cache can be enabled.
|
|
||||||
|
|
||||||
Date: Mon, 22 May 2000 14:21:10 -0700
|
|
||||||
From: Neil Russell <caret@c-side.com>
|
|
||||||
|
|
||||||
LiMon (LInux MONitor) runs with and starts Linux with MMU
|
|
||||||
off, I-cache enabled, D-cache disabled. The I-cache doesn't
|
|
||||||
need hints from the MMU to work correctly as the D-cache
|
|
||||||
does. No D-cache means no special code to handle devices in
|
|
||||||
the presence of cache (no snooping, etc). The use of the
|
|
||||||
I-cache means that the monitor can run acceptably fast
|
|
||||||
directly from ROM, rather than having to copy it to RAM.
|
|
||||||
|
|
||||||
- Build the board information structure (see
|
|
||||||
include/asm-ppc/est8260.h for its definition)
|
|
||||||
|
|
||||||
- The compressed Linux kernel (zImage) contains a bootstrap loader
|
|
||||||
that is position independent; you can load it into any RAM,
|
|
||||||
ROM or FLASH memory address >= 0x00500000 (above 5 MB), or
|
|
||||||
at its link address of 0x00400000 (4 MB).
|
|
||||||
|
|
||||||
Note: If zImage is loaded at its link address of 0x00400000 (4 MB),
|
|
||||||
then zImage will skip the step of moving itself to
|
|
||||||
its link address.
|
|
||||||
|
|
||||||
- Load R3 with the address of the board information structure
|
|
||||||
|
|
||||||
- Transfer control to zImage
|
|
||||||
|
|
||||||
- The Linux console port is SMC1, and the baud rate is controlled
|
|
||||||
from the bi_baudrate field of the board information structure.
|
|
||||||
On thing to keep in mind when picking the baud rate, is that
|
|
||||||
there is no flow control on the SMC ports. I would stick
|
|
||||||
with something safe and standard like 19200.
|
|
||||||
|
|
||||||
On the EST SBC8260, the SMC1 port is on the COM1 connector of
|
|
||||||
the board.
|
|
||||||
|
|
||||||
|
|
||||||
EST SBC8260 defaults:
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
Chip
|
|
||||||
Memory Sel Bus Use
|
|
||||||
--------------------- --- --- ----------------------------------
|
|
||||||
0x00000000-0x03FFFFFF CS2 60x (16M or 64M)/64M SDRAM
|
|
||||||
0x04000000-0x04FFFFFF CS4 local 4M/16M SDRAM (soldered to the board)
|
|
||||||
0x21000000-0x21000000 CS7 60x 1B/64K Flash present detect (from the flash SIMM)
|
|
||||||
0x21000001-0x21000001 CS7 60x 1B/64K Switches (read) and LEDs (write)
|
|
||||||
0x22000000-0x2200FFFF CS5 60x 8K/64K EEPROM
|
|
||||||
0xFC000000-0xFCFFFFFF CS6 60x 2M/16M flash (8 bits wide, soldered to the board)
|
|
||||||
0xFE000000-0xFFFFFFFF CS0 60x 4M/16M flash (SIMM)
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
------
|
|
||||||
|
|
||||||
- The chip selects can map 32K blocks and up (powers of 2)
|
|
||||||
|
|
||||||
- The SDRAM machine can handled up to 128Mbytes per chip select
|
|
||||||
|
|
||||||
- Linux uses the 60x bus memory (the SDRAM DIMM) for the
|
|
||||||
communications buffers.
|
|
||||||
|
|
||||||
- BATs can map 128K-256Mbytes each. There are four data BATs and
|
|
||||||
four instruction BATs. Generally the data and instruction BATs
|
|
||||||
are mapped the same.
|
|
||||||
|
|
||||||
- The IMMR must be set above the kernel virtual memory addresses,
|
|
||||||
which start at 0xC0000000. Otherwise, the kernel may crash as
|
|
||||||
soon as you start any threads or processes due to VM collisions
|
|
||||||
in the kernel or user process space.
|
|
||||||
|
|
||||||
|
|
||||||
Details from Dan Malek <dan_malek@mvista.com> on 10/29/1999:
|
|
||||||
|
|
||||||
The user application virtual space consumes the first 2 Gbytes
|
|
||||||
(0x00000000 to 0x7FFFFFFF). The kernel virtual text starts at
|
|
||||||
0xC0000000, with data following. There is a "protection hole"
|
|
||||||
between the end of kernel data and the start of the kernel
|
|
||||||
dynamically allocated space, but this space is still within
|
|
||||||
0xCxxxxxxx.
|
|
||||||
|
|
||||||
Obviously the kernel can't map any physical addresses 1:1 in
|
|
||||||
these ranges.
|
|
||||||
|
|
||||||
|
|
||||||
Details from Dan Malek <dan_malek@mvista.com> on 5/19/2000:
|
|
||||||
|
|
||||||
During the early kernel initialization, the kernel virtual
|
|
||||||
memory allocator is not operational. Prior to this KVM
|
|
||||||
initialization, we choose to map virtual to physical addresses
|
|
||||||
1:1. That is, the kernel virtual address exactly matches the
|
|
||||||
physical address on the bus. These mappings are typically done
|
|
||||||
in arch/ppc/kernel/head.S, or arch/ppc/mm/init.c. Only
|
|
||||||
absolutely necessary mappings should be done at this time, for
|
|
||||||
example board control registers or a serial uart. Normal device
|
|
||||||
driver initialization should map resources later when necessary.
|
|
||||||
|
|
||||||
Although platform dependent, and certainly the case for embedded
|
|
||||||
8xx, traditionally memory is mapped at physical address zero,
|
|
||||||
and I/O devices above physical address 0x80000000. The lowest
|
|
||||||
and highest (above 0xf0000000) I/O addresses are traditionally
|
|
||||||
used for devices or registers we need to map during kernel
|
|
||||||
initialization and prior to KVM operation. For this reason,
|
|
||||||
and since it followed prior PowerPC platform examples, I chose
|
|
||||||
to map the embedded 8xx kernel to the 0xc0000000 virtual address.
|
|
||||||
This way, we can enable the MMU to map the kernel for proper
|
|
||||||
operation, and still map a few windows before the KVM is operational.
|
|
||||||
|
|
||||||
On some systems, you could possibly run the kernel at the
|
|
||||||
0x80000000 or any other virtual address. It just depends upon
|
|
||||||
mapping that must be done prior to KVM operational. You can never
|
|
||||||
map devices or kernel spaces that overlap with the user virtual
|
|
||||||
space. This is why default IMMR mapping used by most BDM tools
|
|
||||||
won't work. They put the IMMR at something like 0x10000000 or
|
|
||||||
0x02000000 for example. You simply can't map these addresses early
|
|
||||||
in the kernel, and continue proper system operation.
|
|
||||||
|
|
||||||
The embedded 8xx/82xx kernel is mature enough that all you should
|
|
||||||
need to do is map the IMMR someplace at or above 0xf0000000 and it
|
|
||||||
should boot far enough to get serial console messages and KGDB
|
|
||||||
connected on any platform. There are lots of other subtle memory
|
|
||||||
management design features that you simply don't need to worry
|
|
||||||
about. If you are changing functions related to MMU initialization,
|
|
||||||
you are likely breaking things that are known to work and are
|
|
||||||
heading down a path of disaster and frustration. Your changes
|
|
||||||
should be to make the flexibility of the processor fit Linux,
|
|
||||||
not force arbitrary and non-workable memory mappings into Linux.
|
|
||||||
|
|
||||||
- You don't want to change KERNELLOAD or KERNELBASE, otherwise the
|
|
||||||
virtual memory and MMU code will get confused.
|
|
||||||
|
|
||||||
arch/ppc/Makefile:KERNELLOAD = 0xc0000000
|
|
||||||
|
|
||||||
include/asm-ppc/page.h:#define PAGE_OFFSET 0xc0000000
|
|
||||||
include/asm-ppc/page.h:#define KERNELBASE PAGE_OFFSET
|
|
||||||
|
|
||||||
- RAM is at physical address 0x00000000, and gets mapped to
|
|
||||||
virtual address 0xC0000000 for the kernel.
|
|
||||||
|
|
||||||
|
|
||||||
Physical addresses used by the Linux kernel:
|
|
||||||
--------------------------------------------
|
|
||||||
|
|
||||||
0x00000000-0x3FFFFFFF 1GB reserved for RAM
|
|
||||||
0xF0000000-0xF001FFFF 128K IMMR 64K used for dual port memory,
|
|
||||||
64K for 8260 registers
|
|
||||||
|
|
||||||
|
|
||||||
Logical addresses used by the Linux kernel:
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
0xF0000000-0xFFFFFFFF 256M BAT0 (IMMR: dual port RAM, registers)
|
|
||||||
0xE0000000-0xEFFFFFFF 256M BAT1 (I/O space for custom boards)
|
|
||||||
0xC0000000-0xCFFFFFFF 256M BAT2 (RAM)
|
|
||||||
0xD0000000-0xDFFFFFFF 256M BAT3 (if RAM > 256MByte)
|
|
||||||
|
|
||||||
|
|
||||||
EST SBC8260 Linux mapping:
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
DBAT0, IBAT0, cache inhibited:
|
|
||||||
|
|
||||||
Chip
|
|
||||||
Memory Sel Use
|
|
||||||
--------------------- --- ---------------------------------
|
|
||||||
0xF0000000-0xF001FFFF n/a IMMR: dual port RAM, registers
|
|
||||||
|
|
||||||
DBAT1, IBAT1, cache inhibited:
|
|
||||||
|
|
@ -7,6 +7,15 @@ Currently defined compatibles:
|
|||||||
- fsl,cpm2-scc-uart
|
- fsl,cpm2-scc-uart
|
||||||
- fsl,qe-uart
|
- fsl,qe-uart
|
||||||
|
|
||||||
|
Modem control lines connected to GPIO controllers are listed in the gpios
|
||||||
|
property as described in booting-without-of.txt, section IX.1 in the following
|
||||||
|
order:
|
||||||
|
|
||||||
|
CTS, RTS, DCD, DSR, DTR, and RI.
|
||||||
|
|
||||||
|
The gpios property is optional and can be left out when control lines are
|
||||||
|
not used.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
serial@11a00 {
|
serial@11a00 {
|
||||||
@ -18,4 +27,6 @@ Example:
|
|||||||
interrupt-parent = <&PIC>;
|
interrupt-parent = <&PIC>;
|
||||||
fsl,cpm-brg = <1>;
|
fsl,cpm-brg = <1>;
|
||||||
fsl,cpm-command = <00800000>;
|
fsl,cpm-command = <00800000>;
|
||||||
|
gpios = <&gpio_c 15 0
|
||||||
|
&gpio_d 29 0>;
|
||||||
};
|
};
|
||||||
|
@ -42,6 +42,9 @@ config GENERIC_HARDIRQS
|
|||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config HAVE_GET_USER_PAGES_FAST
|
||||||
|
def_bool PPC64
|
||||||
|
|
||||||
config HAVE_SETUP_PER_CPU_AREA
|
config HAVE_SETUP_PER_CPU_AREA
|
||||||
def_bool PPC64
|
def_bool PPC64
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x00100000>;
|
ranges = <0x0 0xe0000000 0x00100000>;
|
||||||
reg = <0xe0000000 0x00000200>;
|
reg = <0xe0000000 0x00000200>;
|
||||||
bus-frequency = <132000000>;
|
bus-frequency = <132000000>;
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x00100000>;
|
ranges = <0x0 0xe0000000 0x00100000>;
|
||||||
reg = <0xe0000000 0x00000200>;
|
reg = <0xe0000000 0x00000200>;
|
||||||
bus-frequency = <0>;
|
bus-frequency = <0>;
|
||||||
|
@ -52,6 +52,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x00100000>;
|
ranges = <0x0 0xe0000000 0x00100000>;
|
||||||
reg = <0xe0000000 0x00000200>;
|
reg = <0xe0000000 0x00000200>;
|
||||||
bus-frequency = <0>; // from bootloader
|
bus-frequency = <0>; // from bootloader
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x00100000>;
|
ranges = <0x0 0xe0000000 0x00100000>;
|
||||||
reg = <0xe0000000 0x00000200>;
|
reg = <0xe0000000 0x00000200>;
|
||||||
bus-frequency = <0>; // from bootloader
|
bus-frequency = <0>; // from bootloader
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x00100000>;
|
ranges = <0x0 0xe0000000 0x00100000>;
|
||||||
reg = <0xe0000000 0x00000200>;
|
reg = <0xe0000000 0x00000200>;
|
||||||
bus-frequency = <0>;
|
bus-frequency = <0>;
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x00100000>;
|
ranges = <0x0 0xe0000000 0x00100000>;
|
||||||
reg = <0xe0000000 0x00000200>;
|
reg = <0xe0000000 0x00000200>;
|
||||||
bus-frequency = <264000000>;
|
bus-frequency = <264000000>;
|
||||||
|
@ -149,18 +149,14 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
crypto@30000 {
|
crypto@30000 {
|
||||||
compatible = "fsl,sec2-crypto";
|
compatible = "fsl,sec2.0";
|
||||||
reg = <0x30000 0x10000>;
|
reg = <0x30000 0x10000>;
|
||||||
interrupts = <11 8>;
|
interrupts = <11 0x8>;
|
||||||
interrupt-parent = <&ipic>;
|
interrupt-parent = <&ipic>;
|
||||||
num-channels = <4>;
|
fsl,num-channels = <4>;
|
||||||
channel-fifo-len = <24>;
|
fsl,channel-fifo-len = <24>;
|
||||||
exec-units-mask = <0x7e>;
|
fsl,exec-units-mask = <0x7e>;
|
||||||
/*
|
fsl,descriptor-types-mask = <0x01010ebf>;
|
||||||
* desc mask is for rev1.x, we need runtime fixup
|
|
||||||
* for >=2.x
|
|
||||||
*/
|
|
||||||
descriptor-types-mask = <0x1010ebf>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ipic: interrupt-controller@700 {
|
ipic: interrupt-controller@700 {
|
||||||
|
@ -117,6 +117,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x00100000>;
|
ranges = <0x0 0xe0000000 0x00100000>;
|
||||||
reg = <0xe0000000 0x00000200>;
|
reg = <0xe0000000 0x00000200>;
|
||||||
bus-frequency = <0>;
|
bus-frequency = <0>;
|
||||||
|
@ -117,6 +117,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x00100000>;
|
ranges = <0x0 0xe0000000 0x00100000>;
|
||||||
reg = <0xe0000000 0x00000200>;
|
reg = <0xe0000000 0x00000200>;
|
||||||
bus-frequency = <0>;
|
bus-frequency = <0>;
|
||||||
|
@ -117,6 +117,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x00100000>;
|
ranges = <0x0 0xe0000000 0x00100000>;
|
||||||
reg = <0xe0000000 0x00000200>;
|
reg = <0xe0000000 0x00000200>;
|
||||||
bus-frequency = <0>;
|
bus-frequency = <0>;
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xffe00000 0x100000>;
|
ranges = <0x0 0xffe00000 0x100000>;
|
||||||
reg = <0xffe00000 0x1000>;
|
reg = <0xffe00000 0x1000>;
|
||||||
bus-frequency = <0>; // Filled out by uboot.
|
bus-frequency = <0>; // Filled out by uboot.
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x100000>;
|
ranges = <0x0 0xe0000000 0x100000>;
|
||||||
reg = <0xe0000000 0x100000>; // CCSRBAR 1M
|
reg = <0xe0000000 0x100000>; // CCSRBAR 1M
|
||||||
bus-frequency = <0>;
|
bus-frequency = <0>;
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x100000>;
|
ranges = <0x0 0xe0000000 0x100000>;
|
||||||
reg = <0xe0000000 0x1000>; // CCSRBAR 1M
|
reg = <0xe0000000 0x1000>; // CCSRBAR 1M
|
||||||
bus-frequency = <0>;
|
bus-frequency = <0>;
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
|
|
||||||
ranges = <0x0 0xe0000000 0x100000>;
|
ranges = <0x0 0xe0000000 0x100000>;
|
||||||
reg = <0xe0000000 0x1000>; // CCSRBAR 1M
|
reg = <0xe0000000 0x1000>; // CCSRBAR 1M
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x100000>;
|
ranges = <0x0 0xe0000000 0x100000>;
|
||||||
reg = <0xe0000000 0x1000>; // CCSRBAR
|
reg = <0xe0000000 0x1000>; // CCSRBAR
|
||||||
bus-frequency = <0>;
|
bus-frequency = <0>;
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x100000>;
|
ranges = <0x0 0xe0000000 0x100000>;
|
||||||
reg = <0xe0000000 0x1000>; // CCSRBAR 1M
|
reg = <0xe0000000 0x1000>; // CCSRBAR 1M
|
||||||
bus-frequency = <0>;
|
bus-frequency = <0>;
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x100000>;
|
ranges = <0x0 0xe0000000 0x100000>;
|
||||||
reg = <0xe0000000 0x200>;
|
reg = <0xe0000000 0x200>;
|
||||||
bus-frequency = <330000000>;
|
bus-frequency = <330000000>;
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xe0000000 0x100000>;
|
ranges = <0x0 0xe0000000 0x100000>;
|
||||||
reg = <0xe0000000 0x1000>;
|
reg = <0xe0000000 0x1000>;
|
||||||
bus-frequency = <0>;
|
bus-frequency = <0>;
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
#address-cells = <1>;
|
#address-cells = <1>;
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
device_type = "soc";
|
device_type = "soc";
|
||||||
|
compatible = "simple-bus";
|
||||||
ranges = <0x0 0xffe00000 0x100000>;
|
ranges = <0x0 0xffe00000 0x100000>;
|
||||||
reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
|
reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed
|
||||||
bus-frequency = <0>; // Filled out by uboot.
|
bus-frequency = <0>; // Filled out by uboot.
|
||||||
|
@ -636,10 +636,6 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf,
|
|||||||
retval = -EIO;
|
retval = -EIO;
|
||||||
} else if (retval == H_PARAMETER) {
|
} else if (retval == H_PARAMETER) {
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
} else {
|
|
||||||
printk(KERN_WARNING "%s: received unknown hv return code %ld",
|
|
||||||
__func__, retval);
|
|
||||||
retval = -EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -375,7 +375,7 @@ static int vsr_get(struct task_struct *target, const struct user_regset *regset,
|
|||||||
flush_vsx_to_thread(target);
|
flush_vsx_to_thread(target);
|
||||||
|
|
||||||
for (i = 0; i < 32 ; i++)
|
for (i = 0; i < 32 ; i++)
|
||||||
buf[i] = current->thread.fpr[i][TS_VSRLOWOFFSET];
|
buf[i] = target->thread.fpr[i][TS_VSRLOWOFFSET];
|
||||||
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
||||||
buf, 0, 32 * sizeof(double));
|
buf, 0, 32 * sizeof(double));
|
||||||
|
|
||||||
@ -394,7 +394,7 @@ static int vsr_set(struct task_struct *target, const struct user_regset *regset,
|
|||||||
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
|
||||||
buf, 0, 32 * sizeof(double));
|
buf, 0, 32 * sizeof(double));
|
||||||
for (i = 0; i < 32 ; i++)
|
for (i = 0; i < 32 ; i++)
|
||||||
current->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i];
|
target->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i];
|
||||||
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -975,15 +975,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
case PTRACE_GETVSRREGS:
|
case PTRACE_GETVSRREGS:
|
||||||
return copy_regset_to_user(child, &user_ppc_native_view,
|
return copy_regset_to_user(child, &user_ppc_native_view,
|
||||||
REGSET_VSX,
|
REGSET_VSX,
|
||||||
0, (32 * sizeof(vector128) +
|
0, 32 * sizeof(double),
|
||||||
sizeof(u32)),
|
|
||||||
(void __user *) data);
|
(void __user *) data);
|
||||||
|
|
||||||
case PTRACE_SETVSRREGS:
|
case PTRACE_SETVSRREGS:
|
||||||
return copy_regset_from_user(child, &user_ppc_native_view,
|
return copy_regset_from_user(child, &user_ppc_native_view,
|
||||||
REGSET_VSX,
|
REGSET_VSX,
|
||||||
0, (32 * sizeof(vector128) +
|
0, 32 * sizeof(double),
|
||||||
sizeof(u32)),
|
|
||||||
(const void __user *) data);
|
(const void __user *) data);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_SPE
|
#ifdef CONFIG_SPE
|
||||||
|
@ -294,6 +294,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
|
|||||||
case PTRACE_SETFPREGS:
|
case PTRACE_SETFPREGS:
|
||||||
case PTRACE_GETVRREGS:
|
case PTRACE_GETVRREGS:
|
||||||
case PTRACE_SETVRREGS:
|
case PTRACE_SETVRREGS:
|
||||||
|
case PTRACE_GETVSRREGS:
|
||||||
|
case PTRACE_SETVSRREGS:
|
||||||
case PTRACE_GETREGS64:
|
case PTRACE_GETREGS64:
|
||||||
case PTRACE_SETREGS64:
|
case PTRACE_SETREGS64:
|
||||||
case PPC_PTRACE_GETFPREGS:
|
case PPC_PTRACE_GETFPREGS:
|
||||||
|
@ -12,7 +12,8 @@ obj-y := fault.o mem.o \
|
|||||||
mmu_context_$(CONFIG_WORD_SIZE).o
|
mmu_context_$(CONFIG_WORD_SIZE).o
|
||||||
hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o
|
hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o
|
||||||
obj-$(CONFIG_PPC64) += hash_utils_64.o \
|
obj-$(CONFIG_PPC64) += hash_utils_64.o \
|
||||||
slb_low.o slb.o stab.o mmap.o $(hash-y)
|
slb_low.o slb.o stab.o \
|
||||||
|
gup.o mmap.o $(hash-y)
|
||||||
obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o
|
obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o
|
||||||
obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \
|
obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \
|
||||||
tlb_$(CONFIG_WORD_SIZE).o
|
tlb_$(CONFIG_WORD_SIZE).o
|
||||||
|
280
arch/powerpc/mm/gup.c
Normal file
280
arch/powerpc/mm/gup.c
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
/*
|
||||||
|
* Lockless get_user_pages_fast for powerpc
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Nick Piggin
|
||||||
|
* Copyright (C) 2008 Novell Inc.
|
||||||
|
*/
|
||||||
|
#undef DEBUG
|
||||||
|
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/hugetlb.h>
|
||||||
|
#include <linux/vmstat.h>
|
||||||
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/rwsem.h>
|
||||||
|
#include <asm/pgtable.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The performance critical leaf functions are made noinline otherwise gcc
|
||||||
|
* inlines everything into a single function which results in too much
|
||||||
|
* register pressure.
|
||||||
|
*/
|
||||||
|
static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
|
||||||
|
unsigned long end, int write, struct page **pages, int *nr)
|
||||||
|
{
|
||||||
|
unsigned long mask, result;
|
||||||
|
pte_t *ptep;
|
||||||
|
|
||||||
|
result = _PAGE_PRESENT|_PAGE_USER;
|
||||||
|
if (write)
|
||||||
|
result |= _PAGE_RW;
|
||||||
|
mask = result | _PAGE_SPECIAL;
|
||||||
|
|
||||||
|
ptep = pte_offset_kernel(&pmd, addr);
|
||||||
|
do {
|
||||||
|
pte_t pte = *ptep;
|
||||||
|
struct page *page;
|
||||||
|
|
||||||
|
if ((pte_val(pte) & mask) != result)
|
||||||
|
return 0;
|
||||||
|
VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
|
||||||
|
page = pte_page(pte);
|
||||||
|
if (!page_cache_get_speculative(page))
|
||||||
|
return 0;
|
||||||
|
if (unlikely(pte != *ptep)) {
|
||||||
|
put_page(page);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pages[*nr] = page;
|
||||||
|
(*nr)++;
|
||||||
|
|
||||||
|
} while (ptep++, addr += PAGE_SIZE, addr != end);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HUGETLB_PAGE
|
||||||
|
static noinline int gup_huge_pte(pte_t *ptep, struct hstate *hstate,
|
||||||
|
unsigned long *addr, unsigned long end,
|
||||||
|
int write, struct page **pages, int *nr)
|
||||||
|
{
|
||||||
|
unsigned long mask;
|
||||||
|
unsigned long pte_end;
|
||||||
|
struct page *head, *page;
|
||||||
|
pte_t pte;
|
||||||
|
int refs;
|
||||||
|
|
||||||
|
pte_end = (*addr + huge_page_size(hstate)) & huge_page_mask(hstate);
|
||||||
|
if (pte_end < end)
|
||||||
|
end = pte_end;
|
||||||
|
|
||||||
|
pte = *ptep;
|
||||||
|
mask = _PAGE_PRESENT|_PAGE_USER;
|
||||||
|
if (write)
|
||||||
|
mask |= _PAGE_RW;
|
||||||
|
if ((pte_val(pte) & mask) != mask)
|
||||||
|
return 0;
|
||||||
|
/* hugepages are never "special" */
|
||||||
|
VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
|
||||||
|
|
||||||
|
refs = 0;
|
||||||
|
head = pte_page(pte);
|
||||||
|
page = head + ((*addr & ~huge_page_mask(hstate)) >> PAGE_SHIFT);
|
||||||
|
do {
|
||||||
|
VM_BUG_ON(compound_head(page) != head);
|
||||||
|
pages[*nr] = page;
|
||||||
|
(*nr)++;
|
||||||
|
page++;
|
||||||
|
refs++;
|
||||||
|
} while (*addr += PAGE_SIZE, *addr != end);
|
||||||
|
|
||||||
|
if (!page_cache_add_speculative(head, refs)) {
|
||||||
|
*nr -= refs;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (unlikely(pte != *ptep)) {
|
||||||
|
/* Could be optimized better */
|
||||||
|
while (*nr) {
|
||||||
|
put_page(page);
|
||||||
|
(*nr)--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_HUGETLB_PAGE */
|
||||||
|
|
||||||
|
static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
|
||||||
|
int write, struct page **pages, int *nr)
|
||||||
|
{
|
||||||
|
unsigned long next;
|
||||||
|
pmd_t *pmdp;
|
||||||
|
|
||||||
|
pmdp = pmd_offset(&pud, addr);
|
||||||
|
do {
|
||||||
|
pmd_t pmd = *pmdp;
|
||||||
|
|
||||||
|
next = pmd_addr_end(addr, end);
|
||||||
|
if (pmd_none(pmd))
|
||||||
|
return 0;
|
||||||
|
if (!gup_pte_range(pmd, addr, next, write, pages, nr))
|
||||||
|
return 0;
|
||||||
|
} while (pmdp++, addr = next, addr != end);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
|
||||||
|
int write, struct page **pages, int *nr)
|
||||||
|
{
|
||||||
|
unsigned long next;
|
||||||
|
pud_t *pudp;
|
||||||
|
|
||||||
|
pudp = pud_offset(&pgd, addr);
|
||||||
|
do {
|
||||||
|
pud_t pud = *pudp;
|
||||||
|
|
||||||
|
next = pud_addr_end(addr, end);
|
||||||
|
if (pud_none(pud))
|
||||||
|
return 0;
|
||||||
|
if (!gup_pmd_range(pud, addr, next, write, pages, nr))
|
||||||
|
return 0;
|
||||||
|
} while (pudp++, addr = next, addr != end);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_user_pages_fast(unsigned long start, int nr_pages, int write,
|
||||||
|
struct page **pages)
|
||||||
|
{
|
||||||
|
struct mm_struct *mm = current->mm;
|
||||||
|
unsigned long addr, len, end;
|
||||||
|
unsigned long next;
|
||||||
|
pgd_t *pgdp;
|
||||||
|
int psize, nr = 0;
|
||||||
|
unsigned int shift;
|
||||||
|
|
||||||
|
pr_debug("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read");
|
||||||
|
|
||||||
|
start &= PAGE_MASK;
|
||||||
|
addr = start;
|
||||||
|
len = (unsigned long) nr_pages << PAGE_SHIFT;
|
||||||
|
end = start + len;
|
||||||
|
|
||||||
|
if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
|
||||||
|
start, len)))
|
||||||
|
goto slow_irqon;
|
||||||
|
|
||||||
|
pr_debug(" aligned: %lx .. %lx\n", start, end);
|
||||||
|
|
||||||
|
#ifdef CONFIG_HUGETLB_PAGE
|
||||||
|
/* We bail out on slice boundary crossing when hugetlb is
|
||||||
|
* enabled in order to not have to deal with two different
|
||||||
|
* page table formats
|
||||||
|
*/
|
||||||
|
if (addr < SLICE_LOW_TOP) {
|
||||||
|
if (end > SLICE_LOW_TOP)
|
||||||
|
goto slow_irqon;
|
||||||
|
|
||||||
|
if (unlikely(GET_LOW_SLICE_INDEX(addr) !=
|
||||||
|
GET_LOW_SLICE_INDEX(end - 1)))
|
||||||
|
goto slow_irqon;
|
||||||
|
} else {
|
||||||
|
if (unlikely(GET_HIGH_SLICE_INDEX(addr) !=
|
||||||
|
GET_HIGH_SLICE_INDEX(end - 1)))
|
||||||
|
goto slow_irqon;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_HUGETLB_PAGE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: batch / limit 'nr', to avoid large irq off latency
|
||||||
|
* needs some instrumenting to determine the common sizes used by
|
||||||
|
* important workloads (eg. DB2), and whether limiting the batch size
|
||||||
|
* will decrease performance.
|
||||||
|
*
|
||||||
|
* It seems like we're in the clear for the moment. Direct-IO is
|
||||||
|
* the main guy that batches up lots of get_user_pages, and even
|
||||||
|
* they are limited to 64-at-a-time which is not so many.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This doesn't prevent pagetable teardown, but does prevent
|
||||||
|
* the pagetables from being freed on powerpc.
|
||||||
|
*
|
||||||
|
* So long as we atomically load page table pointers versus teardown,
|
||||||
|
* we can follow the address down to the the page and take a ref on it.
|
||||||
|
*/
|
||||||
|
local_irq_disable();
|
||||||
|
|
||||||
|
psize = get_slice_psize(mm, addr);
|
||||||
|
shift = mmu_psize_defs[psize].shift;
|
||||||
|
|
||||||
|
#ifdef CONFIG_HUGETLB_PAGE
|
||||||
|
if (unlikely(mmu_huge_psizes[psize])) {
|
||||||
|
pte_t *ptep;
|
||||||
|
unsigned long a = addr;
|
||||||
|
unsigned long sz = ((1UL) << shift);
|
||||||
|
struct hstate *hstate = size_to_hstate(sz);
|
||||||
|
|
||||||
|
BUG_ON(!hstate);
|
||||||
|
/*
|
||||||
|
* XXX: could be optimized to avoid hstate
|
||||||
|
* lookup entirely (just use shift)
|
||||||
|
*/
|
||||||
|
|
||||||
|
do {
|
||||||
|
VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, a)].shift);
|
||||||
|
ptep = huge_pte_offset(mm, a);
|
||||||
|
pr_debug(" %016lx: huge ptep %p\n", a, ptep);
|
||||||
|
if (!ptep || !gup_huge_pte(ptep, hstate, &a, end, write, pages,
|
||||||
|
&nr))
|
||||||
|
goto slow;
|
||||||
|
} while (a != end);
|
||||||
|
} else
|
||||||
|
#endif /* CONFIG_HUGETLB_PAGE */
|
||||||
|
{
|
||||||
|
pgdp = pgd_offset(mm, addr);
|
||||||
|
do {
|
||||||
|
pgd_t pgd = *pgdp;
|
||||||
|
|
||||||
|
VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, addr)].shift);
|
||||||
|
pr_debug(" %016lx: normal pgd %p\n", addr, (void *)pgd);
|
||||||
|
next = pgd_addr_end(addr, end);
|
||||||
|
if (pgd_none(pgd))
|
||||||
|
goto slow;
|
||||||
|
if (!gup_pud_range(pgd, addr, next, write, pages, &nr))
|
||||||
|
goto slow;
|
||||||
|
} while (pgdp++, addr = next, addr != end);
|
||||||
|
}
|
||||||
|
local_irq_enable();
|
||||||
|
|
||||||
|
VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT);
|
||||||
|
return nr;
|
||||||
|
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
slow:
|
||||||
|
local_irq_enable();
|
||||||
|
slow_irqon:
|
||||||
|
pr_debug(" slow path ! nr = %d\n", nr);
|
||||||
|
|
||||||
|
/* Try to get the remaining pages with get_user_pages */
|
||||||
|
start += nr << PAGE_SHIFT;
|
||||||
|
pages += nr;
|
||||||
|
|
||||||
|
down_read(&mm->mmap_sem);
|
||||||
|
ret = get_user_pages(current, mm, start,
|
||||||
|
(end - start) >> PAGE_SHIFT, write, 0, pages, NULL);
|
||||||
|
up_read(&mm->mmap_sem);
|
||||||
|
|
||||||
|
/* Have to be a bit careful with return values */
|
||||||
|
if (nr > 0) {
|
||||||
|
if (ret < 0)
|
||||||
|
ret = nr;
|
||||||
|
else
|
||||||
|
ret += nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
@ -105,6 +105,7 @@ static void __init mpc832x_sys_setup_arch(void)
|
|||||||
static struct of_device_id mpc832x_ids[] = {
|
static struct of_device_id mpc832x_ids[] = {
|
||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
{ .compatible = "soc", },
|
{ .compatible = "soc", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{ .type = "qe", },
|
{ .type = "qe", },
|
||||||
{ .compatible = "fsl,qe", },
|
{ .compatible = "fsl,qe", },
|
||||||
{},
|
{},
|
||||||
|
@ -115,6 +115,7 @@ static void __init mpc832x_rdb_setup_arch(void)
|
|||||||
static struct of_device_id mpc832x_ids[] = {
|
static struct of_device_id mpc832x_ids[] = {
|
||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
{ .compatible = "soc", },
|
{ .compatible = "soc", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{ .type = "qe", },
|
{ .type = "qe", },
|
||||||
{ .compatible = "fsl,qe", },
|
{ .compatible = "fsl,qe", },
|
||||||
{},
|
{},
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
static struct of_device_id __initdata mpc834x_itx_ids[] = {
|
static struct of_device_id __initdata mpc834x_itx_ids[] = {
|
||||||
{ .compatible = "fsl,pq2pro-localbus", },
|
{ .compatible = "fsl,pq2pro-localbus", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ static void __init mpc834x_mds_init_IRQ(void)
|
|||||||
static struct of_device_id mpc834x_ids[] = {
|
static struct of_device_id mpc834x_ids[] = {
|
||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
{ .compatible = "soc", },
|
{ .compatible = "soc", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -136,6 +136,7 @@ static void __init mpc836x_mds_setup_arch(void)
|
|||||||
static struct of_device_id mpc836x_ids[] = {
|
static struct of_device_id mpc836x_ids[] = {
|
||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
{ .compatible = "soc", },
|
{ .compatible = "soc", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{ .type = "qe", },
|
{ .type = "qe", },
|
||||||
{ .compatible = "fsl,qe", },
|
{ .compatible = "fsl,qe", },
|
||||||
{},
|
{},
|
||||||
|
@ -83,6 +83,7 @@ static void __init sbc834x_init_IRQ(void)
|
|||||||
static struct __initdata of_device_id sbc834x_ids[] = {
|
static struct __initdata of_device_id sbc834x_ids[] = {
|
||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
{ .compatible = "soc", },
|
{ .compatible = "soc", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -222,6 +222,7 @@ static void ksi8560_show_cpuinfo(struct seq_file *m)
|
|||||||
|
|
||||||
static struct of_device_id __initdata of_bus_ids[] = {
|
static struct of_device_id __initdata of_bus_ids[] = {
|
||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
|
{ .type = "simple-bus", },
|
||||||
{ .name = "cpm", },
|
{ .name = "cpm", },
|
||||||
{ .name = "localbus", },
|
{ .name = "localbus", },
|
||||||
{},
|
{},
|
||||||
|
@ -91,6 +91,7 @@ static void __init mpc8536_ds_setup_arch(void)
|
|||||||
static struct of_device_id __initdata mpc8536_ds_ids[] = {
|
static struct of_device_id __initdata mpc8536_ds_ids[] = {
|
||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
{ .compatible = "soc", },
|
{ .compatible = "soc", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -230,6 +230,7 @@ static struct of_device_id __initdata of_bus_ids[] = {
|
|||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
{ .name = "cpm", },
|
{ .name = "cpm", },
|
||||||
{ .name = "localbus", },
|
{ .name = "localbus", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -186,6 +186,7 @@ static int __init mpc8544_ds_probe(void)
|
|||||||
static struct of_device_id __initdata mpc85xxds_ids[] = {
|
static struct of_device_id __initdata mpc85xxds_ids[] = {
|
||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
{ .compatible = "soc", },
|
{ .compatible = "soc", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -260,6 +260,7 @@ machine_arch_initcall(mpc85xx_mds, board_fixups);
|
|||||||
static struct of_device_id mpc85xx_ids[] = {
|
static struct of_device_id mpc85xx_ids[] = {
|
||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
{ .compatible = "soc", },
|
{ .compatible = "soc", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{ .type = "qe", },
|
{ .type = "qe", },
|
||||||
{ .compatible = "fsl,qe", },
|
{ .compatible = "fsl,qe", },
|
||||||
{},
|
{},
|
||||||
|
@ -217,6 +217,7 @@ static struct of_device_id __initdata of_bus_ids[] = {
|
|||||||
{ .type = "soc", },
|
{ .type = "soc", },
|
||||||
{ .name = "cpm", },
|
{ .name = "cpm", },
|
||||||
{ .name = "localbus", },
|
{ .name = "localbus", },
|
||||||
|
{ .compatible = "simple-bus", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,6 +105,16 @@ config 8xx_COPYBACK
|
|||||||
|
|
||||||
If in doubt, say Y here.
|
If in doubt, say Y here.
|
||||||
|
|
||||||
|
config 8xx_GPIO
|
||||||
|
bool "GPIO API Support"
|
||||||
|
select GENERIC_GPIO
|
||||||
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
|
help
|
||||||
|
Saying Y here will cause the ports on an MPC8xx processor to be used
|
||||||
|
with the GPIO API. If you say N here, the kernel needs less memory.
|
||||||
|
|
||||||
|
If in doubt, say Y here.
|
||||||
|
|
||||||
config 8xx_CPU6
|
config 8xx_CPU6
|
||||||
bool "CPU6 Silicon Errata (860 Pre Rev. C)"
|
bool "CPU6 Silicon Errata (860 Pre Rev. C)"
|
||||||
help
|
help
|
||||||
|
@ -254,6 +254,8 @@ config CPM2
|
|||||||
select CPM
|
select CPM
|
||||||
select PPC_LIB_RHEAP
|
select PPC_LIB_RHEAP
|
||||||
select PPC_PCI_CHOICE
|
select PPC_PCI_CHOICE
|
||||||
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
|
select GENERIC_GPIO
|
||||||
help
|
help
|
||||||
The CPM2 (Communications Processor Module) is a coprocessor on
|
The CPM2 (Communications Processor Module) is a coprocessor on
|
||||||
embedded CPUs made by Freescale. Selecting this option means that
|
embedded CPUs made by Freescale. Selecting this option means that
|
||||||
@ -281,6 +283,7 @@ config FSL_ULI1575
|
|||||||
|
|
||||||
config CPM
|
config CPM
|
||||||
bool
|
bool
|
||||||
|
select PPC_CLOCK
|
||||||
|
|
||||||
config OF_RTC
|
config OF_RTC
|
||||||
bool
|
bool
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/8xx_immap.h>
|
#include <asm/8xx_immap.h>
|
||||||
@ -42,6 +43,10 @@
|
|||||||
|
|
||||||
#include <asm/fs_pd.h>
|
#include <asm/fs_pd.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_8xx_GPIO
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CPM_MAP_SIZE (0x4000)
|
#define CPM_MAP_SIZE (0x4000)
|
||||||
|
|
||||||
cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */
|
cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */
|
||||||
@ -290,20 +295,24 @@ struct cpm_ioport16 {
|
|||||||
__be16 res[3];
|
__be16 res[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cpm_ioport32 {
|
struct cpm_ioport32b {
|
||||||
__be32 dir, par, sor;
|
__be32 dir, par, odr, dat;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cpm_ioport32e {
|
||||||
|
__be32 dir, par, sor, odr, dat;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void cpm1_set_pin32(int port, int pin, int flags)
|
static void cpm1_set_pin32(int port, int pin, int flags)
|
||||||
{
|
{
|
||||||
struct cpm_ioport32 __iomem *iop;
|
struct cpm_ioport32e __iomem *iop;
|
||||||
pin = 1 << (31 - pin);
|
pin = 1 << (31 - pin);
|
||||||
|
|
||||||
if (port == CPM_PORTB)
|
if (port == CPM_PORTB)
|
||||||
iop = (struct cpm_ioport32 __iomem *)
|
iop = (struct cpm_ioport32e __iomem *)
|
||||||
&mpc8xx_immr->im_cpm.cp_pbdir;
|
&mpc8xx_immr->im_cpm.cp_pbdir;
|
||||||
else
|
else
|
||||||
iop = (struct cpm_ioport32 __iomem *)
|
iop = (struct cpm_ioport32e __iomem *)
|
||||||
&mpc8xx_immr->im_cpm.cp_pedir;
|
&mpc8xx_immr->im_cpm.cp_pedir;
|
||||||
|
|
||||||
if (flags & CPM_PIN_OUTPUT)
|
if (flags & CPM_PIN_OUTPUT)
|
||||||
@ -498,3 +507,251 @@ int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GPIO LIB API implementation
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_8xx_GPIO
|
||||||
|
|
||||||
|
struct cpm1_gpio16_chip {
|
||||||
|
struct of_mm_gpio_chip mm_gc;
|
||||||
|
spinlock_t lock;
|
||||||
|
|
||||||
|
/* shadowed data register to clear/set bits safely */
|
||||||
|
u16 cpdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct cpm1_gpio16_chip *
|
||||||
|
to_cpm1_gpio16_chip(struct of_mm_gpio_chip *mm_gc)
|
||||||
|
{
|
||||||
|
return container_of(mm_gc, struct cpm1_gpio16_chip, mm_gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpm1_gpio16_save_regs(struct of_mm_gpio_chip *mm_gc)
|
||||||
|
{
|
||||||
|
struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
|
||||||
|
struct cpm_ioport16 __iomem *iop = mm_gc->regs;
|
||||||
|
|
||||||
|
cpm1_gc->cpdata = in_be16(&iop->dat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm_ioport16 __iomem *iop = mm_gc->regs;
|
||||||
|
u16 pin_mask;
|
||||||
|
|
||||||
|
pin_mask = 1 << (15 - gpio);
|
||||||
|
|
||||||
|
return !!(in_be16(&iop->dat) & pin_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);
|
||||||
|
struct cpm_ioport16 __iomem *iop = mm_gc->regs;
|
||||||
|
unsigned long flags;
|
||||||
|
u16 pin_mask = 1 << (15 - gpio);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&cpm1_gc->lock, flags);
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
cpm1_gc->cpdata |= pin_mask;
|
||||||
|
else
|
||||||
|
cpm1_gc->cpdata &= ~pin_mask;
|
||||||
|
|
||||||
|
out_be16(&iop->dat, cpm1_gc->cpdata);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&cpm1_gc->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm_ioport16 __iomem *iop = mm_gc->regs;
|
||||||
|
u16 pin_mask;
|
||||||
|
|
||||||
|
pin_mask = 1 << (15 - gpio);
|
||||||
|
|
||||||
|
setbits16(&iop->dir, pin_mask);
|
||||||
|
|
||||||
|
cpm1_gpio16_set(gc, gpio, val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm_ioport16 __iomem *iop = mm_gc->regs;
|
||||||
|
u16 pin_mask;
|
||||||
|
|
||||||
|
pin_mask = 1 << (15 - gpio);
|
||||||
|
|
||||||
|
clrbits16(&iop->dir, pin_mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpm1_gpiochip_add16(struct device_node *np)
|
||||||
|
{
|
||||||
|
struct cpm1_gpio16_chip *cpm1_gc;
|
||||||
|
struct of_mm_gpio_chip *mm_gc;
|
||||||
|
struct of_gpio_chip *of_gc;
|
||||||
|
struct gpio_chip *gc;
|
||||||
|
|
||||||
|
cpm1_gc = kzalloc(sizeof(*cpm1_gc), GFP_KERNEL);
|
||||||
|
if (!cpm1_gc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
spin_lock_init(&cpm1_gc->lock);
|
||||||
|
|
||||||
|
mm_gc = &cpm1_gc->mm_gc;
|
||||||
|
of_gc = &mm_gc->of_gc;
|
||||||
|
gc = &of_gc->gc;
|
||||||
|
|
||||||
|
mm_gc->save_regs = cpm1_gpio16_save_regs;
|
||||||
|
of_gc->gpio_cells = 2;
|
||||||
|
gc->ngpio = 16;
|
||||||
|
gc->direction_input = cpm1_gpio16_dir_in;
|
||||||
|
gc->direction_output = cpm1_gpio16_dir_out;
|
||||||
|
gc->get = cpm1_gpio16_get;
|
||||||
|
gc->set = cpm1_gpio16_set;
|
||||||
|
|
||||||
|
return of_mm_gpiochip_add(np, mm_gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cpm1_gpio32_chip {
|
||||||
|
struct of_mm_gpio_chip mm_gc;
|
||||||
|
spinlock_t lock;
|
||||||
|
|
||||||
|
/* shadowed data register to clear/set bits safely */
|
||||||
|
u32 cpdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct cpm1_gpio32_chip *
|
||||||
|
to_cpm1_gpio32_chip(struct of_mm_gpio_chip *mm_gc)
|
||||||
|
{
|
||||||
|
return container_of(mm_gc, struct cpm1_gpio32_chip, mm_gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpm1_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc)
|
||||||
|
{
|
||||||
|
struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
|
||||||
|
struct cpm_ioport32b __iomem *iop = mm_gc->regs;
|
||||||
|
|
||||||
|
cpm1_gc->cpdata = in_be32(&iop->dat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm_ioport32b __iomem *iop = mm_gc->regs;
|
||||||
|
u32 pin_mask;
|
||||||
|
|
||||||
|
pin_mask = 1 << (31 - gpio);
|
||||||
|
|
||||||
|
return !!(in_be32(&iop->dat) & pin_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);
|
||||||
|
struct cpm_ioport32b __iomem *iop = mm_gc->regs;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 pin_mask = 1 << (31 - gpio);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&cpm1_gc->lock, flags);
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
cpm1_gc->cpdata |= pin_mask;
|
||||||
|
else
|
||||||
|
cpm1_gc->cpdata &= ~pin_mask;
|
||||||
|
|
||||||
|
out_be32(&iop->dat, cpm1_gc->cpdata);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&cpm1_gc->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm_ioport32b __iomem *iop = mm_gc->regs;
|
||||||
|
u32 pin_mask;
|
||||||
|
|
||||||
|
pin_mask = 1 << (31 - gpio);
|
||||||
|
|
||||||
|
setbits32(&iop->dir, pin_mask);
|
||||||
|
|
||||||
|
cpm1_gpio32_set(gc, gpio, val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm_ioport32b __iomem *iop = mm_gc->regs;
|
||||||
|
u32 pin_mask;
|
||||||
|
|
||||||
|
pin_mask = 1 << (31 - gpio);
|
||||||
|
|
||||||
|
clrbits32(&iop->dir, pin_mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpm1_gpiochip_add32(struct device_node *np)
|
||||||
|
{
|
||||||
|
struct cpm1_gpio32_chip *cpm1_gc;
|
||||||
|
struct of_mm_gpio_chip *mm_gc;
|
||||||
|
struct of_gpio_chip *of_gc;
|
||||||
|
struct gpio_chip *gc;
|
||||||
|
|
||||||
|
cpm1_gc = kzalloc(sizeof(*cpm1_gc), GFP_KERNEL);
|
||||||
|
if (!cpm1_gc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
spin_lock_init(&cpm1_gc->lock);
|
||||||
|
|
||||||
|
mm_gc = &cpm1_gc->mm_gc;
|
||||||
|
of_gc = &mm_gc->of_gc;
|
||||||
|
gc = &of_gc->gc;
|
||||||
|
|
||||||
|
mm_gc->save_regs = cpm1_gpio32_save_regs;
|
||||||
|
of_gc->gpio_cells = 2;
|
||||||
|
gc->ngpio = 32;
|
||||||
|
gc->direction_input = cpm1_gpio32_dir_in;
|
||||||
|
gc->direction_output = cpm1_gpio32_dir_out;
|
||||||
|
gc->get = cpm1_gpio32_get;
|
||||||
|
gc->set = cpm1_gpio32_set;
|
||||||
|
|
||||||
|
return of_mm_gpiochip_add(np, mm_gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm_init_par_io(void)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
|
||||||
|
for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-a")
|
||||||
|
cpm1_gpiochip_add16(np);
|
||||||
|
|
||||||
|
for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-b")
|
||||||
|
cpm1_gpiochip_add32(np);
|
||||||
|
|
||||||
|
for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-c")
|
||||||
|
cpm1_gpiochip_add16(np);
|
||||||
|
|
||||||
|
for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-d")
|
||||||
|
cpm1_gpiochip_add16(np);
|
||||||
|
|
||||||
|
/* Port E uses CPM2 layout */
|
||||||
|
for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-e")
|
||||||
|
cpm2_gpiochip_add32(np);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
arch_initcall(cpm_init_par_io);
|
||||||
|
|
||||||
|
#endif /* CONFIG_8xx_GPIO */
|
||||||
|
@ -115,16 +115,10 @@ EXPORT_SYMBOL(cpm_command);
|
|||||||
* Baud rate clocks are zero-based in the driver code (as that maps
|
* Baud rate clocks are zero-based in the driver code (as that maps
|
||||||
* to port numbers). Documentation uses 1-based numbering.
|
* to port numbers). Documentation uses 1-based numbering.
|
||||||
*/
|
*/
|
||||||
#define BRG_INT_CLK (get_brgfreq())
|
void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src)
|
||||||
#define BRG_UART_CLK (BRG_INT_CLK/16)
|
|
||||||
|
|
||||||
/* This function is used by UARTS, or anything else that uses a 16x
|
|
||||||
* oversampled clock.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
cpm_setbrg(uint brg, uint rate)
|
|
||||||
{
|
{
|
||||||
u32 __iomem *bp;
|
u32 __iomem *bp;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
/* This is good enough to get SMCs running.....
|
/* This is good enough to get SMCs running.....
|
||||||
*/
|
*/
|
||||||
@ -135,34 +129,14 @@ cpm_setbrg(uint brg, uint rate)
|
|||||||
brg -= 4;
|
brg -= 4;
|
||||||
}
|
}
|
||||||
bp += brg;
|
bp += brg;
|
||||||
out_be32(bp, (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN);
|
val = (((clk / rate) - 1) << 1) | CPM_BRG_EN | src;
|
||||||
|
|
||||||
cpm2_unmap(bp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function is used to set high speed synchronous baud rate
|
|
||||||
* clocks.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
cpm2_fastbrg(uint brg, uint rate, int div16)
|
|
||||||
{
|
|
||||||
u32 __iomem *bp;
|
|
||||||
u32 val;
|
|
||||||
|
|
||||||
if (brg < 4) {
|
|
||||||
bp = cpm2_map_size(im_brgc1, 16);
|
|
||||||
} else {
|
|
||||||
bp = cpm2_map_size(im_brgc5, 16);
|
|
||||||
brg -= 4;
|
|
||||||
}
|
|
||||||
bp += brg;
|
|
||||||
val = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN;
|
|
||||||
if (div16)
|
if (div16)
|
||||||
val |= CPM_BRG_DIV16;
|
val |= CPM_BRG_DIV16;
|
||||||
|
|
||||||
out_be32(bp, val);
|
out_be32(bp, val);
|
||||||
cpm2_unmap(bp);
|
cpm2_unmap(bp);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(__cpm2_setbrg);
|
||||||
|
|
||||||
int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
|
int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
|
||||||
{
|
{
|
||||||
@ -377,3 +351,14 @@ void cpm2_set_pin(int port, int pin, int flags)
|
|||||||
else
|
else
|
||||||
clrbits32(&iop[port].odr, pin);
|
clrbits32(&iop[port].odr, pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cpm_init_par_io(void)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
|
||||||
|
for_each_compatible_node(np, NULL, "fsl,cpm2-pario-bank")
|
||||||
|
cpm2_gpiochip_add32(np);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
arch_initcall(cpm_init_par_io);
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
|
||||||
#include <asm/udbg.h>
|
#include <asm/udbg.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
@ -28,6 +30,10 @@
|
|||||||
|
|
||||||
#include <mm/mmu_decl.h>
|
#include <mm/mmu_decl.h>
|
||||||
|
|
||||||
|
#if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO)
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
|
#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
|
||||||
static u32 __iomem *cpm_udbg_txdesc =
|
static u32 __iomem *cpm_udbg_txdesc =
|
||||||
(u32 __iomem __force *)CONFIG_PPC_EARLY_DEBUG_CPM_ADDR;
|
(u32 __iomem __force *)CONFIG_PPC_EARLY_DEBUG_CPM_ADDR;
|
||||||
@ -207,3 +213,120 @@ dma_addr_t cpm_muram_dma(void __iomem *addr)
|
|||||||
return muram_pbase + ((u8 __iomem *)addr - muram_vbase);
|
return muram_pbase + ((u8 __iomem *)addr - muram_vbase);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cpm_muram_dma);
|
EXPORT_SYMBOL(cpm_muram_dma);
|
||||||
|
|
||||||
|
#if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO)
|
||||||
|
|
||||||
|
struct cpm2_ioports {
|
||||||
|
u32 dir, par, sor, odr, dat;
|
||||||
|
u32 res[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cpm2_gpio32_chip {
|
||||||
|
struct of_mm_gpio_chip mm_gc;
|
||||||
|
spinlock_t lock;
|
||||||
|
|
||||||
|
/* shadowed data register to clear/set bits safely */
|
||||||
|
u32 cpdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct cpm2_gpio32_chip *
|
||||||
|
to_cpm2_gpio32_chip(struct of_mm_gpio_chip *mm_gc)
|
||||||
|
{
|
||||||
|
return container_of(mm_gc, struct cpm2_gpio32_chip, mm_gc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpm2_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc)
|
||||||
|
{
|
||||||
|
struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
|
||||||
|
struct cpm2_ioports __iomem *iop = mm_gc->regs;
|
||||||
|
|
||||||
|
cpm2_gc->cpdata = in_be32(&iop->dat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm2_gpio32_get(struct gpio_chip *gc, unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm2_ioports __iomem *iop = mm_gc->regs;
|
||||||
|
u32 pin_mask;
|
||||||
|
|
||||||
|
pin_mask = 1 << (31 - gpio);
|
||||||
|
|
||||||
|
return !!(in_be32(&iop->dat) & pin_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpm2_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc);
|
||||||
|
struct cpm2_ioports __iomem *iop = mm_gc->regs;
|
||||||
|
unsigned long flags;
|
||||||
|
u32 pin_mask = 1 << (31 - gpio);
|
||||||
|
|
||||||
|
spin_lock_irqsave(&cpm2_gc->lock, flags);
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
cpm2_gc->cpdata |= pin_mask;
|
||||||
|
else
|
||||||
|
cpm2_gc->cpdata &= ~pin_mask;
|
||||||
|
|
||||||
|
out_be32(&iop->dat, cpm2_gc->cpdata);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&cpm2_gc->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm2_ioports __iomem *iop = mm_gc->regs;
|
||||||
|
u32 pin_mask;
|
||||||
|
|
||||||
|
pin_mask = 1 << (31 - gpio);
|
||||||
|
|
||||||
|
setbits32(&iop->dir, pin_mask);
|
||||||
|
|
||||||
|
cpm2_gpio32_set(gc, gpio, val);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cpm2_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
|
||||||
|
struct cpm2_ioports __iomem *iop = mm_gc->regs;
|
||||||
|
u32 pin_mask;
|
||||||
|
|
||||||
|
pin_mask = 1 << (31 - gpio);
|
||||||
|
|
||||||
|
clrbits32(&iop->dir, pin_mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cpm2_gpiochip_add32(struct device_node *np)
|
||||||
|
{
|
||||||
|
struct cpm2_gpio32_chip *cpm2_gc;
|
||||||
|
struct of_mm_gpio_chip *mm_gc;
|
||||||
|
struct of_gpio_chip *of_gc;
|
||||||
|
struct gpio_chip *gc;
|
||||||
|
|
||||||
|
cpm2_gc = kzalloc(sizeof(*cpm2_gc), GFP_KERNEL);
|
||||||
|
if (!cpm2_gc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
spin_lock_init(&cpm2_gc->lock);
|
||||||
|
|
||||||
|
mm_gc = &cpm2_gc->mm_gc;
|
||||||
|
of_gc = &mm_gc->of_gc;
|
||||||
|
gc = &of_gc->gc;
|
||||||
|
|
||||||
|
mm_gc->save_regs = cpm2_gpio32_save_regs;
|
||||||
|
of_gc->gpio_cells = 2;
|
||||||
|
gc->ngpio = 32;
|
||||||
|
gc->direction_input = cpm2_gpio32_dir_in;
|
||||||
|
gc->direction_output = cpm2_gpio32_dir_out;
|
||||||
|
gc->get = cpm2_gpio32_get;
|
||||||
|
gc->set = cpm2_gpio32_set;
|
||||||
|
|
||||||
|
return of_mm_gpiochip_add(np, mm_gc);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_CPM2 || CONFIG_8xx_GPIO */
|
||||||
|
@ -21,6 +21,7 @@ static int __init add_rtc(void)
|
|||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
struct platform_device *pd;
|
struct platform_device *pd;
|
||||||
struct resource res[2];
|
struct resource res[2];
|
||||||
|
unsigned int num_res = 1;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memset(&res, 0, sizeof(res));
|
memset(&res, 0, sizeof(res));
|
||||||
@ -41,14 +42,24 @@ static int __init add_rtc(void)
|
|||||||
if (res[0].start != RTC_PORT(0))
|
if (res[0].start != RTC_PORT(0))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Use a fixed interrupt value of 8 since on PPC if we are using this
|
np = of_find_compatible_node(NULL, NULL, "chrp,iic");
|
||||||
* its off an i8259 which we ensure has interrupt numbers 0..15. */
|
if (!np)
|
||||||
res[1].start = 8;
|
np = of_find_compatible_node(NULL, NULL, "pnpPNP,000");
|
||||||
res[1].end = 8;
|
if (np) {
|
||||||
res[1].flags = IORESOURCE_IRQ;
|
of_node_put(np);
|
||||||
|
/*
|
||||||
|
* Use a fixed interrupt value of 8 since on PPC if we are
|
||||||
|
* using this its off an i8259 which we ensure has interrupt
|
||||||
|
* numbers 0..15.
|
||||||
|
*/
|
||||||
|
res[1].start = 8;
|
||||||
|
res[1].end = 8;
|
||||||
|
res[1].flags = IORESOURCE_IRQ;
|
||||||
|
num_res++;
|
||||||
|
}
|
||||||
|
|
||||||
pd = platform_device_register_simple("rtc_cmos", -1,
|
pd = platform_device_register_simple("rtc_cmos", -1,
|
||||||
&res[0], 2);
|
&res[0], num_res);
|
||||||
|
|
||||||
if (IS_ERR(pd))
|
if (IS_ERR(pd))
|
||||||
return PTR_ERR(pd);
|
return PTR_ERR(pd);
|
||||||
|
@ -66,8 +66,8 @@
|
|||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_OF
|
#ifdef CONFIG_PPC_OF
|
||||||
#include <asm/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <asm/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PFX "ipmi_si: "
|
#define PFX "ipmi_si: "
|
||||||
|
@ -1086,6 +1086,11 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
|
|||||||
/* Make sure we have sane timings */
|
/* Make sure we have sane timings */
|
||||||
sanitize_timings(pmif);
|
sanitize_timings(pmif);
|
||||||
|
|
||||||
|
host = ide_host_alloc(&d, hws);
|
||||||
|
if (host == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
hwif = host->ports[0];
|
||||||
|
|
||||||
#ifndef CONFIG_PPC64
|
#ifndef CONFIG_PPC64
|
||||||
/* XXX FIXME: Media bay stuff need re-organizing */
|
/* XXX FIXME: Media bay stuff need re-organizing */
|
||||||
if (np->parent && np->parent->name
|
if (np->parent && np->parent->name
|
||||||
@ -1119,11 +1124,11 @@ static int __devinit pmac_ide_setup_device(pmac_ide_hwif_t *pmif, hw_regs_t *hw)
|
|||||||
pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
|
pmif->mdev ? "macio" : "PCI", pmif->aapl_bus_id,
|
||||||
pmif->mediabay ? " (mediabay)" : "", hw->irq);
|
pmif->mediabay ? " (mediabay)" : "", hw->irq);
|
||||||
|
|
||||||
rc = ide_host_add(&d, hws, &host);
|
rc = ide_host_register(host, &d, hws);
|
||||||
if (rc)
|
if (rc) {
|
||||||
|
ide_host_free(host);
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
hwif = host->ports[0];
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,15 @@
|
|||||||
|
|
||||||
#define SCC_WAIT_CLOSING 100
|
#define SCC_WAIT_CLOSING 100
|
||||||
|
|
||||||
|
#define GPIO_CTS 0
|
||||||
|
#define GPIO_RTS 1
|
||||||
|
#define GPIO_DCD 2
|
||||||
|
#define GPIO_DSR 3
|
||||||
|
#define GPIO_DTR 4
|
||||||
|
#define GPIO_RI 5
|
||||||
|
|
||||||
|
#define NUM_GPIOS (GPIO_RI+1)
|
||||||
|
|
||||||
struct uart_cpm_port {
|
struct uart_cpm_port {
|
||||||
struct uart_port port;
|
struct uart_port port;
|
||||||
u16 rx_nrfifos;
|
u16 rx_nrfifos;
|
||||||
@ -68,6 +77,7 @@ struct uart_cpm_port {
|
|||||||
unsigned char *rx_buf;
|
unsigned char *rx_buf;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
void (*set_lineif)(struct uart_cpm_port *);
|
void (*set_lineif)(struct uart_cpm_port *);
|
||||||
|
struct clk *clk;
|
||||||
u8 brg;
|
u8 brg;
|
||||||
uint dp_addr;
|
uint dp_addr;
|
||||||
void *mem_addr;
|
void *mem_addr;
|
||||||
@ -82,6 +92,7 @@ struct uart_cpm_port {
|
|||||||
int wait_closing;
|
int wait_closing;
|
||||||
/* value to combine with opcode to form cpm command */
|
/* value to combine with opcode to form cpm command */
|
||||||
u32 command;
|
u32 command;
|
||||||
|
int gpios[NUM_GPIOS];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int cpm_uart_nr;
|
extern int cpm_uart_nr;
|
||||||
|
@ -43,6 +43,9 @@
|
|||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/fs_uart_pd.h>
|
#include <linux/fs_uart_pd.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/gpio.h>
|
||||||
|
#include <linux/of_gpio.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
@ -96,13 +99,41 @@ static unsigned int cpm_uart_tx_empty(struct uart_port *port)
|
|||||||
|
|
||||||
static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
|
||||||
{
|
{
|
||||||
/* Whee. Do nothing. */
|
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||||
|
|
||||||
|
if (pinfo->gpios[GPIO_RTS] >= 0)
|
||||||
|
gpio_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS));
|
||||||
|
|
||||||
|
if (pinfo->gpios[GPIO_DTR] >= 0)
|
||||||
|
gpio_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR));
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
|
static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
|
||||||
{
|
{
|
||||||
/* Whee. Do nothing. */
|
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||||
return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
|
unsigned int mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
|
||||||
|
|
||||||
|
if (pinfo->gpios[GPIO_CTS] >= 0) {
|
||||||
|
if (gpio_get_value(pinfo->gpios[GPIO_CTS]))
|
||||||
|
mctrl &= ~TIOCM_CTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pinfo->gpios[GPIO_DSR] >= 0) {
|
||||||
|
if (gpio_get_value(pinfo->gpios[GPIO_DSR]))
|
||||||
|
mctrl &= ~TIOCM_DSR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pinfo->gpios[GPIO_DCD] >= 0) {
|
||||||
|
if (gpio_get_value(pinfo->gpios[GPIO_DCD]))
|
||||||
|
mctrl &= ~TIOCM_CAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pinfo->gpios[GPIO_RI] >= 0) {
|
||||||
|
if (!gpio_get_value(pinfo->gpios[GPIO_RI]))
|
||||||
|
mctrl |= TIOCM_RNG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mctrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -566,7 +597,10 @@ static void cpm_uart_set_termios(struct uart_port *port,
|
|||||||
out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
|
out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpm_set_brg(pinfo->brg - 1, baud);
|
if (pinfo->clk)
|
||||||
|
clk_set_rate(pinfo->clk, baud);
|
||||||
|
else
|
||||||
|
cpm_set_brg(pinfo->brg - 1, baud);
|
||||||
spin_unlock_irqrestore(&port->lock, flags);
|
spin_unlock_irqrestore(&port->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -991,14 +1025,23 @@ static int cpm_uart_init_port(struct device_node *np,
|
|||||||
void __iomem *mem, *pram;
|
void __iomem *mem, *pram;
|
||||||
int len;
|
int len;
|
||||||
int ret;
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
data = of_get_property(np, "fsl,cpm-brg", &len);
|
data = of_get_property(np, "clock", NULL);
|
||||||
if (!data || len != 4) {
|
if (data) {
|
||||||
printk(KERN_ERR "CPM UART %s has no/invalid "
|
struct clk *clk = clk_get(NULL, (const char*)data);
|
||||||
"fsl,cpm-brg property.\n", np->name);
|
if (!IS_ERR(clk))
|
||||||
return -EINVAL;
|
pinfo->clk = clk;
|
||||||
|
}
|
||||||
|
if (!pinfo->clk) {
|
||||||
|
data = of_get_property(np, "fsl,cpm-brg", &len);
|
||||||
|
if (!data || len != 4) {
|
||||||
|
printk(KERN_ERR "CPM UART %s has no/invalid "
|
||||||
|
"fsl,cpm-brg property.\n", np->name);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
pinfo->brg = *data;
|
||||||
}
|
}
|
||||||
pinfo->brg = *data;
|
|
||||||
|
|
||||||
data = of_get_property(np, "fsl,cpm-command", &len);
|
data = of_get_property(np, "fsl,cpm-command", &len);
|
||||||
if (!data || len != 4) {
|
if (!data || len != 4) {
|
||||||
@ -1050,6 +1093,9 @@ static int cpm_uart_init_port(struct device_node *np,
|
|||||||
goto out_pram;
|
goto out_pram;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_GPIOS; i++)
|
||||||
|
pinfo->gpios[i] = of_get_gpio(np, i);
|
||||||
|
|
||||||
return cpm_uart_request_port(&pinfo->port);
|
return cpm_uart_request_port(&pinfo->port);
|
||||||
|
|
||||||
out_pram:
|
out_pram:
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
|
||||||
/* Opcodes common to CPM1 and CPM2
|
/* Opcodes common to CPM1 and CPM2
|
||||||
*/
|
*/
|
||||||
@ -100,4 +101,6 @@ unsigned long cpm_muram_offset(void __iomem *addr);
|
|||||||
dma_addr_t cpm_muram_dma(void __iomem *addr);
|
dma_addr_t cpm_muram_dma(void __iomem *addr);
|
||||||
int cpm_command(u32 command, u8 opcode);
|
int cpm_command(u32 command, u8 opcode);
|
||||||
|
|
||||||
|
int cpm2_gpiochip_add32(struct device_node *np);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <asm/immap_cpm2.h>
|
#include <asm/immap_cpm2.h>
|
||||||
#include <asm/cpm.h>
|
#include <asm/cpm.h>
|
||||||
|
#include <sysdev/fsl_soc.h>
|
||||||
|
|
||||||
#ifdef CONFIG_PPC_85xx
|
#ifdef CONFIG_PPC_85xx
|
||||||
#define CPM_MAP_ADDR (get_immrbase() + 0x80000)
|
#define CPM_MAP_ADDR (get_immrbase() + 0x80000)
|
||||||
@ -93,10 +94,40 @@ extern cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor */
|
|||||||
#define cpm_dpfree cpm_muram_free
|
#define cpm_dpfree cpm_muram_free
|
||||||
#define cpm_dpram_addr cpm_muram_addr
|
#define cpm_dpram_addr cpm_muram_addr
|
||||||
|
|
||||||
extern void cpm_setbrg(uint brg, uint rate);
|
|
||||||
extern void cpm2_fastbrg(uint brg, uint rate, int div16);
|
|
||||||
extern void cpm2_reset(void);
|
extern void cpm2_reset(void);
|
||||||
|
|
||||||
|
/* Baud rate generators.
|
||||||
|
*/
|
||||||
|
#define CPM_BRG_RST ((uint)0x00020000)
|
||||||
|
#define CPM_BRG_EN ((uint)0x00010000)
|
||||||
|
#define CPM_BRG_EXTC_INT ((uint)0x00000000)
|
||||||
|
#define CPM_BRG_EXTC_CLK3_9 ((uint)0x00004000)
|
||||||
|
#define CPM_BRG_EXTC_CLK5_15 ((uint)0x00008000)
|
||||||
|
#define CPM_BRG_ATB ((uint)0x00002000)
|
||||||
|
#define CPM_BRG_CD_MASK ((uint)0x00001ffe)
|
||||||
|
#define CPM_BRG_DIV16 ((uint)0x00000001)
|
||||||
|
|
||||||
|
#define CPM2_BRG_INT_CLK (get_brgfreq())
|
||||||
|
#define CPM2_BRG_UART_CLK (CPM2_BRG_INT_CLK/16)
|
||||||
|
|
||||||
|
extern void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src);
|
||||||
|
|
||||||
|
/* This function is used by UARTS, or anything else that uses a 16x
|
||||||
|
* oversampled clock.
|
||||||
|
*/
|
||||||
|
static inline void cpm_setbrg(uint brg, uint rate)
|
||||||
|
{
|
||||||
|
__cpm2_setbrg(brg, rate, CPM2_BRG_UART_CLK, 0, CPM_BRG_EXTC_INT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function is used to set high speed synchronous baud rate
|
||||||
|
* clocks.
|
||||||
|
*/
|
||||||
|
static inline void cpm2_fastbrg(uint brg, uint rate, int div16)
|
||||||
|
{
|
||||||
|
__cpm2_setbrg(brg, rate, CPM2_BRG_INT_CLK, div16, CPM_BRG_EXTC_INT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Function code bits, usually generic to devices.
|
/* Function code bits, usually generic to devices.
|
||||||
*/
|
*/
|
||||||
#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */
|
#define CPMFCR_GBL ((u_char)0x20) /* Set memory snooping */
|
||||||
@ -195,17 +226,6 @@ typedef struct smc_uart {
|
|||||||
#define SMCM_TX ((unsigned char)0x02)
|
#define SMCM_TX ((unsigned char)0x02)
|
||||||
#define SMCM_RX ((unsigned char)0x01)
|
#define SMCM_RX ((unsigned char)0x01)
|
||||||
|
|
||||||
/* Baud rate generators.
|
|
||||||
*/
|
|
||||||
#define CPM_BRG_RST ((uint)0x00020000)
|
|
||||||
#define CPM_BRG_EN ((uint)0x00010000)
|
|
||||||
#define CPM_BRG_EXTC_INT ((uint)0x00000000)
|
|
||||||
#define CPM_BRG_EXTC_CLK3_9 ((uint)0x00004000)
|
|
||||||
#define CPM_BRG_EXTC_CLK5_15 ((uint)0x00008000)
|
|
||||||
#define CPM_BRG_ATB ((uint)0x00002000)
|
|
||||||
#define CPM_BRG_CD_MASK ((uint)0x00001ffe)
|
|
||||||
#define CPM_BRG_DIV16 ((uint)0x00000001)
|
|
||||||
|
|
||||||
/* SCCs.
|
/* SCCs.
|
||||||
*/
|
*/
|
||||||
#define SCC_GSMRH_IRP ((uint)0x00040000)
|
#define SCC_GSMRH_IRP ((uint)0x00040000)
|
||||||
|
@ -461,6 +461,8 @@ void pgtable_cache_init(void);
|
|||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long address);
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
||||||
#endif /* _ASM_POWERPC_PGTABLE_PPC64_H_ */
|
#endif /* _ASM_POWERPC_PGTABLE_PPC64_H_ */
|
||||||
|
@ -143,6 +143,29 @@ static inline int page_cache_get_speculative(struct page *page)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Same as above, but add instead of inc (could just be merged)
|
||||||
|
*/
|
||||||
|
static inline int page_cache_add_speculative(struct page *page, int count)
|
||||||
|
{
|
||||||
|
VM_BUG_ON(in_interrupt());
|
||||||
|
|
||||||
|
#if !defined(CONFIG_SMP) && defined(CONFIG_CLASSIC_RCU)
|
||||||
|
# ifdef CONFIG_PREEMPT
|
||||||
|
VM_BUG_ON(!in_atomic());
|
||||||
|
# endif
|
||||||
|
VM_BUG_ON(page_count(page) == 0);
|
||||||
|
atomic_add(count, &page->_count);
|
||||||
|
|
||||||
|
#else
|
||||||
|
if (unlikely(!atomic_add_unless(&page->_count, count, 0)))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
VM_BUG_ON(PageCompound(page) && page != compound_head(page));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int page_freeze_refs(struct page *page, int count)
|
static inline int page_freeze_refs(struct page *page, int count)
|
||||||
{
|
{
|
||||||
return likely(atomic_cmpxchg(&page->_count, count, 0) == count);
|
return likely(atomic_cmpxchg(&page->_count, count, 0) == count);
|
||||||
|
Loading…
Reference in New Issue
Block a user