forked from luck/tmp_suning_uos_patched
Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (25 commits) [POWERPC] Add support for the mpc832x mds board [POWERPC] Add initial support for the e300c2 core [POWERPC] Add MPC8360EMDS default dts file [POWERPC] Add MPC8360EMDS board support [POWERPC] Add QUICC Engine (QE) infrastructure [POWERPC] Add QE device tree node definition [POWERPC] Don't try to just continue if xmon has no input device [POWERPC] Fix a printk in pseries_mpic_init_IRQ [POWERPC] Get default baud rate in udbg_scc [POWERPC] Fix zImage.coff on oldworld PowerMac [POWERPC] Fix xmon=off and cleanup xmon initialisation [POWERPC] Cleanup include/asm-powerpc/xmon.h [POWERPC] Update swim3 printk after blkdev.h change [POWERPC] Cell interrupt rework POWERPC: mpc82xx merge: board-specific/platform stuff(resend) POWERPC: 8272ads merge to powerpc: common stuff POWERPC: Added devicetree for mpc8272ads board [POWERPC] iSeries has no legacy I/O [POWERPC] implement BEGIN/END_FW_FTR_SECTION [POWERPC] iSeries does not need pcibios_fixup_resources ...
This commit is contained in:
commit
13bbd8d906
|
@ -1440,6 +1440,258 @@ platforms are moved over to use the flattened-device-tree model.
|
|||
descriptor-types-mask = <012b0ebf>;
|
||||
};
|
||||
|
||||
h) Board Control and Status (BCSR)
|
||||
|
||||
Required properties:
|
||||
|
||||
- device_type : Should be "board-control"
|
||||
- reg : Offset and length of the register set for the device
|
||||
|
||||
Example:
|
||||
|
||||
bcsr@f8000000 {
|
||||
device_type = "board-control";
|
||||
reg = <f8000000 8000>;
|
||||
};
|
||||
|
||||
i) Freescale QUICC Engine module (QE)
|
||||
This represents qe module that is installed on PowerQUICC II Pro.
|
||||
Hopefully it will merge backward compatibility with CPM/CPM2.
|
||||
Basically, it is a bus of devices, that could act more or less
|
||||
as a complete entity (UCC, USB etc ). All of them should be siblings on
|
||||
the "root" qe node, using the common properties from there.
|
||||
The description below applies to the the qe of MPC8360 and
|
||||
more nodes and properties would be extended in the future.
|
||||
|
||||
i) Root QE device
|
||||
|
||||
Required properties:
|
||||
- device_type : should be "qe";
|
||||
- model : precise model of the QE, Can be "QE", "CPM", or "CPM2"
|
||||
- reg : offset and length of the device registers.
|
||||
- bus-frequency : the clock frequency for QUICC Engine.
|
||||
|
||||
Recommended properties
|
||||
- brg-frequency : the internal clock source frequency for baud-rate
|
||||
generators in Hz.
|
||||
|
||||
Example:
|
||||
qe@e0100000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#interrupt-cells = <2>;
|
||||
device_type = "qe";
|
||||
model = "QE";
|
||||
ranges = <0 e0100000 00100000>;
|
||||
reg = <e0100000 480>;
|
||||
brg-frequency = <0>;
|
||||
bus-frequency = <179A7B00>;
|
||||
}
|
||||
|
||||
|
||||
ii) SPI (Serial Peripheral Interface)
|
||||
|
||||
Required properties:
|
||||
- device_type : should be "spi".
|
||||
- compatible : should be "fsl_spi".
|
||||
- mode : the spi operation mode, it can be "cpu" or "qe".
|
||||
- reg : Offset and length of the register set for the device
|
||||
- interrupts : <a b> where a is the interrupt number and b is a
|
||||
field that represents an encoding of the sense and level
|
||||
information for the interrupt. This should be encoded based on
|
||||
the information in section 2) depending on the type of interrupt
|
||||
controller you have.
|
||||
- interrupt-parent : the phandle for the interrupt controller that
|
||||
services interrupts for this device.
|
||||
|
||||
Example:
|
||||
spi@4c0 {
|
||||
device_type = "spi";
|
||||
compatible = "fsl_spi";
|
||||
reg = <4c0 40>;
|
||||
interrupts = <82 0>;
|
||||
interrupt-parent = <700>;
|
||||
mode = "cpu";
|
||||
};
|
||||
|
||||
|
||||
iii) USB (Universal Serial Bus Controller)
|
||||
|
||||
Required properties:
|
||||
- device_type : should be "usb".
|
||||
- compatible : could be "qe_udc" or "fhci-hcd".
|
||||
- mode : the could be "host" or "slave".
|
||||
- reg : Offset and length of the register set for the device
|
||||
- interrupts : <a b> where a is the interrupt number and b is a
|
||||
field that represents an encoding of the sense and level
|
||||
information for the interrupt. This should be encoded based on
|
||||
the information in section 2) depending on the type of interrupt
|
||||
controller you have.
|
||||
- interrupt-parent : the phandle for the interrupt controller that
|
||||
services interrupts for this device.
|
||||
|
||||
Example(slave):
|
||||
usb@6c0 {
|
||||
device_type = "usb";
|
||||
compatible = "qe_udc";
|
||||
reg = <6c0 40>;
|
||||
interrupts = <8b 0>;
|
||||
interrupt-parent = <700>;
|
||||
mode = "slave";
|
||||
};
|
||||
|
||||
|
||||
iv) UCC (Unified Communications Controllers)
|
||||
|
||||
Required properties:
|
||||
- device_type : should be "network", "hldc", "uart", "transparent"
|
||||
"bisync" or "atm".
|
||||
- compatible : could be "ucc_geth" or "fsl_atm" and so on.
|
||||
- model : should be "UCC".
|
||||
- device-id : the ucc number(1-8), corresponding to UCCx in UM.
|
||||
- reg : Offset and length of the register set for the device
|
||||
- interrupts : <a b> where a is the interrupt number and b is a
|
||||
field that represents an encoding of the sense and level
|
||||
information for the interrupt. This should be encoded based on
|
||||
the information in section 2) depending on the type of interrupt
|
||||
controller you have.
|
||||
- interrupt-parent : the phandle for the interrupt controller that
|
||||
services interrupts for this device.
|
||||
- pio-handle : The phandle for the Parallel I/O port configuration.
|
||||
- rx-clock : represents the UCC receive clock source.
|
||||
0x00 : clock source is disabled;
|
||||
0x1~0x10 : clock source is BRG1~BRG16 respectively;
|
||||
0x11~0x28: clock source is QE_CLK1~QE_CLK24 respectively.
|
||||
- tx-clock: represents the UCC transmit clock source;
|
||||
0x00 : clock source is disabled;
|
||||
0x1~0x10 : clock source is BRG1~BRG16 respectively;
|
||||
0x11~0x28: clock source is QE_CLK1~QE_CLK24 respectively.
|
||||
|
||||
Required properties for network device_type:
|
||||
- mac-address : list of bytes representing the ethernet address.
|
||||
- phy-handle : The phandle for the PHY connected to this controller.
|
||||
|
||||
Example:
|
||||
ucc@2000 {
|
||||
device_type = "network";
|
||||
compatible = "ucc_geth";
|
||||
model = "UCC";
|
||||
device-id = <1>;
|
||||
reg = <2000 200>;
|
||||
interrupts = <a0 0>;
|
||||
interrupt-parent = <700>;
|
||||
mac-address = [ 00 04 9f 00 23 23 ];
|
||||
rx-clock = "none";
|
||||
tx-clock = "clk9";
|
||||
phy-handle = <212000>;
|
||||
pio-handle = <140001>;
|
||||
};
|
||||
|
||||
|
||||
v) Parallel I/O Ports
|
||||
|
||||
This node configures Parallel I/O ports for CPUs with QE support.
|
||||
The node should reside in the "soc" node of the tree. For each
|
||||
device that using parallel I/O ports, a child node should be created.
|
||||
See the definition of the Pin configuration nodes below for more
|
||||
information.
|
||||
|
||||
Required properties:
|
||||
- device_type : should be "par_io".
|
||||
- reg : offset to the register set and its length.
|
||||
- num-ports : number of Parallel I/O ports
|
||||
|
||||
Example:
|
||||
par_io@1400 {
|
||||
reg = <1400 100>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
device_type = "par_io";
|
||||
num-ports = <7>;
|
||||
ucc_pin@01 {
|
||||
......
|
||||
};
|
||||
|
||||
|
||||
vi) Pin configuration nodes
|
||||
|
||||
Required properties:
|
||||
- linux,phandle : phandle of this node; likely referenced by a QE
|
||||
device.
|
||||
- pio-map : array of pin configurations. Each pin is defined by 6
|
||||
integers. The six numbers are respectively: port, pin, dir,
|
||||
open_drain, assignment, has_irq.
|
||||
- port : port number of the pin; 0-6 represent port A-G in UM.
|
||||
- pin : pin number in the port.
|
||||
- dir : direction of the pin, should encode as follows:
|
||||
|
||||
0 = The pin is disabled
|
||||
1 = The pin is an output
|
||||
2 = The pin is an input
|
||||
3 = The pin is I/O
|
||||
|
||||
- open_drain : indicates the pin is normal or wired-OR:
|
||||
|
||||
0 = The pin is actively driven as an output
|
||||
1 = The pin is an open-drain driver. As an output, the pin is
|
||||
driven active-low, otherwise it is three-stated.
|
||||
|
||||
- assignment : function number of the pin according to the Pin Assignment
|
||||
tables in User Manual. Each pin can have up to 4 possible functions in
|
||||
QE and two options for CPM.
|
||||
- has_irq : indicates if the pin is used as source of exteral
|
||||
interrupts.
|
||||
|
||||
Example:
|
||||
ucc_pin@01 {
|
||||
linux,phandle = <140001>;
|
||||
pio-map = <
|
||||
/* port pin dir open_drain assignment has_irq */
|
||||
0 3 1 0 1 0 /* TxD0 */
|
||||
0 4 1 0 1 0 /* TxD1 */
|
||||
0 5 1 0 1 0 /* TxD2 */
|
||||
0 6 1 0 1 0 /* TxD3 */
|
||||
1 6 1 0 3 0 /* TxD4 */
|
||||
1 7 1 0 1 0 /* TxD5 */
|
||||
1 9 1 0 2 0 /* TxD6 */
|
||||
1 a 1 0 2 0 /* TxD7 */
|
||||
0 9 2 0 1 0 /* RxD0 */
|
||||
0 a 2 0 1 0 /* RxD1 */
|
||||
0 b 2 0 1 0 /* RxD2 */
|
||||
0 c 2 0 1 0 /* RxD3 */
|
||||
0 d 2 0 1 0 /* RxD4 */
|
||||
1 1 2 0 2 0 /* RxD5 */
|
||||
1 0 2 0 2 0 /* RxD6 */
|
||||
1 4 2 0 2 0 /* RxD7 */
|
||||
0 7 1 0 1 0 /* TX_EN */
|
||||
0 8 1 0 1 0 /* TX_ER */
|
||||
0 f 2 0 1 0 /* RX_DV */
|
||||
0 10 2 0 1 0 /* RX_ER */
|
||||
0 0 2 0 1 0 /* RX_CLK */
|
||||
2 9 1 0 3 0 /* GTX_CLK - CLK10 */
|
||||
2 8 2 0 1 0>; /* GTX125 - CLK9 */
|
||||
};
|
||||
|
||||
vii) Multi-User RAM (MURAM)
|
||||
|
||||
Required properties:
|
||||
- device_type : should be "muram".
|
||||
- mode : the could be "host" or "slave".
|
||||
- ranges : Should be defined as specified in 1) to describe the
|
||||
translation of MURAM addresses.
|
||||
- data-only : sub-node which defines the address area under MURAM
|
||||
bus that can be allocated as data/parameter
|
||||
|
||||
Example:
|
||||
|
||||
muram@10000 {
|
||||
device_type = "muram";
|
||||
ranges = <0 00010000 0000c000>;
|
||||
|
||||
data-only@0{
|
||||
reg = <0 c000>;
|
||||
};
|
||||
};
|
||||
|
||||
More devices will be defined as this spec matures.
|
||||
|
||||
|
|
|
@ -338,10 +338,6 @@ config PPC_MULTIPLATFORM
|
|||
RS/6000 machine, an Apple machine, or a PReP, CHRP,
|
||||
Maple or Cell-based machine.
|
||||
|
||||
config PPC_ISERIES
|
||||
bool "IBM Legacy iSeries"
|
||||
depends on PPC64
|
||||
|
||||
config EMBEDDED6xx
|
||||
bool "Embedded 6xx/7xx/7xxx-based board"
|
||||
depends on PPC32 && (BROKEN||BROKEN_ON_SMP)
|
||||
|
@ -355,6 +351,16 @@ config APUS
|
|||
<http://linux-apus.sourceforge.net/>.
|
||||
endchoice
|
||||
|
||||
config QUICC_ENGINE
|
||||
bool
|
||||
depends on PPC_MPC836x || PPC_MPC832x
|
||||
default y
|
||||
help
|
||||
The QUICC Engine (QE) is a new generation of communications
|
||||
coprocessors on Freescale embedded CPUs (akin to CPM in older chips).
|
||||
Selecting this option means that you wish to build a kernel
|
||||
for a machine with a QE coprocessor.
|
||||
|
||||
config PPC_PSERIES
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
bool "IBM pSeries & new (POWER5-based) iSeries"
|
||||
|
@ -365,6 +371,10 @@ config PPC_PSERIES
|
|||
select PPC_UDBG_16550
|
||||
default y
|
||||
|
||||
config PPC_ISERIES
|
||||
bool "IBM Legacy iSeries"
|
||||
depends on PPC_MULTIPLATFORM && PPC64
|
||||
|
||||
config PPC_CHRP
|
||||
bool "Common Hardware Reference Platform (CHRP) based machines"
|
||||
depends on PPC_MULTIPLATFORM && PPC32
|
||||
|
@ -594,6 +604,7 @@ endmenu
|
|||
|
||||
source arch/powerpc/platforms/embedded6xx/Kconfig
|
||||
source arch/powerpc/platforms/4xx/Kconfig
|
||||
source arch/powerpc/platforms/82xx/Kconfig
|
||||
source arch/powerpc/platforms/83xx/Kconfig
|
||||
source arch/powerpc/platforms/85xx/Kconfig
|
||||
source arch/powerpc/platforms/86xx/Kconfig
|
||||
|
@ -1058,6 +1069,8 @@ source "fs/Kconfig"
|
|||
|
||||
# XXX source "arch/ppc/8260_io/Kconfig"
|
||||
|
||||
source "arch/powerpc/sysdev/qe_lib/Kconfig"
|
||||
|
||||
source "arch/powerpc/platforms/iseries/Kconfig"
|
||||
|
||||
source "lib/Kconfig"
|
||||
|
|
223
arch/powerpc/boot/dts/mpc8272ads.dts
Normal file
223
arch/powerpc/boot/dts/mpc8272ads.dts
Normal file
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* MPC8272 ADS Device Tree Source
|
||||
*
|
||||
* Copyright 2005 Freescale Semiconductor Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
/ {
|
||||
model = "MPC8272ADS";
|
||||
compatible = "MPC8260ADS";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
linux,phandle = <100>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
linux,phandle = <200>;
|
||||
|
||||
PowerPC,8272@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
d-cache-line-size = <20>; // 32 bytes
|
||||
i-cache-line-size = <20>; // 32 bytes
|
||||
d-cache-size = <4000>; // L1, 16K
|
||||
i-cache-size = <4000>; // L1, 16K
|
||||
timebase-frequency = <0>;
|
||||
bus-frequency = <0>;
|
||||
clock-frequency = <0>;
|
||||
32-bit;
|
||||
linux,phandle = <201>;
|
||||
linux,boot-cpu;
|
||||
};
|
||||
};
|
||||
|
||||
interrupt-controller@f8200000 {
|
||||
linux,phandle = <f8200000>;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
reg = <f8200000 f8200004>;
|
||||
built-in;
|
||||
device_type = "pci-pic";
|
||||
};
|
||||
memory {
|
||||
device_type = "memory";
|
||||
linux,phandle = <300>;
|
||||
reg = <00000000 4000000 f4500000 00000020>;
|
||||
};
|
||||
|
||||
soc8272@f0000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#interrupt-cells = <2>;
|
||||
device_type = "soc";
|
||||
ranges = < 0 0 2 00000000 f0000000 00053000>;
|
||||
reg = <f0000000 0>;
|
||||
|
||||
mdio@0 {
|
||||
device_type = "mdio";
|
||||
compatible = "fs_enet";
|
||||
reg = <0 0>;
|
||||
linux,phandle = <24520>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
ethernet-phy@0 {
|
||||
linux,phandle = <2452000>;
|
||||
interrupt-parent = <10c00>;
|
||||
interrupts = <19 1>;
|
||||
reg = <0>;
|
||||
bitbang = [ 12 12 13 02 02 01 ];
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
ethernet-phy@1 {
|
||||
linux,phandle = <2452001>;
|
||||
interrupt-parent = <10c00>;
|
||||
interrupts = <19 1>;
|
||||
bitbang = [ 12 12 13 02 02 01 ];
|
||||
reg = <3>;
|
||||
device_type = "ethernet-phy";
|
||||
};
|
||||
};
|
||||
|
||||
ethernet@24000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
device_type = "network";
|
||||
device-id = <2>;
|
||||
compatible = "fs_enet";
|
||||
model = "FCC";
|
||||
reg = <11300 20 8400 100 11380 30>;
|
||||
mac-address = [ 00 11 2F 99 43 54 ];
|
||||
interrupts = <20 2>;
|
||||
interrupt-parent = <10c00>;
|
||||
phy-handle = <2452000>;
|
||||
rx-clock = <13>;
|
||||
tx-clock = <12>;
|
||||
};
|
||||
|
||||
ethernet@25000 {
|
||||
device_type = "network";
|
||||
device-id = <3>;
|
||||
compatible = "fs_enet";
|
||||
model = "FCC";
|
||||
reg = <11320 20 8500 100 113b0 30>;
|
||||
mac-address = [ 00 11 2F 99 44 54 ];
|
||||
interrupts = <21 2>;
|
||||
interrupt-parent = <10c00>;
|
||||
phy-handle = <2452001>;
|
||||
rx-clock = <17>;
|
||||
tx-clock = <18>;
|
||||
};
|
||||
|
||||
cpm@f0000000 {
|
||||
linux,phandle = <f0000000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#interrupt-cells = <2>;
|
||||
device_type = "cpm";
|
||||
model = "CPM2";
|
||||
ranges = <00000000 00000000 3ffff>;
|
||||
reg = <10d80 3280>;
|
||||
command-proc = <119c0>;
|
||||
brg-frequency = <17D7840>;
|
||||
cpm_clk = <BEBC200>;
|
||||
|
||||
scc@11a00 {
|
||||
device_type = "serial";
|
||||
compatible = "cpm_uart";
|
||||
model = "SCC";
|
||||
device-id = <2>;
|
||||
reg = <11a00 20 8000 100>;
|
||||
current-speed = <1c200>;
|
||||
interrupts = <28 2>;
|
||||
interrupt-parent = <10c00>;
|
||||
clock-setup = <0 00ffffff>;
|
||||
rx-clock = <1>;
|
||||
tx-clock = <1>;
|
||||
};
|
||||
|
||||
scc@11a60 {
|
||||
device_type = "serial";
|
||||
compatible = "cpm_uart";
|
||||
model = "SCC";
|
||||
device-id = <5>;
|
||||
reg = <11a60 20 8300 100>;
|
||||
current-speed = <1c200>;
|
||||
interrupts = <2b 2>;
|
||||
interrupt-parent = <10c00>;
|
||||
clock-setup = <1b ffffff00>;
|
||||
rx-clock = <4>;
|
||||
tx-clock = <4>;
|
||||
};
|
||||
|
||||
};
|
||||
interrupt-controller@10c00 {
|
||||
linux,phandle = <10c00>;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
interrupt-controller;
|
||||
reg = <10c00 80>;
|
||||
built-in;
|
||||
device_type = "cpm-pic";
|
||||
compatible = "CPM2";
|
||||
};
|
||||
pci@0500 {
|
||||
linux,phandle = <0500>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
compatible = "8272";
|
||||
device_type = "pci";
|
||||
reg = <10430 4dc>;
|
||||
clock-frequency = <3f940aa>;
|
||||
interrupt-map-mask = <f800 0 0 7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x16 */
|
||||
b000 0 0 1 f8200000 40 0
|
||||
b000 0 0 2 f8200000 41 0
|
||||
b000 0 0 3 f8200000 42 0
|
||||
b000 0 0 4 f8200000 43 0
|
||||
|
||||
/* IDSEL 0x17 */
|
||||
b800 0 0 1 f8200000 43 0
|
||||
b800 0 0 2 f8200000 40 0
|
||||
b800 0 0 3 f8200000 41 0
|
||||
b800 0 0 4 f8200000 42 0
|
||||
|
||||
/* IDSEL 0x18 */
|
||||
c000 0 0 1 f8200000 42 0
|
||||
c000 0 0 2 f8200000 43 0
|
||||
c000 0 0 3 f8200000 40 0
|
||||
c000 0 0 4 f8200000 41 0>;
|
||||
interrupt-parent = <10c00>;
|
||||
interrupts = <14 3>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <02000000 0 80000000 80000000 0 40000000
|
||||
01000000 0 00000000 f6000000 0 02000000>;
|
||||
};
|
||||
|
||||
/* May need to remove if on a part without crypto engine */
|
||||
crypto@30000 {
|
||||
device_type = "crypto";
|
||||
model = "SEC2";
|
||||
compatible = "talitos";
|
||||
reg = <30000 10000>;
|
||||
interrupts = <b 0>;
|
||||
interrupt-parent = <10c00>;
|
||||
num-channels = <4>;
|
||||
channel-fifo-len = <18>;
|
||||
exec-units-mask = <0000007e>;
|
||||
/* desc mask is for rev1.x, we need runtime fixup for >=2.x */
|
||||
descriptor-types-mask = <01010ebf>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
375
arch/powerpc/boot/dts/mpc8360emds.dts
Normal file
375
arch/powerpc/boot/dts/mpc8360emds.dts
Normal file
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
* MPC8360E EMDS Device Tree Source
|
||||
*
|
||||
* Copyright 2006 Freescale Semiconductor Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
/memreserve/ 00000000 1000000;
|
||||
*/
|
||||
|
||||
/ {
|
||||
model = "MPC8360EPB";
|
||||
compatible = "MPC83xx";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
linux,phandle = <100>;
|
||||
|
||||
cpus {
|
||||
#cpus = <1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
linux,phandle = <200>;
|
||||
|
||||
PowerPC,8360@0 {
|
||||
device_type = "cpu";
|
||||
reg = <0>;
|
||||
d-cache-line-size = <20>; // 32 bytes
|
||||
i-cache-line-size = <20>; // 32 bytes
|
||||
d-cache-size = <8000>; // L1, 32K
|
||||
i-cache-size = <8000>; // L1, 32K
|
||||
timebase-frequency = <3EF1480>;
|
||||
bus-frequency = <FBC5200>;
|
||||
clock-frequency = <1F78A400>;
|
||||
32-bit;
|
||||
linux,phandle = <201>;
|
||||
linux,boot-cpu;
|
||||
};
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
linux,phandle = <300>;
|
||||
reg = <00000000 10000000>;
|
||||
};
|
||||
|
||||
bcsr@f8000000 {
|
||||
device_type = "board-control";
|
||||
reg = <f8000000 8000>;
|
||||
};
|
||||
|
||||
soc8360@e0000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
#interrupt-cells = <2>;
|
||||
device_type = "soc";
|
||||
ranges = <0 e0000000 00100000>;
|
||||
reg = <e0000000 00000200>;
|
||||
bus-frequency = <FBC5200>;
|
||||
|
||||
wdt@200 {
|
||||
device_type = "watchdog";
|
||||
compatible = "mpc83xx_wdt";
|
||||
reg = <200 100>;
|
||||
};
|
||||
|
||||
i2c@3000 {
|
||||
device_type = "i2c";
|
||||
compatible = "fsl-i2c";
|
||||
reg = <3000 100>;
|
||||
interrupts = <e 8>;
|
||||
interrupt-parent = <700>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
i2c@3100 {
|
||||
device_type = "i2c";
|
||||
compatible = "fsl-i2c";
|
||||
reg = <3100 100>;
|
||||
interrupts = <f 8>;
|
||||
interrupt-parent = <700>;
|
||||
dfsrr;
|
||||
};
|
||||
|
||||
serial@4500 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <4500 100>;
|
||||
clock-frequency = <FBC5200>;
|
||||
interrupts = <9 8>;
|
||||
interrupt-parent = <700>;
|
||||
};
|
||||
|
||||
serial@4600 {
|
||||
device_type = "serial";
|
||||
compatible = "ns16550";
|
||||
reg = <4600 100>;
|
||||
clock-frequency = <FBC5200>;
|
||||
interrupts = <a 8>;
|
||||
interrupt-parent = <700>;
|
||||
};
|
||||
|
||||
crypto@30000 {
|
||||
device_type = "crypto";
|
||||
model = "SEC2";
|
||||
compatible = "talitos";
|
||||
reg = <30000 10000>;
|
||||
interrupts = <b 8>;
|
||||
interrupt-parent = <700>;
|
||||
num-channels = <4>;
|
||||
channel-fifo-len = <18>;
|
||||
exec-units-mask = <0000007e>;
|
||||
/* desc mask is for rev1.x, we need runtime fixup for >=2.x */
|
||||
descriptor-types-mask = <01010ebf>;
|
||||
};
|
||||
|
||||
pci@8500 {
|
||||
linux,phandle = <8500>;
|
||||
interrupt-map-mask = <f800 0 0 7>;
|
||||
interrupt-map = <
|
||||
|
||||
/* IDSEL 0x11 AD17 */
|
||||
8800 0 0 1 700 14 8
|
||||
8800 0 0 2 700 15 8
|
||||
8800 0 0 3 700 16 8
|
||||
8800 0 0 4 700 17 8
|
||||
|
||||
/* IDSEL 0x12 AD18 */
|
||||
9000 0 0 1 700 16 8
|
||||
9000 0 0 2 700 17 8
|
||||
9000 0 0 3 700 14 8
|
||||
9000 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x13 AD19 */
|
||||
9800 0 0 1 700 17 8
|
||||
9800 0 0 2 700 14 8
|
||||
9800 0 0 3 700 15 8
|
||||
9800 0 0 4 700 16 8
|
||||
|
||||
/* IDSEL 0x15 AD21*/
|
||||
a800 0 0 1 700 14 8
|
||||
a800 0 0 2 700 15 8
|
||||
a800 0 0 3 700 16 8
|
||||
a800 0 0 4 700 17 8
|
||||
|
||||
/* IDSEL 0x16 AD22*/
|
||||
b000 0 0 1 700 17 8
|
||||
b000 0 0 2 700 14 8
|
||||
b000 0 0 3 700 15 8
|
||||
b000 0 0 4 700 16 8
|
||||
|
||||
/* IDSEL 0x17 AD23*/
|
||||
b800 0 0 1 700 16 8
|
||||
b800 0 0 2 700 17 8
|
||||
b800 0 0 3 700 14 8
|
||||
b800 0 0 4 700 15 8
|
||||
|
||||
/* IDSEL 0x18 AD24*/
|
||||
c000 0 0 1 700 15 8
|
||||
c000 0 0 2 700 16 8
|
||||
c000 0 0 3 700 17 8
|
||||
c000 0 0 4 700 14 8>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <42 8>;
|
||||
bus-range = <0 0>;
|
||||
ranges = <02000000 0 a0000000 a0000000 0 10000000
|
||||
42000000 0 80000000 80000000 0 10000000
|
||||
01000000 0 00000000 e2000000 0 00100000>;
|
||||
clock-frequency = <3f940aa>;
|
||||
#interrupt-cells = <1>;
|
||||
#size-cells = <2>;
|
||||
#address-cells = <3>;
|
||||
reg = <8500 100>;
|
||||
compatible = "83xx";
|
||||
device_type = "pci";
|
||||
};
|
||||
|
||||
pic@700 {
|
||||
linux,phandle = <700>;
|
||||
interrupt-controller;
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <2>;
|
||||
reg = <700 100>;
|
||||
built-in;
|
||||
device_type = "ipic";
|
||||
};
|
||||
|
||||
par_io@1400 {
|
||||
reg = <1400 100>;
|
||||
device_type = "par_io";
|
||||
num-ports = <7>;
|
||||
|
||||
ucc_pin@01 {
|
||||
linux,phandle = <140001>;
|
||||
pio-map = <
|
||||
/* port pin dir open_drain assignment has_irq */
|
||||
0 3 1 0 1 0 /* TxD0 */
|
||||
0 4 1 0 1 0 /* TxD1 */
|
||||
0 5 1 0 1 0 /* TxD2 */
|
||||
0 6 1 0 1 0 /* TxD3 */
|
||||
1 6 1 0 3 0 /* TxD4 */
|
||||
1 7 1 0 1 0 /* TxD5 */
|
||||
1 9 1 0 2 0 /* TxD6 */
|
||||
1 a 1 0 2 0 /* TxD7 */
|
||||
0 9 2 0 1 0 /* RxD0 */
|
||||
0 a 2 0 1 0 /* RxD1 */
|
||||
0 b 2 0 1 0 /* RxD2 */
|
||||
0 c 2 0 1 0 /* RxD3 */
|
||||
0 d 2 0 1 0 /* RxD4 */
|
||||
1 1 2 0 2 0 /* RxD5 */
|
||||
1 0 2 0 2 0 /* RxD6 */
|
||||
1 4 2 0 2 0 /* RxD7 */
|
||||
0 7 1 0 1 0 /* TX_EN */
|
||||
0 8 1 0 1 0 /* TX_ER */
|
||||
0 f 2 0 1 0 /* RX_DV */
|
||||
0 10 2 0 1 0 /* RX_ER */
|
||||
0 0 2 0 1 0 /* RX_CLK */
|
||||
2 9 1 0 3 0 /* GTX_CLK - CLK10 */
|
||||
2 8 2 0 1 0>; /* GTX125 - CLK9 */
|
||||
};
|
||||
ucc_pin@02 {
|
||||
linux,phandle = <140002>;
|
||||
pio-map = <
|
||||
/* port pin dir open_drain assignment has_irq */
|
||||
0 11 1 0 1 0 /* TxD0 */
|
||||
0 12 1 0 1 0 /* TxD1 */
|
||||
0 13 1 0 1 0 /* TxD2 */
|
||||
0 14 1 0 1 0 /* TxD3 */
|
||||
1 2 1 0 1 0 /* TxD4 */
|
||||
1 3 1 0 2 0 /* TxD5 */
|
||||
1 5 1 0 3 0 /* TxD6 */
|
||||
1 8 1 0 3 0 /* TxD7 */
|
||||
0 17 2 0 1 0 /* RxD0 */
|
||||
0 18 2 0 1 0 /* RxD1 */
|
||||
0 19 2 0 1 0 /* RxD2 */
|
||||
0 1a 2 0 1 0 /* RxD3 */
|
||||
0 1b 2 0 1 0 /* RxD4 */
|
||||
1 c 2 0 2 0 /* RxD5 */
|
||||
1 d 2 0 3 0 /* RxD6 */
|
||||
1 b 2 0 2 0 /* RxD7 */
|
||||
0 15 1 0 1 0 /* TX_EN */
|
||||
0 16 1 0 1 0 /* TX_ER */
|
||||
0 1d 2 0 1 0 /* RX_DV */
|
||||
0 1e 2 0 1 0 /* RX_ER */
|
||||
0 1f 2 0 1 0 /* RX_CLK */
|
||||
2 2 1 0 2 0 /* GTX_CLK - CLK10 */
|
||||
2 3 2 0 1 0 /* GTX125 - CLK4 */
|
||||
0 1 3 0 2 0 /* MDIO */
|
||||
0 2 1 0 1 0>; /* MDC */
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
qe@e0100000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
device_type = "qe";
|
||||
model = "QE";
|
||||
ranges = <0 e0100000 00100000>;
|
||||
reg = <e0100000 480>;
|
||||
brg-frequency = <0>;
|
||||
bus-frequency = <179A7B00>;
|
||||
|
||||
muram@10000 {
|
||||
device_type = "muram";
|
||||
ranges = <0 00010000 0000c000>;
|
||||
|
||||
data-only@0{
|
||||
reg = <0 c000>;
|
||||
};
|
||||
};
|
||||
|
||||
spi@4c0 {
|
||||
device_type = "spi";
|
||||
compatible = "fsl_spi";
|
||||
reg = <4c0 40>;
|
||||
interrupts = <2>;
|
||||
interrupt-parent = <80>;
|
||||
mode = "cpu";
|
||||
};
|
||||
|
||||
spi@500 {
|
||||
device_type = "spi";
|
||||
compatible = "fsl_spi";
|
||||
reg = <500 40>;
|
||||
interrupts = <1>;
|
||||
interrupt-parent = <80>;
|
||||
mode = "cpu";
|
||||
};
|
||||
|
||||
usb@6c0 {
|
||||
device_type = "usb";
|
||||
compatible = "qe_udc";
|
||||
reg = <6c0 40 8B00 100>;
|
||||
interrupts = <b>;
|
||||
interrupt-parent = <80>;
|
||||
mode = "slave";
|
||||
};
|
||||
|
||||
ucc@2000 {
|
||||
device_type = "network";
|
||||
compatible = "ucc_geth";
|
||||
model = "UCC";
|
||||
device-id = <1>;
|
||||
reg = <2000 200>;
|
||||
interrupts = <20>;
|
||||
interrupt-parent = <80>;
|
||||
mac-address = [ 00 04 9f 00 23 23 ];
|
||||
rx-clock = <0>;
|
||||
tx-clock = <19>;
|
||||
phy-handle = <212000>;
|
||||
pio-handle = <140001>;
|
||||
};
|
||||
|
||||
ucc@3000 {
|
||||
device_type = "network";
|
||||
compatible = "ucc_geth";
|
||||
model = "UCC";
|
||||
device-id = <2>;
|
||||
reg = <3000 200>;
|
||||
interrupts = <21>;
|
||||
interrupt-parent = <80>;
|
||||
mac-address = [ 00 11 22 33 44 55 ];
|
||||
rx-clock = <0>;
|
||||
tx-clock = <14>;
|
||||
phy-handle = <212001>;
|
||||
pio-handle = <140002>;
|
||||
};
|
||||
|
||||
mdio@2120 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <2120 18>;
|
||||
device_type = "mdio";
|
||||
compatible = "ucc_geth_phy";
|
||||
|
||||
ethernet-phy@00 {
|
||||
linux,phandle = <212000>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <11 2>;
|
||||
reg = <0>;
|
||||
device_type = "ethernet-phy";
|
||||
interface = <6>; //ENET_1000_GMII
|
||||
};
|
||||
ethernet-phy@01 {
|
||||
linux,phandle = <212001>;
|
||||
interrupt-parent = <700>;
|
||||
interrupts = <12 2>;
|
||||
reg = <1>;
|
||||
device_type = "ethernet-phy";
|
||||
interface = <6>;
|
||||
};
|
||||
};
|
||||
|
||||
qeic@80 {
|
||||
linux,phandle = <80>;
|
||||
interrupt-controller;
|
||||
device_type = "qeic";
|
||||
#address-cells = <0>;
|
||||
#interrupt-cells = <1>;
|
||||
reg = <80 80>;
|
||||
built-in;
|
||||
big-endian;
|
||||
interrupts = <20 8 21 8>; //high:32 low:33
|
||||
interrupt-parent = <700>;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
|
@ -15,6 +15,7 @@ SECTIONS
|
|||
{
|
||||
*(.rodata*)
|
||||
*(.data*)
|
||||
*(__builtin_*)
|
||||
*(.sdata*)
|
||||
__got2_start = .;
|
||||
*(.got2)
|
||||
|
|
1018
arch/powerpc/configs/mpc8360emds_defconfig
Normal file
1018
arch/powerpc/configs/mpc8360emds_defconfig
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -763,10 +763,10 @@ struct cpu_spec cpu_specs[] = {
|
|||
.cpu_setup = __setup_cpu_603,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* e300 (a 603e core, plus some) on 83xx */
|
||||
{ /* e300c1 (a 603e core, plus some) on 83xx */
|
||||
.pvr_mask = 0x7fff0000,
|
||||
.pvr_value = 0x00830000,
|
||||
.cpu_name = "e300",
|
||||
.cpu_name = "e300c1",
|
||||
.cpu_features = CPU_FTRS_E300,
|
||||
.cpu_user_features = COMMON_USER,
|
||||
.icache_bsize = 32,
|
||||
|
@ -774,6 +774,17 @@ struct cpu_spec cpu_specs[] = {
|
|||
.cpu_setup = __setup_cpu_603,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* e300c2 (an e300c1 core, plus some, minus FPU) on 83xx */
|
||||
.pvr_mask = 0x7fff0000,
|
||||
.pvr_value = 0x00840000,
|
||||
.cpu_name = "e300c2",
|
||||
.cpu_features = CPU_FTRS_E300,
|
||||
.cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
|
||||
.icache_bsize = 32,
|
||||
.dcache_bsize = 32,
|
||||
.cpu_setup = __setup_cpu_603,
|
||||
.platform = "ppc603",
|
||||
},
|
||||
{ /* default match, we assume split I/D cache & TB (non-601)... */
|
||||
.pvr_mask = 0x00000000,
|
||||
.pvr_value = 0x00000000,
|
||||
|
|
|
@ -27,10 +27,7 @@
|
|||
#include <asm/ppc_asm.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/cputable.h>
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
#define DO_SOFT_DISABLE
|
||||
#endif
|
||||
#include <asm/firmware.h>
|
||||
|
||||
/*
|
||||
* System calls.
|
||||
|
@ -91,6 +88,7 @@ system_call_common:
|
|||
ld r11,exception_marker@toc(r2)
|
||||
std r11,-16(r9) /* "regshere" marker */
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
BEGIN_FW_FTR_SECTION
|
||||
/* Hack for handling interrupts when soft-enabling on iSeries */
|
||||
cmpdi cr1,r0,0x5555 /* syscall 0x5555 */
|
||||
andi. r10,r12,MSR_PR /* from kernel */
|
||||
|
@ -98,6 +96,7 @@ system_call_common:
|
|||
beq hardware_interrupt_entry
|
||||
lbz r10,PACAPROCENABLED(r13)
|
||||
std r10,SOFTE(r1)
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
#endif
|
||||
mfmsr r11
|
||||
ori r11,r11,MSR_EE
|
||||
|
@ -462,6 +461,7 @@ _GLOBAL(ret_from_except_lite)
|
|||
|
||||
restore:
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
BEGIN_FW_FTR_SECTION
|
||||
ld r5,SOFTE(r1)
|
||||
cmpdi 0,r5,0
|
||||
beq 4f
|
||||
|
@ -480,6 +480,7 @@ restore:
|
|||
b .ret_from_except_lite /* loop back and handle more */
|
||||
|
||||
4: stb r5,PACAPROCENABLED(r13)
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
#endif
|
||||
|
||||
ld r3,_MSR(r1)
|
||||
|
@ -538,18 +539,23 @@ do_work:
|
|||
lwz r8,TI_PREEMPT(r9)
|
||||
cmpwi cr1,r8,0
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
BEGIN_FW_FTR_SECTION
|
||||
ld r0,SOFTE(r1)
|
||||
cmpdi r0,0
|
||||
#else
|
||||
andi. r0,r3,MSR_EE
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
#endif
|
||||
BEGIN_FW_FTR_SECTION
|
||||
andi. r0,r3,MSR_EE
|
||||
END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
|
||||
crandc eq,cr1*4+eq,eq
|
||||
bne restore
|
||||
/* here we are preempting the current task */
|
||||
1:
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
BEGIN_FW_FTR_SECTION
|
||||
li r0,1
|
||||
stb r0,PACAPROCENABLED(r13)
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
#endif
|
||||
ori r10,r10,MSR_EE
|
||||
mtmsrd r10,1 /* reenable interrupts */
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <asm/hvcall.h>
|
||||
#include <asm/iseries/lpar_map.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
#define DO_SOFT_DISABLE
|
||||
|
@ -365,19 +366,28 @@ label##_iSeries: \
|
|||
|
||||
#ifdef DO_SOFT_DISABLE
|
||||
#define DISABLE_INTS \
|
||||
BEGIN_FW_FTR_SECTION; \
|
||||
lbz r10,PACAPROCENABLED(r13); \
|
||||
li r11,0; \
|
||||
std r10,SOFTE(r1); \
|
||||
mfmsr r10; \
|
||||
stb r11,PACAPROCENABLED(r13); \
|
||||
ori r10,r10,MSR_EE; \
|
||||
mtmsrd r10,1
|
||||
mtmsrd r10,1; \
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
|
||||
#define ENABLE_INTS \
|
||||
BEGIN_FW_FTR_SECTION; \
|
||||
lbz r10,PACAPROCENABLED(r13); \
|
||||
mfmsr r11; \
|
||||
std r10,SOFTE(r1); \
|
||||
ori r11,r11,MSR_EE; \
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \
|
||||
BEGIN_FW_FTR_SECTION; \
|
||||
ld r12,_MSR(r1); \
|
||||
mfmsr r11; \
|
||||
rlwimi r11,r12,0,MSR_EE; \
|
||||
END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \
|
||||
mtmsrd r11,1
|
||||
|
||||
#else /* hard enable/disable interrupts */
|
||||
|
@ -1071,8 +1081,10 @@ _GLOBAL(slb_miss_realmode)
|
|||
ld r3,PACA_EXSLB+EX_R3(r13)
|
||||
lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
BEGIN_FW_FTR_SECTION
|
||||
ld r11,PACALPPACAPTR(r13)
|
||||
ld r11,LPPACASRR0(r11) /* get SRR0 value */
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
|
||||
mtlr r10
|
||||
|
@ -1087,8 +1099,10 @@ _GLOBAL(slb_miss_realmode)
|
|||
.machine pop
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
BEGIN_FW_FTR_SECTION
|
||||
mtspr SPRN_SRR0,r11
|
||||
mtspr SPRN_SRR1,r12
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
ld r9,PACA_EXSLB+EX_R9(r13)
|
||||
ld r10,PACA_EXSLB+EX_R10(r13)
|
||||
|
@ -1301,6 +1315,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
|
|||
cmpdi r3,0 /* see if hash_page succeeded */
|
||||
|
||||
#ifdef DO_SOFT_DISABLE
|
||||
BEGIN_FW_FTR_SECTION
|
||||
/*
|
||||
* If we had interrupts soft-enabled at the point where the
|
||||
* DSI/ISI occurred, and an interrupt came in during hash_page,
|
||||
|
@ -1321,12 +1336,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
|
|||
ld r3,SOFTE(r1)
|
||||
bl .local_irq_restore
|
||||
b 11f
|
||||
#else
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
#endif
|
||||
BEGIN_FW_FTR_SECTION
|
||||
beq fast_exception_return /* Return from exception on success */
|
||||
ble- 12f /* Failure return from hash_page */
|
||||
|
||||
/* fall through */
|
||||
#endif
|
||||
END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
|
||||
|
||||
/* Here we have a page fault that hash_page can't handle. */
|
||||
_GLOBAL(handle_page_fault)
|
||||
|
@ -1861,7 +1878,9 @@ _GLOBAL(__secondary_start)
|
|||
LOAD_REG_ADDR(r3, .start_secondary_prolog)
|
||||
LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
|
||||
#ifdef DO_SOFT_DISABLE
|
||||
BEGIN_FW_FTR_SECTION
|
||||
ori r4,r4,MSR_EE
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
#endif
|
||||
mtspr SPRN_SRR0,r3
|
||||
mtspr SPRN_SRR1,r4
|
||||
|
@ -1986,6 +2005,7 @@ _STATIC(start_here_common)
|
|||
*/
|
||||
li r3,0
|
||||
bl .do_cpu_ftr_fixups
|
||||
bl .do_fw_ftr_fixups
|
||||
|
||||
/* ptr to current */
|
||||
LOAD_REG_IMMEDIATE(r4, init_task)
|
||||
|
@ -2000,11 +2020,13 @@ _STATIC(start_here_common)
|
|||
/* Load up the kernel context */
|
||||
5:
|
||||
#ifdef DO_SOFT_DISABLE
|
||||
BEGIN_FW_FTR_SECTION
|
||||
li r5,0
|
||||
stb r5,PACAPROCENABLED(r13) /* Soft Disabled */
|
||||
mfmsr r5
|
||||
ori r5,r5,MSR_EE /* Hard Enabled */
|
||||
mtmsrd r5
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
#endif
|
||||
|
||||
bl .start_kernel
|
||||
|
|
|
@ -325,6 +325,52 @@ _GLOBAL(do_cpu_ftr_fixups)
|
|||
isync
|
||||
b 1b
|
||||
|
||||
/*
|
||||
* do_fw_ftr_fixups - goes through the list of firmware feature fixups
|
||||
* and writes nop's over sections of code that don't apply for this firmware.
|
||||
* r3 = data offset (not changed)
|
||||
*/
|
||||
_GLOBAL(do_fw_ftr_fixups)
|
||||
/* Get firmware features */
|
||||
LOAD_REG_IMMEDIATE(r6,powerpc_firmware_features)
|
||||
sub r6,r6,r3
|
||||
ld r4,0(r6)
|
||||
/* Get the fixup table */
|
||||
LOAD_REG_IMMEDIATE(r6,__start___fw_ftr_fixup)
|
||||
sub r6,r6,r3
|
||||
LOAD_REG_IMMEDIATE(r7,__stop___fw_ftr_fixup)
|
||||
sub r7,r7,r3
|
||||
/* Do the fixup */
|
||||
1: cmpld r6,r7
|
||||
bgelr
|
||||
addi r6,r6,32
|
||||
ld r8,-32(r6) /* mask */
|
||||
and r8,r8,r4
|
||||
ld r9,-24(r6) /* value */
|
||||
cmpld r8,r9
|
||||
beq 1b
|
||||
ld r8,-16(r6) /* section begin */
|
||||
ld r9,-8(r6) /* section end */
|
||||
subf. r9,r8,r9
|
||||
beq 1b
|
||||
/* write nops over the section of code */
|
||||
/* todo: if large section, add a branch at the start of it */
|
||||
srwi r9,r9,2
|
||||
mtctr r9
|
||||
sub r8,r8,r3
|
||||
lis r0,0x60000000@h /* nop */
|
||||
3: stw r0,0(r8)
|
||||
BEGIN_FTR_SECTION
|
||||
dcbst 0,r8 /* suboptimal, but simpler */
|
||||
sync
|
||||
icbi 0,r8
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_SPLIT_ID_CACHE)
|
||||
addi r8,r8,4
|
||||
bdnz 3b
|
||||
sync /* additional sync needed on g4 */
|
||||
isync
|
||||
b 1b
|
||||
|
||||
#if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE)
|
||||
/*
|
||||
* Do an IO access in real mode
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <asm/byteorder.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/ppc-pci.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <asm/udbg.h>
|
||||
|
@ -209,7 +210,6 @@ void pcibios_free_controller(struct pci_controller *phb)
|
|||
kfree(phb);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PPC_ISERIES
|
||||
void __devinit pcibios_claim_one_bus(struct pci_bus *b)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
@ -238,10 +238,12 @@ static void __init pcibios_claim_of_setup(void)
|
|||
{
|
||||
struct pci_bus *b;
|
||||
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
return;
|
||||
|
||||
list_for_each_entry(b, &pci_root_buses, node)
|
||||
pcibios_claim_one_bus(b);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
static u32 get_int_prop(struct device_node *np, const char *name, u32 def)
|
||||
|
@ -554,9 +556,8 @@ static int __init pcibios_init(void)
|
|||
*/
|
||||
ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot;
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
iSeries_pcibios_init();
|
||||
#endif
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
iSeries_pcibios_init();
|
||||
|
||||
printk(KERN_DEBUG "PCI: Probing PCI hardware\n");
|
||||
|
||||
|
@ -566,15 +567,15 @@ static int __init pcibios_init(void)
|
|||
pci_bus_add_devices(hose->bus);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PPC_ISERIES
|
||||
if (pci_probe_only)
|
||||
pcibios_claim_of_setup();
|
||||
else
|
||||
/* FIXME: `else' will be removed when
|
||||
pci_assign_unassigned_resources() is able to work
|
||||
correctly with [partially] allocated PCI tree. */
|
||||
pci_assign_unassigned_resources();
|
||||
#endif /* !CONFIG_PPC_ISERIES */
|
||||
if (!firmware_has_feature(FW_FEATURE_ISERIES)) {
|
||||
if (pci_probe_only)
|
||||
pcibios_claim_of_setup();
|
||||
else
|
||||
/* FIXME: `else' will be removed when
|
||||
pci_assign_unassigned_resources() is able to work
|
||||
correctly with [partially] allocated PCI tree. */
|
||||
pci_assign_unassigned_resources();
|
||||
}
|
||||
|
||||
/* Call machine dependent final fixup */
|
||||
if (ppc_md.pcibios_fixup)
|
||||
|
@ -586,8 +587,9 @@ static int __init pcibios_init(void)
|
|||
printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev));
|
||||
|
||||
#ifdef CONFIG_PPC_MULTIPLATFORM
|
||||
/* map in PCI I/O space */
|
||||
phbs_remap_io();
|
||||
if (!firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
/* map in PCI I/O space */
|
||||
phbs_remap_io();
|
||||
#endif
|
||||
|
||||
printk(KERN_DEBUG "PCI: Probing PCI hardware done\n");
|
||||
|
@ -637,13 +639,13 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
|
|||
*/
|
||||
int pci_domain_nr(struct pci_bus *bus)
|
||||
{
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
return 0;
|
||||
#else
|
||||
struct pci_controller *hose = pci_bus_to_host(bus);
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
return 0;
|
||||
else {
|
||||
struct pci_controller *hose = pci_bus_to_host(bus);
|
||||
|
||||
return hose->global_number;
|
||||
#endif
|
||||
return hose->global_number;
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(pci_domain_nr);
|
||||
|
@ -651,12 +653,12 @@ EXPORT_SYMBOL(pci_domain_nr);
|
|||
/* Decide whether to display the domain number in /proc */
|
||||
int pci_proc_domain(struct pci_bus *bus)
|
||||
{
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
return 0;
|
||||
#else
|
||||
struct pci_controller *hose = pci_bus_to_host(bus);
|
||||
return hose->buid;
|
||||
#endif
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
return 0;
|
||||
else {
|
||||
struct pci_controller *hose = pci_bus_to_host(bus);
|
||||
return hose->buid;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -442,31 +442,6 @@ void __init smp_setup_cpu_maps(void)
|
|||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
int __initdata do_early_xmon;
|
||||
#ifdef CONFIG_XMON
|
||||
extern int xmon_no_auto_backtrace;
|
||||
|
||||
static int __init early_xmon(char *p)
|
||||
{
|
||||
/* ensure xmon is enabled */
|
||||
if (p) {
|
||||
if (strncmp(p, "on", 2) == 0)
|
||||
xmon_init(1);
|
||||
if (strncmp(p, "off", 3) == 0)
|
||||
xmon_init(0);
|
||||
if (strncmp(p, "nobt", 4) == 0)
|
||||
xmon_no_auto_backtrace = 1;
|
||||
if (strncmp(p, "early", 5) != 0)
|
||||
return 0;
|
||||
}
|
||||
xmon_init(1);
|
||||
do_early_xmon = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("xmon", early_xmon);
|
||||
#endif
|
||||
|
||||
static __init int add_pcspkr(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
|
|
@ -238,12 +238,11 @@ void __init setup_arch(char **cmdline_p)
|
|||
|
||||
smp_setup_cpu_maps();
|
||||
|
||||
#ifdef CONFIG_XMON_DEFAULT
|
||||
xmon_init(1);
|
||||
#endif
|
||||
/* Register early console */
|
||||
register_early_udbg_console();
|
||||
|
||||
xmon_setup();
|
||||
|
||||
#if defined(CONFIG_KGDB)
|
||||
if (ppc_md.kgdb_map_scc)
|
||||
ppc_md.kgdb_map_scc();
|
||||
|
@ -280,9 +279,6 @@ void __init setup_arch(char **cmdline_p)
|
|||
init_mm.end_data = (unsigned long) _edata;
|
||||
init_mm.brk = klimit;
|
||||
|
||||
if (do_early_xmon)
|
||||
debugger(NULL);
|
||||
|
||||
/* set up the bootmem stuff with available memory */
|
||||
do_init_bootmem();
|
||||
if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
|
||||
|
|
|
@ -390,19 +390,15 @@ void __init setup_system(void)
|
|||
*/
|
||||
find_legacy_serial_ports();
|
||||
|
||||
/*
|
||||
* Initialize xmon
|
||||
*/
|
||||
#ifdef CONFIG_XMON_DEFAULT
|
||||
xmon_init(1);
|
||||
#endif
|
||||
/*
|
||||
* Register early console
|
||||
*/
|
||||
register_early_udbg_console();
|
||||
|
||||
if (do_early_xmon)
|
||||
debugger(NULL);
|
||||
/*
|
||||
* Initialize xmon
|
||||
*/
|
||||
xmon_setup();
|
||||
|
||||
check_smt_enabled();
|
||||
smp_setup_cpu_maps();
|
||||
|
|
|
@ -132,6 +132,14 @@ SECTIONS
|
|||
*(__ftr_fixup)
|
||||
__stop___ftr_fixup = .;
|
||||
}
|
||||
#ifdef CONFIG_PPC64
|
||||
. = ALIGN(8);
|
||||
__fw_ftr_fixup : {
|
||||
__start___fw_ftr_fixup = .;
|
||||
*(__fw_ftr_fixup)
|
||||
__stop___fw_ftr_fixup = .;
|
||||
}
|
||||
#endif
|
||||
|
||||
. = ALIGN(PAGE_SIZE);
|
||||
.init.ramfs : {
|
||||
|
|
|
@ -63,32 +63,13 @@
|
|||
#include <asm/iommu.h>
|
||||
#include <asm/abs_addr.h>
|
||||
#include <asm/vdso.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
#include "mmu_decl.h"
|
||||
|
||||
unsigned long ioremap_bot = IMALLOC_BASE;
|
||||
static unsigned long phbs_io_bot = PHBS_IO_BASE;
|
||||
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
|
||||
void __iomem *ioremap(unsigned long addr, unsigned long size)
|
||||
{
|
||||
return (void __iomem *)addr;
|
||||
}
|
||||
|
||||
extern void __iomem *__ioremap(unsigned long addr, unsigned long size,
|
||||
unsigned long flags)
|
||||
{
|
||||
return (void __iomem *)addr;
|
||||
}
|
||||
|
||||
void iounmap(volatile void __iomem *addr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* map_io_page currently only called by __ioremap
|
||||
* map_io_page adds an entry to the ioremap page table
|
||||
|
@ -161,6 +142,9 @@ void __iomem * __ioremap(unsigned long addr, unsigned long size,
|
|||
unsigned long pa, ea;
|
||||
void __iomem *ret;
|
||||
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
return (void __iomem *)addr;
|
||||
|
||||
/*
|
||||
* Choose an address to map it to.
|
||||
* Once the imalloc system is running, we use it.
|
||||
|
@ -255,6 +239,9 @@ void iounmap(volatile void __iomem *token)
|
|||
{
|
||||
void *addr;
|
||||
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
return;
|
||||
|
||||
if (!mem_init_done)
|
||||
return;
|
||||
|
||||
|
@ -315,8 +302,6 @@ int iounmap_explicit(volatile void __iomem *start, unsigned long size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
EXPORT_SYMBOL(ioremap);
|
||||
EXPORT_SYMBOL(__ioremap);
|
||||
EXPORT_SYMBOL(iounmap);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <asm/page.h>
|
||||
#include <asm/mmu.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
/* void slb_allocate_realmode(unsigned long ea);
|
||||
*
|
||||
|
@ -183,6 +184,7 @@ slb_finish_load:
|
|||
* dont have any LRU information to help us choose a slot.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_ISERIES
|
||||
BEGIN_FW_FTR_SECTION
|
||||
/*
|
||||
* On iSeries, the "bolted" stack segment can be cast out on
|
||||
* shared processor switch so we need to check for a miss on
|
||||
|
@ -194,6 +196,7 @@ slb_finish_load:
|
|||
li r10,SLB_NUM_BOLTED-1 /* Stack goes in last bolted slot */
|
||||
cmpld r9,r3
|
||||
beq 3f
|
||||
END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
|
||||
#endif /* CONFIG_PPC_ISERIES */
|
||||
|
||||
ld r10,PACASTABRR(r13)
|
||||
|
|
21
arch/powerpc/platforms/82xx/Kconfig
Normal file
21
arch/powerpc/platforms/82xx/Kconfig
Normal file
|
@ -0,0 +1,21 @@
|
|||
menu "Platform support"
|
||||
depends on PPC_82xx
|
||||
|
||||
choice
|
||||
prompt "Machine Type"
|
||||
default MPC82xx_ADS
|
||||
|
||||
config MPC82xx_ADS
|
||||
bool "Freescale MPC82xx ADS"
|
||||
select DEFAULT_UIMAGE
|
||||
select PQ2ADS
|
||||
select 8272
|
||||
select 8260
|
||||
select CPM2
|
||||
select FSL_SOC
|
||||
help
|
||||
This option enables support for the MPC8272 ADS board
|
||||
|
||||
endchoice
|
||||
|
||||
endmenu
|
5
arch/powerpc/platforms/82xx/Makefile
Normal file
5
arch/powerpc/platforms/82xx/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Makefile for the PowerPC 82xx linux kernel.
|
||||
#
|
||||
obj-$(CONFIG_PPC_82xx) += mpc82xx.o
|
||||
obj-$(CONFIG_MPC82xx_ADS) += mpc82xx_ads.o
|
19
arch/powerpc/platforms/82xx/m82xx_pci.h
Normal file
19
arch/powerpc/platforms/82xx/m82xx_pci.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef _PPC_KERNEL_M82XX_PCI_H
|
||||
#define _PPC_KERNEL_M82XX_PCI_H
|
||||
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <asm/m8260_pci.h>
|
||||
|
||||
#define SIU_INT_IRQ1 ((uint)0x13 + CPM_IRQ_OFFSET)
|
||||
|
||||
#ifndef _IO_BASE
|
||||
#define _IO_BASE isa_io_base
|
||||
#endif
|
||||
|
||||
#endif /* _PPC_KERNEL_M8260_PCI_H */
|
111
arch/powerpc/platforms/82xx/mpc82xx.c
Normal file
111
arch/powerpc/platforms/82xx/mpc82xx.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* MPC82xx setup and early boot code plus other random bits.
|
||||
*
|
||||
* Author: Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
*
|
||||
* Copyright (c) 2006 MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fsl_devices.h>
|
||||
#include <linux/fs_uart_pd.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/mpc8260.h>
|
||||
#include <asm/irq.h>
|
||||
#include <mm/mmu_decl.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/cpm2.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/i8259.h>
|
||||
#include <linux/fs_enet_pd.h>
|
||||
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/cpm2_pic.h>
|
||||
|
||||
#include "pq2ads_pd.h"
|
||||
|
||||
static int __init get_freq(char *name, unsigned long *val)
|
||||
{
|
||||
struct device_node *cpu;
|
||||
unsigned int *fp;
|
||||
int found = 0;
|
||||
|
||||
/* The cpu node should have timebase and clock frequency properties */
|
||||
cpu = of_find_node_by_type(NULL, "cpu");
|
||||
|
||||
if (cpu) {
|
||||
fp = (unsigned int *)get_property(cpu, name, NULL);
|
||||
if (fp) {
|
||||
found = 1;
|
||||
*val = *fp++;
|
||||
}
|
||||
|
||||
of_node_put(cpu);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
void __init m82xx_calibrate_decr(void)
|
||||
{
|
||||
ppc_tb_freq = 125000000;
|
||||
if (!get_freq("bus-frequency", &ppc_tb_freq)) {
|
||||
printk(KERN_ERR "WARNING: Estimating decrementer frequency "
|
||||
"(not found)\n");
|
||||
}
|
||||
ppc_tb_freq /= 4;
|
||||
ppc_proc_freq = 1000000000;
|
||||
if (!get_freq("clock-frequency", &ppc_proc_freq))
|
||||
printk(KERN_ERR "WARNING: Estimating processor frequency"
|
||||
"(not found)\n");
|
||||
}
|
||||
|
||||
void mpc82xx_ads_show_cpuinfo(struct seq_file *m)
|
||||
{
|
||||
uint pvid, svid, phid1;
|
||||
uint memsize = total_memory;
|
||||
|
||||
pvid = mfspr(SPRN_PVR);
|
||||
svid = mfspr(SPRN_SVR);
|
||||
|
||||
seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
|
||||
seq_printf(m, "Machine\t\t: %s\n", CPUINFO_MACHINE);
|
||||
seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
|
||||
seq_printf(m, "SVR\t\t: 0x%x\n", svid);
|
||||
|
||||
/* Display cpu Pll setting */
|
||||
phid1 = mfspr(SPRN_HID1);
|
||||
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
|
||||
|
||||
/* Display the amount of memory */
|
||||
seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
|
||||
}
|
661
arch/powerpc/platforms/82xx/mpc82xx_ads.c
Normal file
661
arch/powerpc/platforms/82xx/mpc82xx_ads.c
Normal file
|
@ -0,0 +1,661 @@
|
|||
/*
|
||||
* MPC82xx_ads setup and early boot code plus other random bits.
|
||||
*
|
||||
* Author: Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
* m82xx_restart fix by Wade Farnsworth <wfarnsworth@mvista.com>
|
||||
*
|
||||
* Copyright (c) 2006 MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fsl_devices.h>
|
||||
#include <linux/fs_uart_pd.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <asm/mpc8260.h>
|
||||
#include <asm/irq.h>
|
||||
#include <mm/mmu_decl.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/cpm2.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/i8259.h>
|
||||
#include <linux/fs_enet_pd.h>
|
||||
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <../sysdev/cpm2_pic.h>
|
||||
|
||||
#include "pq2ads_pd.h"
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static uint pci_clk_frq;
|
||||
static struct {
|
||||
unsigned long *pci_int_stat_reg;
|
||||
unsigned long *pci_int_mask_reg;
|
||||
} pci_regs;
|
||||
|
||||
static unsigned long pci_int_base;
|
||||
static struct irq_host *pci_pic_host;
|
||||
static struct device_node *pci_pic_node;
|
||||
#endif
|
||||
|
||||
static void __init mpc82xx_ads_pic_init(void)
|
||||
{
|
||||
struct device_node *np = of_find_compatible_node(NULL, "cpm-pic", "CPM2");
|
||||
struct resource r;
|
||||
cpm2_map_t *cpm_reg;
|
||||
|
||||
if (np == NULL) {
|
||||
printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
|
||||
return;
|
||||
}
|
||||
if (of_address_to_resource(np, 0, &r)) {
|
||||
printk(KERN_ERR "PIC init: invalid resource\n");
|
||||
of_node_put(np);
|
||||
return;
|
||||
}
|
||||
cpm2_pic_init(np);
|
||||
of_node_put(np);
|
||||
|
||||
/* Initialize the default interrupt mapping priorities,
|
||||
* in case the boot rom changed something on us.
|
||||
*/
|
||||
cpm_reg = (cpm2_map_t *) ioremap(get_immrbase(), sizeof(cpm2_map_t));
|
||||
cpm_reg->im_intctl.ic_siprr = 0x05309770;
|
||||
iounmap(cpm_reg);
|
||||
#ifdef CONFIG_PCI
|
||||
/* Initialize stuff for the 82xx CPLD IC and install demux */
|
||||
m82xx_pci_init_irq();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void init_fcc1_ioports(struct fs_platform_info *fpi)
|
||||
{
|
||||
struct io_port *io;
|
||||
u32 tempval;
|
||||
cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
|
||||
struct device_node *np;
|
||||
struct resource r;
|
||||
u32 *bcsr;
|
||||
|
||||
np = of_find_node_by_type(NULL, "memory");
|
||||
if (!np) {
|
||||
printk(KERN_INFO "No memory node in device tree\n");
|
||||
return;
|
||||
}
|
||||
if (of_address_to_resource(np, 1, &r)) {
|
||||
printk(KERN_INFO "No memory reg property [1] in devicetree\n");
|
||||
return;
|
||||
}
|
||||
of_node_put(np);
|
||||
bcsr = ioremap(r.start + 4, sizeof(u32));
|
||||
io = &immap->im_ioport;
|
||||
|
||||
/* Enable the PHY */
|
||||
clrbits32(bcsr, BCSR1_FETHIEN);
|
||||
setbits32(bcsr, BCSR1_FETH_RST);
|
||||
|
||||
/* FCC1 pins are on port A/C. */
|
||||
/* Configure port A and C pins for FCC1 Ethernet. */
|
||||
|
||||
tempval = in_be32(&io->iop_pdira);
|
||||
tempval &= ~PA1_DIRA0;
|
||||
tempval |= PA1_DIRA1;
|
||||
out_be32(&io->iop_pdira, tempval);
|
||||
|
||||
tempval = in_be32(&io->iop_psora);
|
||||
tempval &= ~PA1_PSORA0;
|
||||
tempval |= PA1_PSORA1;
|
||||
out_be32(&io->iop_psora, tempval);
|
||||
|
||||
setbits32(&io->iop_ppara, PA1_DIRA0 | PA1_DIRA1);
|
||||
|
||||
/* Alter clocks */
|
||||
tempval = PC_CLK(fpi->clk_tx - 8) | PC_CLK(fpi->clk_rx - 8);
|
||||
|
||||
clrbits32(&io->iop_psorc, tempval);
|
||||
clrbits32(&io->iop_pdirc, tempval);
|
||||
setbits32(&io->iop_pparc, tempval);
|
||||
|
||||
cpm2_clk_setup(CPM_CLK_FCC1, fpi->clk_rx, CPM_CLK_RX);
|
||||
cpm2_clk_setup(CPM_CLK_FCC1, fpi->clk_tx, CPM_CLK_TX);
|
||||
|
||||
iounmap(bcsr);
|
||||
iounmap(immap);
|
||||
}
|
||||
|
||||
static void init_fcc2_ioports(struct fs_platform_info *fpi)
|
||||
{
|
||||
cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
|
||||
struct device_node *np;
|
||||
struct resource r;
|
||||
u32 *bcsr;
|
||||
|
||||
struct io_port *io;
|
||||
u32 tempval;
|
||||
|
||||
np = of_find_node_by_type(NULL, "memory");
|
||||
if (!np) {
|
||||
printk(KERN_INFO "No memory node in device tree\n");
|
||||
return;
|
||||
}
|
||||
if (of_address_to_resource(np, 1, &r)) {
|
||||
printk(KERN_INFO "No memory reg property [1] in devicetree\n");
|
||||
return;
|
||||
}
|
||||
of_node_put(np);
|
||||
io = &immap->im_ioport;
|
||||
bcsr = ioremap(r.start + 12, sizeof(u32));
|
||||
|
||||
/* Enable the PHY */
|
||||
clrbits32(bcsr, BCSR3_FETHIEN2);
|
||||
setbits32(bcsr, BCSR3_FETH2_RST);
|
||||
|
||||
/* FCC2 are port B/C. */
|
||||
/* Configure port A and C pins for FCC2 Ethernet. */
|
||||
|
||||
tempval = in_be32(&io->iop_pdirb);
|
||||
tempval &= ~PB2_DIRB0;
|
||||
tempval |= PB2_DIRB1;
|
||||
out_be32(&io->iop_pdirb, tempval);
|
||||
|
||||
tempval = in_be32(&io->iop_psorb);
|
||||
tempval &= ~PB2_PSORB0;
|
||||
tempval |= PB2_PSORB1;
|
||||
out_be32(&io->iop_psorb, tempval);
|
||||
|
||||
setbits32(&io->iop_pparb, PB2_DIRB0 | PB2_DIRB1);
|
||||
|
||||
tempval = PC_CLK(fpi->clk_tx - 8) | PC_CLK(fpi->clk_rx - 8);
|
||||
|
||||
/* Alter clocks */
|
||||
clrbits32(&io->iop_psorc, tempval);
|
||||
clrbits32(&io->iop_pdirc, tempval);
|
||||
setbits32(&io->iop_pparc, tempval);
|
||||
|
||||
cpm2_clk_setup(CPM_CLK_FCC2, fpi->clk_rx, CPM_CLK_RX);
|
||||
cpm2_clk_setup(CPM_CLK_FCC2, fpi->clk_tx, CPM_CLK_TX);
|
||||
|
||||
iounmap(bcsr);
|
||||
iounmap(immap);
|
||||
}
|
||||
|
||||
void init_fcc_ioports(struct fs_platform_info *fpi)
|
||||
{
|
||||
int fcc_no = fs_get_fcc_index(fpi->fs_no);
|
||||
|
||||
switch (fcc_no) {
|
||||
case 0:
|
||||
init_fcc1_ioports(fpi);
|
||||
break;
|
||||
case 1:
|
||||
init_fcc2_ioports(fpi);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "init_fcc_ioports: invalid FCC number\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void init_scc1_uart_ioports(struct fs_uart_platform_info *data)
|
||||
{
|
||||
cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
|
||||
|
||||
/* SCC1 is only on port D */
|
||||
setbits32(&immap->im_ioport.iop_ppard, 0x00000003);
|
||||
clrbits32(&immap->im_ioport.iop_psord, 0x00000001);
|
||||
setbits32(&immap->im_ioport.iop_psord, 0x00000002);
|
||||
clrbits32(&immap->im_ioport.iop_pdird, 0x00000001);
|
||||
setbits32(&immap->im_ioport.iop_pdird, 0x00000002);
|
||||
|
||||
clrbits32(&immap->im_cpmux.cmx_scr, (0x00000007 << (4 - data->clk_tx)));
|
||||
clrbits32(&immap->im_cpmux.cmx_scr, (0x00000038 << (4 - data->clk_rx)));
|
||||
setbits32(&immap->im_cpmux.cmx_scr,
|
||||
((data->clk_tx - 1) << (4 - data->clk_tx)));
|
||||
setbits32(&immap->im_cpmux.cmx_scr,
|
||||
((data->clk_rx - 1) << (4 - data->clk_rx)));
|
||||
|
||||
iounmap(immap);
|
||||
}
|
||||
|
||||
static void init_scc4_uart_ioports(struct fs_uart_platform_info *data)
|
||||
{
|
||||
cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
|
||||
|
||||
setbits32(&immap->im_ioport.iop_ppard, 0x00000600);
|
||||
clrbits32(&immap->im_ioport.iop_psord, 0x00000600);
|
||||
clrbits32(&immap->im_ioport.iop_pdird, 0x00000200);
|
||||
setbits32(&immap->im_ioport.iop_pdird, 0x00000400);
|
||||
|
||||
clrbits32(&immap->im_cpmux.cmx_scr, (0x00000007 << (4 - data->clk_tx)));
|
||||
clrbits32(&immap->im_cpmux.cmx_scr, (0x00000038 << (4 - data->clk_rx)));
|
||||
setbits32(&immap->im_cpmux.cmx_scr,
|
||||
((data->clk_tx - 1) << (4 - data->clk_tx)));
|
||||
setbits32(&immap->im_cpmux.cmx_scr,
|
||||
((data->clk_rx - 1) << (4 - data->clk_rx)));
|
||||
|
||||
iounmap(immap);
|
||||
}
|
||||
|
||||
void init_scc_ioports(struct fs_uart_platform_info *data)
|
||||
{
|
||||
int scc_no = fs_get_scc_index(data->fs_no);
|
||||
|
||||
switch (scc_no) {
|
||||
case 0:
|
||||
init_scc1_uart_ioports(data);
|
||||
data->brg = data->clk_rx;
|
||||
break;
|
||||
case 3:
|
||||
init_scc4_uart_ioports(data);
|
||||
data->brg = data->clk_rx;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void __init m82xx_board_setup(void)
|
||||
{
|
||||
cpm2_map_t *immap = ioremap(get_immrbase(), sizeof(cpm2_map_t));
|
||||
struct device_node *np;
|
||||
struct resource r;
|
||||
u32 *bcsr;
|
||||
|
||||
np = of_find_node_by_type(NULL, "memory");
|
||||
if (!np) {
|
||||
printk(KERN_INFO "No memory node in device tree\n");
|
||||
return;
|
||||
}
|
||||
if (of_address_to_resource(np, 1, &r)) {
|
||||
printk(KERN_INFO "No memory reg property [1] in devicetree\n");
|
||||
return;
|
||||
}
|
||||
of_node_put(np);
|
||||
bcsr = ioremap(r.start + 4, sizeof(u32));
|
||||
/* Enable the 2nd UART port */
|
||||
clrbits32(bcsr, BCSR1_RS232_EN2);
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC1
|
||||
clrbits32((u32 *) & immap->im_scc[0].scc_sccm,
|
||||
UART_SCCM_TX | UART_SCCM_RX);
|
||||
clrbits32((u32 *) & immap->im_scc[0].scc_gsmrl,
|
||||
SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC2
|
||||
clrbits32((u32 *) & immap->im_scc[1].scc_sccm,
|
||||
UART_SCCM_TX | UART_SCCM_RX);
|
||||
clrbits32((u32 *) & immap->im_scc[1].scc_gsmrl,
|
||||
SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC3
|
||||
clrbits32((u32 *) & immap->im_scc[2].scc_sccm,
|
||||
UART_SCCM_TX | UART_SCCM_RX);
|
||||
clrbits32((u32 *) & immap->im_scc[2].scc_gsmrl,
|
||||
SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_SCC4
|
||||
clrbits32((u32 *) & immap->im_scc[3].scc_sccm,
|
||||
UART_SCCM_TX | UART_SCCM_RX);
|
||||
clrbits32((u32 *) & immap->im_scc[3].scc_gsmrl,
|
||||
SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
#endif
|
||||
|
||||
iounmap(bcsr);
|
||||
iounmap(immap);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
static void m82xx_pci_mask_irq(unsigned int irq)
|
||||
{
|
||||
int bit = irq - pci_int_base;
|
||||
|
||||
*pci_regs.pci_int_mask_reg |= (1 << (31 - bit));
|
||||
return;
|
||||
}
|
||||
|
||||
static void m82xx_pci_unmask_irq(unsigned int irq)
|
||||
{
|
||||
int bit = irq - pci_int_base;
|
||||
|
||||
*pci_regs.pci_int_mask_reg &= ~(1 << (31 - bit));
|
||||
return;
|
||||
}
|
||||
|
||||
static void m82xx_pci_mask_and_ack(unsigned int irq)
|
||||
{
|
||||
int bit = irq - pci_int_base;
|
||||
|
||||
*pci_regs.pci_int_mask_reg |= (1 << (31 - bit));
|
||||
return;
|
||||
}
|
||||
|
||||
static void m82xx_pci_end_irq(unsigned int irq)
|
||||
{
|
||||
int bit = irq - pci_int_base;
|
||||
|
||||
*pci_regs.pci_int_mask_reg &= ~(1 << (31 - bit));
|
||||
return;
|
||||
}
|
||||
|
||||
struct hw_interrupt_type m82xx_pci_ic = {
|
||||
.typename = "MPC82xx ADS PCI",
|
||||
.name = "MPC82xx ADS PCI",
|
||||
.enable = m82xx_pci_unmask_irq,
|
||||
.disable = m82xx_pci_mask_irq,
|
||||
.ack = m82xx_pci_mask_and_ack,
|
||||
.end = m82xx_pci_end_irq,
|
||||
.mask = m82xx_pci_mask_irq,
|
||||
.mask_ack = m82xx_pci_mask_and_ack,
|
||||
.unmask = m82xx_pci_unmask_irq,
|
||||
.eoi = m82xx_pci_end_irq,
|
||||
};
|
||||
|
||||
static void
|
||||
m82xx_pci_irq_demux(unsigned int irq, struct irq_desc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long stat, mask, pend;
|
||||
int bit;
|
||||
|
||||
for (;;) {
|
||||
stat = *pci_regs.pci_int_stat_reg;
|
||||
mask = *pci_regs.pci_int_mask_reg;
|
||||
pend = stat & ~mask & 0xf0000000;
|
||||
if (!pend)
|
||||
break;
|
||||
for (bit = 0; pend != 0; ++bit, pend <<= 1) {
|
||||
if (pend & 0x80000000)
|
||||
__do_IRQ(pci_int_base + bit, regs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int pci_pic_host_match(struct irq_host *h, struct device_node *node)
|
||||
{
|
||||
return node == pci_pic_node;
|
||||
}
|
||||
|
||||
static int pci_pic_host_map(struct irq_host *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
get_irq_desc(virq)->status |= IRQ_LEVEL;
|
||||
set_irq_chip(virq, &m82xx_pci_ic);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_host_unmap(struct irq_host *h, unsigned int virq)
|
||||
{
|
||||
/* remove chip and handler */
|
||||
set_irq_chip(virq, NULL);
|
||||
}
|
||||
|
||||
static struct irq_host_ops pci_pic_host_ops = {
|
||||
.match = pci_pic_host_match,
|
||||
.map = pci_pic_host_map,
|
||||
.unmap = pci_host_unmap,
|
||||
};
|
||||
|
||||
void m82xx_pci_init_irq(void)
|
||||
{
|
||||
int irq;
|
||||
cpm2_map_t *immap;
|
||||
struct device_node *np;
|
||||
struct resource r;
|
||||
const u32 *regs;
|
||||
unsigned int size;
|
||||
const u32 *irq_map;
|
||||
int i;
|
||||
unsigned int irq_max, irq_min;
|
||||
|
||||
if ((np = of_find_node_by_type(NULL, "soc")) == NULL) {
|
||||
printk(KERN_INFO "No SOC node in device tree\n");
|
||||
return;
|
||||
}
|
||||
memset(&r, 0, sizeof(r));
|
||||
if (of_address_to_resource(np, 0, &r)) {
|
||||
printk(KERN_INFO "No SOC reg property in device tree\n");
|
||||
return;
|
||||
}
|
||||
immap = ioremap(r.start, sizeof(*immap));
|
||||
of_node_put(np);
|
||||
|
||||
/* install the demultiplexer for the PCI cascade interrupt */
|
||||
np = of_find_node_by_type(NULL, "pci");
|
||||
if (!np) {
|
||||
printk(KERN_INFO "No pci node on device tree\n");
|
||||
iounmap(immap);
|
||||
return;
|
||||
}
|
||||
irq_map = get_property(np, "interrupt-map", &size);
|
||||
if ((!irq_map) || (size <= 7)) {
|
||||
printk(KERN_INFO "No interrupt-map property of pci node\n");
|
||||
iounmap(immap);
|
||||
return;
|
||||
}
|
||||
size /= sizeof(irq_map[0]);
|
||||
for (i = 0, irq_max = 0, irq_min = 512; i < size; i += 7, irq_map += 7) {
|
||||
if (irq_map[5] < irq_min)
|
||||
irq_min = irq_map[5];
|
||||
if (irq_map[5] > irq_max)
|
||||
irq_max = irq_map[5];
|
||||
}
|
||||
pci_int_base = irq_min;
|
||||
irq = irq_of_parse_and_map(np, 0);
|
||||
set_irq_chained_handler(irq, m82xx_pci_irq_demux);
|
||||
of_node_put(np);
|
||||
np = of_find_node_by_type(NULL, "pci-pic");
|
||||
if (!np) {
|
||||
printk(KERN_INFO "No pci pic node on device tree\n");
|
||||
iounmap(immap);
|
||||
return;
|
||||
}
|
||||
pci_pic_node = of_node_get(np);
|
||||
/* PCI interrupt controller registers: status and mask */
|
||||
regs = get_property(np, "reg", &size);
|
||||
if ((!regs) || (size <= 2)) {
|
||||
printk(KERN_INFO "No reg property in pci pic node\n");
|
||||
iounmap(immap);
|
||||
return;
|
||||
}
|
||||
pci_regs.pci_int_stat_reg =
|
||||
ioremap(regs[0], sizeof(*pci_regs.pci_int_stat_reg));
|
||||
pci_regs.pci_int_mask_reg =
|
||||
ioremap(regs[1], sizeof(*pci_regs.pci_int_mask_reg));
|
||||
of_node_put(np);
|
||||
/* configure chip select for PCI interrupt controller */
|
||||
immap->im_memctl.memc_br3 = regs[0] | 0x00001801;
|
||||
immap->im_memctl.memc_or3 = 0xffff8010;
|
||||
/* make PCI IRQ level sensitive */
|
||||
immap->im_intctl.ic_siexr &= ~(1 << (14 - (irq - SIU_INT_IRQ1)));
|
||||
|
||||
/* mask all PCI interrupts */
|
||||
*pci_regs.pci_int_mask_reg |= 0xfff00000;
|
||||
iounmap(immap);
|
||||
pci_pic_host =
|
||||
irq_alloc_host(IRQ_HOST_MAP_LINEAR, irq_max - irq_min + 1,
|
||||
&pci_pic_host_ops, irq_max + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
static int m82xx_pci_exclude_device(u_char bus, u_char devfn)
|
||||
{
|
||||
if (bus == 0 && PCI_SLOT(devfn) == 0)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
else
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static void
|
||||
__init mpc82xx_pcibios_fixup(void)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
for_each_pci_dev(dev) {
|
||||
pci_read_irq_line(dev);
|
||||
}
|
||||
}
|
||||
|
||||
void __init add_bridge(struct device_node *np)
|
||||
{
|
||||
int len;
|
||||
struct pci_controller *hose;
|
||||
struct resource r;
|
||||
const int *bus_range;
|
||||
const void *ptr;
|
||||
|
||||
memset(&r, 0, sizeof(r));
|
||||
if (of_address_to_resource(np, 0, &r)) {
|
||||
printk(KERN_INFO "No PCI reg property in device tree\n");
|
||||
return;
|
||||
}
|
||||
if (!(ptr = get_property(np, "clock-frequency", NULL))) {
|
||||
printk(KERN_INFO "No clock-frequency property in PCI node");
|
||||
return;
|
||||
}
|
||||
pci_clk_frq = *(uint *) ptr;
|
||||
of_node_put(np);
|
||||
bus_range = get_property(np, "bus-range", &len);
|
||||
if (bus_range == NULL || len < 2 * sizeof(int)) {
|
||||
printk(KERN_WARNING "Can't get bus-range for %s, assume"
|
||||
" bus 0\n", np->full_name);
|
||||
}
|
||||
|
||||
pci_assign_all_buses = 1;
|
||||
|
||||
hose = pcibios_alloc_controller();
|
||||
|
||||
if (!hose)
|
||||
return;
|
||||
|
||||
hose->arch_data = np;
|
||||
hose->set_cfg_type = 1;
|
||||
|
||||
hose->first_busno = bus_range ? bus_range[0] : 0;
|
||||
hose->last_busno = bus_range ? bus_range[1] : 0xff;
|
||||
hose->bus_offset = 0;
|
||||
|
||||
hose->set_cfg_type = 1;
|
||||
|
||||
setup_indirect_pci(hose,
|
||||
r.start + offsetof(pci_cpm2_t, pci_cfg_addr),
|
||||
r.start + offsetof(pci_cpm2_t, pci_cfg_data));
|
||||
|
||||
pci_process_bridge_OF_ranges(hose, np, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Setup the architecture
|
||||
*/
|
||||
static void __init mpc82xx_ads_setup_arch(void)
|
||||
{
|
||||
#ifdef CONFIG_PCI
|
||||
struct device_node *np;
|
||||
#endif
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc82xx_ads_setup_arch()", 0);
|
||||
cpm2_reset();
|
||||
|
||||
/* Map I/O region to a 256MB BAT */
|
||||
|
||||
m82xx_board_setup();
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
ppc_md.pci_exclude_device = m82xx_pci_exclude_device;
|
||||
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
|
||||
add_bridge(np);
|
||||
|
||||
of_node_put(np);
|
||||
ppc_md.pci_map_irq = NULL;
|
||||
ppc_md.pcibios_fixup = mpc82xx_pcibios_fixup;
|
||||
ppc_md.pcibios_fixup_bus = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ROOT_NFS
|
||||
ROOT_DEV = Root_NFS;
|
||||
#else
|
||||
ROOT_DEV = Root_HDA1;
|
||||
#endif
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc82xx_ads_setup_arch(), finish", 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called very early, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc82xx_ads_probe(void)
|
||||
{
|
||||
/* We always match for now, eventually we should look at
|
||||
* the flat dev tree to ensure this is the board we are
|
||||
* supposed to run on
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define RMR_CSRE 0x00000001
|
||||
static void m82xx_restart(char *cmd)
|
||||
{
|
||||
__volatile__ unsigned char dummy;
|
||||
|
||||
local_irq_disable();
|
||||
((cpm2_map_t *) cpm2_immr)->im_clkrst.car_rmr |= RMR_CSRE;
|
||||
|
||||
/* Clear the ME,EE,IR & DR bits in MSR to cause checkstop */
|
||||
mtmsr(mfmsr() & ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR));
|
||||
dummy = ((cpm2_map_t *) cpm2_immr)->im_clkrst.res[0];
|
||||
printk("Restart failed\n");
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
static void m82xx_halt(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
while (1) ;
|
||||
}
|
||||
|
||||
define_machine(mpc82xx_ads)
|
||||
{
|
||||
.name = "MPC82xx ADS",
|
||||
.probe = mpc82xx_ads_probe,
|
||||
.setup_arch = mpc82xx_ads_setup_arch,
|
||||
.init_IRQ = mpc82xx_ads_pic_init,
|
||||
.show_cpuinfo = mpc82xx_ads_show_cpuinfo,
|
||||
.get_irq = cpm2_get_irq,
|
||||
.calibrate_decr = m82xx_calibrate_decr,
|
||||
.restart = m82xx_restart,.halt = m82xx_halt,
|
||||
};
|
67
arch/powerpc/platforms/82xx/pq2ads.h
Normal file
67
arch/powerpc/platforms/82xx/pq2ads.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* PQ2/mpc8260 board-specific stuff
|
||||
*
|
||||
* A collection of structures, addresses, and values associated with
|
||||
* the Freescale MPC8260ADS/MPC8266ADS-PCI boards.
|
||||
* Copied from the RPX-Classic and SBS8260 stuff.
|
||||
*
|
||||
* Author: Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
*
|
||||
* Originally written by Dan Malek for Motorola MPC8260 family
|
||||
*
|
||||
* Copyright (c) 2001 Dan Malek <dan@embeddedalley.com>
|
||||
* Copyright (c) 2006 MontaVista Software, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifndef __MACH_ADS8260_DEFS
|
||||
#define __MACH_ADS8260_DEFS
|
||||
|
||||
#include <linux/config.h>
|
||||
|
||||
#include <asm/ppcboot.h>
|
||||
|
||||
/* For our show_cpuinfo hooks. */
|
||||
#define CPUINFO_VENDOR "Freescale Semiconductor"
|
||||
#define CPUINFO_MACHINE "PQ2 ADS PowerPC"
|
||||
|
||||
/* Backword-compatibility stuff for the drivers */
|
||||
#define CPM_MAP_ADDR ((uint)0xf0000000)
|
||||
#define CPM_IRQ_OFFSET 0
|
||||
|
||||
/* The ADS8260 has 16, 32-bit wide control/status registers, accessed
|
||||
* only on word boundaries.
|
||||
* Not all are used (yet), or are interesting to us (yet).
|
||||
*/
|
||||
|
||||
/* Things of interest in the CSR.
|
||||
*/
|
||||
#define BCSR0_LED0 ((uint)0x02000000) /* 0 == on */
|
||||
#define BCSR0_LED1 ((uint)0x01000000) /* 0 == on */
|
||||
#define BCSR1_FETHIEN ((uint)0x08000000) /* 0 == enable*/
|
||||
#define BCSR1_FETH_RST ((uint)0x04000000) /* 0 == reset */
|
||||
#define BCSR1_RS232_EN1 ((uint)0x02000000) /* 0 ==enable */
|
||||
#define BCSR1_RS232_EN2 ((uint)0x01000000) /* 0 ==enable */
|
||||
#define BCSR3_FETHIEN2 ((uint)0x10000000) /* 0 == enable*/
|
||||
#define BCSR3_FETH2_RS ((uint)0x80000000) /* 0 == reset */
|
||||
|
||||
/* cpm serial driver works with constants below */
|
||||
|
||||
#define SIU_INT_SMC1 ((uint)0x04+CPM_IRQ_OFFSET)
|
||||
#define SIU_INT_SMC2i ((uint)0x05+CPM_IRQ_OFFSET)
|
||||
#define SIU_INT_SCC1 ((uint)0x28+CPM_IRQ_OFFSET)
|
||||
#define SIU_INT_SCC2 ((uint)0x29+CPM_IRQ_OFFSET)
|
||||
#define SIU_INT_SCC3 ((uint)0x2a+CPM_IRQ_OFFSET)
|
||||
#define SIU_INT_SCC4 ((uint)0x2b+CPM_IRQ_OFFSET)
|
||||
|
||||
void m82xx_pci_init_irq(void);
|
||||
void mpc82xx_ads_show_cpuinfo(struct seq_file*);
|
||||
void m82xx_calibrate_decr(void);
|
||||
|
||||
#endif /* __MACH_ADS8260_DEFS */
|
||||
#endif /* __KERNEL__ */
|
|
@ -5,6 +5,13 @@ choice
|
|||
prompt "Machine Type"
|
||||
default MPC834x_SYS
|
||||
|
||||
config MPC832x_MDS
|
||||
bool "Freescale MPC832x MDS"
|
||||
select DEFAULT_UIMAGE
|
||||
select QUICC_ENGINE
|
||||
help
|
||||
This option enables support for the MPC832x MDS evaluation board.
|
||||
|
||||
config MPC834x_SYS
|
||||
bool "Freescale MPC834x SYS"
|
||||
select DEFAULT_UIMAGE
|
||||
|
@ -27,6 +34,12 @@ config MPC834x_ITX
|
|||
|
||||
endchoice
|
||||
|
||||
config PPC_MPC832x
|
||||
bool
|
||||
select PPC_UDBG_16550
|
||||
select PPC_INDIRECT_PCI
|
||||
default y if MPC832x_MDS
|
||||
|
||||
config MPC834x
|
||||
bool
|
||||
select PPC_UDBG_16550
|
||||
|
|
215
arch/powerpc/platforms/83xx/mpc832x_mds.c
Normal file
215
arch/powerpc/platforms/83xx/mpc832x_mds.c
Normal file
|
@ -0,0 +1,215 @@
|
|||
/*
|
||||
* Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
|
||||
*
|
||||
* Description:
|
||||
* MPC832xE MDS board specific routines.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/initrd.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <asm/qe.h>
|
||||
#include <asm/qe_ic.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
#include "mpc832x_mds.h"
|
||||
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PCI
|
||||
unsigned long isa_io_base = 0;
|
||||
unsigned long isa_mem_base = 0;
|
||||
#endif
|
||||
|
||||
static u8 *bcsr_regs = NULL;
|
||||
|
||||
u8 *get_bcsr(void)
|
||||
{
|
||||
return bcsr_regs;
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init mpc832x_sys_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc832x_sys_setup_arch()", 0);
|
||||
|
||||
np = of_find_node_by_type(NULL, "cpu");
|
||||
if (np != 0) {
|
||||
unsigned int *fp =
|
||||
(int *)get_property(np, "clock-frequency", NULL);
|
||||
if (fp != 0)
|
||||
loops_per_jiffy = *fp / HZ;
|
||||
else
|
||||
loops_per_jiffy = 50000000 / HZ;
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
/* Map BCSR area */
|
||||
np = of_find_node_by_name(NULL, "bcsr");
|
||||
if (np != 0) {
|
||||
struct resource res;
|
||||
|
||||
of_address_to_resource(np, 0, &res);
|
||||
bcsr_regs = ioremap(res.start, res.end - res.start +1);
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
|
||||
add_bridge(np);
|
||||
|
||||
ppc_md.pci_swizzle = common_swizzle;
|
||||
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
qe_reset();
|
||||
|
||||
if ((np = of_find_node_by_name(np, "par_io")) != NULL) {
|
||||
par_io_init(np);
|
||||
of_node_put(np);
|
||||
|
||||
for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
|
||||
par_io_of_config(np);
|
||||
}
|
||||
|
||||
if ((np = of_find_compatible_node(NULL, "network", "ucc_geth"))
|
||||
!= NULL){
|
||||
/* Reset the Ethernet PHY */
|
||||
bcsr_regs[9] &= ~0x20;
|
||||
udelay(1000);
|
||||
bcsr_regs[9] |= 0x20;
|
||||
iounmap(bcsr_regs);
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (initrd_start)
|
||||
ROOT_DEV = Root_RAM0;
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_ROOT_NFS
|
||||
ROOT_DEV = Root_NFS;
|
||||
#else
|
||||
ROOT_DEV = Root_HDA1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init mpc832x_sys_init_IRQ(void)
|
||||
{
|
||||
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_node_by_type(NULL, "ipic");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
ipic_init(np, 0);
|
||||
|
||||
/* Initialize the default interrupt mapping priorities,
|
||||
* in case the boot rom changed something on us.
|
||||
*/
|
||||
ipic_set_default_priority();
|
||||
of_node_put(np);
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
np = of_find_node_by_type(NULL, "qeic");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
qe_ic_init(np, 0);
|
||||
of_node_put(np);
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
|
||||
extern ulong ds1374_get_rtc_time(void);
|
||||
extern int ds1374_set_rtc_time(ulong);
|
||||
|
||||
static int __init mpc832x_rtc_hookup(void)
|
||||
{
|
||||
struct timespec tv;
|
||||
|
||||
ppc_md.get_rtc_time = ds1374_get_rtc_time;
|
||||
ppc_md.set_rtc_time = ds1374_set_rtc_time;
|
||||
|
||||
tv.tv_nsec = 0;
|
||||
tv.tv_sec = (ppc_md.get_rtc_time) ();
|
||||
do_settimeofday(&tv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(mpc832x_rtc_hookup);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc832x_sys_probe(void)
|
||||
{
|
||||
char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
|
||||
"model", NULL);
|
||||
|
||||
if (model == NULL)
|
||||
return 0;
|
||||
if (strcmp(model, "MPC8323EMDS"))
|
||||
return 0;
|
||||
|
||||
DBG("%s found\n", model);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
define_machine(mpc832x_mds) {
|
||||
.name = "MPC832x MDS",
|
||||
.probe = mpc832x_sys_probe,
|
||||
.setup_arch = mpc832x_sys_setup_arch,
|
||||
.init_IRQ = mpc832x_sys_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
19
arch/powerpc/platforms/83xx/mpc832x_mds.h
Normal file
19
arch/powerpc/platforms/83xx/mpc832x_mds.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
|
||||
*
|
||||
* Description:
|
||||
* MPC832x MDS board specific header.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MACH_MPC832x_MDS_H__
|
||||
#define __MACH_MPC832x_MDS_H__
|
||||
|
||||
extern u8 *get_bcsr(void);
|
||||
|
||||
#endif /* __MACH_MPC832x_MDS_H__ */
|
219
arch/powerpc/platforms/83xx/mpc8360e_pb.c
Normal file
219
arch/powerpc/platforms/83xx/mpc8360e_pb.c
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
|
||||
*
|
||||
* Author: Li Yang <LeoLi@freescale.com>
|
||||
* Yin Olivia <Hong-hua.Yin@freescale.com>
|
||||
*
|
||||
* Description:
|
||||
* MPC8360E MDS PB board specific routines.
|
||||
*
|
||||
* Changelog:
|
||||
* Jun 21, 2006 Initial version
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/console.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/root_dev.h>
|
||||
#include <linux/initrd.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/ipic.h>
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <asm/qe.h>
|
||||
#include <asm/qe_ic.h>
|
||||
|
||||
#include "mpc83xx.h"
|
||||
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DBG(fmt...) udbg_printf(fmt)
|
||||
#else
|
||||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_PCI
|
||||
unsigned long isa_io_base = 0;
|
||||
unsigned long isa_mem_base = 0;
|
||||
#endif
|
||||
|
||||
static u8 *bcsr_regs = NULL;
|
||||
|
||||
u8 *get_bcsr(void)
|
||||
{
|
||||
return bcsr_regs;
|
||||
}
|
||||
|
||||
/* ************************************************************************
|
||||
*
|
||||
* Setup the architecture
|
||||
*
|
||||
*/
|
||||
static void __init mpc8360_sys_setup_arch(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
if (ppc_md.progress)
|
||||
ppc_md.progress("mpc8360_sys_setup_arch()", 0);
|
||||
|
||||
np = of_find_node_by_type(NULL, "cpu");
|
||||
if (np != 0) {
|
||||
const unsigned int *fp =
|
||||
get_property(np, "clock-frequency", NULL);
|
||||
if (fp != 0)
|
||||
loops_per_jiffy = *fp / HZ;
|
||||
else
|
||||
loops_per_jiffy = 50000000 / HZ;
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
/* Map BCSR area */
|
||||
np = of_find_node_by_name(NULL, "bcsr");
|
||||
if (np != 0) {
|
||||
struct resource res;
|
||||
|
||||
of_address_to_resource(np, 0, &res);
|
||||
bcsr_regs = ioremap(res.start, res.end - res.start +1);
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
|
||||
add_bridge(np);
|
||||
|
||||
ppc_md.pci_swizzle = common_swizzle;
|
||||
ppc_md.pci_exclude_device = mpc83xx_exclude_device;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
qe_reset();
|
||||
|
||||
if ((np = of_find_node_by_name(np, "par_io")) != NULL) {
|
||||
par_io_init(np);
|
||||
of_node_put(np);
|
||||
|
||||
for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
|
||||
par_io_of_config(np);
|
||||
}
|
||||
|
||||
if ((np = of_find_compatible_node(NULL, "network", "ucc_geth"))
|
||||
!= NULL){
|
||||
/* Reset the Ethernet PHY */
|
||||
bcsr_regs[9] &= ~0x20;
|
||||
udelay(1000);
|
||||
bcsr_regs[9] |= 0x20;
|
||||
iounmap(bcsr_regs);
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
if (initrd_start)
|
||||
ROOT_DEV = Root_RAM0;
|
||||
else
|
||||
#endif
|
||||
#ifdef CONFIG_ROOT_NFS
|
||||
ROOT_DEV = Root_NFS;
|
||||
#else
|
||||
ROOT_DEV = Root_HDA1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init mpc8360_sys_init_IRQ(void)
|
||||
{
|
||||
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_node_by_type(NULL, "ipic");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
ipic_init(np, 0);
|
||||
|
||||
/* Initialize the default interrupt mapping priorities,
|
||||
* in case the boot rom changed something on us.
|
||||
*/
|
||||
ipic_set_default_priority();
|
||||
of_node_put(np);
|
||||
|
||||
#ifdef CONFIG_QUICC_ENGINE
|
||||
np = of_find_node_by_type(NULL, "qeic");
|
||||
if (!np)
|
||||
return;
|
||||
|
||||
qe_ic_init(np, 0);
|
||||
of_node_put(np);
|
||||
#endif /* CONFIG_QUICC_ENGINE */
|
||||
}
|
||||
|
||||
#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
|
||||
extern ulong ds1374_get_rtc_time(void);
|
||||
extern int ds1374_set_rtc_time(ulong);
|
||||
|
||||
static int __init mpc8360_rtc_hookup(void)
|
||||
{
|
||||
struct timespec tv;
|
||||
|
||||
ppc_md.get_rtc_time = ds1374_get_rtc_time;
|
||||
ppc_md.set_rtc_time = ds1374_set_rtc_time;
|
||||
|
||||
tv.tv_nsec = 0;
|
||||
tv.tv_sec = (ppc_md.get_rtc_time) ();
|
||||
do_settimeofday(&tv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
late_initcall(mpc8360_rtc_hookup);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Called very early, MMU is off, device-tree isn't unflattened
|
||||
*/
|
||||
static int __init mpc8360_sys_probe(void)
|
||||
{
|
||||
char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
|
||||
"model", NULL);
|
||||
if (model == NULL)
|
||||
return 0;
|
||||
if (strcmp(model, "MPC8360EPB"))
|
||||
return 0;
|
||||
|
||||
DBG("MPC8360EMDS-PB found\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
define_machine(mpc8360_sys) {
|
||||
.name = "MPC8360E PB",
|
||||
.probe = mpc8360_sys_probe,
|
||||
.setup_arch = mpc8360_sys_setup_arch,
|
||||
.init_IRQ = mpc8360_sys_init_IRQ,
|
||||
.get_irq = ipic_get_irq,
|
||||
.restart = mpc83xx_restart,
|
||||
.time_init = mpc83xx_time_init,
|
||||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = udbg_progress,
|
||||
};
|
|
@ -21,6 +21,12 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* TODO:
|
||||
* - Fix various assumptions related to HW CPU numbers vs. linux CPU numbers
|
||||
* vs node numbers in the setup code
|
||||
* - Implement proper handling of maxcpus=1/2 (that is, routing of irqs from
|
||||
* a non-active node to the active node)
|
||||
*/
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
|
@ -44,24 +50,25 @@ struct iic {
|
|||
u8 target_id;
|
||||
u8 eoi_stack[16];
|
||||
int eoi_ptr;
|
||||
struct irq_host *host;
|
||||
struct device_node *node;
|
||||
};
|
||||
|
||||
static DEFINE_PER_CPU(struct iic, iic);
|
||||
#define IIC_NODE_COUNT 2
|
||||
static struct irq_host *iic_hosts[IIC_NODE_COUNT];
|
||||
static struct irq_host *iic_host;
|
||||
|
||||
/* Convert between "pending" bits and hw irq number */
|
||||
static irq_hw_number_t iic_pending_to_hwnum(struct cbe_iic_pending_bits bits)
|
||||
{
|
||||
unsigned char unit = bits.source & 0xf;
|
||||
unsigned char node = bits.source >> 4;
|
||||
unsigned char class = bits.class & 3;
|
||||
|
||||
/* Decode IPIs */
|
||||
if (bits.flags & CBE_IIC_IRQ_IPI)
|
||||
return IIC_IRQ_IPI0 | (bits.prio >> 4);
|
||||
else if (bits.class <= 3)
|
||||
return (bits.class << 4) | unit;
|
||||
return IIC_IRQ_TYPE_IPI | (bits.prio >> 4);
|
||||
else
|
||||
return IIC_IRQ_INVALID;
|
||||
return (node << IIC_IRQ_NODE_SHIFT) | (class << 4) | unit;
|
||||
}
|
||||
|
||||
static void iic_mask(unsigned int irq)
|
||||
|
@ -86,21 +93,70 @@ static struct irq_chip iic_chip = {
|
|||
.eoi = iic_eoi,
|
||||
};
|
||||
|
||||
|
||||
static void iic_ioexc_eoi(unsigned int irq)
|
||||
{
|
||||
}
|
||||
|
||||
static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct cbe_iic_regs *node_iic = desc->handler_data;
|
||||
unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
|
||||
unsigned long bits, ack;
|
||||
int cascade;
|
||||
|
||||
for (;;) {
|
||||
bits = in_be64(&node_iic->iic_is);
|
||||
if (bits == 0)
|
||||
break;
|
||||
/* pre-ack edge interrupts */
|
||||
ack = bits & IIC_ISR_EDGE_MASK;
|
||||
if (ack)
|
||||
out_be64(&node_iic->iic_is, ack);
|
||||
/* handle them */
|
||||
for (cascade = 63; cascade >= 0; cascade--)
|
||||
if (bits & (0x8000000000000000UL >> cascade)) {
|
||||
unsigned int cirq =
|
||||
irq_linear_revmap(iic_host,
|
||||
base | cascade);
|
||||
if (cirq != NO_IRQ)
|
||||
generic_handle_irq(cirq, regs);
|
||||
}
|
||||
/* post-ack level interrupts */
|
||||
ack = bits & ~IIC_ISR_EDGE_MASK;
|
||||
if (ack)
|
||||
out_be64(&node_iic->iic_is, ack);
|
||||
}
|
||||
desc->chip->eoi(irq);
|
||||
}
|
||||
|
||||
|
||||
static struct irq_chip iic_ioexc_chip = {
|
||||
.typename = " CELL-IOEX",
|
||||
.mask = iic_mask,
|
||||
.unmask = iic_unmask,
|
||||
.eoi = iic_ioexc_eoi,
|
||||
};
|
||||
|
||||
/* Get an IRQ number from the pending state register of the IIC */
|
||||
static unsigned int iic_get_irq(struct pt_regs *regs)
|
||||
{
|
||||
struct cbe_iic_pending_bits pending;
|
||||
struct iic *iic;
|
||||
unsigned int virq;
|
||||
|
||||
iic = &__get_cpu_var(iic);
|
||||
*(unsigned long *) &pending =
|
||||
in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
|
||||
if (!(pending.flags & CBE_IIC_IRQ_VALID))
|
||||
return NO_IRQ;
|
||||
virq = irq_linear_revmap(iic_host, iic_pending_to_hwnum(pending));
|
||||
if (virq == NO_IRQ)
|
||||
return NO_IRQ;
|
||||
iic->eoi_stack[++iic->eoi_ptr] = pending.prio;
|
||||
BUG_ON(iic->eoi_ptr > 15);
|
||||
if (pending.flags & CBE_IIC_IRQ_VALID)
|
||||
return irq_linear_revmap(iic->host,
|
||||
iic_pending_to_hwnum(pending));
|
||||
return NO_IRQ;
|
||||
return virq;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
@ -108,12 +164,7 @@ static unsigned int iic_get_irq(struct pt_regs *regs)
|
|||
/* Use the highest interrupt priorities for IPI */
|
||||
static inline int iic_ipi_to_irq(int ipi)
|
||||
{
|
||||
return IIC_IRQ_IPI0 + IIC_NUM_IPIS - 1 - ipi;
|
||||
}
|
||||
|
||||
static inline int iic_irq_to_ipi(int irq)
|
||||
{
|
||||
return IIC_NUM_IPIS - 1 - (irq - IIC_IRQ_IPI0);
|
||||
return IIC_IRQ_TYPE_IPI + 0xf - ipi;
|
||||
}
|
||||
|
||||
void iic_setup_cpu(void)
|
||||
|
@ -123,7 +174,7 @@ void iic_setup_cpu(void)
|
|||
|
||||
void iic_cause_IPI(int cpu, int mesg)
|
||||
{
|
||||
out_be64(&per_cpu(iic, cpu).regs->generate, (IIC_NUM_IPIS - 1 - mesg) << 4);
|
||||
out_be64(&per_cpu(iic, cpu).regs->generate, (0xf - mesg) << 4);
|
||||
}
|
||||
|
||||
u8 iic_get_target_id(int cpu)
|
||||
|
@ -134,9 +185,7 @@ EXPORT_SYMBOL_GPL(iic_get_target_id);
|
|||
|
||||
struct irq_host *iic_get_irq_host(int node)
|
||||
{
|
||||
if (node < 0 || node >= IIC_NODE_COUNT)
|
||||
return NULL;
|
||||
return iic_hosts[node];
|
||||
return iic_host;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iic_get_irq_host);
|
||||
|
||||
|
@ -149,34 +198,20 @@ static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
|
|||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void iic_request_ipi(int ipi, const char *name)
|
||||
{
|
||||
int node, virq;
|
||||
int virq;
|
||||
|
||||
for (node = 0; node < IIC_NODE_COUNT; node++) {
|
||||
char *rname;
|
||||
if (iic_hosts[node] == NULL)
|
||||
continue;
|
||||
virq = irq_create_mapping(iic_hosts[node],
|
||||
iic_ipi_to_irq(ipi));
|
||||
if (virq == NO_IRQ) {
|
||||
printk(KERN_ERR
|
||||
"iic: failed to map IPI %s on node %d\n",
|
||||
name, node);
|
||||
continue;
|
||||
}
|
||||
rname = kzalloc(strlen(name) + 16, GFP_KERNEL);
|
||||
if (rname)
|
||||
sprintf(rname, "%s node %d", name, node);
|
||||
else
|
||||
rname = (char *)name;
|
||||
if (request_irq(virq, iic_ipi_action, IRQF_DISABLED,
|
||||
rname, (void *)(long)ipi))
|
||||
printk(KERN_ERR
|
||||
"iic: failed to request IPI %s on node %d\n",
|
||||
name, node);
|
||||
virq = irq_create_mapping(iic_host, iic_ipi_to_irq(ipi));
|
||||
if (virq == NO_IRQ) {
|
||||
printk(KERN_ERR
|
||||
"iic: failed to map IPI %s\n", name);
|
||||
return;
|
||||
}
|
||||
if (request_irq(virq, iic_ipi_action, IRQF_DISABLED, name,
|
||||
(void *)(long)ipi))
|
||||
printk(KERN_ERR
|
||||
"iic: failed to request IPI %s\n", name);
|
||||
}
|
||||
|
||||
void iic_request_IPIs(void)
|
||||
|
@ -193,16 +228,24 @@ void iic_request_IPIs(void)
|
|||
|
||||
static int iic_host_match(struct irq_host *h, struct device_node *node)
|
||||
{
|
||||
return h->host_data != NULL && node == h->host_data;
|
||||
return device_is_compatible(node,
|
||||
"IBM,CBEA-Internal-Interrupt-Controller");
|
||||
}
|
||||
|
||||
static int iic_host_map(struct irq_host *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
if (hw < IIC_IRQ_IPI0)
|
||||
set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
|
||||
else
|
||||
switch (hw & IIC_IRQ_TYPE_MASK) {
|
||||
case IIC_IRQ_TYPE_IPI:
|
||||
set_irq_chip_and_handler(virq, &iic_chip, handle_percpu_irq);
|
||||
break;
|
||||
case IIC_IRQ_TYPE_IOEXC:
|
||||
set_irq_chip_and_handler(virq, &iic_ioexc_chip,
|
||||
handle_fasteoi_irq);
|
||||
break;
|
||||
default:
|
||||
set_irq_chip_and_handler(virq, &iic_chip, handle_fasteoi_irq);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -211,11 +254,39 @@ static int iic_host_xlate(struct irq_host *h, struct device_node *ct,
|
|||
irq_hw_number_t *out_hwirq, unsigned int *out_flags)
|
||||
|
||||
{
|
||||
/* Currently, we don't translate anything. That needs to be fixed as
|
||||
* we get better defined device-trees. iic interrupts have to be
|
||||
* explicitely mapped by whoever needs them
|
||||
*/
|
||||
return -ENODEV;
|
||||
unsigned int node, ext, unit, class;
|
||||
const u32 *val;
|
||||
|
||||
if (!device_is_compatible(ct,
|
||||
"IBM,CBEA-Internal-Interrupt-Controller"))
|
||||
return -ENODEV;
|
||||
if (intsize != 1)
|
||||
return -ENODEV;
|
||||
val = get_property(ct, "#interrupt-cells", NULL);
|
||||
if (val == NULL || *val != 1)
|
||||
return -ENODEV;
|
||||
|
||||
node = intspec[0] >> 24;
|
||||
ext = (intspec[0] >> 16) & 0xff;
|
||||
class = (intspec[0] >> 8) & 0xff;
|
||||
unit = intspec[0] & 0xff;
|
||||
|
||||
/* Check if node is in supported range */
|
||||
if (node > 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Build up interrupt number, special case for IO exceptions */
|
||||
*out_hwirq = (node << IIC_IRQ_NODE_SHIFT);
|
||||
if (unit == IIC_UNIT_IIC && class == 1)
|
||||
*out_hwirq |= IIC_IRQ_TYPE_IOEXC | ext;
|
||||
else
|
||||
*out_hwirq |= IIC_IRQ_TYPE_NORMAL |
|
||||
(class << IIC_IRQ_CLASS_SHIFT) | unit;
|
||||
|
||||
/* Dummy flags, ignored by iic code */
|
||||
*out_flags = IRQ_TYPE_EDGE_RISING;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_host_ops iic_host_ops = {
|
||||
|
@ -225,7 +296,7 @@ static struct irq_host_ops iic_host_ops = {
|
|||
};
|
||||
|
||||
static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
|
||||
struct irq_host *host)
|
||||
struct device_node *node)
|
||||
{
|
||||
/* XXX FIXME: should locate the linux CPU number from the HW cpu
|
||||
* number properly. We are lucky for now
|
||||
|
@ -237,19 +308,19 @@ static void __init init_one_iic(unsigned int hw_cpu, unsigned long addr,
|
|||
|
||||
iic->target_id = ((hw_cpu & 2) << 3) | ((hw_cpu & 1) ? 0xf : 0xe);
|
||||
iic->eoi_stack[0] = 0xff;
|
||||
iic->host = host;
|
||||
iic->node = of_node_get(node);
|
||||
out_be64(&iic->regs->prio, 0);
|
||||
|
||||
printk(KERN_INFO "IIC for CPU %d at %lx mapped to %p, target id 0x%x\n",
|
||||
hw_cpu, addr, iic->regs, iic->target_id);
|
||||
printk(KERN_INFO "IIC for CPU %d target id 0x%x : %s\n",
|
||||
hw_cpu, iic->target_id, node->full_name);
|
||||
}
|
||||
|
||||
static int __init setup_iic(void)
|
||||
{
|
||||
struct device_node *dn;
|
||||
struct resource r0, r1;
|
||||
struct irq_host *host;
|
||||
int found = 0;
|
||||
unsigned int node, cascade, found = 0;
|
||||
struct cbe_iic_regs *node_iic;
|
||||
const u32 *np;
|
||||
|
||||
for (dn = NULL;
|
||||
|
@ -269,19 +340,33 @@ static int __init setup_iic(void)
|
|||
of_node_put(dn);
|
||||
return -ENODEV;
|
||||
}
|
||||
host = NULL;
|
||||
if (found < IIC_NODE_COUNT) {
|
||||
host = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
|
||||
IIC_SOURCE_COUNT,
|
||||
&iic_host_ops,
|
||||
IIC_IRQ_INVALID);
|
||||
iic_hosts[found] = host;
|
||||
BUG_ON(iic_hosts[found] == NULL);
|
||||
iic_hosts[found]->host_data = of_node_get(dn);
|
||||
found++;
|
||||
}
|
||||
init_one_iic(np[0], r0.start, host);
|
||||
init_one_iic(np[1], r1.start, host);
|
||||
found++;
|
||||
init_one_iic(np[0], r0.start, dn);
|
||||
init_one_iic(np[1], r1.start, dn);
|
||||
|
||||
/* Setup cascade for IO exceptions. XXX cleanup tricks to get
|
||||
* node vs CPU etc...
|
||||
* Note that we configure the IIC_IRR here with a hard coded
|
||||
* priority of 1. We might want to improve that later.
|
||||
*/
|
||||
node = np[0] >> 1;
|
||||
node_iic = cbe_get_cpu_iic_regs(np[0]);
|
||||
cascade = node << IIC_IRQ_NODE_SHIFT;
|
||||
cascade |= 1 << IIC_IRQ_CLASS_SHIFT;
|
||||
cascade |= IIC_UNIT_IIC;
|
||||
cascade = irq_create_mapping(iic_host, cascade);
|
||||
if (cascade == NO_IRQ)
|
||||
continue;
|
||||
set_irq_data(cascade, node_iic);
|
||||
set_irq_chained_handler(cascade , iic_ioexc_cascade);
|
||||
out_be64(&node_iic->iic_ir,
|
||||
(1 << 12) /* priority */ |
|
||||
(node << 4) /* dest node */ |
|
||||
IIC_UNIT_THREAD_0 /* route them to thread 0 */);
|
||||
/* Flush pending (make sure it triggers if there is
|
||||
* anything pending
|
||||
*/
|
||||
out_be64(&node_iic->iic_is, 0xfffffffffffffffful);
|
||||
}
|
||||
|
||||
if (found)
|
||||
|
@ -292,6 +377,12 @@ static int __init setup_iic(void)
|
|||
|
||||
void __init iic_init_IRQ(void)
|
||||
{
|
||||
/* Setup an irq host data structure */
|
||||
iic_host = irq_alloc_host(IRQ_HOST_MAP_LINEAR, IIC_SOURCE_COUNT,
|
||||
&iic_host_ops, IIC_IRQ_INVALID);
|
||||
BUG_ON(iic_host == NULL);
|
||||
irq_set_default_host(iic_host);
|
||||
|
||||
/* Discover and initialize iics */
|
||||
if (setup_iic() < 0)
|
||||
panic("IIC: Failed to initialize !\n");
|
||||
|
|
|
@ -2,48 +2,76 @@
|
|||
#define ASM_CELL_PIC_H
|
||||
#ifdef __KERNEL__
|
||||
/*
|
||||
* Mapping of IIC pending bits into per-node
|
||||
* interrupt numbers.
|
||||
* Mapping of IIC pending bits into per-node interrupt numbers.
|
||||
*
|
||||
* IRQ FF CC SS PP FF CC SS PP Description
|
||||
* Interrupt numbers are in the range 0...0x1ff where the top bit
|
||||
* (0x100) represent the source node. Only 2 nodes are supported with
|
||||
* the current code though it's trivial to extend that if necessary using
|
||||
* higher level bits
|
||||
*
|
||||
* 00-3f 80 02 +0 00 - 80 02 +0 3f South Bridge
|
||||
* 00-3f 80 02 +b 00 - 80 02 +b 3f South Bridge
|
||||
* 41-4a 80 00 +1 ** - 80 00 +a ** SPU Class 0
|
||||
* 51-5a 80 01 +1 ** - 80 01 +a ** SPU Class 1
|
||||
* 61-6a 80 02 +1 ** - 80 02 +a ** SPU Class 2
|
||||
* 70-7f C0 ** ** 00 - C0 ** ** 0f IPI
|
||||
* The bottom 8 bits are split into 2 type bits and 6 data bits that
|
||||
* depend on the type:
|
||||
*
|
||||
* F flags
|
||||
* C class
|
||||
* S source
|
||||
* P Priority
|
||||
* + node number
|
||||
* * don't care
|
||||
* 00 (0x00 | data) : normal interrupt. data is (class << 4) | source
|
||||
* 01 (0x40 | data) : IO exception. data is the exception number as
|
||||
* defined by bit numbers in IIC_SR
|
||||
* 10 (0x80 | data) : IPI. data is the IPI number (obtained from the priority)
|
||||
* and node is always 0 (IPIs are per-cpu, their source is
|
||||
* not relevant)
|
||||
* 11 (0xc0 | data) : reserved
|
||||
*
|
||||
* A node consists of a Cell Broadband Engine and an optional
|
||||
* south bridge device providing a maximum of 64 IRQs.
|
||||
* The south bridge may be connected to either IOIF0
|
||||
* or IOIF1.
|
||||
* Each SPE is represented as three IRQ lines, one per
|
||||
* interrupt class.
|
||||
* 16 IRQ numbers are reserved for inter processor
|
||||
* interruptions, although these are only used in the
|
||||
* range of the first node.
|
||||
* In addition, interrupt number 0x80000000 is defined as always invalid
|
||||
* (that is the node field is expected to never extend to move than 23 bits)
|
||||
*
|
||||
* This scheme needs 128 IRQ numbers per BIF node ID,
|
||||
* which means that with the total of 512 lines
|
||||
* available, we can have a maximum of four nodes.
|
||||
*/
|
||||
|
||||
enum {
|
||||
IIC_IRQ_INVALID = 0xff,
|
||||
IIC_IRQ_MAX = 0x3f,
|
||||
IIC_IRQ_EXT_IOIF0 = 0x20,
|
||||
IIC_IRQ_EXT_IOIF1 = 0x2b,
|
||||
IIC_IRQ_IPI0 = 0x40,
|
||||
IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */
|
||||
IIC_SOURCE_COUNT = 0x50,
|
||||
IIC_IRQ_INVALID = 0x80000000u,
|
||||
IIC_IRQ_NODE_MASK = 0x100,
|
||||
IIC_IRQ_NODE_SHIFT = 8,
|
||||
IIC_IRQ_MAX = 0x1ff,
|
||||
IIC_IRQ_TYPE_MASK = 0xc0,
|
||||
IIC_IRQ_TYPE_NORMAL = 0x00,
|
||||
IIC_IRQ_TYPE_IOEXC = 0x40,
|
||||
IIC_IRQ_TYPE_IPI = 0x80,
|
||||
IIC_IRQ_CLASS_SHIFT = 4,
|
||||
IIC_IRQ_CLASS_0 = 0x00,
|
||||
IIC_IRQ_CLASS_1 = 0x10,
|
||||
IIC_IRQ_CLASS_2 = 0x20,
|
||||
IIC_SOURCE_COUNT = 0x200,
|
||||
|
||||
/* Here are defined the various source/dest units. Avoid using those
|
||||
* definitions if you can, they are mostly here for reference
|
||||
*/
|
||||
IIC_UNIT_SPU_0 = 0x4,
|
||||
IIC_UNIT_SPU_1 = 0x7,
|
||||
IIC_UNIT_SPU_2 = 0x3,
|
||||
IIC_UNIT_SPU_3 = 0x8,
|
||||
IIC_UNIT_SPU_4 = 0x2,
|
||||
IIC_UNIT_SPU_5 = 0x9,
|
||||
IIC_UNIT_SPU_6 = 0x1,
|
||||
IIC_UNIT_SPU_7 = 0xa,
|
||||
IIC_UNIT_IOC_0 = 0x0,
|
||||
IIC_UNIT_IOC_1 = 0xb,
|
||||
IIC_UNIT_THREAD_0 = 0xe, /* target only */
|
||||
IIC_UNIT_THREAD_1 = 0xf, /* target only */
|
||||
IIC_UNIT_IIC = 0xe, /* source only (IO exceptions) */
|
||||
|
||||
/* Base numbers for the external interrupts */
|
||||
IIC_IRQ_EXT_IOIF0 =
|
||||
IIC_IRQ_TYPE_NORMAL | IIC_IRQ_CLASS_2 | IIC_UNIT_IOC_0,
|
||||
IIC_IRQ_EXT_IOIF1 =
|
||||
IIC_IRQ_TYPE_NORMAL | IIC_IRQ_CLASS_2 | IIC_UNIT_IOC_1,
|
||||
|
||||
/* Base numbers for the IIC_ISR interrupts */
|
||||
IIC_IRQ_IOEX_TMI = IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 63,
|
||||
IIC_IRQ_IOEX_PMI = IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 62,
|
||||
IIC_IRQ_IOEX_ATI = IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 61,
|
||||
IIC_IRQ_IOEX_MATBFI = IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 60,
|
||||
IIC_IRQ_IOEX_ELDI = IIC_IRQ_TYPE_IOEXC | IIC_IRQ_CLASS_1 | 59,
|
||||
|
||||
/* Which bits in IIC_ISR are edge sensitive */
|
||||
IIC_ISR_EDGE_MASK = 0x4ul,
|
||||
};
|
||||
|
||||
extern void iic_init_IRQ(void);
|
||||
|
@ -52,7 +80,6 @@ extern void iic_request_IPIs(void);
|
|||
extern void iic_setup_cpu(void);
|
||||
|
||||
extern u8 iic_get_target_id(int cpu);
|
||||
extern struct irq_host *iic_get_irq_host(int node);
|
||||
|
||||
extern void spider_init_IRQ(void);
|
||||
|
||||
|
|
|
@ -243,7 +243,6 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
|
|||
const u32 *imap, *tmp;
|
||||
int imaplen, intsize, unit;
|
||||
struct device_node *iic;
|
||||
struct irq_host *iic_host;
|
||||
|
||||
#if 0 /* Enable that when we have a way to retreive the node as well */
|
||||
/* First, we check wether we have a real "interrupts" in the device
|
||||
|
@ -289,11 +288,11 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic)
|
|||
* the iic host from the iic OF node, but that way I'm still compatible
|
||||
* with really really old old firmwares for which we don't have a node
|
||||
*/
|
||||
iic_host = iic_get_irq_host(pic->node_id);
|
||||
if (iic_host == NULL)
|
||||
return NO_IRQ;
|
||||
/* Manufacture an IIC interrupt number of class 2 */
|
||||
virq = irq_create_mapping(iic_host, 0x20 | unit);
|
||||
virq = irq_create_mapping(NULL,
|
||||
(pic->node_id << IIC_IRQ_NODE_SHIFT) |
|
||||
(2 << IIC_IRQ_CLASS_SHIFT) |
|
||||
unit);
|
||||
if (virq == NO_IRQ)
|
||||
printk(KERN_ERR "spider_pic: failed to map cascade !");
|
||||
return virq;
|
||||
|
|
|
@ -568,24 +568,23 @@ static void spu_unmap(struct spu *spu)
|
|||
/* This function shall be abstracted for HV platforms */
|
||||
static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
|
||||
{
|
||||
struct irq_host *host;
|
||||
unsigned int isrc;
|
||||
const u32 *tmp;
|
||||
|
||||
host = iic_get_irq_host(spu->node);
|
||||
if (host == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
/* Get the interrupt source from the device-tree */
|
||||
/* Get the interrupt source unit from the device-tree */
|
||||
tmp = get_property(np, "isrc", NULL);
|
||||
if (!tmp)
|
||||
return -ENODEV;
|
||||
spu->isrc = isrc = tmp[0];
|
||||
isrc = tmp[0];
|
||||
|
||||
/* Add the node number */
|
||||
isrc |= spu->node << IIC_IRQ_NODE_SHIFT;
|
||||
spu->isrc = isrc;
|
||||
|
||||
/* Now map interrupts of all 3 classes */
|
||||
spu->irqs[0] = irq_create_mapping(host, 0x00 | isrc);
|
||||
spu->irqs[1] = irq_create_mapping(host, 0x10 | isrc);
|
||||
spu->irqs[2] = irq_create_mapping(host, 0x20 | isrc);
|
||||
spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc);
|
||||
spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc);
|
||||
spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc);
|
||||
|
||||
/* Right now, we only fail if class 2 failed */
|
||||
return spu->irqs[2] == NO_IRQ ? -EINVAL : 0;
|
||||
|
|
|
@ -262,14 +262,6 @@ void __init iSeries_pci_final_fixup(void)
|
|||
mf_display_src(0xC9000200);
|
||||
}
|
||||
|
||||
void pcibios_fixup_bus(struct pci_bus *PciBus)
|
||||
{
|
||||
}
|
||||
|
||||
void pcibios_fixup_resources(struct pci_dev *pdev)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Look down the chain to find the matching Device Device
|
||||
*/
|
||||
|
|
|
@ -649,15 +649,21 @@ static void iseries_dedicated_idle(void)
|
|||
void __init iSeries_init_IRQ(void) { }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* iSeries has no legacy IO, anything calling this function has to
|
||||
* fail or bad things will happen
|
||||
*/
|
||||
static int iseries_check_legacy_ioport(unsigned int baseport)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int __init iseries_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
if (!of_flat_dt_is_compatible(root, "IBM,iSeries"))
|
||||
return 0;
|
||||
|
||||
powerpc_firmware_features |= FW_FEATURE_ISERIES;
|
||||
powerpc_firmware_features |= FW_FEATURE_LPAR;
|
||||
|
||||
hpte_init_iSeries();
|
||||
|
||||
return 1;
|
||||
|
@ -680,6 +686,7 @@ define_machine(iseries) {
|
|||
.calibrate_decr = generic_calibrate_decr,
|
||||
.progress = iSeries_progress,
|
||||
.probe = iseries_probe,
|
||||
.check_legacy_ioport = iseries_check_legacy_ioport,
|
||||
/* XXX Implement enable_pmcs for iSeries */
|
||||
};
|
||||
|
||||
|
@ -687,6 +694,9 @@ void * __init iSeries_early_setup(void)
|
|||
{
|
||||
unsigned long phys_mem_size;
|
||||
|
||||
powerpc_firmware_features |= FW_FEATURE_ISERIES;
|
||||
powerpc_firmware_features |= FW_FEATURE_LPAR;
|
||||
|
||||
iSeries_fixup_klimit();
|
||||
|
||||
/*
|
||||
|
|
|
@ -111,8 +111,6 @@ void udbg_scc_init(int force_scc)
|
|||
pmac_call_feature(PMAC_FTR_SCC_ENABLE, ch,
|
||||
PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
|
||||
|
||||
|
||||
/* Setup for 57600 8N1 */
|
||||
if (ch == ch_a)
|
||||
addr += 0x20;
|
||||
sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
|
||||
|
@ -125,9 +123,21 @@ void udbg_scc_init(int force_scc)
|
|||
x = in_8(sccc);
|
||||
out_8(sccc, 0x09); /* reset A or B side */
|
||||
out_8(sccc, 0xc0);
|
||||
|
||||
/* If SCC was the OF output port, read the BRG value, else
|
||||
* Setup for 57600 8N1
|
||||
*/
|
||||
if (ch_def != NULL) {
|
||||
out_8(sccc, 13);
|
||||
scc_inittab[1] = in_8(sccc);
|
||||
out_8(sccc, 12);
|
||||
scc_inittab[3] = in_8(sccc);
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(scc_inittab); ++i)
|
||||
out_8(sccc, scc_inittab[i]);
|
||||
|
||||
|
||||
udbg_putc = udbg_scc_putc;
|
||||
udbg_getc = udbg_scc_getc;
|
||||
udbg_getc_poll = udbg_scc_getc_poll;
|
||||
|
|
|
@ -180,7 +180,7 @@ static void __init pseries_mpic_init_IRQ(void)
|
|||
|
||||
cascade_irq = irq_of_parse_and_map(cascade, 0);
|
||||
if (cascade == NO_IRQ) {
|
||||
printk(KERN_ERR "xics: failed to map cascade interrupt");
|
||||
printk(KERN_ERR "mpic: failed to map cascade interrupt");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o
|
|||
obj-$(CONFIG_FSL_SOC) += fsl_soc.o
|
||||
obj-$(CONFIG_PPC_TODC) += todc.o
|
||||
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
|
||||
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
|
||||
|
||||
ifeq ($(CONFIG_PPC_MERGE),y)
|
||||
obj-$(CONFIG_PPC_I8259) += i8259.o
|
||||
|
|
|
@ -147,7 +147,7 @@ static struct irq_chip cpm2_pic = {
|
|||
.end = cpm2_end_irq,
|
||||
};
|
||||
|
||||
int cpm2_get_irq(struct pt_regs *regs)
|
||||
unsigned int cpm2_get_irq(struct pt_regs *regs)
|
||||
{
|
||||
int irq;
|
||||
unsigned long bits;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
extern intctl_cpm2_t *cpm2_intctl;
|
||||
|
||||
extern int cpm2_get_irq(struct pt_regs *regs);
|
||||
extern unsigned int cpm2_get_irq(struct pt_regs *regs);
|
||||
|
||||
extern void cpm2_pic_init(struct device_node*);
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include <asm/cpm2.h>
|
||||
|
||||
extern void init_fcc_ioports(struct fs_platform_info*);
|
||||
extern void init_scc_ioports(struct fs_uart_platform_info*);
|
||||
static phys_addr_t immrbase = -1;
|
||||
|
||||
phys_addr_t get_immrbase(void)
|
||||
|
@ -566,7 +567,7 @@ static int __init fs_enet_of_init(void)
|
|||
struct resource r[4];
|
||||
struct device_node *phy, *mdio;
|
||||
struct fs_platform_info fs_enet_data;
|
||||
const unsigned int *id, *phy_addr;
|
||||
const unsigned int *id, *phy_addr, phy_irq;
|
||||
const void *mac_addr;
|
||||
const phandle *ph;
|
||||
const char *model;
|
||||
|
@ -588,6 +589,7 @@ static int __init fs_enet_of_init(void)
|
|||
if (ret)
|
||||
goto err;
|
||||
r[2].name = fcc_regs_c;
|
||||
fs_enet_data.fcc_regs_c = r[2].start;
|
||||
|
||||
r[3].start = r[3].end = irq_of_parse_and_map(np, 0);
|
||||
r[3].flags = IORESOURCE_IRQ;
|
||||
|
@ -620,6 +622,8 @@ static int __init fs_enet_of_init(void)
|
|||
phy_addr = get_property(phy, "reg", NULL);
|
||||
fs_enet_data.phy_addr = *phy_addr;
|
||||
|
||||
phy_irq = get_property(phy, "interrupts", NULL);
|
||||
|
||||
id = get_property(np, "device-id", NULL);
|
||||
fs_enet_data.fs_no = *id;
|
||||
strcpy(fs_enet_data.fs_type, model);
|
||||
|
@ -637,6 +641,7 @@ static int __init fs_enet_of_init(void)
|
|||
|
||||
if (strstr(model, "FCC")) {
|
||||
int fcc_index = *id - 1;
|
||||
unsigned char* mdio_bb_prop;
|
||||
|
||||
fs_enet_data.dpram_offset = (u32)cpm_dpram_addr(0);
|
||||
fs_enet_data.rx_ring = 32;
|
||||
|
@ -652,14 +657,57 @@ static int __init fs_enet_of_init(void)
|
|||
(u32)res.start, fs_enet_data.phy_addr);
|
||||
fs_enet_data.bus_id = (char*)&bus_id[(*id)];
|
||||
fs_enet_data.init_ioports = init_fcc_ioports;
|
||||
}
|
||||
|
||||
of_node_put(phy);
|
||||
of_node_put(mdio);
|
||||
mdio_bb_prop = get_property(phy, "bitbang", NULL);
|
||||
if (mdio_bb_prop) {
|
||||
struct platform_device *fs_enet_mdio_bb_dev;
|
||||
struct fs_mii_bb_platform_info fs_enet_mdio_bb_data;
|
||||
|
||||
ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
|
||||
sizeof(struct
|
||||
fs_platform_info));
|
||||
fs_enet_mdio_bb_dev =
|
||||
platform_device_register_simple("fsl-bb-mdio",
|
||||
i, NULL, 0);
|
||||
memset(&fs_enet_mdio_bb_data, 0,
|
||||
sizeof(struct fs_mii_bb_platform_info));
|
||||
fs_enet_mdio_bb_data.mdio_dat.bit =
|
||||
mdio_bb_prop[0];
|
||||
fs_enet_mdio_bb_data.mdio_dir.bit =
|
||||
mdio_bb_prop[1];
|
||||
fs_enet_mdio_bb_data.mdc_dat.bit =
|
||||
mdio_bb_prop[2];
|
||||
fs_enet_mdio_bb_data.mdio_port =
|
||||
mdio_bb_prop[3];
|
||||
fs_enet_mdio_bb_data.mdc_port =
|
||||
mdio_bb_prop[4];
|
||||
fs_enet_mdio_bb_data.delay =
|
||||
mdio_bb_prop[5];
|
||||
|
||||
fs_enet_mdio_bb_data.irq[0] = phy_irq[0];
|
||||
fs_enet_mdio_bb_data.irq[1] = -1;
|
||||
fs_enet_mdio_bb_data.irq[2] = -1;
|
||||
fs_enet_mdio_bb_data.irq[3] = phy_irq[0];
|
||||
fs_enet_mdio_bb_data.irq[31] = -1;
|
||||
|
||||
fs_enet_mdio_bb_data.mdio_dat.offset =
|
||||
(u32)&cpm2_immr->im_ioport.iop_pdatc;
|
||||
fs_enet_mdio_bb_data.mdio_dir.offset =
|
||||
(u32)&cpm2_immr->im_ioport.iop_pdirc;
|
||||
fs_enet_mdio_bb_data.mdc_dat.offset =
|
||||
(u32)&cpm2_immr->im_ioport.iop_pdatc;
|
||||
|
||||
ret = platform_device_add_data(
|
||||
fs_enet_mdio_bb_dev,
|
||||
&fs_enet_mdio_bb_data,
|
||||
sizeof(struct fs_mii_bb_platform_info));
|
||||
if (ret)
|
||||
goto unreg;
|
||||
}
|
||||
|
||||
of_node_put(phy);
|
||||
of_node_put(mdio);
|
||||
|
||||
ret = platform_device_add_data(fs_enet_dev, &fs_enet_data,
|
||||
sizeof(struct
|
||||
fs_platform_info));
|
||||
if (ret)
|
||||
goto unreg;
|
||||
}
|
||||
|
|
30
arch/powerpc/sysdev/qe_lib/Kconfig
Normal file
30
arch/powerpc/sysdev/qe_lib/Kconfig
Normal file
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# QE Communication options
|
||||
#
|
||||
|
||||
menu "QE Options"
|
||||
depends on QUICC_ENGINE
|
||||
|
||||
config UCC_SLOW
|
||||
bool "UCC Slow Protocols Support"
|
||||
default n
|
||||
select UCC
|
||||
help
|
||||
This option provides qe_lib support to UCC slow
|
||||
protocols: UART, BISYNC, QMC
|
||||
|
||||
config UCC_FAST
|
||||
bool "UCC Fast Protocols Support"
|
||||
default n
|
||||
select UCC
|
||||
select UCC_SLOW
|
||||
help
|
||||
This option provides qe_lib support to UCC fast
|
||||
protocols: HDLC, Ethernet, ATM, transparent
|
||||
|
||||
config UCC
|
||||
bool
|
||||
default y if UCC_FAST || UCC_SLOW
|
||||
|
||||
endmenu
|
||||
|
8
arch/powerpc/sysdev/qe_lib/Makefile
Normal file
8
arch/powerpc/sysdev/qe_lib/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
#
|
||||
# Makefile for the linux ppc-specific parts of QE
|
||||
#
|
||||
obj-$(CONFIG_QUICC_ENGINE)+= qe.o qe_ic.o qe_io.o
|
||||
|
||||
obj-$(CONFIG_UCC) += ucc.o
|
||||
obj-$(CONFIG_UCC_SLOW) += ucc_slow.o
|
||||
obj-$(CONFIG_UCC_FAST) += ucc_fast.o
|
353
arch/powerpc/sysdev/qe_lib/qe.c
Normal file
353
arch/powerpc/sysdev/qe_lib/qe.c
Normal file
|
@ -0,0 +1,353 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Authors: Shlomi Gridish <gridish@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
* Based on cpm2_common.c from Dan Malek (dmalek@jlc.net)
|
||||
*
|
||||
* Description:
|
||||
* General Purpose functions for the global management of the
|
||||
* QUICC Engine (QE).
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#include <linux/errno.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/param.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/immap_qe.h>
|
||||
#include <asm/qe.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/rheap.h>
|
||||
|
||||
static void qe_snums_init(void);
|
||||
static void qe_muram_init(void);
|
||||
static int qe_sdma_init(void);
|
||||
|
||||
static DEFINE_SPINLOCK(qe_lock);
|
||||
|
||||
/* QE snum state */
|
||||
enum qe_snum_state {
|
||||
QE_SNUM_STATE_USED,
|
||||
QE_SNUM_STATE_FREE
|
||||
};
|
||||
|
||||
/* QE snum */
|
||||
struct qe_snum {
|
||||
u8 num;
|
||||
enum qe_snum_state state;
|
||||
};
|
||||
|
||||
/* We allocate this here because it is used almost exclusively for
|
||||
* the communication processor devices.
|
||||
*/
|
||||
struct qe_immap *qe_immr = NULL;
|
||||
EXPORT_SYMBOL(qe_immr);
|
||||
|
||||
static struct qe_snum snums[QE_NUM_OF_SNUM]; /* Dynamically allocated SNUMs */
|
||||
|
||||
static phys_addr_t qebase = -1;
|
||||
|
||||
phys_addr_t get_qe_base(void)
|
||||
{
|
||||
struct device_node *qe;
|
||||
|
||||
if (qebase != -1)
|
||||
return qebase;
|
||||
|
||||
qe = of_find_node_by_type(NULL, "qe");
|
||||
if (qe) {
|
||||
unsigned int size;
|
||||
const void *prop = get_property(qe, "reg", &size);
|
||||
qebase = of_translate_address(qe, prop);
|
||||
of_node_put(qe);
|
||||
};
|
||||
|
||||
return qebase;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(get_qe_base);
|
||||
|
||||
void qe_reset(void)
|
||||
{
|
||||
if (qe_immr == NULL)
|
||||
qe_immr = ioremap(get_qe_base(), QE_IMMAP_SIZE);
|
||||
|
||||
qe_snums_init();
|
||||
|
||||
qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
|
||||
QE_CR_PROTOCOL_UNSPECIFIED, 0);
|
||||
|
||||
/* Reclaim the MURAM memory for our use. */
|
||||
qe_muram_init();
|
||||
|
||||
if (qe_sdma_init())
|
||||
panic("sdma init failed!");
|
||||
}
|
||||
|
||||
int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
|
||||
{
|
||||
unsigned long flags;
|
||||
u8 mcn_shift = 0, dev_shift = 0;
|
||||
|
||||
spin_lock_irqsave(&qe_lock, flags);
|
||||
if (cmd == QE_RESET) {
|
||||
out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
|
||||
} else {
|
||||
if (cmd == QE_ASSIGN_PAGE) {
|
||||
/* Here device is the SNUM, not sub-block */
|
||||
dev_shift = QE_CR_SNUM_SHIFT;
|
||||
} else if (cmd == QE_ASSIGN_RISC) {
|
||||
/* Here device is the SNUM, and mcnProtocol is
|
||||
* e_QeCmdRiscAssignment value */
|
||||
dev_shift = QE_CR_SNUM_SHIFT;
|
||||
mcn_shift = QE_CR_MCN_RISC_ASSIGN_SHIFT;
|
||||
} else {
|
||||
if (device == QE_CR_SUBBLOCK_USB)
|
||||
mcn_shift = QE_CR_MCN_USB_SHIFT;
|
||||
else
|
||||
mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
|
||||
}
|
||||
|
||||
out_be32(&qe_immr->cp.cecdr,
|
||||
immrbar_virt_to_phys((void *)cmd_input));
|
||||
out_be32(&qe_immr->cp.cecr,
|
||||
(cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
|
||||
mcn_protocol << mcn_shift));
|
||||
}
|
||||
|
||||
/* wait for the QE_CR_FLG to clear */
|
||||
while(in_be32(&qe_immr->cp.cecr) & QE_CR_FLG)
|
||||
cpu_relax();
|
||||
spin_unlock_irqrestore(&qe_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(qe_issue_cmd);
|
||||
|
||||
/* Set a baud rate generator. This needs lots of work. There are
|
||||
* 16 BRGs, which can be connected to the QE channels or output
|
||||
* as clocks. The BRGs are in two different block of internal
|
||||
* memory mapped space.
|
||||
* The baud rate clock is the system clock divided by something.
|
||||
* It was set up long ago during the initial boot phase and is
|
||||
* is given to us.
|
||||
* Baud rate clocks are zero-based in the driver code (as that maps
|
||||
* to port numbers). Documentation uses 1-based numbering.
|
||||
*/
|
||||
static unsigned int brg_clk = 0;
|
||||
|
||||
unsigned int get_brg_clk(void)
|
||||
{
|
||||
struct device_node *qe;
|
||||
if (brg_clk)
|
||||
return brg_clk;
|
||||
|
||||
qe = of_find_node_by_type(NULL, "qe");
|
||||
if (qe) {
|
||||
unsigned int size;
|
||||
const u32 *prop = get_property(qe, "brg-frequency", &size);
|
||||
brg_clk = *prop;
|
||||
of_node_put(qe);
|
||||
};
|
||||
return brg_clk;
|
||||
}
|
||||
|
||||
/* This function is used by UARTS, or anything else that uses a 16x
|
||||
* oversampled clock.
|
||||
*/
|
||||
void qe_setbrg(u32 brg, u32 rate)
|
||||
{
|
||||
volatile u32 *bp;
|
||||
u32 divisor, tempval;
|
||||
int div16 = 0;
|
||||
|
||||
bp = &qe_immr->brg.brgc1;
|
||||
bp += brg;
|
||||
|
||||
divisor = (get_brg_clk() / rate);
|
||||
if (divisor > QE_BRGC_DIVISOR_MAX + 1) {
|
||||
div16 = 1;
|
||||
divisor /= 16;
|
||||
}
|
||||
|
||||
tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) | QE_BRGC_ENABLE;
|
||||
if (div16)
|
||||
tempval |= QE_BRGC_DIV16;
|
||||
|
||||
out_be32(bp, tempval);
|
||||
}
|
||||
|
||||
/* Initialize SNUMs (thread serial numbers) according to
|
||||
* QE Module Control chapter, SNUM table
|
||||
*/
|
||||
static void qe_snums_init(void)
|
||||
{
|
||||
int i;
|
||||
static const u8 snum_init[] = {
|
||||
0x04, 0x05, 0x0C, 0x0D, 0x14, 0x15, 0x1C, 0x1D,
|
||||
0x24, 0x25, 0x2C, 0x2D, 0x34, 0x35, 0x88, 0x89,
|
||||
0x98, 0x99, 0xA8, 0xA9, 0xB8, 0xB9, 0xC8, 0xC9,
|
||||
0xD8, 0xD9, 0xE8, 0xE9,
|
||||
};
|
||||
|
||||
for (i = 0; i < QE_NUM_OF_SNUM; i++) {
|
||||
snums[i].num = snum_init[i];
|
||||
snums[i].state = QE_SNUM_STATE_FREE;
|
||||
}
|
||||
}
|
||||
|
||||
int qe_get_snum(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
int snum = -EBUSY;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&qe_lock, flags);
|
||||
for (i = 0; i < QE_NUM_OF_SNUM; i++) {
|
||||
if (snums[i].state == QE_SNUM_STATE_FREE) {
|
||||
snums[i].state = QE_SNUM_STATE_USED;
|
||||
snum = snums[i].num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&qe_lock, flags);
|
||||
|
||||
return snum;
|
||||
}
|
||||
EXPORT_SYMBOL(qe_get_snum);
|
||||
|
||||
void qe_put_snum(u8 snum)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < QE_NUM_OF_SNUM; i++) {
|
||||
if (snums[i].num == snum) {
|
||||
snums[i].state = QE_SNUM_STATE_FREE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(qe_put_snum);
|
||||
|
||||
static int qe_sdma_init(void)
|
||||
{
|
||||
struct sdma *sdma = &qe_immr->sdma;
|
||||
u32 sdma_buf_offset;
|
||||
|
||||
if (!sdma)
|
||||
return -ENODEV;
|
||||
|
||||
/* allocate 2 internal temporary buffers (512 bytes size each) for
|
||||
* the SDMA */
|
||||
sdma_buf_offset = qe_muram_alloc(512 * 2, 64);
|
||||
if (IS_MURAM_ERR(sdma_buf_offset))
|
||||
return -ENOMEM;
|
||||
|
||||
out_be32(&sdma->sdebcr, sdma_buf_offset & QE_SDEBCR_BA_MASK);
|
||||
out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK | (0x1 >>
|
||||
QE_SDMR_CEN_SHIFT)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* muram_alloc / muram_free bits.
|
||||
*/
|
||||
static DEFINE_SPINLOCK(qe_muram_lock);
|
||||
|
||||
/* 16 blocks should be enough to satisfy all requests
|
||||
* until the memory subsystem goes up... */
|
||||
static rh_block_t qe_boot_muram_rh_block[16];
|
||||
static rh_info_t qe_muram_info;
|
||||
|
||||
static void qe_muram_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
u32 address;
|
||||
u64 size;
|
||||
unsigned int flags;
|
||||
|
||||
/* initialize the info header */
|
||||
rh_init(&qe_muram_info, 1,
|
||||
sizeof(qe_boot_muram_rh_block) /
|
||||
sizeof(qe_boot_muram_rh_block[0]), qe_boot_muram_rh_block);
|
||||
|
||||
/* Attach the usable muram area */
|
||||
/* XXX: This is a subset of the available muram. It
|
||||
* varies with the processor and the microcode patches activated.
|
||||
*/
|
||||
if ((np = of_find_node_by_name(NULL, "data-only")) != NULL) {
|
||||
address = *of_get_address(np, 0, &size, &flags);
|
||||
of_node_put(np);
|
||||
rh_attach_region(&qe_muram_info,
|
||||
(void *)address, (int)size);
|
||||
}
|
||||
}
|
||||
|
||||
/* This function returns an index into the MURAM area.
|
||||
*/
|
||||
u32 qe_muram_alloc(u32 size, u32 align)
|
||||
{
|
||||
void *start;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&qe_muram_lock, flags);
|
||||
start = rh_alloc_align(&qe_muram_info, size, align, "QE");
|
||||
spin_unlock_irqrestore(&qe_muram_lock, flags);
|
||||
|
||||
return (u32) start;
|
||||
}
|
||||
EXPORT_SYMBOL(qe_muram_alloc);
|
||||
|
||||
int qe_muram_free(u32 offset)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&qe_muram_lock, flags);
|
||||
ret = rh_free(&qe_muram_info, (void *)offset);
|
||||
spin_unlock_irqrestore(&qe_muram_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(qe_muram_free);
|
||||
|
||||
/* not sure if this is ever needed */
|
||||
u32 qe_muram_alloc_fixed(u32 offset, u32 size)
|
||||
{
|
||||
void *start;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&qe_muram_lock, flags);
|
||||
start = rh_alloc_fixed(&qe_muram_info, (void *)offset, size, "commproc");
|
||||
spin_unlock_irqrestore(&qe_muram_lock, flags);
|
||||
|
||||
return (u32) start;
|
||||
}
|
||||
EXPORT_SYMBOL(qe_muram_alloc_fixed);
|
||||
|
||||
void qe_muram_dump(void)
|
||||
{
|
||||
rh_dump(&qe_muram_info);
|
||||
}
|
||||
EXPORT_SYMBOL(qe_muram_dump);
|
||||
|
||||
void *qe_muram_addr(u32 offset)
|
||||
{
|
||||
return (void *)&qe_immr->muram[offset];
|
||||
}
|
||||
EXPORT_SYMBOL(qe_muram_addr);
|
555
arch/powerpc/sysdev/qe_lib/qe_ic.c
Normal file
555
arch/powerpc/sysdev/qe_lib/qe_ic.c
Normal file
|
@ -0,0 +1,555 @@
|
|||
/*
|
||||
* arch/powerpc/sysdev/qe_lib/qe_ic.c
|
||||
*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Author: Li Yang <leoli@freescale.com>
|
||||
* Based on code from Shlomi Gridish <gridish@freescale.com>
|
||||
*
|
||||
* QUICC ENGINE Interrupt Controller
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/qe_ic.h>
|
||||
|
||||
#include "qe_ic.h"
|
||||
|
||||
static DEFINE_SPINLOCK(qe_ic_lock);
|
||||
|
||||
static struct qe_ic_info qe_ic_info[] = {
|
||||
[1] = {
|
||||
.mask = 0x00008000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 0,
|
||||
.pri_reg = QEIC_CIPWCC,
|
||||
},
|
||||
[2] = {
|
||||
.mask = 0x00004000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 1,
|
||||
.pri_reg = QEIC_CIPWCC,
|
||||
},
|
||||
[3] = {
|
||||
.mask = 0x00002000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 2,
|
||||
.pri_reg = QEIC_CIPWCC,
|
||||
},
|
||||
[10] = {
|
||||
.mask = 0x00000040,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 1,
|
||||
.pri_reg = QEIC_CIPZCC,
|
||||
},
|
||||
[11] = {
|
||||
.mask = 0x00000020,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 2,
|
||||
.pri_reg = QEIC_CIPZCC,
|
||||
},
|
||||
[12] = {
|
||||
.mask = 0x00000010,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 3,
|
||||
.pri_reg = QEIC_CIPZCC,
|
||||
},
|
||||
[13] = {
|
||||
.mask = 0x00000008,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 4,
|
||||
.pri_reg = QEIC_CIPZCC,
|
||||
},
|
||||
[14] = {
|
||||
.mask = 0x00000004,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 5,
|
||||
.pri_reg = QEIC_CIPZCC,
|
||||
},
|
||||
[15] = {
|
||||
.mask = 0x00000002,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 6,
|
||||
.pri_reg = QEIC_CIPZCC,
|
||||
},
|
||||
[20] = {
|
||||
.mask = 0x10000000,
|
||||
.mask_reg = QEIC_CRIMR,
|
||||
.pri_code = 3,
|
||||
.pri_reg = QEIC_CIPRTA,
|
||||
},
|
||||
[25] = {
|
||||
.mask = 0x00800000,
|
||||
.mask_reg = QEIC_CRIMR,
|
||||
.pri_code = 0,
|
||||
.pri_reg = QEIC_CIPRTB,
|
||||
},
|
||||
[26] = {
|
||||
.mask = 0x00400000,
|
||||
.mask_reg = QEIC_CRIMR,
|
||||
.pri_code = 1,
|
||||
.pri_reg = QEIC_CIPRTB,
|
||||
},
|
||||
[27] = {
|
||||
.mask = 0x00200000,
|
||||
.mask_reg = QEIC_CRIMR,
|
||||
.pri_code = 2,
|
||||
.pri_reg = QEIC_CIPRTB,
|
||||
},
|
||||
[28] = {
|
||||
.mask = 0x00100000,
|
||||
.mask_reg = QEIC_CRIMR,
|
||||
.pri_code = 3,
|
||||
.pri_reg = QEIC_CIPRTB,
|
||||
},
|
||||
[32] = {
|
||||
.mask = 0x80000000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 0,
|
||||
.pri_reg = QEIC_CIPXCC,
|
||||
},
|
||||
[33] = {
|
||||
.mask = 0x40000000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 1,
|
||||
.pri_reg = QEIC_CIPXCC,
|
||||
},
|
||||
[34] = {
|
||||
.mask = 0x20000000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 2,
|
||||
.pri_reg = QEIC_CIPXCC,
|
||||
},
|
||||
[35] = {
|
||||
.mask = 0x10000000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 3,
|
||||
.pri_reg = QEIC_CIPXCC,
|
||||
},
|
||||
[36] = {
|
||||
.mask = 0x08000000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 4,
|
||||
.pri_reg = QEIC_CIPXCC,
|
||||
},
|
||||
[40] = {
|
||||
.mask = 0x00800000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 0,
|
||||
.pri_reg = QEIC_CIPYCC,
|
||||
},
|
||||
[41] = {
|
||||
.mask = 0x00400000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 1,
|
||||
.pri_reg = QEIC_CIPYCC,
|
||||
},
|
||||
[42] = {
|
||||
.mask = 0x00200000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 2,
|
||||
.pri_reg = QEIC_CIPYCC,
|
||||
},
|
||||
[43] = {
|
||||
.mask = 0x00100000,
|
||||
.mask_reg = QEIC_CIMR,
|
||||
.pri_code = 3,
|
||||
.pri_reg = QEIC_CIPYCC,
|
||||
},
|
||||
};
|
||||
|
||||
static inline u32 qe_ic_read(volatile __be32 __iomem * base, unsigned int reg)
|
||||
{
|
||||
return in_be32(base + (reg >> 2));
|
||||
}
|
||||
|
||||
static inline void qe_ic_write(volatile __be32 __iomem * base, unsigned int reg,
|
||||
u32 value)
|
||||
{
|
||||
out_be32(base + (reg >> 2), value);
|
||||
}
|
||||
|
||||
static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
|
||||
{
|
||||
return irq_desc[virq].chip_data;
|
||||
}
|
||||
|
||||
#define virq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
|
||||
|
||||
static void qe_ic_unmask_irq(unsigned int virq)
|
||||
{
|
||||
struct qe_ic *qe_ic = qe_ic_from_irq(virq);
|
||||
unsigned int src = virq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
spin_lock_irqsave(&qe_ic_lock, flags);
|
||||
|
||||
temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
|
||||
qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
|
||||
temp | qe_ic_info[src].mask);
|
||||
|
||||
spin_unlock_irqrestore(&qe_ic_lock, flags);
|
||||
}
|
||||
|
||||
static void qe_ic_mask_irq(unsigned int virq)
|
||||
{
|
||||
struct qe_ic *qe_ic = qe_ic_from_irq(virq);
|
||||
unsigned int src = virq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
spin_lock_irqsave(&qe_ic_lock, flags);
|
||||
|
||||
temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
|
||||
qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
|
||||
temp & ~qe_ic_info[src].mask);
|
||||
|
||||
spin_unlock_irqrestore(&qe_ic_lock, flags);
|
||||
}
|
||||
|
||||
static void qe_ic_mask_irq_and_ack(unsigned int virq)
|
||||
{
|
||||
struct qe_ic *qe_ic = qe_ic_from_irq(virq);
|
||||
unsigned int src = virq_to_hw(virq);
|
||||
unsigned long flags;
|
||||
u32 temp;
|
||||
|
||||
spin_lock_irqsave(&qe_ic_lock, flags);
|
||||
|
||||
temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);
|
||||
qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,
|
||||
temp & ~qe_ic_info[src].mask);
|
||||
|
||||
/* There is nothing to do for ack here, ack is handled in ISR */
|
||||
|
||||
spin_unlock_irqrestore(&qe_ic_lock, flags);
|
||||
}
|
||||
|
||||
static struct irq_chip qe_ic_irq_chip = {
|
||||
.typename = " QEIC ",
|
||||
.unmask = qe_ic_unmask_irq,
|
||||
.mask = qe_ic_mask_irq,
|
||||
.mask_ack = qe_ic_mask_irq_and_ack,
|
||||
};
|
||||
|
||||
static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
|
||||
{
|
||||
struct qe_ic *qe_ic = h->host_data;
|
||||
|
||||
/* Exact match, unless qe_ic node is NULL */
|
||||
return qe_ic->of_node == NULL || qe_ic->of_node == node;
|
||||
}
|
||||
|
||||
static int qe_ic_host_map(struct irq_host *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
struct qe_ic *qe_ic = h->host_data;
|
||||
struct irq_chip *chip;
|
||||
|
||||
if (qe_ic_info[hw].mask == 0) {
|
||||
printk(KERN_ERR "Can't map reserved IRQ \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Default chip */
|
||||
chip = &qe_ic->hc_irq;
|
||||
|
||||
set_irq_chip_data(virq, qe_ic);
|
||||
get_irq_desc(virq)->status |= IRQ_LEVEL;
|
||||
|
||||
set_irq_chip_and_handler(virq, chip, handle_level_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qe_ic_host_xlate(struct irq_host *h, struct device_node *ct,
|
||||
u32 * intspec, unsigned int intsize,
|
||||
irq_hw_number_t * out_hwirq,
|
||||
unsigned int *out_flags)
|
||||
{
|
||||
*out_hwirq = intspec[0];
|
||||
if (intsize > 1)
|
||||
*out_flags = intspec[1];
|
||||
else
|
||||
*out_flags = IRQ_TYPE_NONE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_host_ops qe_ic_host_ops = {
|
||||
.match = qe_ic_host_match,
|
||||
.map = qe_ic_host_map,
|
||||
.xlate = qe_ic_host_xlate,
|
||||
};
|
||||
|
||||
/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
|
||||
unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic, struct pt_regs *regs)
|
||||
{
|
||||
int irq;
|
||||
|
||||
BUG_ON(qe_ic == NULL);
|
||||
|
||||
/* get the interrupt source vector. */
|
||||
irq = qe_ic_read(qe_ic->regs, QEIC_CIVEC) >> 26;
|
||||
|
||||
if (irq == 0)
|
||||
return NO_IRQ;
|
||||
|
||||
return irq_linear_revmap(qe_ic->irqhost, irq);
|
||||
}
|
||||
|
||||
/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
|
||||
unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic, struct pt_regs *regs)
|
||||
{
|
||||
int irq;
|
||||
|
||||
BUG_ON(qe_ic == NULL);
|
||||
|
||||
/* get the interrupt source vector. */
|
||||
irq = qe_ic_read(qe_ic->regs, QEIC_CHIVEC) >> 26;
|
||||
|
||||
if (irq == 0)
|
||||
return NO_IRQ;
|
||||
|
||||
return irq_linear_revmap(qe_ic->irqhost, irq);
|
||||
}
|
||||
|
||||
/* FIXME: We mask all the QE Low interrupts while handling. We should
|
||||
* let other interrupt come in, but BAD interrupts are generated */
|
||||
void fastcall qe_ic_cascade_low(unsigned int irq, struct irq_desc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct qe_ic *qe_ic = desc->handler_data;
|
||||
struct irq_chip *chip = irq_desc[irq].chip;
|
||||
|
||||
unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic, regs);
|
||||
|
||||
chip->mask_ack(irq);
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq, regs);
|
||||
chip->unmask(irq);
|
||||
}
|
||||
|
||||
/* FIXME: We mask all the QE High interrupts while handling. We should
|
||||
* let other interrupt come in, but BAD interrupts are generated */
|
||||
void fastcall qe_ic_cascade_high(unsigned int irq, struct irq_desc *desc,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct qe_ic *qe_ic = desc->handler_data;
|
||||
struct irq_chip *chip = irq_desc[irq].chip;
|
||||
|
||||
unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic, regs);
|
||||
|
||||
chip->mask_ack(irq);
|
||||
if (cascade_irq != NO_IRQ)
|
||||
generic_handle_irq(cascade_irq, regs);
|
||||
chip->unmask(irq);
|
||||
}
|
||||
|
||||
void __init qe_ic_init(struct device_node *node, unsigned int flags)
|
||||
{
|
||||
struct qe_ic *qe_ic;
|
||||
struct resource res;
|
||||
u32 temp = 0, ret, high_active = 0;
|
||||
|
||||
qe_ic = alloc_bootmem(sizeof(struct qe_ic));
|
||||
if (qe_ic == NULL)
|
||||
return;
|
||||
|
||||
memset(qe_ic, 0, sizeof(struct qe_ic));
|
||||
qe_ic->of_node = node ? of_node_get(node) : NULL;
|
||||
|
||||
qe_ic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR,
|
||||
NR_QE_IC_INTS, &qe_ic_host_ops, 0);
|
||||
if (qe_ic->irqhost == NULL) {
|
||||
of_node_put(node);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = of_address_to_resource(node, 0, &res);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
qe_ic->regs = ioremap(res.start, res.end - res.start + 1);
|
||||
|
||||
qe_ic->irqhost->host_data = qe_ic;
|
||||
qe_ic->hc_irq = qe_ic_irq_chip;
|
||||
|
||||
qe_ic->virq_high = irq_of_parse_and_map(node, 0);
|
||||
qe_ic->virq_low = irq_of_parse_and_map(node, 1);
|
||||
|
||||
if (qe_ic->virq_low == NO_IRQ) {
|
||||
printk(KERN_ERR "Failed to map QE_IC low IRQ\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* default priority scheme is grouped. If spread mode is */
|
||||
/* required, configure cicr accordingly. */
|
||||
if (flags & QE_IC_SPREADMODE_GRP_W)
|
||||
temp |= CICR_GWCC;
|
||||
if (flags & QE_IC_SPREADMODE_GRP_X)
|
||||
temp |= CICR_GXCC;
|
||||
if (flags & QE_IC_SPREADMODE_GRP_Y)
|
||||
temp |= CICR_GYCC;
|
||||
if (flags & QE_IC_SPREADMODE_GRP_Z)
|
||||
temp |= CICR_GZCC;
|
||||
if (flags & QE_IC_SPREADMODE_GRP_RISCA)
|
||||
temp |= CICR_GRTA;
|
||||
if (flags & QE_IC_SPREADMODE_GRP_RISCB)
|
||||
temp |= CICR_GRTB;
|
||||
|
||||
/* choose destination signal for highest priority interrupt */
|
||||
if (flags & QE_IC_HIGH_SIGNAL) {
|
||||
temp |= (SIGNAL_HIGH << CICR_HPIT_SHIFT);
|
||||
high_active = 1;
|
||||
}
|
||||
|
||||
qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
|
||||
|
||||
set_irq_data(qe_ic->virq_low, qe_ic);
|
||||
set_irq_chained_handler(qe_ic->virq_low, qe_ic_cascade_low);
|
||||
|
||||
if (qe_ic->virq_high != NO_IRQ) {
|
||||
set_irq_data(qe_ic->virq_high, qe_ic);
|
||||
set_irq_chained_handler(qe_ic->virq_high, qe_ic_cascade_high);
|
||||
}
|
||||
|
||||
printk("QEIC (%d IRQ sources) at %p\n", NR_QE_IC_INTS, qe_ic->regs);
|
||||
}
|
||||
|
||||
void qe_ic_set_highest_priority(unsigned int virq, int high)
|
||||
{
|
||||
struct qe_ic *qe_ic = qe_ic_from_irq(virq);
|
||||
unsigned int src = virq_to_hw(virq);
|
||||
u32 temp = 0;
|
||||
|
||||
temp = qe_ic_read(qe_ic->regs, QEIC_CICR);
|
||||
|
||||
temp &= ~CICR_HP_MASK;
|
||||
temp |= src << CICR_HP_SHIFT;
|
||||
|
||||
temp &= ~CICR_HPIT_MASK;
|
||||
temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << CICR_HPIT_SHIFT;
|
||||
|
||||
qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
|
||||
}
|
||||
|
||||
/* Set Priority level within its group, from 1 to 8 */
|
||||
int qe_ic_set_priority(unsigned int virq, unsigned int priority)
|
||||
{
|
||||
struct qe_ic *qe_ic = qe_ic_from_irq(virq);
|
||||
unsigned int src = virq_to_hw(virq);
|
||||
u32 temp;
|
||||
|
||||
if (priority > 8 || priority == 0)
|
||||
return -EINVAL;
|
||||
if (src > 127)
|
||||
return -EINVAL;
|
||||
if (qe_ic_info[src].pri_reg == 0)
|
||||
return -EINVAL;
|
||||
|
||||
temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].pri_reg);
|
||||
|
||||
if (priority < 4) {
|
||||
temp &= ~(0x7 << (32 - priority * 3));
|
||||
temp |= qe_ic_info[src].pri_code << (32 - priority * 3);
|
||||
} else {
|
||||
temp &= ~(0x7 << (24 - priority * 3));
|
||||
temp |= qe_ic_info[src].pri_code << (24 - priority * 3);
|
||||
}
|
||||
|
||||
qe_ic_write(qe_ic->regs, qe_ic_info[src].pri_reg, temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set a QE priority to use high irq, only priority 1~2 can use high irq */
|
||||
int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high)
|
||||
{
|
||||
struct qe_ic *qe_ic = qe_ic_from_irq(virq);
|
||||
unsigned int src = virq_to_hw(virq);
|
||||
u32 temp, control_reg = QEIC_CICNR, shift = 0;
|
||||
|
||||
if (priority > 2 || priority == 0)
|
||||
return -EINVAL;
|
||||
|
||||
switch (qe_ic_info[src].pri_reg) {
|
||||
case QEIC_CIPZCC:
|
||||
shift = CICNR_ZCC1T_SHIFT;
|
||||
break;
|
||||
case QEIC_CIPWCC:
|
||||
shift = CICNR_WCC1T_SHIFT;
|
||||
break;
|
||||
case QEIC_CIPYCC:
|
||||
shift = CICNR_YCC1T_SHIFT;
|
||||
break;
|
||||
case QEIC_CIPXCC:
|
||||
shift = CICNR_XCC1T_SHIFT;
|
||||
break;
|
||||
case QEIC_CIPRTA:
|
||||
shift = CRICR_RTA1T_SHIFT;
|
||||
control_reg = QEIC_CRICR;
|
||||
break;
|
||||
case QEIC_CIPRTB:
|
||||
shift = CRICR_RTB1T_SHIFT;
|
||||
control_reg = QEIC_CRICR;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
shift += (2 - priority) * 2;
|
||||
temp = qe_ic_read(qe_ic->regs, control_reg);
|
||||
temp &= ~(SIGNAL_MASK << shift);
|
||||
temp |= (high ? SIGNAL_HIGH : SIGNAL_LOW) << shift;
|
||||
qe_ic_write(qe_ic->regs, control_reg, temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct sysdev_class qe_ic_sysclass = {
|
||||
set_kset_name("qe_ic"),
|
||||
};
|
||||
|
||||
static struct sys_device device_qe_ic = {
|
||||
.id = 0,
|
||||
.cls = &qe_ic_sysclass,
|
||||
};
|
||||
|
||||
static int __init init_qe_ic_sysfs(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
printk(KERN_DEBUG "Registering qe_ic with sysfs...\n");
|
||||
|
||||
rc = sysdev_class_register(&qe_ic_sysclass);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Failed registering qe_ic sys class\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
rc = sysdev_register(&device_qe_ic);
|
||||
if (rc) {
|
||||
printk(KERN_ERR "Failed registering qe_ic sys device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(init_qe_ic_sysfs);
|
106
arch/powerpc/sysdev/qe_lib/qe_ic.h
Normal file
106
arch/powerpc/sysdev/qe_lib/qe_ic.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* arch/powerpc/sysdev/qe_lib/qe_ic.h
|
||||
*
|
||||
* QUICC ENGINE Interrupt Controller Header
|
||||
*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Author: Li Yang <leoli@freescale.com>
|
||||
* Based on code from Shlomi Gridish <gridish@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#ifndef _POWERPC_SYSDEV_QE_IC_H
|
||||
#define _POWERPC_SYSDEV_QE_IC_H
|
||||
|
||||
#include <asm/qe_ic.h>
|
||||
|
||||
#define NR_QE_IC_INTS 64
|
||||
|
||||
/* QE IC registers offset */
|
||||
#define QEIC_CICR 0x00
|
||||
#define QEIC_CIVEC 0x04
|
||||
#define QEIC_CRIPNR 0x08
|
||||
#define QEIC_CIPNR 0x0c
|
||||
#define QEIC_CIPXCC 0x10
|
||||
#define QEIC_CIPYCC 0x14
|
||||
#define QEIC_CIPWCC 0x18
|
||||
#define QEIC_CIPZCC 0x1c
|
||||
#define QEIC_CIMR 0x20
|
||||
#define QEIC_CRIMR 0x24
|
||||
#define QEIC_CICNR 0x28
|
||||
#define QEIC_CIPRTA 0x30
|
||||
#define QEIC_CIPRTB 0x34
|
||||
#define QEIC_CRICR 0x3c
|
||||
#define QEIC_CHIVEC 0x60
|
||||
|
||||
/* Interrupt priority registers */
|
||||
#define CIPCC_SHIFT_PRI0 29
|
||||
#define CIPCC_SHIFT_PRI1 26
|
||||
#define CIPCC_SHIFT_PRI2 23
|
||||
#define CIPCC_SHIFT_PRI3 20
|
||||
#define CIPCC_SHIFT_PRI4 13
|
||||
#define CIPCC_SHIFT_PRI5 10
|
||||
#define CIPCC_SHIFT_PRI6 7
|
||||
#define CIPCC_SHIFT_PRI7 4
|
||||
|
||||
/* CICR priority modes */
|
||||
#define CICR_GWCC 0x00040000
|
||||
#define CICR_GXCC 0x00020000
|
||||
#define CICR_GYCC 0x00010000
|
||||
#define CICR_GZCC 0x00080000
|
||||
#define CICR_GRTA 0x00200000
|
||||
#define CICR_GRTB 0x00400000
|
||||
#define CICR_HPIT_SHIFT 8
|
||||
#define CICR_HPIT_MASK 0x00000300
|
||||
#define CICR_HP_SHIFT 24
|
||||
#define CICR_HP_MASK 0x3f000000
|
||||
|
||||
/* CICNR */
|
||||
#define CICNR_WCC1T_SHIFT 20
|
||||
#define CICNR_ZCC1T_SHIFT 28
|
||||
#define CICNR_YCC1T_SHIFT 12
|
||||
#define CICNR_XCC1T_SHIFT 4
|
||||
|
||||
/* CRICR */
|
||||
#define CRICR_RTA1T_SHIFT 20
|
||||
#define CRICR_RTB1T_SHIFT 28
|
||||
|
||||
/* Signal indicator */
|
||||
#define SIGNAL_MASK 3
|
||||
#define SIGNAL_HIGH 2
|
||||
#define SIGNAL_LOW 0
|
||||
|
||||
struct qe_ic {
|
||||
/* Control registers offset */
|
||||
volatile u32 __iomem *regs;
|
||||
|
||||
/* The remapper for this QEIC */
|
||||
struct irq_host *irqhost;
|
||||
|
||||
/* The "linux" controller struct */
|
||||
struct irq_chip hc_irq;
|
||||
|
||||
/* The device node of the interrupt controller */
|
||||
struct device_node *of_node;
|
||||
|
||||
/* VIRQ numbers of QE high/low irqs */
|
||||
unsigned int virq_high;
|
||||
unsigned int virq_low;
|
||||
};
|
||||
|
||||
/*
|
||||
* QE interrupt controller internal structure
|
||||
*/
|
||||
struct qe_ic_info {
|
||||
u32 mask; /* location of this source at the QIMR register. */
|
||||
u32 mask_reg; /* Mask register offset */
|
||||
u8 pri_code; /* for grouped interrupts sources - the interrupt
|
||||
code as appears at the group priority register */
|
||||
u32 pri_reg; /* Group priority register offset */
|
||||
};
|
||||
|
||||
#endif /* _POWERPC_SYSDEV_QE_IC_H */
|
226
arch/powerpc/sysdev/qe_lib/qe_io.c
Normal file
226
arch/powerpc/sysdev/qe_lib/qe_io.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
* arch/powerpc/sysdev/qe_lib/qe_io.c
|
||||
*
|
||||
* QE Parallel I/O ports configuration routines
|
||||
*
|
||||
* Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
|
||||
*
|
||||
* Author: Li Yang <LeoLi@freescale.com>
|
||||
* Based on code from Shlomi Gridish <gridish@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/config.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/prom.h>
|
||||
#include <sysdev/fsl_soc.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#define NUM_OF_PINS 32
|
||||
|
||||
struct port_regs {
|
||||
__be32 cpodr; /* Open drain register */
|
||||
__be32 cpdata; /* Data register */
|
||||
__be32 cpdir1; /* Direction register */
|
||||
__be32 cpdir2; /* Direction register */
|
||||
__be32 cppar1; /* Pin assignment register */
|
||||
__be32 cppar2; /* Pin assignment register */
|
||||
};
|
||||
|
||||
static struct port_regs *par_io = NULL;
|
||||
static int num_par_io_ports = 0;
|
||||
|
||||
int par_io_init(struct device_node *np)
|
||||
{
|
||||
struct resource res;
|
||||
int ret;
|
||||
const u32 *num_ports;
|
||||
|
||||
/* Map Parallel I/O ports registers */
|
||||
ret = of_address_to_resource(np, 0, &res);
|
||||
if (ret)
|
||||
return ret;
|
||||
par_io = ioremap(res.start, res.end - res.start + 1);
|
||||
|
||||
num_ports = get_property(np, "num-ports", NULL);
|
||||
if (num_ports)
|
||||
num_par_io_ports = *num_ports;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
|
||||
int assignment, int has_irq)
|
||||
{
|
||||
u32 pin_mask1bit, pin_mask2bits, new_mask2bits, tmp_val;
|
||||
|
||||
if (!par_io)
|
||||
return -1;
|
||||
|
||||
/* calculate pin location for single and 2 bits information */
|
||||
pin_mask1bit = (u32) (1 << (NUM_OF_PINS - (pin + 1)));
|
||||
|
||||
/* Set open drain, if required */
|
||||
tmp_val = in_be32(&par_io[port].cpodr);
|
||||
if (open_drain)
|
||||
out_be32(&par_io[port].cpodr, pin_mask1bit | tmp_val);
|
||||
else
|
||||
out_be32(&par_io[port].cpodr, ~pin_mask1bit & tmp_val);
|
||||
|
||||
/* define direction */
|
||||
tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
|
||||
in_be32(&par_io[port].cpdir2) :
|
||||
in_be32(&par_io[port].cpdir1);
|
||||
|
||||
/* get all bits mask for 2 bit per port */
|
||||
pin_mask2bits = (u32) (0x3 << (NUM_OF_PINS -
|
||||
(pin % (NUM_OF_PINS / 2) + 1) * 2));
|
||||
|
||||
/* Get the final mask we need for the right definition */
|
||||
new_mask2bits = (u32) (dir << (NUM_OF_PINS -
|
||||
(pin % (NUM_OF_PINS / 2) + 1) * 2));
|
||||
|
||||
/* clear and set 2 bits mask */
|
||||
if (pin > (NUM_OF_PINS / 2) - 1) {
|
||||
out_be32(&par_io[port].cpdir2,
|
||||
~pin_mask2bits & tmp_val);
|
||||
tmp_val &= ~pin_mask2bits;
|
||||
out_be32(&par_io[port].cpdir2, new_mask2bits | tmp_val);
|
||||
} else {
|
||||
out_be32(&par_io[port].cpdir1,
|
||||
~pin_mask2bits & tmp_val);
|
||||
tmp_val &= ~pin_mask2bits;
|
||||
out_be32(&par_io[port].cpdir1, new_mask2bits | tmp_val);
|
||||
}
|
||||
/* define pin assignment */
|
||||
tmp_val = (pin > (NUM_OF_PINS / 2) - 1) ?
|
||||
in_be32(&par_io[port].cppar2) :
|
||||
in_be32(&par_io[port].cppar1);
|
||||
|
||||
new_mask2bits = (u32) (assignment << (NUM_OF_PINS -
|
||||
(pin % (NUM_OF_PINS / 2) + 1) * 2));
|
||||
/* clear and set 2 bits mask */
|
||||
if (pin > (NUM_OF_PINS / 2) - 1) {
|
||||
out_be32(&par_io[port].cppar2,
|
||||
~pin_mask2bits & tmp_val);
|
||||
tmp_val &= ~pin_mask2bits;
|
||||
out_be32(&par_io[port].cppar2, new_mask2bits | tmp_val);
|
||||
} else {
|
||||
out_be32(&par_io[port].cppar1,
|
||||
~pin_mask2bits & tmp_val);
|
||||
tmp_val &= ~pin_mask2bits;
|
||||
out_be32(&par_io[port].cppar1, new_mask2bits | tmp_val);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(par_io_config_pin);
|
||||
|
||||
int par_io_data_set(u8 port, u8 pin, u8 val)
|
||||
{
|
||||
u32 pin_mask, tmp_val;
|
||||
|
||||
if (port >= num_par_io_ports)
|
||||
return -EINVAL;
|
||||
if (pin >= NUM_OF_PINS)
|
||||
return -EINVAL;
|
||||
/* calculate pin location */
|
||||
pin_mask = (u32) (1 << (NUM_OF_PINS - 1 - pin));
|
||||
|
||||
tmp_val = in_be32(&par_io[port].cpdata);
|
||||
|
||||
if (val == 0) /* clear */
|
||||
out_be32(&par_io[port].cpdata, ~pin_mask & tmp_val);
|
||||
else /* set */
|
||||
out_be32(&par_io[port].cpdata, pin_mask | tmp_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(par_io_data_set);
|
||||
|
||||
int par_io_of_config(struct device_node *np)
|
||||
{
|
||||
struct device_node *pio;
|
||||
const phandle *ph;
|
||||
int pio_map_len;
|
||||
const unsigned int *pio_map;
|
||||
|
||||
if (par_io == NULL) {
|
||||
printk(KERN_ERR "par_io not initialized \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ph = get_property(np, "pio-handle", NULL);
|
||||
if (ph == 0) {
|
||||
printk(KERN_ERR "pio-handle not available \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pio = of_find_node_by_phandle(*ph);
|
||||
|
||||
pio_map = get_property(pio, "pio-map", &pio_map_len);
|
||||
if (pio_map == NULL) {
|
||||
printk(KERN_ERR "pio-map is not set! \n");
|
||||
return -1;
|
||||
}
|
||||
pio_map_len /= sizeof(unsigned int);
|
||||
if ((pio_map_len % 6) != 0) {
|
||||
printk(KERN_ERR "pio-map format wrong! \n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (pio_map_len > 0) {
|
||||
par_io_config_pin((u8) pio_map[0], (u8) pio_map[1],
|
||||
(int) pio_map[2], (int) pio_map[3],
|
||||
(int) pio_map[4], (int) pio_map[5]);
|
||||
pio_map += 6;
|
||||
pio_map_len -= 6;
|
||||
}
|
||||
of_node_put(pio);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(par_io_of_config);
|
||||
|
||||
#ifdef DEBUG
|
||||
static void dump_par_io(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk(KERN_INFO "PAR IO registars:\n");
|
||||
printk(KERN_INFO "Base address: 0x%08x\n", (u32) par_io);
|
||||
for (i = 0; i < num_par_io_ports; i++) {
|
||||
printk(KERN_INFO "cpodr[%d] : addr - 0x%08x, val - 0x%08x\n",
|
||||
i, (u32) & par_io[i].cpodr,
|
||||
in_be32(&par_io[i].cpodr));
|
||||
printk(KERN_INFO "cpdata[%d]: addr - 0x%08x, val - 0x%08x\n",
|
||||
i, (u32) & par_io[i].cpdata,
|
||||
in_be32(&par_io[i].cpdata));
|
||||
printk(KERN_INFO "cpdir1[%d]: addr - 0x%08x, val - 0x%08x\n",
|
||||
i, (u32) & par_io[i].cpdir1,
|
||||
in_be32(&par_io[i].cpdir1));
|
||||
printk(KERN_INFO "cpdir2[%d]: addr - 0x%08x, val - 0x%08x\n",
|
||||
i, (u32) & par_io[i].cpdir2,
|
||||
in_be32(&par_io[i].cpdir2));
|
||||
printk(KERN_INFO "cppar1[%d]: addr - 0x%08x, val - 0x%08x\n",
|
||||
i, (u32) & par_io[i].cppar1,
|
||||
in_be32(&par_io[i].cppar1));
|
||||
printk(KERN_INFO "cppar2[%d]: addr - 0x%08x, val - 0x%08x\n",
|
||||
i, (u32) & par_io[i].cppar2,
|
||||
in_be32(&par_io[i].cppar2));
|
||||
}
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(dump_par_io);
|
||||
#endif /* DEBUG */
|
251
arch/powerpc/sysdev/qe_lib/ucc.c
Normal file
251
arch/powerpc/sysdev/qe_lib/ucc.c
Normal file
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* arch/powerpc/sysdev/qe_lib/ucc.c
|
||||
*
|
||||
* QE UCC API Set - UCC specific routines implementations.
|
||||
*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Authors: Shlomi Gridish <gridish@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stddef.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/immap_qe.h>
|
||||
#include <asm/qe.h>
|
||||
#include <asm/ucc.h>
|
||||
|
||||
static DEFINE_SPINLOCK(ucc_lock);
|
||||
|
||||
int ucc_set_qe_mux_mii_mng(int ucc_num)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ucc_lock, flags);
|
||||
out_be32(&qe_immr->qmx.cmxgcr,
|
||||
((in_be32(&qe_immr->qmx.cmxgcr) &
|
||||
~QE_CMXGCR_MII_ENET_MNG) |
|
||||
(ucc_num << QE_CMXGCR_MII_ENET_MNG_SHIFT)));
|
||||
spin_unlock_irqrestore(&ucc_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ucc_set_type(int ucc_num, struct ucc_common *regs,
|
||||
enum ucc_speed_type speed)
|
||||
{
|
||||
u8 guemr = 0;
|
||||
|
||||
/* check if the UCC number is in range. */
|
||||
if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
|
||||
return -EINVAL;
|
||||
|
||||
guemr = regs->guemr;
|
||||
guemr &= ~(UCC_GUEMR_MODE_MASK_RX | UCC_GUEMR_MODE_MASK_TX);
|
||||
switch (speed) {
|
||||
case UCC_SPEED_TYPE_SLOW:
|
||||
guemr |= (UCC_GUEMR_MODE_SLOW_RX | UCC_GUEMR_MODE_SLOW_TX);
|
||||
break;
|
||||
case UCC_SPEED_TYPE_FAST:
|
||||
guemr |= (UCC_GUEMR_MODE_FAST_RX | UCC_GUEMR_MODE_FAST_TX);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
regs->guemr = guemr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ucc_init_guemr(struct ucc_common *regs)
|
||||
{
|
||||
u8 guemr = 0;
|
||||
|
||||
if (!regs)
|
||||
return -EINVAL;
|
||||
|
||||
/* Set bit 3 (which is reserved in the GUEMR register) to 1 */
|
||||
guemr = UCC_GUEMR_SET_RESERVED3;
|
||||
|
||||
regs->guemr = guemr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void get_cmxucr_reg(int ucc_num, volatile u32 ** p_cmxucr, u8 * reg_num,
|
||||
u8 * shift)
|
||||
{
|
||||
switch (ucc_num) {
|
||||
case 0: *p_cmxucr = &(qe_immr->qmx.cmxucr1);
|
||||
*reg_num = 1;
|
||||
*shift = 16;
|
||||
break;
|
||||
case 2: *p_cmxucr = &(qe_immr->qmx.cmxucr1);
|
||||
*reg_num = 1;
|
||||
*shift = 0;
|
||||
break;
|
||||
case 4: *p_cmxucr = &(qe_immr->qmx.cmxucr2);
|
||||
*reg_num = 2;
|
||||
*shift = 16;
|
||||
break;
|
||||
case 6: *p_cmxucr = &(qe_immr->qmx.cmxucr2);
|
||||
*reg_num = 2;
|
||||
*shift = 0;
|
||||
break;
|
||||
case 1: *p_cmxucr = &(qe_immr->qmx.cmxucr3);
|
||||
*reg_num = 3;
|
||||
*shift = 16;
|
||||
break;
|
||||
case 3: *p_cmxucr = &(qe_immr->qmx.cmxucr3);
|
||||
*reg_num = 3;
|
||||
*shift = 0;
|
||||
break;
|
||||
case 5: *p_cmxucr = &(qe_immr->qmx.cmxucr4);
|
||||
*reg_num = 4;
|
||||
*shift = 16;
|
||||
break;
|
||||
case 7: *p_cmxucr = &(qe_immr->qmx.cmxucr4);
|
||||
*reg_num = 4;
|
||||
*shift = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ucc_mux_set_grant_tsa_bkpt(int ucc_num, int set, u32 mask)
|
||||
{
|
||||
volatile u32 *p_cmxucr;
|
||||
u8 reg_num;
|
||||
u8 shift;
|
||||
|
||||
/* check if the UCC number is in range. */
|
||||
if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
|
||||
return -EINVAL;
|
||||
|
||||
get_cmxucr_reg(ucc_num, &p_cmxucr, ®_num, &shift);
|
||||
|
||||
if (set)
|
||||
out_be32(p_cmxucr, in_be32(p_cmxucr) | (mask << shift));
|
||||
else
|
||||
out_be32(p_cmxucr, in_be32(p_cmxucr) & ~(mask << shift));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode)
|
||||
{
|
||||
volatile u32 *p_cmxucr;
|
||||
u8 reg_num;
|
||||
u8 shift;
|
||||
u32 clock_bits;
|
||||
u32 clock_mask;
|
||||
int source = -1;
|
||||
|
||||
/* check if the UCC number is in range. */
|
||||
if ((ucc_num > UCC_MAX_NUM - 1) || (ucc_num < 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (!((mode == COMM_DIR_RX) || (mode == COMM_DIR_TX))) {
|
||||
printk(KERN_ERR
|
||||
"ucc_set_qe_mux_rxtx: bad comm mode type passed.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
get_cmxucr_reg(ucc_num, &p_cmxucr, ®_num, &shift);
|
||||
|
||||
switch (reg_num) {
|
||||
case 1:
|
||||
switch (clock) {
|
||||
case QE_BRG1: source = 1; break;
|
||||
case QE_BRG2: source = 2; break;
|
||||
case QE_BRG7: source = 3; break;
|
||||
case QE_BRG8: source = 4; break;
|
||||
case QE_CLK9: source = 5; break;
|
||||
case QE_CLK10: source = 6; break;
|
||||
case QE_CLK11: source = 7; break;
|
||||
case QE_CLK12: source = 8; break;
|
||||
case QE_CLK15: source = 9; break;
|
||||
case QE_CLK16: source = 10; break;
|
||||
default: source = -1; break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (clock) {
|
||||
case QE_BRG5: source = 1; break;
|
||||
case QE_BRG6: source = 2; break;
|
||||
case QE_BRG7: source = 3; break;
|
||||
case QE_BRG8: source = 4; break;
|
||||
case QE_CLK13: source = 5; break;
|
||||
case QE_CLK14: source = 6; break;
|
||||
case QE_CLK19: source = 7; break;
|
||||
case QE_CLK20: source = 8; break;
|
||||
case QE_CLK15: source = 9; break;
|
||||
case QE_CLK16: source = 10; break;
|
||||
default: source = -1; break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
switch (clock) {
|
||||
case QE_BRG9: source = 1; break;
|
||||
case QE_BRG10: source = 2; break;
|
||||
case QE_BRG15: source = 3; break;
|
||||
case QE_BRG16: source = 4; break;
|
||||
case QE_CLK3: source = 5; break;
|
||||
case QE_CLK4: source = 6; break;
|
||||
case QE_CLK17: source = 7; break;
|
||||
case QE_CLK18: source = 8; break;
|
||||
case QE_CLK7: source = 9; break;
|
||||
case QE_CLK8: source = 10; break;
|
||||
default: source = -1; break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
switch (clock) {
|
||||
case QE_BRG13: source = 1; break;
|
||||
case QE_BRG14: source = 2; break;
|
||||
case QE_BRG15: source = 3; break;
|
||||
case QE_BRG16: source = 4; break;
|
||||
case QE_CLK5: source = 5; break;
|
||||
case QE_CLK6: source = 6; break;
|
||||
case QE_CLK21: source = 7; break;
|
||||
case QE_CLK22: source = 8; break;
|
||||
case QE_CLK7: source = 9; break;
|
||||
case QE_CLK8: source = 10; break;
|
||||
default: source = -1; break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
source = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (source == -1) {
|
||||
printk(KERN_ERR
|
||||
"ucc_set_qe_mux_rxtx: Bad combination of clock and UCC.");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
clock_bits = (u32) source;
|
||||
clock_mask = QE_CMXUCR_TX_CLK_SRC_MASK;
|
||||
if (mode == COMM_DIR_RX) {
|
||||
clock_bits <<= 4; /* Rx field is 4 bits to left of Tx field */
|
||||
clock_mask <<= 4; /* Rx field is 4 bits to left of Tx field */
|
||||
}
|
||||
clock_bits <<= shift;
|
||||
clock_mask <<= shift;
|
||||
|
||||
out_be32(p_cmxucr, (in_be32(p_cmxucr) & ~clock_mask) | clock_bits);
|
||||
|
||||
return 0;
|
||||
}
|
396
arch/powerpc/sysdev/qe_lib/ucc_fast.c
Normal file
396
arch/powerpc/sysdev/qe_lib/ucc_fast.c
Normal file
|
@ -0,0 +1,396 @@
|
|||
/*
|
||||
* arch/powerpc/sysdev/qe_lib/ucc_fast.c
|
||||
*
|
||||
* QE UCC Fast API Set - UCC Fast specific routines implementations.
|
||||
*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Authors: Shlomi Gridish <gridish@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
#include <asm/immap_qe.h>
|
||||
#include <asm/qe.h>
|
||||
|
||||
#include <asm/ucc.h>
|
||||
#include <asm/ucc_fast.h>
|
||||
|
||||
#define uccf_printk(level, format, arg...) \
|
||||
printk(level format "\n", ## arg)
|
||||
|
||||
#define uccf_dbg(format, arg...) \
|
||||
uccf_printk(KERN_DEBUG , format , ## arg)
|
||||
#define uccf_err(format, arg...) \
|
||||
uccf_printk(KERN_ERR , format , ## arg)
|
||||
#define uccf_info(format, arg...) \
|
||||
uccf_printk(KERN_INFO , format , ## arg)
|
||||
#define uccf_warn(format, arg...) \
|
||||
uccf_printk(KERN_WARNING , format , ## arg)
|
||||
|
||||
#ifdef UCCF_VERBOSE_DEBUG
|
||||
#define uccf_vdbg uccf_dbg
|
||||
#else
|
||||
#define uccf_vdbg(fmt, args...) do { } while (0)
|
||||
#endif /* UCCF_VERBOSE_DEBUG */
|
||||
|
||||
void ucc_fast_dump_regs(struct ucc_fast_private * uccf)
|
||||
{
|
||||
uccf_info("UCC%d Fast registers:", uccf->uf_info->ucc_num);
|
||||
uccf_info("Base address: 0x%08x", (u32) uccf->uf_regs);
|
||||
|
||||
uccf_info("gumr : addr - 0x%08x, val - 0x%08x",
|
||||
(u32) & uccf->uf_regs->gumr, in_be32(&uccf->uf_regs->gumr));
|
||||
uccf_info("upsmr : addr - 0x%08x, val - 0x%08x",
|
||||
(u32) & uccf->uf_regs->upsmr, in_be32(&uccf->uf_regs->upsmr));
|
||||
uccf_info("utodr : addr - 0x%08x, val - 0x%04x",
|
||||
(u32) & uccf->uf_regs->utodr, in_be16(&uccf->uf_regs->utodr));
|
||||
uccf_info("udsr : addr - 0x%08x, val - 0x%04x",
|
||||
(u32) & uccf->uf_regs->udsr, in_be16(&uccf->uf_regs->udsr));
|
||||
uccf_info("ucce : addr - 0x%08x, val - 0x%08x",
|
||||
(u32) & uccf->uf_regs->ucce, in_be32(&uccf->uf_regs->ucce));
|
||||
uccf_info("uccm : addr - 0x%08x, val - 0x%08x",
|
||||
(u32) & uccf->uf_regs->uccm, in_be32(&uccf->uf_regs->uccm));
|
||||
uccf_info("uccs : addr - 0x%08x, val - 0x%02x",
|
||||
(u32) & uccf->uf_regs->uccs, uccf->uf_regs->uccs);
|
||||
uccf_info("urfb : addr - 0x%08x, val - 0x%08x",
|
||||
(u32) & uccf->uf_regs->urfb, in_be32(&uccf->uf_regs->urfb));
|
||||
uccf_info("urfs : addr - 0x%08x, val - 0x%04x",
|
||||
(u32) & uccf->uf_regs->urfs, in_be16(&uccf->uf_regs->urfs));
|
||||
uccf_info("urfet : addr - 0x%08x, val - 0x%04x",
|
||||
(u32) & uccf->uf_regs->urfet, in_be16(&uccf->uf_regs->urfet));
|
||||
uccf_info("urfset: addr - 0x%08x, val - 0x%04x",
|
||||
(u32) & uccf->uf_regs->urfset,
|
||||
in_be16(&uccf->uf_regs->urfset));
|
||||
uccf_info("utfb : addr - 0x%08x, val - 0x%08x",
|
||||
(u32) & uccf->uf_regs->utfb, in_be32(&uccf->uf_regs->utfb));
|
||||
uccf_info("utfs : addr - 0x%08x, val - 0x%04x",
|
||||
(u32) & uccf->uf_regs->utfs, in_be16(&uccf->uf_regs->utfs));
|
||||
uccf_info("utfet : addr - 0x%08x, val - 0x%04x",
|
||||
(u32) & uccf->uf_regs->utfet, in_be16(&uccf->uf_regs->utfet));
|
||||
uccf_info("utftt : addr - 0x%08x, val - 0x%04x",
|
||||
(u32) & uccf->uf_regs->utftt, in_be16(&uccf->uf_regs->utftt));
|
||||
uccf_info("utpt : addr - 0x%08x, val - 0x%04x",
|
||||
(u32) & uccf->uf_regs->utpt, in_be16(&uccf->uf_regs->utpt));
|
||||
uccf_info("urtry : addr - 0x%08x, val - 0x%08x",
|
||||
(u32) & uccf->uf_regs->urtry, in_be32(&uccf->uf_regs->urtry));
|
||||
uccf_info("guemr : addr - 0x%08x, val - 0x%02x",
|
||||
(u32) & uccf->uf_regs->guemr, uccf->uf_regs->guemr);
|
||||
}
|
||||
|
||||
u32 ucc_fast_get_qe_cr_subblock(int uccf_num)
|
||||
{
|
||||
switch (uccf_num) {
|
||||
case 0: return QE_CR_SUBBLOCK_UCCFAST1;
|
||||
case 1: return QE_CR_SUBBLOCK_UCCFAST2;
|
||||
case 2: return QE_CR_SUBBLOCK_UCCFAST3;
|
||||
case 3: return QE_CR_SUBBLOCK_UCCFAST4;
|
||||
case 4: return QE_CR_SUBBLOCK_UCCFAST5;
|
||||
case 5: return QE_CR_SUBBLOCK_UCCFAST6;
|
||||
case 6: return QE_CR_SUBBLOCK_UCCFAST7;
|
||||
case 7: return QE_CR_SUBBLOCK_UCCFAST8;
|
||||
default: return QE_CR_SUBBLOCK_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf)
|
||||
{
|
||||
out_be16(&uccf->uf_regs->utodr, UCC_FAST_TOD);
|
||||
}
|
||||
|
||||
void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode)
|
||||
{
|
||||
struct ucc_fast *uf_regs;
|
||||
u32 gumr;
|
||||
|
||||
uf_regs = uccf->uf_regs;
|
||||
|
||||
/* Enable reception and/or transmission on this UCC. */
|
||||
gumr = in_be32(&uf_regs->gumr);
|
||||
if (mode & COMM_DIR_TX) {
|
||||
gumr |= UCC_FAST_GUMR_ENT;
|
||||
uccf->enabled_tx = 1;
|
||||
}
|
||||
if (mode & COMM_DIR_RX) {
|
||||
gumr |= UCC_FAST_GUMR_ENR;
|
||||
uccf->enabled_rx = 1;
|
||||
}
|
||||
out_be32(&uf_regs->gumr, gumr);
|
||||
}
|
||||
|
||||
void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode)
|
||||
{
|
||||
struct ucc_fast *uf_regs;
|
||||
u32 gumr;
|
||||
|
||||
uf_regs = uccf->uf_regs;
|
||||
|
||||
/* Disable reception and/or transmission on this UCC. */
|
||||
gumr = in_be32(&uf_regs->gumr);
|
||||
if (mode & COMM_DIR_TX) {
|
||||
gumr &= ~UCC_FAST_GUMR_ENT;
|
||||
uccf->enabled_tx = 0;
|
||||
}
|
||||
if (mode & COMM_DIR_RX) {
|
||||
gumr &= ~UCC_FAST_GUMR_ENR;
|
||||
uccf->enabled_rx = 0;
|
||||
}
|
||||
out_be32(&uf_regs->gumr, gumr);
|
||||
}
|
||||
|
||||
int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret)
|
||||
{
|
||||
struct ucc_fast_private *uccf;
|
||||
struct ucc_fast *uf_regs;
|
||||
u32 gumr = 0;
|
||||
int ret;
|
||||
|
||||
uccf_vdbg("%s: IN", __FUNCTION__);
|
||||
|
||||
if (!uf_info)
|
||||
return -EINVAL;
|
||||
|
||||
/* check if the UCC port number is in range. */
|
||||
if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) {
|
||||
uccf_err("ucc_fast_init: Illagal UCC number!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check that 'max_rx_buf_length' is properly aligned (4). */
|
||||
if (uf_info->max_rx_buf_length & (UCC_FAST_MRBLR_ALIGNMENT - 1)) {
|
||||
uccf_err("ucc_fast_init: max_rx_buf_length not aligned.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Validate Virtual Fifo register values */
|
||||
if (uf_info->urfs < UCC_FAST_URFS_MIN_VAL) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Virtual Fifo register urfs too small.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (uf_info->urfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Virtual Fifo register urfs not aligned.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (uf_info->urfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Virtual Fifo register urfet not aligned.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (uf_info->urfset & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Virtual Fifo register urfset not aligned.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (uf_info->utfs & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Virtual Fifo register utfs not aligned.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (uf_info->utfet & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Virtual Fifo register utfet not aligned.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (uf_info->utftt & (UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT - 1)) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Virtual Fifo register utftt not aligned.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uccf = (struct ucc_fast_private *)
|
||||
kmalloc(sizeof(struct ucc_fast_private), GFP_KERNEL);
|
||||
if (!uccf) {
|
||||
uccf_err
|
||||
("ucc_fast_init: No memory for UCC slow data structure!");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(uccf, 0, sizeof(struct ucc_fast_private));
|
||||
|
||||
/* Fill fast UCC structure */
|
||||
uccf->uf_info = uf_info;
|
||||
/* Set the PHY base address */
|
||||
uccf->uf_regs =
|
||||
(struct ucc_fast *) ioremap(uf_info->regs, sizeof(struct ucc_fast));
|
||||
if (uccf->uf_regs == NULL) {
|
||||
uccf_err
|
||||
("ucc_fast_init: No memory map for UCC slow controller!");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
uccf->enabled_tx = 0;
|
||||
uccf->enabled_rx = 0;
|
||||
uccf->stopped_tx = 0;
|
||||
uccf->stopped_rx = 0;
|
||||
uf_regs = uccf->uf_regs;
|
||||
uccf->p_ucce = (u32 *) & (uf_regs->ucce);
|
||||
uccf->p_uccm = (u32 *) & (uf_regs->uccm);
|
||||
#ifdef STATISTICS
|
||||
uccf->tx_frames = 0;
|
||||
uccf->rx_frames = 0;
|
||||
uccf->rx_discarded = 0;
|
||||
#endif /* STATISTICS */
|
||||
|
||||
/* Init Guemr register */
|
||||
if ((ret = ucc_init_guemr((struct ucc_common *) (uf_regs)))) {
|
||||
uccf_err("ucc_fast_init: Could not init the guemr register.");
|
||||
ucc_fast_free(uccf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set UCC to fast type */
|
||||
if ((ret = ucc_set_type(uf_info->ucc_num,
|
||||
(struct ucc_common *) (uf_regs),
|
||||
UCC_SPEED_TYPE_FAST))) {
|
||||
uccf_err("ucc_fast_init: Could not set type to fast.");
|
||||
ucc_fast_free(uccf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uccf->mrblr = uf_info->max_rx_buf_length;
|
||||
|
||||
/* Set GUMR */
|
||||
/* For more details see the hardware spec. */
|
||||
/* gumr starts as zero. */
|
||||
if (uf_info->tci)
|
||||
gumr |= UCC_FAST_GUMR_TCI;
|
||||
gumr |= uf_info->ttx_trx;
|
||||
if (uf_info->cdp)
|
||||
gumr |= UCC_FAST_GUMR_CDP;
|
||||
if (uf_info->ctsp)
|
||||
gumr |= UCC_FAST_GUMR_CTSP;
|
||||
if (uf_info->cds)
|
||||
gumr |= UCC_FAST_GUMR_CDS;
|
||||
if (uf_info->ctss)
|
||||
gumr |= UCC_FAST_GUMR_CTSS;
|
||||
if (uf_info->txsy)
|
||||
gumr |= UCC_FAST_GUMR_TXSY;
|
||||
if (uf_info->rsyn)
|
||||
gumr |= UCC_FAST_GUMR_RSYN;
|
||||
gumr |= uf_info->synl;
|
||||
if (uf_info->rtsm)
|
||||
gumr |= UCC_FAST_GUMR_RTSM;
|
||||
gumr |= uf_info->renc;
|
||||
if (uf_info->revd)
|
||||
gumr |= UCC_FAST_GUMR_REVD;
|
||||
gumr |= uf_info->tenc;
|
||||
gumr |= uf_info->tcrc;
|
||||
gumr |= uf_info->mode;
|
||||
out_be32(&uf_regs->gumr, gumr);
|
||||
|
||||
/* Allocate memory for Tx Virtual Fifo */
|
||||
uccf->ucc_fast_tx_virtual_fifo_base_offset =
|
||||
qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
|
||||
if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Can not allocate MURAM memory for "
|
||||
"struct ucc_fastx_virtual_fifo_base_offset.");
|
||||
uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
|
||||
ucc_fast_free(uccf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Allocate memory for Rx Virtual Fifo */
|
||||
uccf->ucc_fast_rx_virtual_fifo_base_offset =
|
||||
qe_muram_alloc(uf_info->urfs +
|
||||
(u32)
|
||||
UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
|
||||
UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
|
||||
if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Can not allocate MURAM memory for "
|
||||
"ucc_fast_rx_virtual_fifo_base_offset.");
|
||||
uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
|
||||
ucc_fast_free(uccf);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Set Virtual Fifo registers */
|
||||
out_be16(&uf_regs->urfs, uf_info->urfs);
|
||||
out_be16(&uf_regs->urfet, uf_info->urfet);
|
||||
out_be16(&uf_regs->urfset, uf_info->urfset);
|
||||
out_be16(&uf_regs->utfs, uf_info->utfs);
|
||||
out_be16(&uf_regs->utfet, uf_info->utfet);
|
||||
out_be16(&uf_regs->utftt, uf_info->utftt);
|
||||
/* utfb, urfb are offsets from MURAM base */
|
||||
out_be32(&uf_regs->utfb, uccf->ucc_fast_tx_virtual_fifo_base_offset);
|
||||
out_be32(&uf_regs->urfb, uccf->ucc_fast_rx_virtual_fifo_base_offset);
|
||||
|
||||
/* Mux clocking */
|
||||
/* Grant Support */
|
||||
ucc_set_qe_mux_grant(uf_info->ucc_num, uf_info->grant_support);
|
||||
/* Breakpoint Support */
|
||||
ucc_set_qe_mux_bkpt(uf_info->ucc_num, uf_info->brkpt_support);
|
||||
/* Set Tsa or NMSI mode. */
|
||||
ucc_set_qe_mux_tsa(uf_info->ucc_num, uf_info->tsa);
|
||||
/* If NMSI (not Tsa), set Tx and Rx clock. */
|
||||
if (!uf_info->tsa) {
|
||||
/* Rx clock routing */
|
||||
if (uf_info->rx_clock != QE_CLK_NONE) {
|
||||
if (ucc_set_qe_mux_rxtx
|
||||
(uf_info->ucc_num, uf_info->rx_clock,
|
||||
COMM_DIR_RX)) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Illegal value for parameter 'RxClock'.");
|
||||
ucc_fast_free(uccf);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* Tx clock routing */
|
||||
if (uf_info->tx_clock != QE_CLK_NONE) {
|
||||
if (ucc_set_qe_mux_rxtx
|
||||
(uf_info->ucc_num, uf_info->tx_clock,
|
||||
COMM_DIR_TX)) {
|
||||
uccf_err
|
||||
("ucc_fast_init: Illegal value for parameter 'TxClock'.");
|
||||
ucc_fast_free(uccf);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set interrupt mask register at UCC level. */
|
||||
out_be32(&uf_regs->uccm, uf_info->uccm_mask);
|
||||
|
||||
/* First, clear anything pending at UCC level,
|
||||
* otherwise, old garbage may come through
|
||||
* as soon as the dam is opened
|
||||
* Writing '1' clears
|
||||
*/
|
||||
out_be32(&uf_regs->ucce, 0xffffffff);
|
||||
|
||||
*uccf_ret = uccf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ucc_fast_free(struct ucc_fast_private * uccf)
|
||||
{
|
||||
if (!uccf)
|
||||
return;
|
||||
|
||||
if (uccf->ucc_fast_tx_virtual_fifo_base_offset)
|
||||
qe_muram_free(uccf->ucc_fast_tx_virtual_fifo_base_offset);
|
||||
|
||||
if (uccf->ucc_fast_rx_virtual_fifo_base_offset)
|
||||
qe_muram_free(uccf->ucc_fast_rx_virtual_fifo_base_offset);
|
||||
|
||||
kfree(uccf);
|
||||
}
|
404
arch/powerpc/sysdev/qe_lib/ucc_slow.c
Normal file
404
arch/powerpc/sysdev/qe_lib/ucc_slow.c
Normal file
|
@ -0,0 +1,404 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Authors: Shlomi Gridish <gridish@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
*
|
||||
* Description:
|
||||
* QE UCC Slow API Set - UCC Slow specific routines implementations.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/immap_qe.h>
|
||||
#include <asm/qe.h>
|
||||
|
||||
#include <asm/ucc.h>
|
||||
#include <asm/ucc_slow.h>
|
||||
|
||||
#define uccs_printk(level, format, arg...) \
|
||||
printk(level format "\n", ## arg)
|
||||
|
||||
#define uccs_dbg(format, arg...) \
|
||||
uccs_printk(KERN_DEBUG , format , ## arg)
|
||||
#define uccs_err(format, arg...) \
|
||||
uccs_printk(KERN_ERR , format , ## arg)
|
||||
#define uccs_info(format, arg...) \
|
||||
uccs_printk(KERN_INFO , format , ## arg)
|
||||
#define uccs_warn(format, arg...) \
|
||||
uccs_printk(KERN_WARNING , format , ## arg)
|
||||
|
||||
#ifdef UCCS_VERBOSE_DEBUG
|
||||
#define uccs_vdbg uccs_dbg
|
||||
#else
|
||||
#define uccs_vdbg(fmt, args...) do { } while (0)
|
||||
#endif /* UCCS_VERBOSE_DEBUG */
|
||||
|
||||
u32 ucc_slow_get_qe_cr_subblock(int uccs_num)
|
||||
{
|
||||
switch (uccs_num) {
|
||||
case 0: return QE_CR_SUBBLOCK_UCCSLOW1;
|
||||
case 1: return QE_CR_SUBBLOCK_UCCSLOW2;
|
||||
case 2: return QE_CR_SUBBLOCK_UCCSLOW3;
|
||||
case 3: return QE_CR_SUBBLOCK_UCCSLOW4;
|
||||
case 4: return QE_CR_SUBBLOCK_UCCSLOW5;
|
||||
case 5: return QE_CR_SUBBLOCK_UCCSLOW6;
|
||||
case 6: return QE_CR_SUBBLOCK_UCCSLOW7;
|
||||
case 7: return QE_CR_SUBBLOCK_UCCSLOW8;
|
||||
default: return QE_CR_SUBBLOCK_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
void ucc_slow_poll_transmitter_now(struct ucc_slow_private * uccs)
|
||||
{
|
||||
out_be16(&uccs->us_regs->utodr, UCC_SLOW_TOD);
|
||||
}
|
||||
|
||||
void ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs)
|
||||
{
|
||||
struct ucc_slow_info *us_info = uccs->us_info;
|
||||
u32 id;
|
||||
|
||||
id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
|
||||
qe_issue_cmd(QE_GRACEFUL_STOP_TX, id,
|
||||
QE_CR_PROTOCOL_UNSPECIFIED, 0);
|
||||
}
|
||||
|
||||
void ucc_slow_stop_tx(struct ucc_slow_private * uccs)
|
||||
{
|
||||
struct ucc_slow_info *us_info = uccs->us_info;
|
||||
u32 id;
|
||||
|
||||
id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
|
||||
qe_issue_cmd(QE_STOP_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
|
||||
}
|
||||
|
||||
void ucc_slow_restart_tx(struct ucc_slow_private * uccs)
|
||||
{
|
||||
struct ucc_slow_info *us_info = uccs->us_info;
|
||||
u32 id;
|
||||
|
||||
id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
|
||||
qe_issue_cmd(QE_RESTART_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
|
||||
}
|
||||
|
||||
void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode)
|
||||
{
|
||||
struct ucc_slow *us_regs;
|
||||
u32 gumr_l;
|
||||
|
||||
us_regs = uccs->us_regs;
|
||||
|
||||
/* Enable reception and/or transmission on this UCC. */
|
||||
gumr_l = in_be32(&us_regs->gumr_l);
|
||||
if (mode & COMM_DIR_TX) {
|
||||
gumr_l |= UCC_SLOW_GUMR_L_ENT;
|
||||
uccs->enabled_tx = 1;
|
||||
}
|
||||
if (mode & COMM_DIR_RX) {
|
||||
gumr_l |= UCC_SLOW_GUMR_L_ENR;
|
||||
uccs->enabled_rx = 1;
|
||||
}
|
||||
out_be32(&us_regs->gumr_l, gumr_l);
|
||||
}
|
||||
|
||||
void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)
|
||||
{
|
||||
struct ucc_slow *us_regs;
|
||||
u32 gumr_l;
|
||||
|
||||
us_regs = uccs->us_regs;
|
||||
|
||||
/* Disable reception and/or transmission on this UCC. */
|
||||
gumr_l = in_be32(&us_regs->gumr_l);
|
||||
if (mode & COMM_DIR_TX) {
|
||||
gumr_l &= ~UCC_SLOW_GUMR_L_ENT;
|
||||
uccs->enabled_tx = 0;
|
||||
}
|
||||
if (mode & COMM_DIR_RX) {
|
||||
gumr_l &= ~UCC_SLOW_GUMR_L_ENR;
|
||||
uccs->enabled_rx = 0;
|
||||
}
|
||||
out_be32(&us_regs->gumr_l, gumr_l);
|
||||
}
|
||||
|
||||
int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret)
|
||||
{
|
||||
u32 i;
|
||||
struct ucc_slow *us_regs;
|
||||
u32 gumr;
|
||||
u8 function_code = 0;
|
||||
u8 *bd;
|
||||
struct ucc_slow_private *uccs;
|
||||
u32 id;
|
||||
u32 command;
|
||||
int ret;
|
||||
|
||||
uccs_vdbg("%s: IN", __FUNCTION__);
|
||||
|
||||
if (!us_info)
|
||||
return -EINVAL;
|
||||
|
||||
/* check if the UCC port number is in range. */
|
||||
if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) {
|
||||
uccs_err("ucc_slow_init: Illagal UCC number!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set mrblr
|
||||
* Check that 'max_rx_buf_length' is properly aligned (4), unless
|
||||
* rfw is 1, meaning that QE accepts one byte at a time, unlike normal
|
||||
* case when QE accepts 32 bits at a time.
|
||||
*/
|
||||
if ((!us_info->rfw) &&
|
||||
(us_info->max_rx_buf_length & (UCC_SLOW_MRBLR_ALIGNMENT - 1))) {
|
||||
uccs_err("max_rx_buf_length not aligned.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uccs = (struct ucc_slow_private *)
|
||||
kmalloc(sizeof(struct ucc_slow_private), GFP_KERNEL);
|
||||
if (!uccs) {
|
||||
uccs_err
|
||||
("ucc_slow_init: No memory for UCC slow data structure!");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(uccs, 0, sizeof(struct ucc_slow_private));
|
||||
|
||||
/* Fill slow UCC structure */
|
||||
uccs->us_info = us_info;
|
||||
uccs->saved_uccm = 0;
|
||||
uccs->p_rx_frame = 0;
|
||||
uccs->us_regs = us_info->us_regs;
|
||||
us_regs = uccs->us_regs;
|
||||
uccs->p_ucce = (u16 *) & (us_regs->ucce);
|
||||
uccs->p_uccm = (u16 *) & (us_regs->uccm);
|
||||
#ifdef STATISTICS
|
||||
uccs->rx_frames = 0;
|
||||
uccs->tx_frames = 0;
|
||||
uccs->rx_discarded = 0;
|
||||
#endif /* STATISTICS */
|
||||
|
||||
/* Get PRAM base */
|
||||
uccs->us_pram_offset = qe_muram_alloc(UCC_SLOW_PRAM_SIZE,
|
||||
ALIGNMENT_OF_UCC_SLOW_PRAM);
|
||||
if (IS_MURAM_ERR(uccs->us_pram_offset)) {
|
||||
uccs_err
|
||||
("ucc_slow_init: Can not allocate MURAM memory "
|
||||
"for Slow UCC.");
|
||||
ucc_slow_free(uccs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
|
||||
qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, id, QE_CR_PROTOCOL_UNSPECIFIED,
|
||||
(u32) uccs->us_pram_offset);
|
||||
|
||||
uccs->us_pram = qe_muram_addr(uccs->us_pram_offset);
|
||||
|
||||
/* Init Guemr register */
|
||||
if ((ret = ucc_init_guemr((struct ucc_common *) (us_info->us_regs)))) {
|
||||
uccs_err("ucc_slow_init: Could not init the guemr register.");
|
||||
ucc_slow_free(uccs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set UCC to slow type */
|
||||
if ((ret = ucc_set_type(us_info->ucc_num,
|
||||
(struct ucc_common *) (us_info->us_regs),
|
||||
UCC_SPEED_TYPE_SLOW))) {
|
||||
uccs_err("ucc_slow_init: Could not init the guemr register.");
|
||||
ucc_slow_free(uccs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
out_be16(&uccs->us_pram->mrblr, us_info->max_rx_buf_length);
|
||||
|
||||
INIT_LIST_HEAD(&uccs->confQ);
|
||||
|
||||
/* Allocate BDs. */
|
||||
uccs->rx_base_offset =
|
||||
qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
|
||||
QE_ALIGNMENT_OF_BD);
|
||||
if (IS_MURAM_ERR(uccs->rx_base_offset)) {
|
||||
uccs_err("ucc_slow_init: No memory for Rx BD's.");
|
||||
uccs->rx_base_offset = 0;
|
||||
ucc_slow_free(uccs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
uccs->tx_base_offset =
|
||||
qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
|
||||
QE_ALIGNMENT_OF_BD);
|
||||
if (IS_MURAM_ERR(uccs->tx_base_offset)) {
|
||||
uccs_err("ucc_slow_init: No memory for Tx BD's.");
|
||||
uccs->tx_base_offset = 0;
|
||||
ucc_slow_free(uccs);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Init Tx bds */
|
||||
bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset);
|
||||
for (i = 0; i < us_info->tx_bd_ring_len; i++) {
|
||||
/* clear bd buffer */
|
||||
out_be32(&(((struct qe_bd *)bd)->buf), 0);
|
||||
/* set bd status and length */
|
||||
out_be32((u32*)bd, 0);
|
||||
bd += sizeof(struct qe_bd);
|
||||
}
|
||||
bd -= sizeof(struct qe_bd);
|
||||
/* set bd status and length */
|
||||
out_be32((u32*)bd, T_W); /* for last BD set Wrap bit */
|
||||
|
||||
/* Init Rx bds */
|
||||
bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);
|
||||
for (i = 0; i < us_info->rx_bd_ring_len; i++) {
|
||||
/* set bd status and length */
|
||||
out_be32((u32*)bd, 0);
|
||||
/* clear bd buffer */
|
||||
out_be32(&(((struct qe_bd *)bd)->buf), 0);
|
||||
bd += sizeof(struct qe_bd);
|
||||
}
|
||||
bd -= sizeof(struct qe_bd);
|
||||
/* set bd status and length */
|
||||
out_be32((u32*)bd, R_W); /* for last BD set Wrap bit */
|
||||
|
||||
/* Set GUMR (For more details see the hardware spec.). */
|
||||
/* gumr_h */
|
||||
gumr = 0;
|
||||
gumr |= us_info->tcrc;
|
||||
if (us_info->cdp)
|
||||
gumr |= UCC_SLOW_GUMR_H_CDP;
|
||||
if (us_info->ctsp)
|
||||
gumr |= UCC_SLOW_GUMR_H_CTSP;
|
||||
if (us_info->cds)
|
||||
gumr |= UCC_SLOW_GUMR_H_CDS;
|
||||
if (us_info->ctss)
|
||||
gumr |= UCC_SLOW_GUMR_H_CTSS;
|
||||
if (us_info->tfl)
|
||||
gumr |= UCC_SLOW_GUMR_H_TFL;
|
||||
if (us_info->rfw)
|
||||
gumr |= UCC_SLOW_GUMR_H_RFW;
|
||||
if (us_info->txsy)
|
||||
gumr |= UCC_SLOW_GUMR_H_TXSY;
|
||||
if (us_info->rtsm)
|
||||
gumr |= UCC_SLOW_GUMR_H_RTSM;
|
||||
out_be32(&us_regs->gumr_h, gumr);
|
||||
|
||||
/* gumr_l */
|
||||
gumr = 0;
|
||||
if (us_info->tci)
|
||||
gumr |= UCC_SLOW_GUMR_L_TCI;
|
||||
if (us_info->rinv)
|
||||
gumr |= UCC_SLOW_GUMR_L_RINV;
|
||||
if (us_info->tinv)
|
||||
gumr |= UCC_SLOW_GUMR_L_TINV;
|
||||
if (us_info->tend)
|
||||
gumr |= UCC_SLOW_GUMR_L_TEND;
|
||||
gumr |= us_info->tdcr;
|
||||
gumr |= us_info->rdcr;
|
||||
gumr |= us_info->tenc;
|
||||
gumr |= us_info->renc;
|
||||
gumr |= us_info->diag;
|
||||
gumr |= us_info->mode;
|
||||
out_be32(&us_regs->gumr_l, gumr);
|
||||
|
||||
/* Function code registers */
|
||||
/* function_code has initial value 0 */
|
||||
|
||||
/* if the data is in cachable memory, the 'global' */
|
||||
/* in the function code should be set. */
|
||||
function_code |= us_info->data_mem_part;
|
||||
function_code |= QE_BMR_BYTE_ORDER_BO_MOT; /* Required for QE */
|
||||
uccs->us_pram->tfcr = function_code;
|
||||
uccs->us_pram->rfcr = function_code;
|
||||
|
||||
/* rbase, tbase are offsets from MURAM base */
|
||||
out_be16(&uccs->us_pram->rbase, uccs->us_pram_offset);
|
||||
out_be16(&uccs->us_pram->tbase, uccs->us_pram_offset);
|
||||
|
||||
/* Mux clocking */
|
||||
/* Grant Support */
|
||||
ucc_set_qe_mux_grant(us_info->ucc_num, us_info->grant_support);
|
||||
/* Breakpoint Support */
|
||||
ucc_set_qe_mux_bkpt(us_info->ucc_num, us_info->brkpt_support);
|
||||
/* Set Tsa or NMSI mode. */
|
||||
ucc_set_qe_mux_tsa(us_info->ucc_num, us_info->tsa);
|
||||
/* If NMSI (not Tsa), set Tx and Rx clock. */
|
||||
if (!us_info->tsa) {
|
||||
/* Rx clock routing */
|
||||
if (ucc_set_qe_mux_rxtx
|
||||
(us_info->ucc_num, us_info->rx_clock, COMM_DIR_RX)) {
|
||||
uccs_err
|
||||
("ucc_slow_init: Illegal value for parameter"
|
||||
" 'RxClock'.");
|
||||
ucc_slow_free(uccs);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Tx clock routing */
|
||||
if (ucc_set_qe_mux_rxtx(us_info->ucc_num,
|
||||
us_info->tx_clock, COMM_DIR_TX)) {
|
||||
uccs_err
|
||||
("ucc_slow_init: Illegal value for parameter "
|
||||
"'TxClock'.");
|
||||
ucc_slow_free(uccs);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* INTERRUPTS
|
||||
*/
|
||||
/* Set interrupt mask register at UCC level. */
|
||||
out_be16(&us_regs->uccm, us_info->uccm_mask);
|
||||
|
||||
/* First, clear anything pending at UCC level, */
|
||||
/* otherwise, old garbage may come through */
|
||||
/* as soon as the dam is opened. */
|
||||
|
||||
/* Writing '1' clears */
|
||||
out_be16(&us_regs->ucce, 0xffff);
|
||||
|
||||
/* Issue QE Init command */
|
||||
if (us_info->init_tx && us_info->init_rx)
|
||||
command = QE_INIT_TX_RX;
|
||||
else if (us_info->init_tx)
|
||||
command = QE_INIT_TX;
|
||||
else
|
||||
command = QE_INIT_RX; /* We know at least one is TRUE */
|
||||
id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
|
||||
qe_issue_cmd(command, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
|
||||
|
||||
*uccs_ret = uccs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ucc_slow_free(struct ucc_slow_private * uccs)
|
||||
{
|
||||
if (!uccs)
|
||||
return;
|
||||
|
||||
if (uccs->rx_base_offset)
|
||||
qe_muram_free(uccs->rx_base_offset);
|
||||
|
||||
if (uccs->tx_base_offset)
|
||||
qe_muram_free(uccs->tx_base_offset);
|
||||
|
||||
if (uccs->us_pram) {
|
||||
qe_muram_free(uccs->us_pram_offset);
|
||||
uccs->us_pram = NULL;
|
||||
}
|
||||
|
||||
kfree(uccs);
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
* Routines providing a simple monitor for use on the PowerMac.
|
||||
*
|
||||
* Copyright (C) 1996-2005 Paul Mackerras.
|
||||
* Copyright (C) 2001 PPC64 Team, IBM Corp
|
||||
* Copyrignt (C) 2006 Michael Ellerman, IBM Corp
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -503,7 +505,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
|
|||
|
||||
mtmsr(msr); /* restore interrupt enable */
|
||||
|
||||
return cmd != 'X';
|
||||
return cmd != 'X' && cmd != EOF;
|
||||
}
|
||||
|
||||
int xmon(struct pt_regs *excp)
|
||||
|
@ -2597,3 +2599,34 @@ static int __init setup_xmon_sysrq(void)
|
|||
}
|
||||
__initcall(setup_xmon_sysrq);
|
||||
#endif /* CONFIG_MAGIC_SYSRQ */
|
||||
|
||||
int __initdata xmon_early, xmon_off;
|
||||
|
||||
static int __init early_parse_xmon(char *p)
|
||||
{
|
||||
if (!p || strncmp(p, "early", 5) == 0) {
|
||||
/* just "xmon" is equivalent to "xmon=early" */
|
||||
xmon_init(1);
|
||||
xmon_early = 1;
|
||||
} else if (strncmp(p, "on", 2) == 0)
|
||||
xmon_init(1);
|
||||
else if (strncmp(p, "off", 3) == 0)
|
||||
xmon_off = 1;
|
||||
else if (strncmp(p, "nobt", 4) == 0)
|
||||
xmon_no_auto_backtrace = 1;
|
||||
else
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("xmon", early_parse_xmon);
|
||||
|
||||
void __init xmon_setup(void)
|
||||
{
|
||||
#ifdef CONFIG_XMON_DEFAULT
|
||||
if (!xmon_off)
|
||||
xmon_init(1);
|
||||
#endif
|
||||
if (xmon_early)
|
||||
debugger(NULL);
|
||||
}
|
||||
|
|
|
@ -636,7 +636,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||
intr = in_8(&sw->intr);
|
||||
err = (intr & ERROR_INTR)? in_8(&sw->error): 0;
|
||||
if ((intr & ERROR_INTR) && fs->state != do_transfer)
|
||||
printk(KERN_ERR "swim3_interrupt, state=%d, dir=%lx, intr=%x, err=%x\n",
|
||||
printk(KERN_ERR "swim3_interrupt, state=%d, dir=%x, intr=%x, err=%x\n",
|
||||
fs->state, rq_data_dir(fd_req), intr, err);
|
||||
switch (fs->state) {
|
||||
case locating:
|
||||
|
@ -742,7 +742,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
|||
if ((stat & ACTIVE) == 0 || resid != 0) {
|
||||
/* musta been an error */
|
||||
printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid);
|
||||
printk(KERN_ERR " state=%d, dir=%lx, intr=%x, err=%x\n",
|
||||
printk(KERN_ERR " state=%d, dir=%x, intr=%x, err=%x\n",
|
||||
fs->state, rq_data_dir(fd_req), intr, err);
|
||||
end_request(fd_req, 0);
|
||||
fs->state = idle;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <asm/hvconsole.h>
|
||||
#include <asm/vio.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/iseries/vio.h>
|
||||
#include <asm/iseries/hv_call.h>
|
||||
#include <asm/iseries/hv_lp_config.h>
|
||||
|
@ -488,6 +489,9 @@ static int hvc_vio_init(void)
|
|||
atomic_t wait_flag;
|
||||
int rc;
|
||||
|
||||
if (!firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
return -EIO;
|
||||
|
||||
/* +2 for fudge */
|
||||
rc = viopath_open(HvLpConfig_getPrimaryLpIndex(),
|
||||
viomajorsubtype_chario, VIOCHAR_WINDOW + 2);
|
||||
|
@ -562,7 +566,7 @@ static int hvc_find_vtys(void)
|
|||
|
||||
for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
|
||||
vty = of_find_node_by_name(vty, "vty")) {
|
||||
uint32_t *vtermno;
|
||||
const uint32_t *vtermno;
|
||||
|
||||
/* We have statically defined space for only a certain number
|
||||
* of console adapters.
|
||||
|
@ -571,7 +575,7 @@ static int hvc_find_vtys(void)
|
|||
(num_found >= VTTY_PORTS))
|
||||
break;
|
||||
|
||||
vtermno = (uint32_t *)get_property(vty, "reg", NULL);
|
||||
vtermno = get_property(vty, "reg", NULL);
|
||||
if (!vtermno)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <asm/hvconsole.h>
|
||||
#include <asm/vio.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/firmware.h>
|
||||
|
||||
#include "hvc_console.h"
|
||||
|
||||
|
@ -120,6 +121,9 @@ static int hvc_vio_init(void)
|
|||
{
|
||||
int rc;
|
||||
|
||||
if (firmware_has_feature(FW_FEATURE_ISERIES))
|
||||
return -EIO;
|
||||
|
||||
/* Register as a vio device to receive callbacks */
|
||||
rc = vio_register_driver(&hvc_vio_driver);
|
||||
|
||||
|
|
|
@ -14,34 +14,36 @@
|
|||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#include <asm/asm-compat.h>
|
||||
|
||||
/* firmware feature bitmask values */
|
||||
#define FIRMWARE_MAX_FEATURES 63
|
||||
|
||||
#define FW_FEATURE_PFT (1UL<<0)
|
||||
#define FW_FEATURE_TCE (1UL<<1)
|
||||
#define FW_FEATURE_SPRG0 (1UL<<2)
|
||||
#define FW_FEATURE_DABR (1UL<<3)
|
||||
#define FW_FEATURE_COPY (1UL<<4)
|
||||
#define FW_FEATURE_ASR (1UL<<5)
|
||||
#define FW_FEATURE_DEBUG (1UL<<6)
|
||||
#define FW_FEATURE_TERM (1UL<<7)
|
||||
#define FW_FEATURE_PERF (1UL<<8)
|
||||
#define FW_FEATURE_DUMP (1UL<<9)
|
||||
#define FW_FEATURE_INTERRUPT (1UL<<10)
|
||||
#define FW_FEATURE_MIGRATE (1UL<<11)
|
||||
#define FW_FEATURE_PERFMON (1UL<<12)
|
||||
#define FW_FEATURE_CRQ (1UL<<13)
|
||||
#define FW_FEATURE_VIO (1UL<<14)
|
||||
#define FW_FEATURE_RDMA (1UL<<15)
|
||||
#define FW_FEATURE_LLAN (1UL<<16)
|
||||
#define FW_FEATURE_BULK (1UL<<17)
|
||||
#define FW_FEATURE_XDABR (1UL<<18)
|
||||
#define FW_FEATURE_MULTITCE (1UL<<19)
|
||||
#define FW_FEATURE_SPLPAR (1UL<<20)
|
||||
#define FW_FEATURE_ISERIES (1UL<<21)
|
||||
#define FW_FEATURE_LPAR (1UL<<22)
|
||||
#define FW_FEATURE_PFT ASM_CONST(0x0000000000000001)
|
||||
#define FW_FEATURE_TCE ASM_CONST(0x0000000000000002)
|
||||
#define FW_FEATURE_SPRG0 ASM_CONST(0x0000000000000004)
|
||||
#define FW_FEATURE_DABR ASM_CONST(0x0000000000000008)
|
||||
#define FW_FEATURE_COPY ASM_CONST(0x0000000000000010)
|
||||
#define FW_FEATURE_ASR ASM_CONST(0x0000000000000020)
|
||||
#define FW_FEATURE_DEBUG ASM_CONST(0x0000000000000040)
|
||||
#define FW_FEATURE_TERM ASM_CONST(0x0000000000000080)
|
||||
#define FW_FEATURE_PERF ASM_CONST(0x0000000000000100)
|
||||
#define FW_FEATURE_DUMP ASM_CONST(0x0000000000000200)
|
||||
#define FW_FEATURE_INTERRUPT ASM_CONST(0x0000000000000400)
|
||||
#define FW_FEATURE_MIGRATE ASM_CONST(0x0000000000000800)
|
||||
#define FW_FEATURE_PERFMON ASM_CONST(0x0000000000001000)
|
||||
#define FW_FEATURE_CRQ ASM_CONST(0x0000000000002000)
|
||||
#define FW_FEATURE_VIO ASM_CONST(0x0000000000004000)
|
||||
#define FW_FEATURE_RDMA ASM_CONST(0x0000000000008000)
|
||||
#define FW_FEATURE_LLAN ASM_CONST(0x0000000000010000)
|
||||
#define FW_FEATURE_BULK ASM_CONST(0x0000000000020000)
|
||||
#define FW_FEATURE_XDABR ASM_CONST(0x0000000000040000)
|
||||
#define FW_FEATURE_MULTITCE ASM_CONST(0x0000000000080000)
|
||||
#define FW_FEATURE_SPLPAR ASM_CONST(0x0000000000100000)
|
||||
#define FW_FEATURE_ISERIES ASM_CONST(0x0000000000200000)
|
||||
#define FW_FEATURE_LPAR ASM_CONST(0x0000000000400000)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
enum {
|
||||
#ifdef CONFIG_PPC64
|
||||
|
@ -94,6 +96,23 @@ extern void machine_check_fwnmi(void);
|
|||
/* This is true if we are using the firmware NMI handler (typically LPAR) */
|
||||
extern int fwnmi_active;
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
#define BEGIN_FW_FTR_SECTION 96:
|
||||
|
||||
#define END_FW_FTR_SECTION(msk, val) \
|
||||
97: \
|
||||
.section __fw_ftr_fixup,"a"; \
|
||||
.align 3; \
|
||||
.llong msk; \
|
||||
.llong val; \
|
||||
.llong 96b; \
|
||||
.llong 97b; \
|
||||
.previous
|
||||
|
||||
#define END_FW_FTR_SECTION_IFSET(msk) END_FW_FTR_SECTION((msk), (msk))
|
||||
#define END_FW_FTR_SECTION_IFCLR(msk) END_FW_FTR_SECTION((msk), 0)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* __ASM_POWERPC_FIRMWARE_H */
|
||||
|
|
477
include/asm-powerpc/immap_qe.h
Normal file
477
include/asm-powerpc/immap_qe.h
Normal file
|
@ -0,0 +1,477 @@
|
|||
/*
|
||||
* include/asm-powerpc/immap_qe.h
|
||||
*
|
||||
* QUICC Engine (QE) Internal Memory Map.
|
||||
* The Internal Memory Map for devices with QE on them. This
|
||||
* is the superset of all QE devices (8360, etc.).
|
||||
|
||||
* Copyright (C) 2006. Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Authors: Shlomi Gridish <gridish@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#ifndef _ASM_POWERPC_IMMAP_QE_H
|
||||
#define _ASM_POWERPC_IMMAP_QE_H
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#define QE_IMMAP_SIZE (1024 * 1024) /* 1MB from 1MB+IMMR */
|
||||
|
||||
/* QE I-RAM */
|
||||
struct qe_iram {
|
||||
__be32 iadd; /* I-RAM Address Register */
|
||||
__be32 idata; /* I-RAM Data Register */
|
||||
u8 res0[0x78];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* QE Interrupt Controller */
|
||||
struct qe_ic_regs {
|
||||
__be32 qicr;
|
||||
__be32 qivec;
|
||||
__be32 qripnr;
|
||||
__be32 qipnr;
|
||||
__be32 qipxcc;
|
||||
__be32 qipycc;
|
||||
__be32 qipwcc;
|
||||
__be32 qipzcc;
|
||||
__be32 qimr;
|
||||
__be32 qrimr;
|
||||
__be32 qicnr;
|
||||
u8 res0[0x4];
|
||||
__be32 qiprta;
|
||||
__be32 qiprtb;
|
||||
u8 res1[0x4];
|
||||
__be32 qricr;
|
||||
u8 res2[0x20];
|
||||
__be32 qhivec;
|
||||
u8 res3[0x1C];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Communications Processor */
|
||||
struct cp_qe {
|
||||
__be32 cecr; /* QE command register */
|
||||
__be32 ceccr; /* QE controller configuration register */
|
||||
__be32 cecdr; /* QE command data register */
|
||||
u8 res0[0xA];
|
||||
__be16 ceter; /* QE timer event register */
|
||||
u8 res1[0x2];
|
||||
__be16 cetmr; /* QE timers mask register */
|
||||
__be32 cetscr; /* QE time-stamp timer control register */
|
||||
__be32 cetsr1; /* QE time-stamp register 1 */
|
||||
__be32 cetsr2; /* QE time-stamp register 2 */
|
||||
u8 res2[0x8];
|
||||
__be32 cevter; /* QE virtual tasks event register */
|
||||
__be32 cevtmr; /* QE virtual tasks mask register */
|
||||
__be16 cercr; /* QE RAM control register */
|
||||
u8 res3[0x2];
|
||||
u8 res4[0x24];
|
||||
__be16 ceexe1; /* QE external request 1 event register */
|
||||
u8 res5[0x2];
|
||||
__be16 ceexm1; /* QE external request 1 mask register */
|
||||
u8 res6[0x2];
|
||||
__be16 ceexe2; /* QE external request 2 event register */
|
||||
u8 res7[0x2];
|
||||
__be16 ceexm2; /* QE external request 2 mask register */
|
||||
u8 res8[0x2];
|
||||
__be16 ceexe3; /* QE external request 3 event register */
|
||||
u8 res9[0x2];
|
||||
__be16 ceexm3; /* QE external request 3 mask register */
|
||||
u8 res10[0x2];
|
||||
__be16 ceexe4; /* QE external request 4 event register */
|
||||
u8 res11[0x2];
|
||||
__be16 ceexm4; /* QE external request 4 mask register */
|
||||
u8 res12[0x2];
|
||||
u8 res13[0x280];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* QE Multiplexer */
|
||||
struct qe_mux {
|
||||
__be32 cmxgcr; /* CMX general clock route register */
|
||||
__be32 cmxsi1cr_l; /* CMX SI1 clock route low register */
|
||||
__be32 cmxsi1cr_h; /* CMX SI1 clock route high register */
|
||||
__be32 cmxsi1syr; /* CMX SI1 SYNC route register */
|
||||
__be32 cmxucr1; /* CMX UCC1, UCC3 clock route register */
|
||||
__be32 cmxucr2; /* CMX UCC5, UCC7 clock route register */
|
||||
__be32 cmxucr3; /* CMX UCC2, UCC4 clock route register */
|
||||
__be32 cmxucr4; /* CMX UCC6, UCC8 clock route register */
|
||||
__be32 cmxupcr; /* CMX UPC clock route register */
|
||||
u8 res0[0x1C];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* QE Timers */
|
||||
struct qe_timers {
|
||||
u8 gtcfr1; /* Timer 1 and Timer 2 global config register*/
|
||||
u8 res0[0x3];
|
||||
u8 gtcfr2; /* Timer 3 and timer 4 global config register*/
|
||||
u8 res1[0xB];
|
||||
__be16 gtmdr1; /* Timer 1 mode register */
|
||||
__be16 gtmdr2; /* Timer 2 mode register */
|
||||
__be16 gtrfr1; /* Timer 1 reference register */
|
||||
__be16 gtrfr2; /* Timer 2 reference register */
|
||||
__be16 gtcpr1; /* Timer 1 capture register */
|
||||
__be16 gtcpr2; /* Timer 2 capture register */
|
||||
__be16 gtcnr1; /* Timer 1 counter */
|
||||
__be16 gtcnr2; /* Timer 2 counter */
|
||||
__be16 gtmdr3; /* Timer 3 mode register */
|
||||
__be16 gtmdr4; /* Timer 4 mode register */
|
||||
__be16 gtrfr3; /* Timer 3 reference register */
|
||||
__be16 gtrfr4; /* Timer 4 reference register */
|
||||
__be16 gtcpr3; /* Timer 3 capture register */
|
||||
__be16 gtcpr4; /* Timer 4 capture register */
|
||||
__be16 gtcnr3; /* Timer 3 counter */
|
||||
__be16 gtcnr4; /* Timer 4 counter */
|
||||
__be16 gtevr1; /* Timer 1 event register */
|
||||
__be16 gtevr2; /* Timer 2 event register */
|
||||
__be16 gtevr3; /* Timer 3 event register */
|
||||
__be16 gtevr4; /* Timer 4 event register */
|
||||
__be16 gtps; /* Timer 1 prescale register */
|
||||
u8 res2[0x46];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* BRG */
|
||||
struct qe_brg {
|
||||
__be32 brgc1; /* BRG1 configuration register */
|
||||
__be32 brgc2; /* BRG2 configuration register */
|
||||
__be32 brgc3; /* BRG3 configuration register */
|
||||
__be32 brgc4; /* BRG4 configuration register */
|
||||
__be32 brgc5; /* BRG5 configuration register */
|
||||
__be32 brgc6; /* BRG6 configuration register */
|
||||
__be32 brgc7; /* BRG7 configuration register */
|
||||
__be32 brgc8; /* BRG8 configuration register */
|
||||
__be32 brgc9; /* BRG9 configuration register */
|
||||
__be32 brgc10; /* BRG10 configuration register */
|
||||
__be32 brgc11; /* BRG11 configuration register */
|
||||
__be32 brgc12; /* BRG12 configuration register */
|
||||
__be32 brgc13; /* BRG13 configuration register */
|
||||
__be32 brgc14; /* BRG14 configuration register */
|
||||
__be32 brgc15; /* BRG15 configuration register */
|
||||
__be32 brgc16; /* BRG16 configuration register */
|
||||
u8 res0[0x40];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* SPI */
|
||||
struct spi {
|
||||
u8 res0[0x20];
|
||||
__be32 spmode; /* SPI mode register */
|
||||
u8 res1[0x2];
|
||||
u8 spie; /* SPI event register */
|
||||
u8 res2[0x1];
|
||||
u8 res3[0x2];
|
||||
u8 spim; /* SPI mask register */
|
||||
u8 res4[0x1];
|
||||
u8 res5[0x1];
|
||||
u8 spcom; /* SPI command register */
|
||||
u8 res6[0x2];
|
||||
__be32 spitd; /* SPI transmit data register (cpu mode) */
|
||||
__be32 spird; /* SPI receive data register (cpu mode) */
|
||||
u8 res7[0x8];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* SI */
|
||||
struct si1 {
|
||||
__be16 siamr1; /* SI1 TDMA mode register */
|
||||
__be16 sibmr1; /* SI1 TDMB mode register */
|
||||
__be16 sicmr1; /* SI1 TDMC mode register */
|
||||
__be16 sidmr1; /* SI1 TDMD mode register */
|
||||
u8 siglmr1_h; /* SI1 global mode register high */
|
||||
u8 res0[0x1];
|
||||
u8 sicmdr1_h; /* SI1 command register high */
|
||||
u8 res2[0x1];
|
||||
u8 sistr1_h; /* SI1 status register high */
|
||||
u8 res3[0x1];
|
||||
__be16 sirsr1_h; /* SI1 RAM shadow address register high */
|
||||
u8 sitarc1; /* SI1 RAM counter Tx TDMA */
|
||||
u8 sitbrc1; /* SI1 RAM counter Tx TDMB */
|
||||
u8 sitcrc1; /* SI1 RAM counter Tx TDMC */
|
||||
u8 sitdrc1; /* SI1 RAM counter Tx TDMD */
|
||||
u8 sirarc1; /* SI1 RAM counter Rx TDMA */
|
||||
u8 sirbrc1; /* SI1 RAM counter Rx TDMB */
|
||||
u8 sircrc1; /* SI1 RAM counter Rx TDMC */
|
||||
u8 sirdrc1; /* SI1 RAM counter Rx TDMD */
|
||||
u8 res4[0x8];
|
||||
__be16 siemr1; /* SI1 TDME mode register 16 bits */
|
||||
__be16 sifmr1; /* SI1 TDMF mode register 16 bits */
|
||||
__be16 sigmr1; /* SI1 TDMG mode register 16 bits */
|
||||
__be16 sihmr1; /* SI1 TDMH mode register 16 bits */
|
||||
u8 siglmg1_l; /* SI1 global mode register low 8 bits */
|
||||
u8 res5[0x1];
|
||||
u8 sicmdr1_l; /* SI1 command register low 8 bits */
|
||||
u8 res6[0x1];
|
||||
u8 sistr1_l; /* SI1 status register low 8 bits */
|
||||
u8 res7[0x1];
|
||||
__be16 sirsr1_l; /* SI1 RAM shadow address register low 16 bits*/
|
||||
u8 siterc1; /* SI1 RAM counter Tx TDME 8 bits */
|
||||
u8 sitfrc1; /* SI1 RAM counter Tx TDMF 8 bits */
|
||||
u8 sitgrc1; /* SI1 RAM counter Tx TDMG 8 bits */
|
||||
u8 sithrc1; /* SI1 RAM counter Tx TDMH 8 bits */
|
||||
u8 sirerc1; /* SI1 RAM counter Rx TDME 8 bits */
|
||||
u8 sirfrc1; /* SI1 RAM counter Rx TDMF 8 bits */
|
||||
u8 sirgrc1; /* SI1 RAM counter Rx TDMG 8 bits */
|
||||
u8 sirhrc1; /* SI1 RAM counter Rx TDMH 8 bits */
|
||||
u8 res8[0x8];
|
||||
__be32 siml1; /* SI1 multiframe limit register */
|
||||
u8 siedm1; /* SI1 extended diagnostic mode register */
|
||||
u8 res9[0xBB];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* SI Routing Tables */
|
||||
struct sir {
|
||||
u8 tx[0x400];
|
||||
u8 rx[0x400];
|
||||
u8 res0[0x800];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* USB Controller */
|
||||
struct usb_ctlr {
|
||||
u8 usb_usmod;
|
||||
u8 usb_usadr;
|
||||
u8 usb_uscom;
|
||||
u8 res1[1];
|
||||
__be16 usb_usep1;
|
||||
__be16 usb_usep2;
|
||||
__be16 usb_usep3;
|
||||
__be16 usb_usep4;
|
||||
u8 res2[4];
|
||||
__be16 usb_usber;
|
||||
u8 res3[2];
|
||||
__be16 usb_usbmr;
|
||||
u8 res4[1];
|
||||
u8 usb_usbs;
|
||||
__be16 usb_ussft;
|
||||
u8 res5[2];
|
||||
__be16 usb_usfrn;
|
||||
u8 res6[0x22];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* MCC */
|
||||
struct mcc {
|
||||
__be32 mcce; /* MCC event register */
|
||||
__be32 mccm; /* MCC mask register */
|
||||
__be32 mccf; /* MCC configuration register */
|
||||
__be32 merl; /* MCC emergency request level register */
|
||||
u8 res0[0xF0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* QE UCC Slow */
|
||||
struct ucc_slow {
|
||||
__be32 gumr_l; /* UCCx general mode register (low) */
|
||||
__be32 gumr_h; /* UCCx general mode register (high) */
|
||||
__be16 upsmr; /* UCCx protocol-specific mode register */
|
||||
u8 res0[0x2];
|
||||
__be16 utodr; /* UCCx transmit on demand register */
|
||||
__be16 udsr; /* UCCx data synchronization register */
|
||||
__be16 ucce; /* UCCx event register */
|
||||
u8 res1[0x2];
|
||||
__be16 uccm; /* UCCx mask register */
|
||||
u8 res2[0x1];
|
||||
u8 uccs; /* UCCx status register */
|
||||
u8 res3[0x24];
|
||||
__be16 utpt;
|
||||
u8 guemr; /* UCC general extended mode register */
|
||||
u8 res4[0x200 - 0x091];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* QE UCC Fast */
|
||||
struct ucc_fast {
|
||||
__be32 gumr; /* UCCx general mode register */
|
||||
__be32 upsmr; /* UCCx protocol-specific mode register */
|
||||
__be16 utodr; /* UCCx transmit on demand register */
|
||||
u8 res0[0x2];
|
||||
__be16 udsr; /* UCCx data synchronization register */
|
||||
u8 res1[0x2];
|
||||
__be32 ucce; /* UCCx event register */
|
||||
__be32 uccm; /* UCCx mask register */
|
||||
u8 uccs; /* UCCx status register */
|
||||
u8 res2[0x7];
|
||||
__be32 urfb; /* UCC receive FIFO base */
|
||||
__be16 urfs; /* UCC receive FIFO size */
|
||||
u8 res3[0x2];
|
||||
__be16 urfet; /* UCC receive FIFO emergency threshold */
|
||||
__be16 urfset; /* UCC receive FIFO special emergency
|
||||
threshold */
|
||||
__be32 utfb; /* UCC transmit FIFO base */
|
||||
__be16 utfs; /* UCC transmit FIFO size */
|
||||
u8 res4[0x2];
|
||||
__be16 utfet; /* UCC transmit FIFO emergency threshold */
|
||||
u8 res5[0x2];
|
||||
__be16 utftt; /* UCC transmit FIFO transmit threshold */
|
||||
u8 res6[0x2];
|
||||
__be16 utpt; /* UCC transmit polling timer */
|
||||
u8 res7[0x2];
|
||||
__be32 urtry; /* UCC retry counter register */
|
||||
u8 res8[0x4C];
|
||||
u8 guemr; /* UCC general extended mode register */
|
||||
u8 res9[0x100 - 0x091];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* QE UCC */
|
||||
struct ucc_common {
|
||||
u8 res1[0x90];
|
||||
u8 guemr;
|
||||
u8 res2[0x200 - 0x091];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ucc {
|
||||
union {
|
||||
struct ucc_slow slow;
|
||||
struct ucc_fast fast;
|
||||
struct ucc_common common;
|
||||
};
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* MultiPHY UTOPIA POS Controllers (UPC) */
|
||||
struct upc {
|
||||
__be32 upgcr; /* UTOPIA/POS general configuration register */
|
||||
__be32 uplpa; /* UTOPIA/POS last PHY address */
|
||||
__be32 uphec; /* ATM HEC register */
|
||||
__be32 upuc; /* UTOPIA/POS UCC configuration */
|
||||
__be32 updc1; /* UTOPIA/POS device 1 configuration */
|
||||
__be32 updc2; /* UTOPIA/POS device 2 configuration */
|
||||
__be32 updc3; /* UTOPIA/POS device 3 configuration */
|
||||
__be32 updc4; /* UTOPIA/POS device 4 configuration */
|
||||
__be32 upstpa; /* UTOPIA/POS STPA threshold */
|
||||
u8 res0[0xC];
|
||||
__be32 updrs1_h; /* UTOPIA/POS device 1 rate select */
|
||||
__be32 updrs1_l; /* UTOPIA/POS device 1 rate select */
|
||||
__be32 updrs2_h; /* UTOPIA/POS device 2 rate select */
|
||||
__be32 updrs2_l; /* UTOPIA/POS device 2 rate select */
|
||||
__be32 updrs3_h; /* UTOPIA/POS device 3 rate select */
|
||||
__be32 updrs3_l; /* UTOPIA/POS device 3 rate select */
|
||||
__be32 updrs4_h; /* UTOPIA/POS device 4 rate select */
|
||||
__be32 updrs4_l; /* UTOPIA/POS device 4 rate select */
|
||||
__be32 updrp1; /* UTOPIA/POS device 1 receive priority low */
|
||||
__be32 updrp2; /* UTOPIA/POS device 2 receive priority low */
|
||||
__be32 updrp3; /* UTOPIA/POS device 3 receive priority low */
|
||||
__be32 updrp4; /* UTOPIA/POS device 4 receive priority low */
|
||||
__be32 upde1; /* UTOPIA/POS device 1 event */
|
||||
__be32 upde2; /* UTOPIA/POS device 2 event */
|
||||
__be32 upde3; /* UTOPIA/POS device 3 event */
|
||||
__be32 upde4; /* UTOPIA/POS device 4 event */
|
||||
__be16 uprp1;
|
||||
__be16 uprp2;
|
||||
__be16 uprp3;
|
||||
__be16 uprp4;
|
||||
u8 res1[0x8];
|
||||
__be16 uptirr1_0; /* Device 1 transmit internal rate 0 */
|
||||
__be16 uptirr1_1; /* Device 1 transmit internal rate 1 */
|
||||
__be16 uptirr1_2; /* Device 1 transmit internal rate 2 */
|
||||
__be16 uptirr1_3; /* Device 1 transmit internal rate 3 */
|
||||
__be16 uptirr2_0; /* Device 2 transmit internal rate 0 */
|
||||
__be16 uptirr2_1; /* Device 2 transmit internal rate 1 */
|
||||
__be16 uptirr2_2; /* Device 2 transmit internal rate 2 */
|
||||
__be16 uptirr2_3; /* Device 2 transmit internal rate 3 */
|
||||
__be16 uptirr3_0; /* Device 3 transmit internal rate 0 */
|
||||
__be16 uptirr3_1; /* Device 3 transmit internal rate 1 */
|
||||
__be16 uptirr3_2; /* Device 3 transmit internal rate 2 */
|
||||
__be16 uptirr3_3; /* Device 3 transmit internal rate 3 */
|
||||
__be16 uptirr4_0; /* Device 4 transmit internal rate 0 */
|
||||
__be16 uptirr4_1; /* Device 4 transmit internal rate 1 */
|
||||
__be16 uptirr4_2; /* Device 4 transmit internal rate 2 */
|
||||
__be16 uptirr4_3; /* Device 4 transmit internal rate 3 */
|
||||
__be32 uper1; /* Device 1 port enable register */
|
||||
__be32 uper2; /* Device 2 port enable register */
|
||||
__be32 uper3; /* Device 3 port enable register */
|
||||
__be32 uper4; /* Device 4 port enable register */
|
||||
u8 res2[0x150];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* SDMA */
|
||||
struct sdma {
|
||||
__be32 sdsr; /* Serial DMA status register */
|
||||
__be32 sdmr; /* Serial DMA mode register */
|
||||
__be32 sdtr1; /* SDMA system bus threshold register */
|
||||
__be32 sdtr2; /* SDMA secondary bus threshold register */
|
||||
__be32 sdhy1; /* SDMA system bus hysteresis register */
|
||||
__be32 sdhy2; /* SDMA secondary bus hysteresis register */
|
||||
__be32 sdta1; /* SDMA system bus address register */
|
||||
__be32 sdta2; /* SDMA secondary bus address register */
|
||||
__be32 sdtm1; /* SDMA system bus MSNUM register */
|
||||
__be32 sdtm2; /* SDMA secondary bus MSNUM register */
|
||||
u8 res0[0x10];
|
||||
__be32 sdaqr; /* SDMA address bus qualify register */
|
||||
__be32 sdaqmr; /* SDMA address bus qualify mask register */
|
||||
u8 res1[0x4];
|
||||
__be32 sdebcr; /* SDMA CAM entries base register */
|
||||
u8 res2[0x38];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Debug Space */
|
||||
struct dbg {
|
||||
__be32 bpdcr; /* Breakpoint debug command register */
|
||||
__be32 bpdsr; /* Breakpoint debug status register */
|
||||
__be32 bpdmr; /* Breakpoint debug mask register */
|
||||
__be32 bprmrr0; /* Breakpoint request mode risc register 0 */
|
||||
__be32 bprmrr1; /* Breakpoint request mode risc register 1 */
|
||||
u8 res0[0x8];
|
||||
__be32 bprmtr0; /* Breakpoint request mode trb register 0 */
|
||||
__be32 bprmtr1; /* Breakpoint request mode trb register 1 */
|
||||
u8 res1[0x8];
|
||||
__be32 bprmir; /* Breakpoint request mode immediate register */
|
||||
__be32 bprmsr; /* Breakpoint request mode serial register */
|
||||
__be32 bpemr; /* Breakpoint exit mode register */
|
||||
u8 res2[0x48];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* RISC Special Registers (Trap and Breakpoint) */
|
||||
struct rsp {
|
||||
u8 fixme[0x100];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct qe_immap {
|
||||
struct qe_iram iram; /* I-RAM */
|
||||
struct qe_ic_regs ic; /* Interrupt Controller */
|
||||
struct cp_qe cp; /* Communications Processor */
|
||||
struct qe_mux qmx; /* QE Multiplexer */
|
||||
struct qe_timers qet; /* QE Timers */
|
||||
struct spi spi[0x2]; /* spi */
|
||||
struct mcc mcc; /* mcc */
|
||||
struct qe_brg brg; /* brg */
|
||||
struct usb_ctlr usb; /* USB */
|
||||
struct si1 si1; /* SI */
|
||||
u8 res11[0x800];
|
||||
struct sir sir; /* SI Routing Tables */
|
||||
struct ucc ucc1; /* ucc1 */
|
||||
struct ucc ucc3; /* ucc3 */
|
||||
struct ucc ucc5; /* ucc5 */
|
||||
struct ucc ucc7; /* ucc7 */
|
||||
u8 res12[0x600];
|
||||
struct upc upc1; /* MultiPHY UTOPIA POS Ctrlr 1*/
|
||||
struct ucc ucc2; /* ucc2 */
|
||||
struct ucc ucc4; /* ucc4 */
|
||||
struct ucc ucc6; /* ucc6 */
|
||||
struct ucc ucc8; /* ucc8 */
|
||||
u8 res13[0x600];
|
||||
struct upc upc2; /* MultiPHY UTOPIA POS Ctrlr 2*/
|
||||
struct sdma sdma; /* SDMA */
|
||||
struct dbg dbg; /* Debug Space */
|
||||
struct rsp rsp[0x2]; /* RISC Special Registers
|
||||
(Trap and Breakpoint) */
|
||||
u8 res14[0x300];
|
||||
u8 res15[0x3A00];
|
||||
u8 res16[0x8000]; /* 0x108000 - 0x110000 */
|
||||
u8 muram[0xC000]; /* 0x110000 - 0x11C000
|
||||
Multi-user RAM */
|
||||
u8 res17[0x24000]; /* 0x11C000 - 0x140000 */
|
||||
u8 res18[0xC0000]; /* 0x140000 - 0x200000 */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
extern struct qe_immap *qe_immr;
|
||||
extern phys_addr_t get_qe_base(void);
|
||||
|
||||
static inline unsigned long immrbar_virt_to_phys(volatile void * address)
|
||||
{
|
||||
if ( ((u32)address >= (u32)qe_immr) &&
|
||||
((u32)address < ((u32)qe_immr + QE_IMMAP_SIZE)) )
|
||||
return (unsigned long)(address - (u32)qe_immr +
|
||||
(u32)get_qe_base());
|
||||
return (unsigned long)virt_to_phys(address);
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_IMMAP_QE_H */
|
457
include/asm-powerpc/qe.h
Normal file
457
include/asm-powerpc/qe.h
Normal file
|
@ -0,0 +1,457 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Authors: Shlomi Gridish <gridish@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
*
|
||||
* Description:
|
||||
* QUICC Engine (QE) external definitions and structure.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#ifndef _ASM_POWERPC_QE_H
|
||||
#define _ASM_POWERPC_QE_H
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <asm/immap_qe.h>
|
||||
|
||||
#define QE_NUM_OF_SNUM 28
|
||||
#define QE_NUM_OF_BRGS 16
|
||||
#define QE_NUM_OF_PORTS 1024
|
||||
|
||||
/* Memory partitions
|
||||
*/
|
||||
#define MEM_PART_SYSTEM 0
|
||||
#define MEM_PART_SECONDARY 1
|
||||
#define MEM_PART_MURAM 2
|
||||
|
||||
/* Export QE common operations */
|
||||
extern void qe_reset(void);
|
||||
extern int par_io_init(struct device_node *np);
|
||||
extern int par_io_of_config(struct device_node *np);
|
||||
|
||||
/* QE internal API */
|
||||
int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
|
||||
void qe_setbrg(u32 brg, u32 rate);
|
||||
int qe_get_snum(void);
|
||||
void qe_put_snum(u8 snum);
|
||||
u32 qe_muram_alloc(u32 size, u32 align);
|
||||
int qe_muram_free(u32 offset);
|
||||
u32 qe_muram_alloc_fixed(u32 offset, u32 size);
|
||||
void qe_muram_dump(void);
|
||||
void *qe_muram_addr(u32 offset);
|
||||
|
||||
/* Buffer descriptors */
|
||||
struct qe_bd {
|
||||
u16 status;
|
||||
u16 length;
|
||||
u32 buf;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define BD_STATUS_MASK 0xffff0000
|
||||
#define BD_LENGTH_MASK 0x0000ffff
|
||||
|
||||
/* Alignment */
|
||||
#define QE_INTR_TABLE_ALIGN 16 /* ??? */
|
||||
#define QE_ALIGNMENT_OF_BD 8
|
||||
#define QE_ALIGNMENT_OF_PRAM 64
|
||||
|
||||
/* RISC allocation */
|
||||
enum qe_risc_allocation {
|
||||
QE_RISC_ALLOCATION_RISC1 = 1, /* RISC 1 */
|
||||
QE_RISC_ALLOCATION_RISC2 = 2, /* RISC 2 */
|
||||
QE_RISC_ALLOCATION_RISC1_AND_RISC2 = 3 /* Dynamically choose
|
||||
RISC 1 or RISC 2 */
|
||||
};
|
||||
|
||||
/* QE extended filtering Table Lookup Key Size */
|
||||
enum qe_fltr_tbl_lookup_key_size {
|
||||
QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES
|
||||
= 0x3f, /* LookupKey parsed by the Generate LookupKey
|
||||
CMD is truncated to 8 bytes */
|
||||
QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES
|
||||
= 0x5f, /* LookupKey parsed by the Generate LookupKey
|
||||
CMD is truncated to 16 bytes */
|
||||
};
|
||||
|
||||
/* QE FLTR extended filtering Largest External Table Lookup Key Size */
|
||||
enum qe_fltr_largest_external_tbl_lookup_key_size {
|
||||
QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE
|
||||
= 0x0,/* not used */
|
||||
QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_8_BYTES
|
||||
= QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES, /* 8 bytes */
|
||||
QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_16_BYTES
|
||||
= QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES, /* 16 bytes */
|
||||
};
|
||||
|
||||
/* structure representing QE parameter RAM */
|
||||
struct qe_timer_tables {
|
||||
u16 tm_base; /* QE timer table base adr */
|
||||
u16 tm_ptr; /* QE timer table pointer */
|
||||
u16 r_tmr; /* QE timer mode register */
|
||||
u16 r_tmv; /* QE timer valid register */
|
||||
u32 tm_cmd; /* QE timer cmd register */
|
||||
u32 tm_cnt; /* QE timer internal cnt */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define QE_FLTR_TAD_SIZE 8
|
||||
|
||||
/* QE extended filtering Termination Action Descriptor (TAD) */
|
||||
struct qe_fltr_tad {
|
||||
u8 serialized[QE_FLTR_TAD_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Communication Direction */
|
||||
enum comm_dir {
|
||||
COMM_DIR_NONE = 0,
|
||||
COMM_DIR_RX = 1,
|
||||
COMM_DIR_TX = 2,
|
||||
COMM_DIR_RX_AND_TX = 3
|
||||
};
|
||||
|
||||
/* Clocks and BRGs */
|
||||
enum qe_clock {
|
||||
QE_CLK_NONE = 0,
|
||||
QE_BRG1, /* Baud Rate Generator 1 */
|
||||
QE_BRG2, /* Baud Rate Generator 2 */
|
||||
QE_BRG3, /* Baud Rate Generator 3 */
|
||||
QE_BRG4, /* Baud Rate Generator 4 */
|
||||
QE_BRG5, /* Baud Rate Generator 5 */
|
||||
QE_BRG6, /* Baud Rate Generator 6 */
|
||||
QE_BRG7, /* Baud Rate Generator 7 */
|
||||
QE_BRG8, /* Baud Rate Generator 8 */
|
||||
QE_BRG9, /* Baud Rate Generator 9 */
|
||||
QE_BRG10, /* Baud Rate Generator 10 */
|
||||
QE_BRG11, /* Baud Rate Generator 11 */
|
||||
QE_BRG12, /* Baud Rate Generator 12 */
|
||||
QE_BRG13, /* Baud Rate Generator 13 */
|
||||
QE_BRG14, /* Baud Rate Generator 14 */
|
||||
QE_BRG15, /* Baud Rate Generator 15 */
|
||||
QE_BRG16, /* Baud Rate Generator 16 */
|
||||
QE_CLK1, /* Clock 1 */
|
||||
QE_CLK2, /* Clock 2 */
|
||||
QE_CLK3, /* Clock 3 */
|
||||
QE_CLK4, /* Clock 4 */
|
||||
QE_CLK5, /* Clock 5 */
|
||||
QE_CLK6, /* Clock 6 */
|
||||
QE_CLK7, /* Clock 7 */
|
||||
QE_CLK8, /* Clock 8 */
|
||||
QE_CLK9, /* Clock 9 */
|
||||
QE_CLK10, /* Clock 10 */
|
||||
QE_CLK11, /* Clock 11 */
|
||||
QE_CLK12, /* Clock 12 */
|
||||
QE_CLK13, /* Clock 13 */
|
||||
QE_CLK14, /* Clock 14 */
|
||||
QE_CLK15, /* Clock 15 */
|
||||
QE_CLK16, /* Clock 16 */
|
||||
QE_CLK17, /* Clock 17 */
|
||||
QE_CLK18, /* Clock 18 */
|
||||
QE_CLK19, /* Clock 19 */
|
||||
QE_CLK20, /* Clock 20 */
|
||||
QE_CLK21, /* Clock 21 */
|
||||
QE_CLK22, /* Clock 22 */
|
||||
QE_CLK23, /* Clock 23 */
|
||||
QE_CLK24, /* Clock 24 */
|
||||
QE_CLK_DUMMY,
|
||||
};
|
||||
|
||||
/* QE CMXUCR Registers.
|
||||
* There are two UCCs represented in each of the four CMXUCR registers.
|
||||
* These values are for the UCC in the LSBs
|
||||
*/
|
||||
#define QE_CMXUCR_MII_ENET_MNG 0x00007000
|
||||
#define QE_CMXUCR_MII_ENET_MNG_SHIFT 12
|
||||
#define QE_CMXUCR_GRANT 0x00008000
|
||||
#define QE_CMXUCR_TSA 0x00004000
|
||||
#define QE_CMXUCR_BKPT 0x00000100
|
||||
#define QE_CMXUCR_TX_CLK_SRC_MASK 0x0000000F
|
||||
|
||||
/* QE CMXGCR Registers.
|
||||
*/
|
||||
#define QE_CMXGCR_MII_ENET_MNG 0x00007000
|
||||
#define QE_CMXGCR_MII_ENET_MNG_SHIFT 12
|
||||
#define QE_CMXGCR_USBCS 0x0000000f
|
||||
|
||||
/* QE CECR Commands.
|
||||
*/
|
||||
#define QE_CR_FLG 0x00010000
|
||||
#define QE_RESET 0x80000000
|
||||
#define QE_INIT_TX_RX 0x00000000
|
||||
#define QE_INIT_RX 0x00000001
|
||||
#define QE_INIT_TX 0x00000002
|
||||
#define QE_ENTER_HUNT_MODE 0x00000003
|
||||
#define QE_STOP_TX 0x00000004
|
||||
#define QE_GRACEFUL_STOP_TX 0x00000005
|
||||
#define QE_RESTART_TX 0x00000006
|
||||
#define QE_CLOSE_RX_BD 0x00000007
|
||||
#define QE_SWITCH_COMMAND 0x00000007
|
||||
#define QE_SET_GROUP_ADDRESS 0x00000008
|
||||
#define QE_START_IDMA 0x00000009
|
||||
#define QE_MCC_STOP_RX 0x00000009
|
||||
#define QE_ATM_TRANSMIT 0x0000000a
|
||||
#define QE_HPAC_CLEAR_ALL 0x0000000b
|
||||
#define QE_GRACEFUL_STOP_RX 0x0000001a
|
||||
#define QE_RESTART_RX 0x0000001b
|
||||
#define QE_HPAC_SET_PRIORITY 0x0000010b
|
||||
#define QE_HPAC_STOP_TX 0x0000020b
|
||||
#define QE_HPAC_STOP_RX 0x0000030b
|
||||
#define QE_HPAC_GRACEFUL_STOP_TX 0x0000040b
|
||||
#define QE_HPAC_GRACEFUL_STOP_RX 0x0000050b
|
||||
#define QE_HPAC_START_TX 0x0000060b
|
||||
#define QE_HPAC_START_RX 0x0000070b
|
||||
#define QE_USB_STOP_TX 0x0000000a
|
||||
#define QE_USB_RESTART_TX 0x0000000b
|
||||
#define QE_QMC_STOP_TX 0x0000000c
|
||||
#define QE_QMC_STOP_RX 0x0000000d
|
||||
#define QE_SS7_SU_FIL_RESET 0x0000000e
|
||||
/* jonathbr added from here down for 83xx */
|
||||
#define QE_RESET_BCS 0x0000000a
|
||||
#define QE_MCC_INIT_TX_RX_16 0x00000003
|
||||
#define QE_MCC_STOP_TX 0x00000004
|
||||
#define QE_MCC_INIT_TX_1 0x00000005
|
||||
#define QE_MCC_INIT_RX_1 0x00000006
|
||||
#define QE_MCC_RESET 0x00000007
|
||||
#define QE_SET_TIMER 0x00000008
|
||||
#define QE_RANDOM_NUMBER 0x0000000c
|
||||
#define QE_ATM_MULTI_THREAD_INIT 0x00000011
|
||||
#define QE_ASSIGN_PAGE 0x00000012
|
||||
#define QE_ADD_REMOVE_HASH_ENTRY 0x00000013
|
||||
#define QE_START_FLOW_CONTROL 0x00000014
|
||||
#define QE_STOP_FLOW_CONTROL 0x00000015
|
||||
#define QE_ASSIGN_PAGE_TO_DEVICE 0x00000016
|
||||
|
||||
#define QE_ASSIGN_RISC 0x00000010
|
||||
#define QE_CR_MCN_NORMAL_SHIFT 6
|
||||
#define QE_CR_MCN_USB_SHIFT 4
|
||||
#define QE_CR_MCN_RISC_ASSIGN_SHIFT 8
|
||||
#define QE_CR_SNUM_SHIFT 17
|
||||
|
||||
/* QE CECR Sub Block - sub block of QE command.
|
||||
*/
|
||||
#define QE_CR_SUBBLOCK_INVALID 0x00000000
|
||||
#define QE_CR_SUBBLOCK_USB 0x03200000
|
||||
#define QE_CR_SUBBLOCK_UCCFAST1 0x02000000
|
||||
#define QE_CR_SUBBLOCK_UCCFAST2 0x02200000
|
||||
#define QE_CR_SUBBLOCK_UCCFAST3 0x02400000
|
||||
#define QE_CR_SUBBLOCK_UCCFAST4 0x02600000
|
||||
#define QE_CR_SUBBLOCK_UCCFAST5 0x02800000
|
||||
#define QE_CR_SUBBLOCK_UCCFAST6 0x02a00000
|
||||
#define QE_CR_SUBBLOCK_UCCFAST7 0x02c00000
|
||||
#define QE_CR_SUBBLOCK_UCCFAST8 0x02e00000
|
||||
#define QE_CR_SUBBLOCK_UCCSLOW1 0x00000000
|
||||
#define QE_CR_SUBBLOCK_UCCSLOW2 0x00200000
|
||||
#define QE_CR_SUBBLOCK_UCCSLOW3 0x00400000
|
||||
#define QE_CR_SUBBLOCK_UCCSLOW4 0x00600000
|
||||
#define QE_CR_SUBBLOCK_UCCSLOW5 0x00800000
|
||||
#define QE_CR_SUBBLOCK_UCCSLOW6 0x00a00000
|
||||
#define QE_CR_SUBBLOCK_UCCSLOW7 0x00c00000
|
||||
#define QE_CR_SUBBLOCK_UCCSLOW8 0x00e00000
|
||||
#define QE_CR_SUBBLOCK_MCC1 0x03800000
|
||||
#define QE_CR_SUBBLOCK_MCC2 0x03a00000
|
||||
#define QE_CR_SUBBLOCK_MCC3 0x03000000
|
||||
#define QE_CR_SUBBLOCK_IDMA1 0x02800000
|
||||
#define QE_CR_SUBBLOCK_IDMA2 0x02a00000
|
||||
#define QE_CR_SUBBLOCK_IDMA3 0x02c00000
|
||||
#define QE_CR_SUBBLOCK_IDMA4 0x02e00000
|
||||
#define QE_CR_SUBBLOCK_HPAC 0x01e00000
|
||||
#define QE_CR_SUBBLOCK_SPI1 0x01400000
|
||||
#define QE_CR_SUBBLOCK_SPI2 0x01600000
|
||||
#define QE_CR_SUBBLOCK_RAND 0x01c00000
|
||||
#define QE_CR_SUBBLOCK_TIMER 0x01e00000
|
||||
#define QE_CR_SUBBLOCK_GENERAL 0x03c00000
|
||||
|
||||
/* QE CECR Protocol - For non-MCC, specifies mode for QE CECR command */
|
||||
#define QE_CR_PROTOCOL_UNSPECIFIED 0x00 /* For all other protocols */
|
||||
#define QE_CR_PROTOCOL_HDLC_TRANSPARENT 0x00
|
||||
#define QE_CR_PROTOCOL_ATM_POS 0x0A
|
||||
#define QE_CR_PROTOCOL_ETHERNET 0x0C
|
||||
#define QE_CR_PROTOCOL_L2_SWITCH 0x0D
|
||||
|
||||
/* BMR byte order */
|
||||
#define QE_BMR_BYTE_ORDER_BO_PPC 0x08 /* powerpc little endian */
|
||||
#define QE_BMR_BYTE_ORDER_BO_MOT 0x10 /* motorola big endian */
|
||||
#define QE_BMR_BYTE_ORDER_BO_MAX 0x18
|
||||
|
||||
/* BRG configuration register */
|
||||
#define QE_BRGC_ENABLE 0x00010000
|
||||
#define QE_BRGC_DIVISOR_SHIFT 1
|
||||
#define QE_BRGC_DIVISOR_MAX 0xFFF
|
||||
#define QE_BRGC_DIV16 1
|
||||
|
||||
/* QE Timers registers */
|
||||
#define QE_GTCFR1_PCAS 0x80
|
||||
#define QE_GTCFR1_STP2 0x20
|
||||
#define QE_GTCFR1_RST2 0x10
|
||||
#define QE_GTCFR1_GM2 0x08
|
||||
#define QE_GTCFR1_GM1 0x04
|
||||
#define QE_GTCFR1_STP1 0x02
|
||||
#define QE_GTCFR1_RST1 0x01
|
||||
|
||||
/* SDMA registers */
|
||||
#define QE_SDSR_BER1 0x02000000
|
||||
#define QE_SDSR_BER2 0x01000000
|
||||
|
||||
#define QE_SDMR_GLB_1_MSK 0x80000000
|
||||
#define QE_SDMR_ADR_SEL 0x20000000
|
||||
#define QE_SDMR_BER1_MSK 0x02000000
|
||||
#define QE_SDMR_BER2_MSK 0x01000000
|
||||
#define QE_SDMR_EB1_MSK 0x00800000
|
||||
#define QE_SDMR_ER1_MSK 0x00080000
|
||||
#define QE_SDMR_ER2_MSK 0x00040000
|
||||
#define QE_SDMR_CEN_MASK 0x0000E000
|
||||
#define QE_SDMR_SBER_1 0x00000200
|
||||
#define QE_SDMR_SBER_2 0x00000200
|
||||
#define QE_SDMR_EB1_PR_MASK 0x000000C0
|
||||
#define QE_SDMR_ER1_PR 0x00000008
|
||||
|
||||
#define QE_SDMR_CEN_SHIFT 13
|
||||
#define QE_SDMR_EB1_PR_SHIFT 6
|
||||
|
||||
#define QE_SDTM_MSNUM_SHIFT 24
|
||||
|
||||
#define QE_SDEBCR_BA_MASK 0x01FFFFFF
|
||||
|
||||
/* UPC */
|
||||
#define UPGCR_PROTOCOL 0x80000000 /* protocol ul2 or pl2 */
|
||||
#define UPGCR_TMS 0x40000000 /* Transmit master/slave mode */
|
||||
#define UPGCR_RMS 0x20000000 /* Receive master/slave mode */
|
||||
#define UPGCR_ADDR 0x10000000 /* Master MPHY Addr multiplexing */
|
||||
#define UPGCR_DIAG 0x01000000 /* Diagnostic mode */
|
||||
|
||||
/* UCC */
|
||||
#define UCC_GUEMR_MODE_MASK_RX 0x02
|
||||
#define UCC_GUEMR_MODE_MASK_TX 0x01
|
||||
#define UCC_GUEMR_MODE_FAST_RX 0x02
|
||||
#define UCC_GUEMR_MODE_FAST_TX 0x01
|
||||
#define UCC_GUEMR_MODE_SLOW_RX 0x00
|
||||
#define UCC_GUEMR_MODE_SLOW_TX 0x00
|
||||
#define UCC_GUEMR_SET_RESERVED3 0x10 /* Bit 3 in the guemr is reserved but
|
||||
must be set 1 */
|
||||
|
||||
/* structure representing UCC SLOW parameter RAM */
|
||||
struct ucc_slow_pram {
|
||||
u16 rbase; /* RX BD base address */
|
||||
u16 tbase; /* TX BD base address */
|
||||
u8 rfcr; /* Rx function code */
|
||||
u8 tfcr; /* Tx function code */
|
||||
u16 mrblr; /* Rx buffer length */
|
||||
u32 rstate; /* Rx internal state */
|
||||
u32 rptr; /* Rx internal data pointer */
|
||||
u16 rbptr; /* rb BD Pointer */
|
||||
u16 rcount; /* Rx internal byte count */
|
||||
u32 rtemp; /* Rx temp */
|
||||
u32 tstate; /* Tx internal state */
|
||||
u32 tptr; /* Tx internal data pointer */
|
||||
u16 tbptr; /* Tx BD pointer */
|
||||
u16 tcount; /* Tx byte count */
|
||||
u32 ttemp; /* Tx temp */
|
||||
u32 rcrc; /* temp receive CRC */
|
||||
u32 tcrc; /* temp transmit CRC */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* General UCC SLOW Mode Register (GUMRH & GUMRL) */
|
||||
#define UCC_SLOW_GUMR_H_CRC16 0x00004000
|
||||
#define UCC_SLOW_GUMR_H_CRC16CCITT 0x00000000
|
||||
#define UCC_SLOW_GUMR_H_CRC32CCITT 0x00008000
|
||||
#define UCC_SLOW_GUMR_H_REVD 0x00002000
|
||||
#define UCC_SLOW_GUMR_H_TRX 0x00001000
|
||||
#define UCC_SLOW_GUMR_H_TTX 0x00000800
|
||||
#define UCC_SLOW_GUMR_H_CDP 0x00000400
|
||||
#define UCC_SLOW_GUMR_H_CTSP 0x00000200
|
||||
#define UCC_SLOW_GUMR_H_CDS 0x00000100
|
||||
#define UCC_SLOW_GUMR_H_CTSS 0x00000080
|
||||
#define UCC_SLOW_GUMR_H_TFL 0x00000040
|
||||
#define UCC_SLOW_GUMR_H_RFW 0x00000020
|
||||
#define UCC_SLOW_GUMR_H_TXSY 0x00000010
|
||||
#define UCC_SLOW_GUMR_H_4SYNC 0x00000004
|
||||
#define UCC_SLOW_GUMR_H_8SYNC 0x00000008
|
||||
#define UCC_SLOW_GUMR_H_16SYNC 0x0000000c
|
||||
#define UCC_SLOW_GUMR_H_RTSM 0x00000002
|
||||
#define UCC_SLOW_GUMR_H_RSYN 0x00000001
|
||||
|
||||
#define UCC_SLOW_GUMR_L_TCI 0x10000000
|
||||
#define UCC_SLOW_GUMR_L_RINV 0x02000000
|
||||
#define UCC_SLOW_GUMR_L_TINV 0x01000000
|
||||
#define UCC_SLOW_GUMR_L_TEND 0x00020000
|
||||
#define UCC_SLOW_GUMR_L_ENR 0x00000020
|
||||
#define UCC_SLOW_GUMR_L_ENT 0x00000010
|
||||
|
||||
/* General UCC FAST Mode Register */
|
||||
#define UCC_FAST_GUMR_TCI 0x20000000
|
||||
#define UCC_FAST_GUMR_TRX 0x10000000
|
||||
#define UCC_FAST_GUMR_TTX 0x08000000
|
||||
#define UCC_FAST_GUMR_CDP 0x04000000
|
||||
#define UCC_FAST_GUMR_CTSP 0x02000000
|
||||
#define UCC_FAST_GUMR_CDS 0x01000000
|
||||
#define UCC_FAST_GUMR_CTSS 0x00800000
|
||||
#define UCC_FAST_GUMR_TXSY 0x00020000
|
||||
#define UCC_FAST_GUMR_RSYN 0x00010000
|
||||
#define UCC_FAST_GUMR_RTSM 0x00002000
|
||||
#define UCC_FAST_GUMR_REVD 0x00000400
|
||||
#define UCC_FAST_GUMR_ENR 0x00000020
|
||||
#define UCC_FAST_GUMR_ENT 0x00000010
|
||||
|
||||
/* Slow UCC Event Register (UCCE) */
|
||||
#define UCC_SLOW_UCCE_GLR 0x1000
|
||||
#define UCC_SLOW_UCCE_GLT 0x0800
|
||||
#define UCC_SLOW_UCCE_DCC 0x0400
|
||||
#define UCC_SLOW_UCCE_FLG 0x0200
|
||||
#define UCC_SLOW_UCCE_AB 0x0200
|
||||
#define UCC_SLOW_UCCE_IDLE 0x0100
|
||||
#define UCC_SLOW_UCCE_GRA 0x0080
|
||||
#define UCC_SLOW_UCCE_TXE 0x0010
|
||||
#define UCC_SLOW_UCCE_RXF 0x0008
|
||||
#define UCC_SLOW_UCCE_CCR 0x0008
|
||||
#define UCC_SLOW_UCCE_RCH 0x0008
|
||||
#define UCC_SLOW_UCCE_BSY 0x0004
|
||||
#define UCC_SLOW_UCCE_TXB 0x0002
|
||||
#define UCC_SLOW_UCCE_TX 0x0002
|
||||
#define UCC_SLOW_UCCE_RX 0x0001
|
||||
#define UCC_SLOW_UCCE_GOV 0x0001
|
||||
#define UCC_SLOW_UCCE_GUN 0x0002
|
||||
#define UCC_SLOW_UCCE_GINT 0x0004
|
||||
#define UCC_SLOW_UCCE_IQOV 0x0008
|
||||
|
||||
#define UCC_SLOW_UCCE_HDLC_SET (UCC_SLOW_UCCE_TXE | UCC_SLOW_UCCE_BSY | \
|
||||
UCC_SLOW_UCCE_GRA | UCC_SLOW_UCCE_TXB | UCC_SLOW_UCCE_RXF | \
|
||||
UCC_SLOW_UCCE_DCC | UCC_SLOW_UCCE_GLT | UCC_SLOW_UCCE_GLR)
|
||||
#define UCC_SLOW_UCCE_ENET_SET (UCC_SLOW_UCCE_TXE | UCC_SLOW_UCCE_BSY | \
|
||||
UCC_SLOW_UCCE_GRA | UCC_SLOW_UCCE_TXB | UCC_SLOW_UCCE_RXF)
|
||||
#define UCC_SLOW_UCCE_TRANS_SET (UCC_SLOW_UCCE_TXE | UCC_SLOW_UCCE_BSY | \
|
||||
UCC_SLOW_UCCE_GRA | UCC_SLOW_UCCE_TX | UCC_SLOW_UCCE_RX | \
|
||||
UCC_SLOW_UCCE_DCC | UCC_SLOW_UCCE_GLT | UCC_SLOW_UCCE_GLR)
|
||||
#define UCC_SLOW_UCCE_UART_SET (UCC_SLOW_UCCE_BSY | UCC_SLOW_UCCE_GRA | \
|
||||
UCC_SLOW_UCCE_TXB | UCC_SLOW_UCCE_TX | UCC_SLOW_UCCE_RX | \
|
||||
UCC_SLOW_UCCE_GLT | UCC_SLOW_UCCE_GLR)
|
||||
#define UCC_SLOW_UCCE_QMC_SET (UCC_SLOW_UCCE_IQOV | UCC_SLOW_UCCE_GINT | \
|
||||
UCC_SLOW_UCCE_GUN | UCC_SLOW_UCCE_GOV)
|
||||
|
||||
#define UCC_SLOW_UCCE_OTHER (UCC_SLOW_UCCE_TXE | UCC_SLOW_UCCE_BSY | \
|
||||
UCC_SLOW_UCCE_GRA | UCC_SLOW_UCCE_DCC | UCC_SLOW_UCCE_GLT | \
|
||||
UCC_SLOW_UCCE_GLR)
|
||||
|
||||
#define UCC_SLOW_INTR_TX UCC_SLOW_UCCE_TXB
|
||||
#define UCC_SLOW_INTR_RX (UCC_SLOW_UCCE_RXF | UCC_SLOW_UCCE_RX)
|
||||
#define UCC_SLOW_INTR (UCC_SLOW_INTR_TX | UCC_SLOW_INTR_RX)
|
||||
|
||||
/* UCC Transmit On Demand Register (UTODR) */
|
||||
#define UCC_SLOW_TOD 0x8000
|
||||
#define UCC_FAST_TOD 0x8000
|
||||
|
||||
/* Function code masks */
|
||||
#define FC_GBL 0x20
|
||||
#define FC_DTB_LCL 0x02
|
||||
#define UCC_FAST_FUNCTION_CODE_GBL 0x20
|
||||
#define UCC_FAST_FUNCTION_CODE_DTB_LCL 0x02
|
||||
#define UCC_FAST_FUNCTION_CODE_BDB_LCL 0x01
|
||||
|
||||
static inline long IS_MURAM_ERR(const u32 offset)
|
||||
{
|
||||
return offset > (u32) - 1000L;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_QE_H */
|
64
include/asm-powerpc/qe_ic.h
Normal file
64
include/asm-powerpc/qe_ic.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* include/asm-powerpc/qe_ic.h
|
||||
*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Authors: Shlomi Gridish <gridish@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
*
|
||||
* Description:
|
||||
* QE IC external definitions and structure.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#ifndef _ASM_POWERPC_QE_IC_H
|
||||
#define _ASM_POWERPC_QE_IC_H
|
||||
|
||||
#include <linux/irq.h>
|
||||
|
||||
#define NUM_OF_QE_IC_GROUPS 6
|
||||
|
||||
/* Flags when we init the QE IC */
|
||||
#define QE_IC_SPREADMODE_GRP_W 0x00000001
|
||||
#define QE_IC_SPREADMODE_GRP_X 0x00000002
|
||||
#define QE_IC_SPREADMODE_GRP_Y 0x00000004
|
||||
#define QE_IC_SPREADMODE_GRP_Z 0x00000008
|
||||
#define QE_IC_SPREADMODE_GRP_RISCA 0x00000010
|
||||
#define QE_IC_SPREADMODE_GRP_RISCB 0x00000020
|
||||
|
||||
#define QE_IC_LOW_SIGNAL 0x00000100
|
||||
#define QE_IC_HIGH_SIGNAL 0x00000200
|
||||
|
||||
#define QE_IC_GRP_W_PRI0_DEST_SIGNAL_HIGH 0x00001000
|
||||
#define QE_IC_GRP_W_PRI1_DEST_SIGNAL_HIGH 0x00002000
|
||||
#define QE_IC_GRP_X_PRI0_DEST_SIGNAL_HIGH 0x00004000
|
||||
#define QE_IC_GRP_X_PRI1_DEST_SIGNAL_HIGH 0x00008000
|
||||
#define QE_IC_GRP_Y_PRI0_DEST_SIGNAL_HIGH 0x00010000
|
||||
#define QE_IC_GRP_Y_PRI1_DEST_SIGNAL_HIGH 0x00020000
|
||||
#define QE_IC_GRP_Z_PRI0_DEST_SIGNAL_HIGH 0x00040000
|
||||
#define QE_IC_GRP_Z_PRI1_DEST_SIGNAL_HIGH 0x00080000
|
||||
#define QE_IC_GRP_RISCA_PRI0_DEST_SIGNAL_HIGH 0x00100000
|
||||
#define QE_IC_GRP_RISCA_PRI1_DEST_SIGNAL_HIGH 0x00200000
|
||||
#define QE_IC_GRP_RISCB_PRI0_DEST_SIGNAL_HIGH 0x00400000
|
||||
#define QE_IC_GRP_RISCB_PRI1_DEST_SIGNAL_HIGH 0x00800000
|
||||
#define QE_IC_GRP_W_DEST_SIGNAL_SHIFT (12)
|
||||
|
||||
/* QE interrupt sources groups */
|
||||
enum qe_ic_grp_id {
|
||||
QE_IC_GRP_W = 0, /* QE interrupt controller group W */
|
||||
QE_IC_GRP_X, /* QE interrupt controller group X */
|
||||
QE_IC_GRP_Y, /* QE interrupt controller group Y */
|
||||
QE_IC_GRP_Z, /* QE interrupt controller group Z */
|
||||
QE_IC_GRP_RISCA, /* QE interrupt controller RISC group A */
|
||||
QE_IC_GRP_RISCB /* QE interrupt controller RISC group B */
|
||||
};
|
||||
|
||||
void qe_ic_init(struct device_node *node, unsigned int flags);
|
||||
void qe_ic_set_highest_priority(unsigned int virq, int high);
|
||||
int qe_ic_set_priority(unsigned int virq, unsigned int priority);
|
||||
int qe_ic_set_high_priority(unsigned int virq, unsigned int priority, int high);
|
||||
|
||||
#endif /* _ASM_POWERPC_QE_IC_H */
|
|
@ -91,10 +91,6 @@ DEBUGGER_BOILERPLATE(debugger_iabr_match)
|
|||
DEBUGGER_BOILERPLATE(debugger_dabr_match)
|
||||
DEBUGGER_BOILERPLATE(debugger_fault_handler)
|
||||
|
||||
#ifdef CONFIG_XMON
|
||||
extern void xmon_init(int enable);
|
||||
#endif
|
||||
|
||||
#else
|
||||
static inline int debugger(struct pt_regs *regs) { return 0; }
|
||||
static inline int debugger_ipi(struct pt_regs *regs) { return 0; }
|
||||
|
|
84
include/asm-powerpc/ucc.h
Normal file
84
include/asm-powerpc/ucc.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Authors: Shlomi Gridish <gridish@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
*
|
||||
* Description:
|
||||
* Internal header file for UCC unit routines.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#ifndef __UCC_H__
|
||||
#define __UCC_H__
|
||||
|
||||
#include <asm/immap_qe.h>
|
||||
#include <asm/qe.h>
|
||||
|
||||
#define STATISTICS
|
||||
|
||||
#define UCC_MAX_NUM 8
|
||||
|
||||
/* Slow or fast type for UCCs.
|
||||
*/
|
||||
enum ucc_speed_type {
|
||||
UCC_SPEED_TYPE_FAST, UCC_SPEED_TYPE_SLOW
|
||||
};
|
||||
|
||||
/* Initial UCCs Parameter RAM address relative to: MEM_MAP_BASE (IMMR).
|
||||
*/
|
||||
enum ucc_pram_initial_offset {
|
||||
UCC_PRAM_OFFSET_UCC1 = 0x8400,
|
||||
UCC_PRAM_OFFSET_UCC2 = 0x8500,
|
||||
UCC_PRAM_OFFSET_UCC3 = 0x8600,
|
||||
UCC_PRAM_OFFSET_UCC4 = 0x9000,
|
||||
UCC_PRAM_OFFSET_UCC5 = 0x8000,
|
||||
UCC_PRAM_OFFSET_UCC6 = 0x8100,
|
||||
UCC_PRAM_OFFSET_UCC7 = 0x8200,
|
||||
UCC_PRAM_OFFSET_UCC8 = 0x8300
|
||||
};
|
||||
|
||||
/* ucc_set_type
|
||||
* Sets UCC to slow or fast mode.
|
||||
*
|
||||
* ucc_num - (In) number of UCC (0-7).
|
||||
* regs - (In) pointer to registers base for the UCC.
|
||||
* speed - (In) slow or fast mode for UCC.
|
||||
*/
|
||||
int ucc_set_type(int ucc_num, struct ucc_common *regs,
|
||||
enum ucc_speed_type speed);
|
||||
|
||||
/* ucc_init_guemr
|
||||
* Init the Guemr register.
|
||||
*
|
||||
* regs - (In) pointer to registers base for the UCC.
|
||||
*/
|
||||
int ucc_init_guemr(struct ucc_common *regs);
|
||||
|
||||
int ucc_set_qe_mux_mii_mng(int ucc_num);
|
||||
|
||||
int ucc_set_qe_mux_rxtx(int ucc_num, enum qe_clock clock, enum comm_dir mode);
|
||||
|
||||
int ucc_mux_set_grant_tsa_bkpt(int ucc_num, int set, u32 mask);
|
||||
|
||||
/* QE MUX clock routing for UCC
|
||||
*/
|
||||
static inline int ucc_set_qe_mux_grant(int ucc_num, int set)
|
||||
{
|
||||
return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_GRANT);
|
||||
}
|
||||
|
||||
static inline int ucc_set_qe_mux_tsa(int ucc_num, int set)
|
||||
{
|
||||
return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_TSA);
|
||||
}
|
||||
|
||||
static inline int ucc_set_qe_mux_bkpt(int ucc_num, int set)
|
||||
{
|
||||
return ucc_mux_set_grant_tsa_bkpt(ucc_num, set, QE_CMXUCR_BKPT);
|
||||
}
|
||||
|
||||
#endif /* __UCC_H__ */
|
243
include/asm-powerpc/ucc_fast.h
Normal file
243
include/asm-powerpc/ucc_fast.h
Normal file
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* include/asm-powerpc/ucc_fast.h
|
||||
*
|
||||
* Internal header file for UCC FAST unit routines.
|
||||
*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Authors: Shlomi Gridish <gridish@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#ifndef __UCC_FAST_H__
|
||||
#define __UCC_FAST_H__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/immap_qe.h>
|
||||
#include <asm/qe.h>
|
||||
|
||||
#include "ucc.h"
|
||||
|
||||
/* Receive BD's status */
|
||||
#define R_E 0x80000000 /* buffer empty */
|
||||
#define R_W 0x20000000 /* wrap bit */
|
||||
#define R_I 0x10000000 /* interrupt on reception */
|
||||
#define R_L 0x08000000 /* last */
|
||||
#define R_F 0x04000000 /* first */
|
||||
|
||||
/* transmit BD's status */
|
||||
#define T_R 0x80000000 /* ready bit */
|
||||
#define T_W 0x20000000 /* wrap bit */
|
||||
#define T_I 0x10000000 /* interrupt on completion */
|
||||
#define T_L 0x08000000 /* last */
|
||||
|
||||
/* Rx Data buffer must be 4 bytes aligned in most cases */
|
||||
#define UCC_FAST_RX_ALIGN 4
|
||||
#define UCC_FAST_MRBLR_ALIGNMENT 4
|
||||
#define UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT 8
|
||||
|
||||
/* Sizes */
|
||||
#define UCC_FAST_URFS_MIN_VAL 0x88
|
||||
#define UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR 8
|
||||
|
||||
/* ucc_fast_channel_protocol_mode - UCC FAST mode */
|
||||
enum ucc_fast_channel_protocol_mode {
|
||||
UCC_FAST_PROTOCOL_MODE_HDLC = 0x00000000,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED01 = 0x00000001,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED_QMC = 0x00000002,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED02 = 0x00000003,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED_UART = 0x00000004,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED03 = 0x00000005,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED_EX_MAC_1 = 0x00000006,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED_EX_MAC_2 = 0x00000007,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED_BISYNC = 0x00000008,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED04 = 0x00000009,
|
||||
UCC_FAST_PROTOCOL_MODE_ATM = 0x0000000A,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED05 = 0x0000000B,
|
||||
UCC_FAST_PROTOCOL_MODE_ETHERNET = 0x0000000C,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED06 = 0x0000000D,
|
||||
UCC_FAST_PROTOCOL_MODE_POS = 0x0000000E,
|
||||
UCC_FAST_PROTOCOL_MODE_RESERVED07 = 0x0000000F
|
||||
};
|
||||
|
||||
/* ucc_fast_transparent_txrx - UCC Fast Transparent TX & RX */
|
||||
enum ucc_fast_transparent_txrx {
|
||||
UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL = 0x00000000,
|
||||
UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_TRANSPARENT = 0x18000000
|
||||
};
|
||||
|
||||
/* UCC fast diagnostic mode */
|
||||
enum ucc_fast_diag_mode {
|
||||
UCC_FAST_DIAGNOSTIC_NORMAL = 0x0,
|
||||
UCC_FAST_DIAGNOSTIC_LOCAL_LOOP_BACK = 0x40000000,
|
||||
UCC_FAST_DIAGNOSTIC_AUTO_ECHO = 0x80000000,
|
||||
UCC_FAST_DIAGNOSTIC_LOOP_BACK_AND_ECHO = 0xC0000000
|
||||
};
|
||||
|
||||
/* UCC fast Sync length (transparent mode only) */
|
||||
enum ucc_fast_sync_len {
|
||||
UCC_FAST_SYNC_LEN_NOT_USED = 0x0,
|
||||
UCC_FAST_SYNC_LEN_AUTOMATIC = 0x00004000,
|
||||
UCC_FAST_SYNC_LEN_8_BIT = 0x00008000,
|
||||
UCC_FAST_SYNC_LEN_16_BIT = 0x0000C000
|
||||
};
|
||||
|
||||
/* UCC fast RTS mode */
|
||||
enum ucc_fast_ready_to_send {
|
||||
UCC_FAST_SEND_IDLES_BETWEEN_FRAMES = 0x00000000,
|
||||
UCC_FAST_SEND_FLAGS_BETWEEN_FRAMES = 0x00002000
|
||||
};
|
||||
|
||||
/* UCC fast receiver decoding mode */
|
||||
enum ucc_fast_rx_decoding_method {
|
||||
UCC_FAST_RX_ENCODING_NRZ = 0x00000000,
|
||||
UCC_FAST_RX_ENCODING_NRZI = 0x00000800,
|
||||
UCC_FAST_RX_ENCODING_RESERVED0 = 0x00001000,
|
||||
UCC_FAST_RX_ENCODING_RESERVED1 = 0x00001800
|
||||
};
|
||||
|
||||
/* UCC fast transmitter encoding mode */
|
||||
enum ucc_fast_tx_encoding_method {
|
||||
UCC_FAST_TX_ENCODING_NRZ = 0x00000000,
|
||||
UCC_FAST_TX_ENCODING_NRZI = 0x00000100,
|
||||
UCC_FAST_TX_ENCODING_RESERVED0 = 0x00000200,
|
||||
UCC_FAST_TX_ENCODING_RESERVED1 = 0x00000300
|
||||
};
|
||||
|
||||
/* UCC fast CRC length */
|
||||
enum ucc_fast_transparent_tcrc {
|
||||
UCC_FAST_16_BIT_CRC = 0x00000000,
|
||||
UCC_FAST_CRC_RESERVED0 = 0x00000040,
|
||||
UCC_FAST_32_BIT_CRC = 0x00000080,
|
||||
UCC_FAST_CRC_RESERVED1 = 0x000000C0
|
||||
};
|
||||
|
||||
/* Fast UCC initialization structure */
|
||||
struct ucc_fast_info {
|
||||
int ucc_num;
|
||||
enum qe_clock rx_clock;
|
||||
enum qe_clock tx_clock;
|
||||
u32 regs;
|
||||
int irq;
|
||||
u32 uccm_mask;
|
||||
int bd_mem_part;
|
||||
int brkpt_support;
|
||||
int grant_support;
|
||||
int tsa;
|
||||
int cdp;
|
||||
int cds;
|
||||
int ctsp;
|
||||
int ctss;
|
||||
int tci;
|
||||
int txsy;
|
||||
int rtsm;
|
||||
int revd;
|
||||
int rsyn;
|
||||
u16 max_rx_buf_length;
|
||||
u16 urfs;
|
||||
u16 urfet;
|
||||
u16 urfset;
|
||||
u16 utfs;
|
||||
u16 utfet;
|
||||
u16 utftt;
|
||||
u16 ufpt;
|
||||
enum ucc_fast_channel_protocol_mode mode;
|
||||
enum ucc_fast_transparent_txrx ttx_trx;
|
||||
enum ucc_fast_tx_encoding_method tenc;
|
||||
enum ucc_fast_rx_decoding_method renc;
|
||||
enum ucc_fast_transparent_tcrc tcrc;
|
||||
enum ucc_fast_sync_len synl;
|
||||
};
|
||||
|
||||
struct ucc_fast_private {
|
||||
struct ucc_fast_info *uf_info;
|
||||
struct ucc_fast *uf_regs; /* a pointer to memory map of UCC regs. */
|
||||
u32 *p_ucce; /* a pointer to the event register in memory. */
|
||||
u32 *p_uccm; /* a pointer to the mask register in memory. */
|
||||
int enabled_tx; /* Whether channel is enabled for Tx (ENT) */
|
||||
int enabled_rx; /* Whether channel is enabled for Rx (ENR) */
|
||||
int stopped_tx; /* Whether channel has been stopped for Tx
|
||||
(STOP_TX, etc.) */
|
||||
int stopped_rx; /* Whether channel has been stopped for Rx */
|
||||
u32 ucc_fast_tx_virtual_fifo_base_offset;/* pointer to base of Tx
|
||||
virtual fifo */
|
||||
u32 ucc_fast_rx_virtual_fifo_base_offset;/* pointer to base of Rx
|
||||
virtual fifo */
|
||||
#ifdef STATISTICS
|
||||
u32 tx_frames; /* Transmitted frames counter. */
|
||||
u32 rx_frames; /* Received frames counter (only frames
|
||||
passed to application). */
|
||||
u32 tx_discarded; /* Discarded tx frames counter (frames that
|
||||
were discarded by the driver due to errors).
|
||||
*/
|
||||
u32 rx_discarded; /* Discarded rx frames counter (frames that
|
||||
were discarded by the driver due to errors).
|
||||
*/
|
||||
#endif /* STATISTICS */
|
||||
u16 mrblr; /* maximum receive buffer length */
|
||||
};
|
||||
|
||||
/* ucc_fast_init
|
||||
* Initializes Fast UCC according to user provided parameters.
|
||||
*
|
||||
* uf_info - (In) pointer to the fast UCC info structure.
|
||||
* uccf_ret - (Out) pointer to the fast UCC structure.
|
||||
*/
|
||||
int ucc_fast_init(struct ucc_fast_info * uf_info, struct ucc_fast_private ** uccf_ret);
|
||||
|
||||
/* ucc_fast_free
|
||||
* Frees all resources for fast UCC.
|
||||
*
|
||||
* uccf - (In) pointer to the fast UCC structure.
|
||||
*/
|
||||
void ucc_fast_free(struct ucc_fast_private * uccf);
|
||||
|
||||
/* ucc_fast_enable
|
||||
* Enables a fast UCC port.
|
||||
* This routine enables Tx and/or Rx through the General UCC Mode Register.
|
||||
*
|
||||
* uccf - (In) pointer to the fast UCC structure.
|
||||
* mode - (In) TX, RX, or both.
|
||||
*/
|
||||
void ucc_fast_enable(struct ucc_fast_private * uccf, enum comm_dir mode);
|
||||
|
||||
/* ucc_fast_disable
|
||||
* Disables a fast UCC port.
|
||||
* This routine disables Tx and/or Rx through the General UCC Mode Register.
|
||||
*
|
||||
* uccf - (In) pointer to the fast UCC structure.
|
||||
* mode - (In) TX, RX, or both.
|
||||
*/
|
||||
void ucc_fast_disable(struct ucc_fast_private * uccf, enum comm_dir mode);
|
||||
|
||||
/* ucc_fast_irq
|
||||
* Handles interrupts on fast UCC.
|
||||
* Called from the general interrupt routine to handle interrupts on fast UCC.
|
||||
*
|
||||
* uccf - (In) pointer to the fast UCC structure.
|
||||
*/
|
||||
void ucc_fast_irq(struct ucc_fast_private * uccf);
|
||||
|
||||
/* ucc_fast_transmit_on_demand
|
||||
* Immediately forces a poll of the transmitter for data to be sent.
|
||||
* Typically, the hardware performs a periodic poll for data that the
|
||||
* transmit routine has set up to be transmitted. In cases where
|
||||
* this polling cycle is not soon enough, this optional routine can
|
||||
* be invoked to force a poll right away, instead. Proper use for
|
||||
* each transmission for which this functionality is desired is to
|
||||
* call the transmit routine and then this routine right after.
|
||||
*
|
||||
* uccf - (In) pointer to the fast UCC structure.
|
||||
*/
|
||||
void ucc_fast_transmit_on_demand(struct ucc_fast_private * uccf);
|
||||
|
||||
u32 ucc_fast_get_qe_cr_subblock(int uccf_num);
|
||||
|
||||
void ucc_fast_dump_regs(struct ucc_fast_private * uccf);
|
||||
|
||||
#endif /* __UCC_FAST_H__ */
|
289
include/asm-powerpc/ucc_slow.h
Normal file
289
include/asm-powerpc/ucc_slow.h
Normal file
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* Copyright (C) 2006 Freescale Semicondutor, Inc. All rights reserved.
|
||||
*
|
||||
* Authors: Shlomi Gridish <gridish@freescale.com>
|
||||
* Li Yang <leoli@freescale.com>
|
||||
*
|
||||
* Description:
|
||||
* Internal header file for UCC SLOW unit routines.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*/
|
||||
#ifndef __UCC_SLOW_H__
|
||||
#define __UCC_SLOW_H__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/immap_qe.h>
|
||||
#include <asm/qe.h>
|
||||
|
||||
#include "ucc.h"
|
||||
|
||||
/* transmit BD's status */
|
||||
#define T_R 0x80000000 /* ready bit */
|
||||
#define T_PAD 0x40000000 /* add pads to short frames */
|
||||
#define T_W 0x20000000 /* wrap bit */
|
||||
#define T_I 0x10000000 /* interrupt on completion */
|
||||
#define T_L 0x08000000 /* last */
|
||||
|
||||
#define T_A 0x04000000 /* Address - the data transmitted as address
|
||||
chars */
|
||||
#define T_TC 0x04000000 /* transmit CRC */
|
||||
#define T_CM 0x02000000 /* continuous mode */
|
||||
#define T_DEF 0x02000000 /* collision on previous attempt to transmit */
|
||||
#define T_P 0x01000000 /* Preamble - send Preamble sequence before
|
||||
data */
|
||||
#define T_HB 0x01000000 /* heartbeat */
|
||||
#define T_NS 0x00800000 /* No Stop */
|
||||
#define T_LC 0x00800000 /* late collision */
|
||||
#define T_RL 0x00400000 /* retransmission limit */
|
||||
#define T_UN 0x00020000 /* underrun */
|
||||
#define T_CT 0x00010000 /* CTS lost */
|
||||
#define T_CSL 0x00010000 /* carrier sense lost */
|
||||
#define T_RC 0x003c0000 /* retry count */
|
||||
|
||||
/* Receive BD's status */
|
||||
#define R_E 0x80000000 /* buffer empty */
|
||||
#define R_W 0x20000000 /* wrap bit */
|
||||
#define R_I 0x10000000 /* interrupt on reception */
|
||||
#define R_L 0x08000000 /* last */
|
||||
#define R_C 0x08000000 /* the last byte in this buffer is a cntl
|
||||
char */
|
||||
#define R_F 0x04000000 /* first */
|
||||
#define R_A 0x04000000 /* the first byte in this buffer is address
|
||||
byte */
|
||||
#define R_CM 0x02000000 /* continuous mode */
|
||||
#define R_ID 0x01000000 /* buffer close on reception of idles */
|
||||
#define R_M 0x01000000 /* Frame received because of promiscuous
|
||||
mode */
|
||||
#define R_AM 0x00800000 /* Address match */
|
||||
#define R_DE 0x00800000 /* Address match */
|
||||
#define R_LG 0x00200000 /* Break received */
|
||||
#define R_BR 0x00200000 /* Frame length violation */
|
||||
#define R_NO 0x00100000 /* Rx Non Octet Aligned Packet */
|
||||
#define R_FR 0x00100000 /* Framing Error (no stop bit) character
|
||||
received */
|
||||
#define R_PR 0x00080000 /* Parity Error character received */
|
||||
#define R_AB 0x00080000 /* Frame Aborted */
|
||||
#define R_SH 0x00080000 /* frame is too short */
|
||||
#define R_CR 0x00040000 /* CRC Error */
|
||||
#define R_OV 0x00020000 /* Overrun */
|
||||
#define R_CD 0x00010000 /* CD lost */
|
||||
#define R_CL 0x00010000 /* this frame is closed because of a
|
||||
collision */
|
||||
|
||||
/* Rx Data buffer must be 4 bytes aligned in most cases.*/
|
||||
#define UCC_SLOW_RX_ALIGN 4
|
||||
#define UCC_SLOW_MRBLR_ALIGNMENT 4
|
||||
#define UCC_SLOW_PRAM_SIZE 0x100
|
||||
#define ALIGNMENT_OF_UCC_SLOW_PRAM 64
|
||||
|
||||
/* UCC Slow Channel Protocol Mode */
|
||||
enum ucc_slow_channel_protocol_mode {
|
||||
UCC_SLOW_CHANNEL_PROTOCOL_MODE_QMC = 0x00000002,
|
||||
UCC_SLOW_CHANNEL_PROTOCOL_MODE_UART = 0x00000004,
|
||||
UCC_SLOW_CHANNEL_PROTOCOL_MODE_BISYNC = 0x00000008,
|
||||
};
|
||||
|
||||
/* UCC Slow Transparent Transmit CRC (TCRC) */
|
||||
enum ucc_slow_transparent_tcrc {
|
||||
/* 16-bit CCITT CRC (HDLC). (X16 + X12 + X5 + 1) */
|
||||
UCC_SLOW_TRANSPARENT_TCRC_CCITT_CRC16 = 0x00000000,
|
||||
/* CRC16 (BISYNC). (X16 + X15 + X2 + 1) */
|
||||
UCC_SLOW_TRANSPARENT_TCRC_CRC16 = 0x00004000,
|
||||
/* 32-bit CCITT CRC (Ethernet and HDLC) */
|
||||
UCC_SLOW_TRANSPARENT_TCRC_CCITT_CRC32 = 0x00008000,
|
||||
};
|
||||
|
||||
/* UCC Slow oversampling rate for transmitter (TDCR) */
|
||||
enum ucc_slow_tx_oversampling_rate {
|
||||
/* 1x clock mode */
|
||||
UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_1 = 0x00000000,
|
||||
/* 8x clock mode */
|
||||
UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_8 = 0x00010000,
|
||||
/* 16x clock mode */
|
||||
UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_16 = 0x00020000,
|
||||
/* 32x clock mode */
|
||||
UCC_SLOW_OVERSAMPLING_RATE_TX_TDCR_32 = 0x00030000,
|
||||
};
|
||||
|
||||
/* UCC Slow Oversampling rate for receiver (RDCR)
|
||||
*/
|
||||
enum ucc_slow_rx_oversampling_rate {
|
||||
/* 1x clock mode */
|
||||
UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_1 = 0x00000000,
|
||||
/* 8x clock mode */
|
||||
UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_8 = 0x00004000,
|
||||
/* 16x clock mode */
|
||||
UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_16 = 0x00008000,
|
||||
/* 32x clock mode */
|
||||
UCC_SLOW_OVERSAMPLING_RATE_RX_RDCR_32 = 0x0000c000,
|
||||
};
|
||||
|
||||
/* UCC Slow Transmitter encoding method (TENC)
|
||||
*/
|
||||
enum ucc_slow_tx_encoding_method {
|
||||
UCC_SLOW_TRANSMITTER_ENCODING_METHOD_TENC_NRZ = 0x00000000,
|
||||
UCC_SLOW_TRANSMITTER_ENCODING_METHOD_TENC_NRZI = 0x00000100
|
||||
};
|
||||
|
||||
/* UCC Slow Receiver decoding method (RENC)
|
||||
*/
|
||||
enum ucc_slow_rx_decoding_method {
|
||||
UCC_SLOW_RECEIVER_DECODING_METHOD_RENC_NRZ = 0x00000000,
|
||||
UCC_SLOW_RECEIVER_DECODING_METHOD_RENC_NRZI = 0x00000800
|
||||
};
|
||||
|
||||
/* UCC Slow Diagnostic mode (DIAG)
|
||||
*/
|
||||
enum ucc_slow_diag_mode {
|
||||
UCC_SLOW_DIAG_MODE_NORMAL = 0x00000000,
|
||||
UCC_SLOW_DIAG_MODE_LOOPBACK = 0x00000040,
|
||||
UCC_SLOW_DIAG_MODE_ECHO = 0x00000080,
|
||||
UCC_SLOW_DIAG_MODE_LOOPBACK_ECHO = 0x000000c0
|
||||
};
|
||||
|
||||
struct ucc_slow_info {
|
||||
int ucc_num;
|
||||
enum qe_clock rx_clock;
|
||||
enum qe_clock tx_clock;
|
||||
struct ucc_slow *us_regs;
|
||||
int irq;
|
||||
u16 uccm_mask;
|
||||
int data_mem_part;
|
||||
int init_tx;
|
||||
int init_rx;
|
||||
u32 tx_bd_ring_len;
|
||||
u32 rx_bd_ring_len;
|
||||
int rx_interrupts;
|
||||
int brkpt_support;
|
||||
int grant_support;
|
||||
int tsa;
|
||||
int cdp;
|
||||
int cds;
|
||||
int ctsp;
|
||||
int ctss;
|
||||
int rinv;
|
||||
int tinv;
|
||||
int rtsm;
|
||||
int rfw;
|
||||
int tci;
|
||||
int tend;
|
||||
int tfl;
|
||||
int txsy;
|
||||
u16 max_rx_buf_length;
|
||||
enum ucc_slow_transparent_tcrc tcrc;
|
||||
enum ucc_slow_channel_protocol_mode mode;
|
||||
enum ucc_slow_diag_mode diag;
|
||||
enum ucc_slow_tx_oversampling_rate tdcr;
|
||||
enum ucc_slow_rx_oversampling_rate rdcr;
|
||||
enum ucc_slow_tx_encoding_method tenc;
|
||||
enum ucc_slow_rx_decoding_method renc;
|
||||
};
|
||||
|
||||
struct ucc_slow_private {
|
||||
struct ucc_slow_info *us_info;
|
||||
struct ucc_slow *us_regs; /* a pointer to memory map of UCC regs */
|
||||
struct ucc_slow_pram *us_pram; /* a pointer to the parameter RAM */
|
||||
u32 us_pram_offset;
|
||||
int enabled_tx; /* Whether channel is enabled for Tx (ENT) */
|
||||
int enabled_rx; /* Whether channel is enabled for Rx (ENR) */
|
||||
int stopped_tx; /* Whether channel has been stopped for Tx
|
||||
(STOP_TX, etc.) */
|
||||
int stopped_rx; /* Whether channel has been stopped for Rx */
|
||||
struct list_head confQ; /* frames passed to chip waiting for tx */
|
||||
u32 first_tx_bd_mask; /* mask is used in Tx routine to save status
|
||||
and length for first BD in a frame */
|
||||
u32 tx_base_offset; /* first BD in Tx BD table offset (In MURAM) */
|
||||
u32 rx_base_offset; /* first BD in Rx BD table offset (In MURAM) */
|
||||
u8 *confBd; /* next BD for confirm after Tx */
|
||||
u8 *tx_bd; /* next BD for new Tx request */
|
||||
u8 *rx_bd; /* next BD to collect after Rx */
|
||||
void *p_rx_frame; /* accumulating receive frame */
|
||||
u16 *p_ucce; /* a pointer to the event register in memory.
|
||||
*/
|
||||
u16 *p_uccm; /* a pointer to the mask register in memory */
|
||||
u16 saved_uccm; /* a saved mask for the RX Interrupt bits */
|
||||
#ifdef STATISTICS
|
||||
u32 tx_frames; /* Transmitted frames counters */
|
||||
u32 rx_frames; /* Received frames counters (only frames
|
||||
passed to application) */
|
||||
u32 rx_discarded; /* Discarded frames counters (frames that
|
||||
were discarded by the driver due to
|
||||
errors) */
|
||||
#endif /* STATISTICS */
|
||||
};
|
||||
|
||||
/* ucc_slow_init
|
||||
* Initializes Slow UCC according to provided parameters.
|
||||
*
|
||||
* us_info - (In) pointer to the slow UCC info structure.
|
||||
* uccs_ret - (Out) pointer to the slow UCC structure.
|
||||
*/
|
||||
int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** uccs_ret);
|
||||
|
||||
/* ucc_slow_free
|
||||
* Frees all resources for slow UCC.
|
||||
*
|
||||
* uccs - (In) pointer to the slow UCC structure.
|
||||
*/
|
||||
void ucc_slow_free(struct ucc_slow_private * uccs);
|
||||
|
||||
/* ucc_slow_enable
|
||||
* Enables a fast UCC port.
|
||||
* This routine enables Tx and/or Rx through the General UCC Mode Register.
|
||||
*
|
||||
* uccs - (In) pointer to the slow UCC structure.
|
||||
* mode - (In) TX, RX, or both.
|
||||
*/
|
||||
void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode);
|
||||
|
||||
/* ucc_slow_disable
|
||||
* Disables a fast UCC port.
|
||||
* This routine disables Tx and/or Rx through the General UCC Mode Register.
|
||||
*
|
||||
* uccs - (In) pointer to the slow UCC structure.
|
||||
* mode - (In) TX, RX, or both.
|
||||
*/
|
||||
void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode);
|
||||
|
||||
/* ucc_slow_poll_transmitter_now
|
||||
* Immediately forces a poll of the transmitter for data to be sent.
|
||||
* Typically, the hardware performs a periodic poll for data that the
|
||||
* transmit routine has set up to be transmitted. In cases where
|
||||
* this polling cycle is not soon enough, this optional routine can
|
||||
* be invoked to force a poll right away, instead. Proper use for
|
||||
* each transmission for which this functionality is desired is to
|
||||
* call the transmit routine and then this routine right after.
|
||||
*
|
||||
* uccs - (In) pointer to the slow UCC structure.
|
||||
*/
|
||||
void ucc_slow_poll_transmitter_now(struct ucc_slow_private * uccs);
|
||||
|
||||
/* ucc_slow_graceful_stop_tx
|
||||
* Smoothly stops transmission on a specified slow UCC.
|
||||
*
|
||||
* uccs - (In) pointer to the slow UCC structure.
|
||||
*/
|
||||
void ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs);
|
||||
|
||||
/* ucc_slow_stop_tx
|
||||
* Stops transmission on a specified slow UCC.
|
||||
*
|
||||
* uccs - (In) pointer to the slow UCC structure.
|
||||
*/
|
||||
void ucc_slow_stop_tx(struct ucc_slow_private * uccs);
|
||||
|
||||
/* ucc_slow_restart_x
|
||||
* Restarts transmitting on a specified slow UCC.
|
||||
*
|
||||
* uccs - (In) pointer to the slow UCC structure.
|
||||
*/
|
||||
void ucc_slow_restart_x(struct ucc_slow_private * uccs);
|
||||
|
||||
u32 ucc_slow_get_qe_cr_subblock(int uccs_num);
|
||||
|
||||
#endif /* __UCC_SLOW_H__ */
|
|
@ -1,12 +1,22 @@
|
|||
#ifndef __PPC_XMON_H
|
||||
#define __PPC_XMON_H
|
||||
#ifndef __ASM_POWERPC_XMON_H
|
||||
#define __ASM_POWERPC_XMON_H
|
||||
|
||||
/*
|
||||
* Copyrignt (C) 2006 IBM Corp
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
struct pt_regs;
|
||||
|
||||
extern int xmon(struct pt_regs *excp);
|
||||
extern void xmon_printf(const char *fmt, ...);
|
||||
extern void xmon_init(int);
|
||||
|
||||
#endif
|
||||
#ifdef CONFIG_XMON
|
||||
extern void xmon_setup(void);
|
||||
#else
|
||||
static inline void xmon_setup(void) { };
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL __ */
|
||||
#endif /* __ASM_POWERPC_XMON_H */
|
||||
|
|
|
@ -46,18 +46,17 @@
|
|||
|
||||
struct gianfar_platform_data {
|
||||
/* device specific information */
|
||||
u32 device_flags;
|
||||
|
||||
u32 device_flags;
|
||||
/* board specific information */
|
||||
u32 board_flags;
|
||||
u32 bus_id;
|
||||
u32 phy_id;
|
||||
u8 mac_addr[6];
|
||||
u32 board_flags;
|
||||
u32 bus_id;
|
||||
u32 phy_id;
|
||||
u8 mac_addr[6];
|
||||
};
|
||||
|
||||
struct gianfar_mdio_data {
|
||||
/* board specific information */
|
||||
int irq[32];
|
||||
int irq[32];
|
||||
};
|
||||
|
||||
/* Flags related to gianfar device features */
|
||||
|
@ -76,14 +75,13 @@ struct gianfar_mdio_data {
|
|||
|
||||
struct fsl_i2c_platform_data {
|
||||
/* device specific information */
|
||||
u32 device_flags;
|
||||
u32 device_flags;
|
||||
};
|
||||
|
||||
/* Flags related to I2C device features */
|
||||
#define FSL_I2C_DEV_SEPARATE_DFSRR 0x00000001
|
||||
#define FSL_I2C_DEV_CLOCK_5200 0x00000002
|
||||
|
||||
|
||||
enum fsl_usb2_operating_modes {
|
||||
FSL_USB2_MPH_HOST,
|
||||
FSL_USB2_DR_HOST,
|
||||
|
@ -101,9 +99,9 @@ enum fsl_usb2_phy_modes {
|
|||
|
||||
struct fsl_usb2_platform_data {
|
||||
/* board specific information */
|
||||
enum fsl_usb2_operating_modes operating_mode;
|
||||
enum fsl_usb2_phy_modes phy_mode;
|
||||
unsigned int port_enables;
|
||||
enum fsl_usb2_operating_modes operating_mode;
|
||||
enum fsl_usb2_phy_modes phy_mode;
|
||||
unsigned int port_enables;
|
||||
};
|
||||
|
||||
/* Flags in fsl_usb2_mph_platform_data */
|
||||
|
@ -121,5 +119,44 @@ struct fsl_spi_platform_data {
|
|||
u32 sysclk;
|
||||
};
|
||||
|
||||
#endif /* _FSL_DEVICE_H_ */
|
||||
#endif /* __KERNEL__ */
|
||||
/* Ethernet interface (phy management and speed)
|
||||
*/
|
||||
enum enet_interface {
|
||||
ENET_10_MII, /* 10 Base T, MII interface */
|
||||
ENET_10_RMII, /* 10 Base T, RMII interface */
|
||||
ENET_10_RGMII, /* 10 Base T, RGMII interface */
|
||||
ENET_100_MII, /* 100 Base T, MII interface */
|
||||
ENET_100_RMII, /* 100 Base T, RMII interface */
|
||||
ENET_100_RGMII, /* 100 Base T, RGMII interface */
|
||||
ENET_1000_GMII, /* 1000 Base T, GMII interface */
|
||||
ENET_1000_RGMII, /* 1000 Base T, RGMII interface */
|
||||
ENET_1000_TBI, /* 1000 Base T, TBI interface */
|
||||
ENET_1000_RTBI /* 1000 Base T, RTBI interface */
|
||||
};
|
||||
|
||||
struct ucc_geth_platform_data {
|
||||
/* device specific information */
|
||||
u32 device_flags;
|
||||
u32 phy_reg_addr;
|
||||
|
||||
/* board specific information */
|
||||
u32 board_flags;
|
||||
u8 rx_clock;
|
||||
u8 tx_clock;
|
||||
u32 phy_id;
|
||||
enum enet_interface phy_interface;
|
||||
u32 phy_interrupt;
|
||||
u8 mac_addr[6];
|
||||
};
|
||||
|
||||
/* Flags related to UCC Gigabit Ethernet device features */
|
||||
#define FSL_UGETH_DEV_HAS_GIGABIT 0x00000001
|
||||
#define FSL_UGETH_DEV_HAS_COALESCE 0x00000002
|
||||
#define FSL_UGETH_DEV_HAS_RMON 0x00000004
|
||||
|
||||
/* Flags in ucc_geth_platform_data */
|
||||
#define FSL_UGETH_BRD_HAS_PHY_INTR 0x00000001
|
||||
/* if not set use a timer */
|
||||
|
||||
#endif /* _FSL_DEVICE_H_ */
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
Loading…
Reference in New Issue
Block a user