提交 68d88485 编写于 作者: R Ralf Baechle

Merge branches 'next/generic', 'next/alchemy', 'next/bcm63xx', 'next/cavium',...

Merge branches 'next/generic', 'next/alchemy', 'next/bcm63xx', 'next/cavium', 'next/jz4740', 'next/lantiq', 'next/loongson1b' and 'next/netlogic' into mips-for-linux-next
* Compact Flash
The Cavium Compact Flash device is connected to the Octeon Boot Bus,
and is thus a child of the Boot Bus device. It can read and write
industry standard compact flash devices.
Properties:
- compatible: "cavium,ebt3000-compact-flash";
Compatibility with many Cavium evaluation boards.
- reg: The base address of the the CF chip select banks. Depending on
the device configuration, there may be one or two banks.
- cavium,bus-width: The width of the connection to the CF devices. Valid
values are 8 and 16.
- cavium,true-ide: Optional, if present the CF connection is in True IDE mode.
- cavium,dma-engine-handle: Optional, a phandle for the DMA Engine connected
to this device.
Example:
compact-flash@5,0 {
compatible = "cavium,ebt3000-compact-flash";
reg = <5 0 0x10000>, <6 0 0x10000>;
cavium,bus-width = <16>;
cavium,true-ide;
cavium,dma-engine-handle = <&dma0>;
};
* General Purpose Input Output (GPIO) bus.
Properties:
- compatible: "cavium,octeon-3860-gpio"
Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
- reg: The base address of the GPIO unit's register bank.
- gpio-controller: This is a GPIO controller.
- #gpio-cells: Must be <2>. The first cell is the GPIO pin.
- interrupt-controller: The GPIO controller is also an interrupt
controller, many of its pins may be configured as an interrupt
source.
- #interrupt-cells: Must be <2>. The first cell is the GPIO pin
connected to the interrupt source. The second cell is the interrupt
triggering protocol and may have one of four values:
1 - edge triggered on the rising edge.
2 - edge triggered on the falling edge
4 - level triggered active high.
8 - level triggered active low.
- interrupts: Interrupt routing for each pin.
Example:
gpio-controller@1070000000800 {
#gpio-cells = <2>;
compatible = "cavium,octeon-3860-gpio";
reg = <0x10700 0x00000800 0x0 0x100>;
gpio-controller;
/* Interrupts are specified by two parts:
* 1) GPIO pin number (0..15)
* 2) Triggering (1 - edge rising
* 2 - edge falling
* 4 - level active high
* 8 - level active low)
*/
interrupt-controller;
#interrupt-cells = <2>;
/* The GPIO pin connect to 16 consecutive CUI bits */
interrupts = <0 16>, <0 17>, <0 18>, <0 19>,
<0 20>, <0 21>, <0 22>, <0 23>,
<0 24>, <0 25>, <0 26>, <0 27>,
<0 28>, <0 29>, <0 30>, <0 31>;
};
* Two Wire Serial Interface (TWSI) / I2C
- compatible: "cavium,octeon-3860-twsi"
Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
- reg: The base address of the TWSI/I2C bus controller register bank.
- #address-cells: Must be <1>.
- #size-cells: Must be <0>. I2C addresses have no size component.
- interrupts: A single interrupt specifier.
- clock-frequency: The I2C bus clock rate in Hz.
Example:
twsi0: i2c@1180000001000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "cavium,octeon-3860-twsi";
reg = <0x11800 0x00001000 0x0 0x200>;
interrupts = <0 45>;
clock-frequency = <100000>;
rtc@68 {
compatible = "dallas,ds1337";
reg = <0x68>;
};
tmp@4c {
compatible = "ti,tmp421";
reg = <0x4c>;
};
};
* Boot Bus
The Octeon Boot Bus is a configurable parallel bus with 8 chip
selects. Each chip select is independently configurable.
Properties:
- compatible: "cavium,octeon-3860-bootbus"
Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
- reg: The base address of the Boot Bus' register bank.
- #address-cells: Must be <2>. The first cell is the chip select
within the bootbus. The second cell is the offset from the chip select.
- #size-cells: Must be <1>.
- ranges: There must be one one triplet of (child-bus-address,
parent-bus-address, length) for each active chip select. If the
length element for any triplet is zero, the chip select is disabled,
making it inactive.
The configuration parameters for each chip select are stored in child
nodes.
Configuration Properties:
- compatible: "cavium,octeon-3860-bootbus-config"
- cavium,cs-index: A single cell indicating the chip select that
corresponds to this configuration.
- cavium,t-adr: A cell specifying the ADR timing (in nS).
- cavium,t-ce: A cell specifying the CE timing (in nS).
- cavium,t-oe: A cell specifying the OE timing (in nS).
- cavium,t-we: A cell specifying the WE timing (in nS).
- cavium,t-rd-hld: A cell specifying the RD_HLD timing (in nS).
- cavium,t-wr-hld: A cell specifying the WR_HLD timing (in nS).
- cavium,t-pause: A cell specifying the PAUSE timing (in nS).
- cavium,t-wait: A cell specifying the WAIT timing (in nS).
- cavium,t-page: A cell specifying the PAGE timing (in nS).
- cavium,t-rd-dly: A cell specifying the RD_DLY timing (in nS).
- cavium,pages: A cell specifying the PAGES parameter (0 = 8 bytes, 1
= 2 bytes, 2 = 4 bytes, 3 = 8 bytes).
- cavium,wait-mode: Optional. If present, wait mode (WAITM) is selected.
- cavium,page-mode: Optional. If present, page mode (PAGEM) is selected.
- cavium,bus-width: A cell specifying the WIDTH parameter (in bits) of
the bus for this chip select.
- cavium,ale-mode: Optional. If present, ALE mode is selected.
- cavium,sam-mode: Optional. If present, SAM mode is selected.
- cavium,or-mode: Optional. If present, OR mode is selected.
Example:
bootbus: bootbus@1180000000000 {
compatible = "cavium,octeon-3860-bootbus";
reg = <0x11800 0x00000000 0x0 0x200>;
/* The chip select number and offset */
#address-cells = <2>;
/* The size of the chip select region */
#size-cells = <1>;
ranges = <0 0 0x0 0x1f400000 0xc00000>,
<1 0 0x10000 0x30000000 0>,
<2 0 0x10000 0x40000000 0>,
<3 0 0x10000 0x50000000 0>,
<4 0 0x0 0x1d020000 0x10000>,
<5 0 0x0 0x1d040000 0x10000>,
<6 0 0x0 0x1d050000 0x10000>,
<7 0 0x10000 0x90000000 0>;
cavium,cs-config@0 {
compatible = "cavium,octeon-3860-bootbus-config";
cavium,cs-index = <0>;
cavium,t-adr = <20>;
cavium,t-ce = <60>;
cavium,t-oe = <60>;
cavium,t-we = <45>;
cavium,t-rd-hld = <35>;
cavium,t-wr-hld = <45>;
cavium,t-pause = <0>;
cavium,t-wait = <0>;
cavium,t-page = <35>;
cavium,t-rd-dly = <0>;
cavium,pages = <0>;
cavium,bus-width = <8>;
};
.
.
.
cavium,cs-config@6 {
compatible = "cavium,octeon-3860-bootbus-config";
cavium,cs-index = <6>;
cavium,t-adr = <5>;
cavium,t-ce = <300>;
cavium,t-oe = <270>;
cavium,t-we = <150>;
cavium,t-rd-hld = <100>;
cavium,t-wr-hld = <70>;
cavium,t-pause = <0>;
cavium,t-wait = <0>;
cavium,t-page = <320>;
cavium,t-rd-dly = <0>;
cavium,pages = <0>;
cavium,wait-mode;
cavium,bus-width = <16>;
};
.
.
.
};
* Central Interrupt Unit
Properties:
- compatible: "cavium,octeon-3860-ciu"
Compatibility with all cn3XXX, cn5XXX and cn63XX SOCs.
- interrupt-controller: This is an interrupt controller.
- reg: The base address of the CIU's register bank.
- #interrupt-cells: Must be <2>. The first cell is the bank within
the CIU and may have a value of 0 or 1. The second cell is the bit
within the bank and may have a value between 0 and 63.
Example:
interrupt-controller@1070000000000 {
compatible = "cavium,octeon-3860-ciu";
interrupt-controller;
/* Interrupts are specified by two parts:
* 1) Controller register (0 or 1)
* 2) Bit within the register (0..63)
*/
#interrupt-cells = <2>;
reg = <0x10700 0x00000000 0x0 0x7000>;
};
* Central Interrupt Unit
Properties:
- compatible: "cavium,octeon-6880-ciu2"
Compatibility with 68XX SOCs.
- interrupt-controller: This is an interrupt controller.
- reg: The base address of the CIU's register bank.
- #interrupt-cells: Must be <2>. The first cell is the bank within
the CIU and may have a value between 0 and 63. The second cell is
the bit within the bank and may also have a value between 0 and 63.
Example:
interrupt-controller@1070100000000 {
compatible = "cavium,octeon-6880-ciu2";
interrupt-controller;
/* Interrupts are specified by two parts:
* 1) Controller register (0..63)
* 2) Bit within the register (0..63)
*/
#address-cells = <0>;
#interrupt-cells = <2>;
reg = <0x10701 0x00000000 0x0 0x4000000>;
};
* DMA Engine.
The Octeon DMA Engine transfers between the Boot Bus and main memory.
The DMA Engine will be refered to by phandle by any device that is
connected to it.
Properties:
- compatible: "cavium,octeon-5750-bootbus-dma"
Compatibility with all cn52XX, cn56XX and cn6XXX SOCs.
- reg: The base address of the DMA Engine's register bank.
- interrupts: A single interrupt specifier.
Example:
dma0: dma-engine@1180000000100 {
compatible = "cavium,octeon-5750-bootbus-dma";
reg = <0x11800 0x00000100 0x0 0x8>;
interrupts = <0 63>;
};
* UCTL USB controller glue
Properties:
- compatible: "cavium,octeon-6335-uctl"
Compatibility with all cn6XXX SOCs.
- reg: The base address of the UCTL register bank.
- #address-cells: Must be <2>.
- #size-cells: Must be <2>.
- ranges: Empty to signify direct mapping of the children.
- refclk-frequency: A single cell containing the reference clock
frequency in Hz.
- refclk-type: A string describing the reference clock connection
either "crystal" or "external".
Example:
uctl@118006f000000 {
compatible = "cavium,octeon-6335-uctl";
reg = <0x11800 0x6f000000 0x0 0x100>;
ranges; /* Direct mapping */
#address-cells = <2>;
#size-cells = <2>;
/* 12MHz, 24MHz and 48MHz allowed */
refclk-frequency = <24000000>;
/* Either "crystal" or "external" */
refclk-type = "crystal";
ehci@16f0000000000 {
compatible = "cavium,octeon-6335-ehci","usb-ehci";
reg = <0x16f00 0x00000000 0x0 0x100>;
interrupts = <0 56>;
big-endian-regs;
};
ohci@16f0000000400 {
compatible = "cavium,octeon-6335-ohci","usb-ohci";
reg = <0x16f00 0x00000400 0x0 0x100>;
interrupts = <0 56>;
big-endian-regs;
};
};
* System Management Interface (SMI) / MDIO
Properties:
- compatible: "cavium,octeon-3860-mdio"
Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
- reg: The base address of the MDIO bus controller register bank.
- #address-cells: Must be <1>.
- #size-cells: Must be <0>. MDIO addresses have no size component.
Typically an MDIO bus might have several children.
Example:
mdio@1180000001800 {
compatible = "cavium,octeon-3860-mdio";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11800 0x00001800 0x0 0x40>;
ethernet-phy@0 {
...
reg = <0>;
};
};
* MIX Ethernet controller.
Properties:
- compatible: "cavium,octeon-5750-mix"
Compatibility with all cn5XXX and cn6XXX SOCs populated with MIX
devices.
- reg: The base addresses of four separate register banks. The first
bank contains the MIX registers. The second bank the corresponding
AGL registers. The third bank are the AGL registers shared by all
MIX devices present. The fourth bank is the AGL_PRT_CTL shared by
all MIX devices present.
- cell-index: A single cell specifying which portion of the shared
register banks corresponds to this MIX device.
- interrupts: Two interrupt specifiers. The first is the MIX
interrupt routing and the second the routing for the AGL interrupts.
- mac-address: Optional, the MAC address to assign to the device.
- local-mac-address: Optional, the MAC address to assign to the device
if mac-address is not specified.
- phy-handle: Optional, a phandle for the PHY device connected to this device.
Example:
ethernet@1070000100800 {
compatible = "cavium,octeon-5750-mix";
reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */
<0x11800 0xE0000800 0x0 0x300>, /* AGL */
<0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
<0x11800 0xE0002008 0x0 0x8>; /* AGL_PRT_CTL */
cell-index = <1>;
interrupts = <1 18>, < 1 46>;
local-mac-address = [ 00 0f b7 10 63 54 ];
phy-handle = <&phy1>;
};
* PIP Ethernet nexus.
The PIP Ethernet nexus can control several data packet input/output
devices. The devices have a two level grouping scheme. There may be
several interfaces, and each interface may have several ports. These
ports might be an individual Ethernet PHY.
Properties for the PIP nexus:
- compatible: "cavium,octeon-3860-pip"
Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
- reg: The base address of the PIP's register bank.
- #address-cells: Must be <1>.
- #size-cells: Must be <0>.
Properties for PIP interfaces which is a child the PIP nexus:
- compatible: "cavium,octeon-3860-pip-interface"
Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
- reg: The interface number.
- #address-cells: Must be <1>.
- #size-cells: Must be <0>.
Properties for PIP port which is a child the PIP interface:
- compatible: "cavium,octeon-3860-pip-port"
Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
- reg: The port number within the interface group.
- mac-address: Optional, the MAC address to assign to the device.
- local-mac-address: Optional, the MAC address to assign to the device
if mac-address is not specified.
- phy-handle: Optional, a phandle for the PHY device connected to this device.
Example:
pip@11800a0000000 {
compatible = "cavium,octeon-3860-pip";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11800 0xa0000000 0x0 0x2000>;
interface@0 {
compatible = "cavium,octeon-3860-pip-interface";
#address-cells = <1>;
#size-cells = <0>;
reg = <0>; /* interface */
ethernet@0 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x0>; /* Port */
local-mac-address = [ 00 0f b7 10 63 60 ];
phy-handle = <&phy2>;
};
ethernet@1 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x1>; /* Port */
local-mac-address = [ 00 0f b7 10 63 61 ];
phy-handle = <&phy3>;
};
ethernet@2 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x2>; /* Port */
local-mac-address = [ 00 0f b7 10 63 62 ];
phy-handle = <&phy4>;
};
ethernet@3 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x3>; /* Port */
local-mac-address = [ 00 0f b7 10 63 63 ];
phy-handle = <&phy5>;
};
};
interface@1 {
compatible = "cavium,octeon-3860-pip-interface";
#address-cells = <1>;
#size-cells = <0>;
reg = <1>; /* interface */
ethernet@0 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x0>; /* Port */
local-mac-address = [ 00 0f b7 10 63 64 ];
phy-handle = <&phy6>;
};
};
};
* Universal Asynchronous Receiver/Transmitter (UART)
- compatible: "cavium,octeon-3860-uart"
Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
- reg: The base address of the UART register bank.
- interrupts: A single interrupt specifier.
- current-speed: Optional, the current bit rate in bits per second.
Example:
uart1: serial@1180000000c00 {
compatible = "cavium,octeon-3860-uart","ns16550";
reg = <0x11800 0x00000c00 0x0 0x400>;
current-speed = <115200>;
interrupts = <0 35>;
};
...@@ -14,6 +14,7 @@ platforms += jz4740 ...@@ -14,6 +14,7 @@ platforms += jz4740
platforms += lantiq platforms += lantiq
platforms += lasat platforms += lasat
platforms += loongson platforms += loongson
platforms += loongson1
platforms += mipssim platforms += mipssim
platforms += mti-malta platforms += mti-malta
platforms += netlogic platforms += netlogic
......
...@@ -209,6 +209,7 @@ config MACH_JZ4740 ...@@ -209,6 +209,7 @@ config MACH_JZ4740
select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_ZBOOT_UART16550
select DMA_NONCOHERENT select DMA_NONCOHERENT
select IRQ_CPU select IRQ_CPU
select GENERIC_GPIO select GENERIC_GPIO
...@@ -264,6 +265,16 @@ config MACH_LOONGSON ...@@ -264,6 +265,16 @@ config MACH_LOONGSON
Chinese Academy of Sciences (CAS) in the People's Republic Chinese Academy of Sciences (CAS) in the People's Republic
of China. The chief architect is Professor Weiwu Hu. of China. The chief architect is Professor Weiwu Hu.
config MACH_LOONGSON1
bool "Loongson 1 family of machines"
select SYS_SUPPORTS_ZBOOT
help
This enables support for the Loongson 1 based machines.
Loongson 1 is a family of 32-bit MIPS-compatible SoCs developed by
the ICT (Institute of Computing Technology) and the Chinese Academy
of Sciences.
config MIPS_MALTA config MIPS_MALTA
bool "MIPS Malta board" bool "MIPS Malta board"
select ARCH_MAY_HAVE_PC_FDC select ARCH_MAY_HAVE_PC_FDC
...@@ -787,6 +798,8 @@ config NLM_XLR_BOARD ...@@ -787,6 +798,8 @@ config NLM_XLR_BOARD
select ZONE_DMA if 64BIT select ZONE_DMA if 64BIT
select SYNC_R4K select SYNC_R4K
select SYS_HAS_EARLY_PRINTK select SYS_HAS_EARLY_PRINTK
select USB_ARCH_HAS_OHCI if USB_SUPPORT
select USB_ARCH_HAS_EHCI if USB_SUPPORT
help help
Support for systems based on Netlogic XLR and XLS processors. Support for systems based on Netlogic XLR and XLS processors.
Say Y here if you have a XLR or XLS based board. Say Y here if you have a XLR or XLS based board.
...@@ -799,7 +812,6 @@ config NLM_XLP_BOARD ...@@ -799,7 +812,6 @@ config NLM_XLP_BOARD
select SYS_HAS_CPU_XLP select SYS_HAS_CPU_XLP
select SYS_SUPPORTS_SMP select SYS_SUPPORTS_SMP
select HW_HAS_PCI select HW_HAS_PCI
select SWAP_IO_SPACE
select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL select SYS_SUPPORTS_64BIT_KERNEL
select 64BIT_PHYS_ADDR select 64BIT_PHYS_ADDR
...@@ -836,6 +848,7 @@ source "arch/mips/txx9/Kconfig" ...@@ -836,6 +848,7 @@ source "arch/mips/txx9/Kconfig"
source "arch/mips/vr41xx/Kconfig" source "arch/mips/vr41xx/Kconfig"
source "arch/mips/cavium-octeon/Kconfig" source "arch/mips/cavium-octeon/Kconfig"
source "arch/mips/loongson/Kconfig" source "arch/mips/loongson/Kconfig"
source "arch/mips/loongson1/Kconfig"
source "arch/mips/netlogic/Kconfig" source "arch/mips/netlogic/Kconfig"
endmenu endmenu
...@@ -1217,6 +1230,14 @@ config CPU_LOONGSON2F ...@@ -1217,6 +1230,14 @@ config CPU_LOONGSON2F
have a similar programming interface with FPGA northbridge used in have a similar programming interface with FPGA northbridge used in
Loongson2E. Loongson2E.
config CPU_LOONGSON1B
bool "Loongson 1B"
depends on SYS_HAS_CPU_LOONGSON1B
select CPU_LOONGSON1
help
The Loongson 1B is a 32-bit SoC, which implements the MIPS32
release 2 instruction set.
config CPU_MIPS32_R1 config CPU_MIPS32_R1
bool "MIPS32 Release 1" bool "MIPS32 Release 1"
depends on SYS_HAS_CPU_MIPS32_R1 depends on SYS_HAS_CPU_MIPS32_R1
...@@ -1432,6 +1453,8 @@ config CPU_CAVIUM_OCTEON ...@@ -1432,6 +1453,8 @@ config CPU_CAVIUM_OCTEON
select WEAK_ORDERING select WEAK_ORDERING
select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HIGHMEM
select CPU_SUPPORTS_HUGEPAGES select CPU_SUPPORTS_HUGEPAGES
select LIBFDT
select USE_OF
help help
The Cavium Octeon processor is a highly integrated chip containing The Cavium Octeon processor is a highly integrated chip containing
many ethernet hardware widgets for networking tasks. The processor many ethernet hardware widgets for networking tasks. The processor
...@@ -1544,6 +1567,14 @@ config CPU_LOONGSON2 ...@@ -1544,6 +1567,14 @@ config CPU_LOONGSON2
select CPU_SUPPORTS_64BIT_KERNEL select CPU_SUPPORTS_64BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HIGHMEM
config CPU_LOONGSON1
bool
select CPU_MIPS32
select CPU_MIPSR2
select CPU_HAS_PREFETCH
select CPU_SUPPORTS_32BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
config CPU_BMIPS config CPU_BMIPS
bool bool
select CPU_MIPS32 select CPU_MIPS32
...@@ -1562,6 +1593,9 @@ config SYS_HAS_CPU_LOONGSON2F ...@@ -1562,6 +1593,9 @@ config SYS_HAS_CPU_LOONGSON2F
select CPU_SUPPORTS_ADDRWINCFG if 64BIT select CPU_SUPPORTS_ADDRWINCFG if 64BIT
select CPU_SUPPORTS_UNCACHED_ACCELERATED select CPU_SUPPORTS_UNCACHED_ACCELERATED
config SYS_HAS_CPU_LOONGSON1B
bool
config SYS_HAS_CPU_MIPS32_R1 config SYS_HAS_CPU_MIPS32_R1
bool bool
...@@ -2366,6 +2400,8 @@ config PCI_DOMAINS ...@@ -2366,6 +2400,8 @@ config PCI_DOMAINS
source "drivers/pci/Kconfig" source "drivers/pci/Kconfig"
source "drivers/pci/pcie/Kconfig"
# #
# ISA support is now enabled via select. Too many systems still have the one # ISA support is now enabled via select. Too many systems still have the one
# or other ISA chip on the board that users don't know about so don't expect # or other ISA chip on the board that users don't know about so don't expect
......
...@@ -81,10 +81,10 @@ static void mtx1_power_off(void) ...@@ -81,10 +81,10 @@ static void mtx1_power_off(void)
void __init board_setup(void) void __init board_setup(void)
{ {
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) #if IS_ENABLED(CONFIG_USB_OHCI_HCD)
/* Enable USB power switch */ /* Enable USB power switch */
alchemy_gpio_direction_output(204, 0); alchemy_gpio_direction_output(204, 0);
#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ #endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */
/* Initialize sys_pinfunc */ /* Initialize sys_pinfunc */
au_writel(SYS_PF_NI2, SYS_PINFUNC); au_writel(SYS_PF_NI2, SYS_PINFUNC);
......
...@@ -334,13 +334,12 @@ static void __init alchemy_setup_macs(int ctype) ...@@ -334,13 +334,12 @@ static void __init alchemy_setup_macs(int ctype)
if (alchemy_get_macs(ctype) < 1) if (alchemy_get_macs(ctype) < 1)
return; return;
macres = kmalloc(sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); macres = kmemdup(au1xxx_eth0_resources[ctype],
sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL);
if (!macres) { if (!macres) {
printk(KERN_INFO "Alchemy: no memory for MAC0 resources\n"); printk(KERN_INFO "Alchemy: no memory for MAC0 resources\n");
return; return;
} }
memcpy(macres, au1xxx_eth0_resources[ctype],
sizeof(struct resource) * MAC_RES_COUNT);
au1xxx_eth0_device.resource = macres; au1xxx_eth0_device.resource = macres;
i = prom_get_ethernet_addr(ethaddr); i = prom_get_ethernet_addr(ethaddr);
...@@ -356,13 +355,12 @@ static void __init alchemy_setup_macs(int ctype) ...@@ -356,13 +355,12 @@ static void __init alchemy_setup_macs(int ctype)
if (alchemy_get_macs(ctype) < 2) if (alchemy_get_macs(ctype) < 2)
return; return;
macres = kmalloc(sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL); macres = kmemdup(au1xxx_eth1_resources[ctype],
sizeof(struct resource) * MAC_RES_COUNT, GFP_KERNEL);
if (!macres) { if (!macres) {
printk(KERN_INFO "Alchemy: no memory for MAC1 resources\n"); printk(KERN_INFO "Alchemy: no memory for MAC1 resources\n");
return; return;
} }
memcpy(macres, au1xxx_eth1_resources[ctype],
sizeof(struct resource) * MAC_RES_COUNT);
au1xxx_eth1_device.resource = macres; au1xxx_eth1_device.resource = macres;
ethaddr[5] += 1; /* next addr for 2nd MAC */ ethaddr[5] += 1; /* next addr for 2nd MAC */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Alchemy Develboards # Alchemy Develboards
# #
obj-y += prom.o bcsr.o platform.o obj-y += bcsr.o platform.o
obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_PM) += pm.o
obj-$(CONFIG_MIPS_PB1100) += pb1100.o obj-$(CONFIG_MIPS_PB1100) += pb1100.o
obj-$(CONFIG_MIPS_PB1500) += pb1500.o obj-$(CONFIG_MIPS_PB1500) += pb1500.o
......
...@@ -90,10 +90,7 @@ static void bcsr_csc_handler(unsigned int irq, struct irq_desc *d) ...@@ -90,10 +90,7 @@ static void bcsr_csc_handler(unsigned int irq, struct irq_desc *d)
unsigned short bisr = __raw_readw(bcsr_virt + BCSR_REG_INTSTAT); unsigned short bisr = __raw_readw(bcsr_virt + BCSR_REG_INTSTAT);
disable_irq_nosync(irq); disable_irq_nosync(irq);
generic_handle_irq(bcsr_csc_base + __ffs(bisr));
for ( ; bisr; bisr &= bisr - 1)
generic_handle_irq(bcsr_csc_base + __ffs(bisr));
enable_irq(irq); enable_irq(irq);
} }
......
...@@ -46,7 +46,7 @@ void __init board_setup(void) ...@@ -46,7 +46,7 @@ void __init board_setup(void)
alchemy_gpio1_input_enable(); alchemy_gpio1_input_enable();
udelay(100); udelay(100);
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) #if IS_ENABLED(CONFIG_USB_OHCI_HCD)
{ {
u32 pin_func, sys_freqctrl, sys_clksrc; u32 pin_func, sys_freqctrl, sys_clksrc;
...@@ -93,7 +93,7 @@ void __init board_setup(void) ...@@ -93,7 +93,7 @@ void __init board_setup(void)
pin_func |= SYS_PF_USB; pin_func |= SYS_PF_USB;
au_writel(pin_func, SYS_PINFUNC); au_writel(pin_func, SYS_PINFUNC);
} }
#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ #endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */
/* Enable sys bus clock divider when IDLE state or no bus activity. */ /* Enable sys bus clock divider when IDLE state or no bus activity. */
au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL); au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);
......
...@@ -53,7 +53,7 @@ void __init board_setup(void) ...@@ -53,7 +53,7 @@ void __init board_setup(void)
alchemy_gpio_direction_input(201); alchemy_gpio_direction_input(201);
alchemy_gpio_direction_input(203); alchemy_gpio_direction_input(203);
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) #if IS_ENABLED(CONFIG_USB_OHCI_HCD)
/* Zero and disable FREQ2 */ /* Zero and disable FREQ2 */
sys_freqctrl = au_readl(SYS_FREQCTRL0); sys_freqctrl = au_readl(SYS_FREQCTRL0);
...@@ -87,7 +87,7 @@ void __init board_setup(void) ...@@ -87,7 +87,7 @@ void __init board_setup(void)
/* 2nd USB port is USB host */ /* 2nd USB port is USB host */
pin_func |= SYS_PF_USB; pin_func |= SYS_PF_USB;
au_writel(pin_func, SYS_PINFUNC); au_writel(pin_func, SYS_PINFUNC);
#endif /* defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) */ #endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
{ {
......
...@@ -10,9 +10,39 @@ ...@@ -10,9 +10,39 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <asm/bootinfo.h>
#include <asm/reboot.h> #include <asm/reboot.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-db1x00/bcsr.h> #include <asm/mach-db1x00/bcsr.h>
#include <prom.h>
void __init prom_init(void)
{
unsigned char *memsize_str;
unsigned long memsize;
prom_argc = (int)fw_arg0;
prom_argv = (char **)fw_arg1;
prom_envp = (char **)fw_arg2;
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
if (!memsize_str || kstrtoul(memsize_str, 0, &memsize))
memsize = 64 << 20; /* all devboards have at least 64MB RAM */
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
void prom_putchar(unsigned char c)
{
#ifdef CONFIG_MIPS_DB1300
alchemy_uart_putchar(AU1300_UART2_PHYS_ADDR, c);
#else
alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
#endif
}
static struct platform_device db1x00_rtc_dev = { static struct platform_device db1x00_rtc_dev = {
.name = "rtc-au1xxx", .name = "rtc-au1xxx",
......
/*
* Common code used by all Alchemy develboards.
*
* Extracted from files which had this to say:
*
* Copyright 2000, 2008 MontaVista Software Inc.
* Author: MontaVista Software, Inc. <source@mvista.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.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* 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.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/bootinfo.h>
#include <asm/mach-au1x00/au1000.h>
#include <prom.h>
#if defined(CONFIG_MIPS_DB1000) || \
defined(CONFIG_MIPS_PB1100) || \
defined(CONFIG_MIPS_PB1500)
#define ALCHEMY_BOARD_DEFAULT_MEMSIZE 0x04000000
#else /* Au1550/Au1200-based develboards */
#define ALCHEMY_BOARD_DEFAULT_MEMSIZE 0x08000000
#endif
void __init prom_init(void)
{
unsigned char *memsize_str;
unsigned long memsize;
prom_argc = (int)fw_arg0;
prom_argv = (char **)fw_arg1;
prom_envp = (char **)fw_arg2;
prom_init_cmdline();
memsize_str = prom_getenv("memsize");
if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize))
memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE;
add_memory_region(0, memsize, BOOT_MEM_RAM);
}
void prom_putchar(unsigned char c)
{
#ifdef CONFIG_MIPS_DB1300
alchemy_uart_putchar(AU1300_UART2_PHYS_ADDR, c);
#else
alchemy_uart_putchar(AU1000_UART0_PHYS_ADDR, c);
#endif
}
menu "CPU support" menu "CPU support"
depends on BCM63XX depends on BCM63XX
config BCM63XX_CPU_6328
bool "support 6328 CPU"
select HW_HAS_PCI
config BCM63XX_CPU_6338 config BCM63XX_CPU_6338
bool "support 6338 CPU" bool "support 6338 CPU"
select HW_HAS_PCI select HW_HAS_PCI
......
obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \ obj-y += clk.o cpu.o cs.o gpio.o irq.o prom.o setup.o timer.o \
dev-dsp.o dev-enet.o dev-pcmcia.o dev-uart.o dev-wdt.o dev-dsp.o dev-enet.o dev-flash.o dev-pcmcia.o dev-rng.o \
dev-spi.o dev-uart.o dev-wdt.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-y += boards/ obj-y += boards/
...@@ -11,9 +11,6 @@ ...@@ -11,9 +11,6 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/ssb/ssb.h> #include <linux/ssb/ssb.h>
#include <asm/addrspace.h> #include <asm/addrspace.h>
#include <bcm63xx_board.h> #include <bcm63xx_board.h>
...@@ -24,7 +21,9 @@ ...@@ -24,7 +21,9 @@
#include <bcm63xx_dev_pci.h> #include <bcm63xx_dev_pci.h>
#include <bcm63xx_dev_enet.h> #include <bcm63xx_dev_enet.h>
#include <bcm63xx_dev_dsp.h> #include <bcm63xx_dev_dsp.h>
#include <bcm63xx_dev_flash.h>
#include <bcm63xx_dev_pcmcia.h> #include <bcm63xx_dev_pcmcia.h>
#include <bcm63xx_dev_spi.h>
#include <board_bcm963xx.h> #include <board_bcm963xx.h>
#define PFX "board_bcm963xx: " #define PFX "board_bcm963xx: "
...@@ -33,6 +32,48 @@ static struct bcm963xx_nvram nvram; ...@@ -33,6 +32,48 @@ static struct bcm963xx_nvram nvram;
static unsigned int mac_addr_used; static unsigned int mac_addr_used;
static struct board_info board; static struct board_info board;
/*
* known 6328 boards
*/
#ifdef CONFIG_BCM63XX_CPU_6328
static struct board_info __initdata board_96328avng = {
.name = "96328avng",
.expected_cpu_id = 0x6328,
.has_uart0 = 1,
.has_pci = 1,
.leds = {
{
.name = "96328avng::ppp-fail",
.gpio = 2,
.active_low = 1,
},
{
.name = "96328avng::power",
.gpio = 4,
.active_low = 1,
.default_trigger = "default-on",
},
{
.name = "96328avng::power-fail",
.gpio = 8,
.active_low = 1,
},
{
.name = "96328avng::wps",
.gpio = 9,
.active_low = 1,
},
{
.name = "96328avng::ppp",
.gpio = 11,
.active_low = 1,
},
},
};
#endif
/* /*
* known 6338 boards * known 6338 boards
*/ */
...@@ -592,6 +633,9 @@ static struct board_info __initdata board_DWVS0 = { ...@@ -592,6 +633,9 @@ static struct board_info __initdata board_DWVS0 = {
* all boards * all boards
*/ */
static const struct board_info __initdata *bcm963xx_boards[] = { static const struct board_info __initdata *bcm963xx_boards[] = {
#ifdef CONFIG_BCM63XX_CPU_6328
&board_96328avng,
#endif
#ifdef CONFIG_BCM63XX_CPU_6338 #ifdef CONFIG_BCM63XX_CPU_6338
&board_96338gw, &board_96338gw,
&board_96338w, &board_96338w,
...@@ -709,9 +753,15 @@ void __init board_prom_init(void) ...@@ -709,9 +753,15 @@ void __init board_prom_init(void)
char cfe_version[32]; char cfe_version[32];
u32 val; u32 val;
/* read base address of boot chip select (0) */ /* read base address of boot chip select (0)
val = bcm_mpi_readl(MPI_CSBASE_REG(0)); * 6328 does not have MPI but boots from a fixed address
val &= MPI_CSBASE_BASE_MASK; */
if (BCMCPU_IS_6328())
val = 0x18000000;
else {
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
val &= MPI_CSBASE_BASE_MASK;
}
boot_addr = (u8 *)KSEG1ADDR(val); boot_addr = (u8 *)KSEG1ADDR(val);
/* dump cfe version */ /* dump cfe version */
...@@ -808,40 +858,6 @@ void __init board_setup(void) ...@@ -808,40 +858,6 @@ void __init board_setup(void)
panic("unexpected CPU for bcm963xx board"); panic("unexpected CPU for bcm963xx board");
} }
static struct mtd_partition mtd_partitions[] = {
{
.name = "cfe",
.offset = 0x0,
.size = 0x40000,
}
};
static const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL };
static struct physmap_flash_data flash_data = {
.width = 2,
.nr_parts = ARRAY_SIZE(mtd_partitions),
.parts = mtd_partitions,
.part_probe_types = bcm63xx_part_types,
};
static struct resource mtd_resources[] = {
{
.start = 0, /* filled at runtime */
.end = 0, /* filled at runtime */
.flags = IORESOURCE_MEM,
}
};
static struct platform_device mtd_dev = {
.name = "physmap-flash",
.resource = mtd_resources,
.num_resources = ARRAY_SIZE(mtd_resources),
.dev = {
.platform_data = &flash_data,
},
};
static struct gpio_led_platform_data bcm63xx_led_data; static struct gpio_led_platform_data bcm63xx_led_data;
static struct platform_device bcm63xx_gpio_leds = { static struct platform_device bcm63xx_gpio_leds = {
...@@ -855,8 +871,6 @@ static struct platform_device bcm63xx_gpio_leds = { ...@@ -855,8 +871,6 @@ static struct platform_device bcm63xx_gpio_leds = {
*/ */
int __init board_register_devices(void) int __init board_register_devices(void)
{ {
u32 val;
if (board.has_uart0) if (board.has_uart0)
bcm63xx_uart_register(0); bcm63xx_uart_register(0);
...@@ -890,14 +904,9 @@ int __init board_register_devices(void) ...@@ -890,14 +904,9 @@ int __init board_register_devices(void)
} }
#endif #endif
/* read base address of boot chip select (0) */ bcm63xx_spi_register();
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
val &= MPI_CSBASE_BASE_MASK;
mtd_resources[0].start = val;
mtd_resources[0].end = 0x1FFFFFFF;
platform_device_register(&mtd_dev); bcm63xx_flash_register();
bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds); bcm63xx_led_data.num_leds = ARRAY_SIZE(board.leds);
bcm63xx_led_data.leds = board.leds; bcm63xx_led_data.leds = board.leds;
......
...@@ -120,7 +120,7 @@ static void enetsw_set(struct clk *clk, int enable) ...@@ -120,7 +120,7 @@ static void enetsw_set(struct clk *clk, int enable)
{ {
if (!BCMCPU_IS_6368()) if (!BCMCPU_IS_6368())
return; return;
bcm_hwclock_set(CKCTL_6368_ROBOSW_CLK_EN | bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
CKCTL_6368_SWPKT_USB_EN | CKCTL_6368_SWPKT_USB_EN |
CKCTL_6368_SWPKT_SAR_EN, enable); CKCTL_6368_SWPKT_SAR_EN, enable);
if (enable) { if (enable) {
...@@ -163,7 +163,7 @@ static void usbh_set(struct clk *clk, int enable) ...@@ -163,7 +163,7 @@ static void usbh_set(struct clk *clk, int enable)
if (BCMCPU_IS_6348()) if (BCMCPU_IS_6348())
bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); bcm_hwclock_set(CKCTL_6348_USBH_EN, enable);
else if (BCMCPU_IS_6368()) else if (BCMCPU_IS_6368())
bcm_hwclock_set(CKCTL_6368_USBH_CLK_EN, enable); bcm_hwclock_set(CKCTL_6368_USBH_EN, enable);
} }
static struct clk clk_usbh = { static struct clk clk_usbh = {
...@@ -181,9 +181,11 @@ static void spi_set(struct clk *clk, int enable) ...@@ -181,9 +181,11 @@ static void spi_set(struct clk *clk, int enable)
mask = CKCTL_6338_SPI_EN; mask = CKCTL_6338_SPI_EN;
else if (BCMCPU_IS_6348()) else if (BCMCPU_IS_6348())
mask = CKCTL_6348_SPI_EN; mask = CKCTL_6348_SPI_EN;
else else if (BCMCPU_IS_6358())
/* BCMCPU_IS_6358 */
mask = CKCTL_6358_SPI_EN; mask = CKCTL_6358_SPI_EN;
else
/* BCMCPU_IS_6368 */
mask = CKCTL_6368_SPI_EN;
bcm_hwclock_set(mask, enable); bcm_hwclock_set(mask, enable);
} }
...@@ -199,7 +201,7 @@ static void xtm_set(struct clk *clk, int enable) ...@@ -199,7 +201,7 @@ static void xtm_set(struct clk *clk, int enable)
if (!BCMCPU_IS_6368()) if (!BCMCPU_IS_6368())
return; return;
bcm_hwclock_set(CKCTL_6368_SAR_CLK_EN | bcm_hwclock_set(CKCTL_6368_SAR_EN |
CKCTL_6368_SWPKT_SAR_EN, enable); CKCTL_6368_SWPKT_SAR_EN, enable);
if (enable) { if (enable) {
...@@ -221,6 +223,18 @@ static struct clk clk_xtm = { ...@@ -221,6 +223,18 @@ static struct clk clk_xtm = {
.set = xtm_set, .set = xtm_set,
}; };
/*
* IPsec clock
*/
static void ipsec_set(struct clk *clk, int enable)
{
bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
}
static struct clk clk_ipsec = {
.set = ipsec_set,
};
/* /*
* Internal peripheral clock * Internal peripheral clock
*/ */
...@@ -278,6 +292,8 @@ struct clk *clk_get(struct device *dev, const char *id) ...@@ -278,6 +292,8 @@ struct clk *clk_get(struct device *dev, const char *id)
return &clk_periph; return &clk_periph;
if (BCMCPU_IS_6358() && !strcmp(id, "pcm")) if (BCMCPU_IS_6358() && !strcmp(id, "pcm"))
return &clk_pcm; return &clk_pcm;
if (BCMCPU_IS_6368() && !strcmp(id, "ipsec"))
return &clk_ipsec;
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
} }
......
...@@ -29,6 +29,14 @@ static u16 bcm63xx_cpu_rev; ...@@ -29,6 +29,14 @@ static u16 bcm63xx_cpu_rev;
static unsigned int bcm63xx_cpu_freq; static unsigned int bcm63xx_cpu_freq;
static unsigned int bcm63xx_memory_size; static unsigned int bcm63xx_memory_size;
static const unsigned long bcm6328_regs_base[] = {
__GEN_CPU_REGS_TABLE(6328)
};
static const int bcm6328_irqs[] = {
__GEN_CPU_IRQ_TABLE(6328)
};
static const unsigned long bcm6338_regs_base[] = { static const unsigned long bcm6338_regs_base[] = {
__GEN_CPU_REGS_TABLE(6338) __GEN_CPU_REGS_TABLE(6338)
}; };
...@@ -99,6 +107,33 @@ unsigned int bcm63xx_get_memory_size(void) ...@@ -99,6 +107,33 @@ unsigned int bcm63xx_get_memory_size(void)
static unsigned int detect_cpu_clock(void) static unsigned int detect_cpu_clock(void)
{ {
switch (bcm63xx_get_cpu_id()) { switch (bcm63xx_get_cpu_id()) {
case BCM6328_CPU_ID:
{
unsigned int tmp, mips_pll_fcvo;
tmp = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
mips_pll_fcvo = (tmp & STRAPBUS_6328_FCVO_MASK)
>> STRAPBUS_6328_FCVO_SHIFT;
switch (mips_pll_fcvo) {
case 0x12:
case 0x14:
case 0x19:
return 160000000;
case 0x1c:
return 192000000;
case 0x13:
case 0x15:
return 200000000;
case 0x1a:
return 384000000;
case 0x16:
return 400000000;
default:
return 320000000;
}
}
case BCM6338_CPU_ID: case BCM6338_CPU_ID:
/* BCM6338 has a fixed 240 Mhz frequency */ /* BCM6338 has a fixed 240 Mhz frequency */
return 240000000; return 240000000;
...@@ -170,6 +205,9 @@ static unsigned int detect_memory_size(void) ...@@ -170,6 +205,9 @@ static unsigned int detect_memory_size(void)
unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0; unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0;
u32 val; u32 val;
if (BCMCPU_IS_6328())
return bcm_ddr_readl(DDR_CSEND_REG) << 24;
if (BCMCPU_IS_6345()) { if (BCMCPU_IS_6345()) {
val = bcm_sdram_readl(SDRAM_MBASE_REG); val = bcm_sdram_readl(SDRAM_MBASE_REG);
return (val * 8 * 1024 * 1024); return (val * 8 * 1024 * 1024);
...@@ -228,17 +266,26 @@ void __init bcm63xx_cpu_init(void) ...@@ -228,17 +266,26 @@ void __init bcm63xx_cpu_init(void)
bcm63xx_irqs = bcm6345_irqs; bcm63xx_irqs = bcm6345_irqs;
break; break;
case CPU_BMIPS4350: case CPU_BMIPS4350:
switch (read_c0_prid() & 0xf0) { if ((read_c0_prid() & 0xf0) == 0x10) {
case 0x10:
expected_cpu_id = BCM6358_CPU_ID; expected_cpu_id = BCM6358_CPU_ID;
bcm63xx_regs_base = bcm6358_regs_base; bcm63xx_regs_base = bcm6358_regs_base;
bcm63xx_irqs = bcm6358_irqs; bcm63xx_irqs = bcm6358_irqs;
break; } else {
case 0x30: /* all newer chips have the same chip id location */
expected_cpu_id = BCM6368_CPU_ID; u16 chip_id = bcm_readw(BCM_6368_PERF_BASE);
bcm63xx_regs_base = bcm6368_regs_base;
bcm63xx_irqs = bcm6368_irqs; switch (chip_id) {
break; case BCM6328_CPU_ID:
expected_cpu_id = BCM6328_CPU_ID;
bcm63xx_regs_base = bcm6328_regs_base;
bcm63xx_irqs = bcm6328_irqs;
break;
case BCM6368_CPU_ID:
expected_cpu_id = BCM6368_CPU_ID;
bcm63xx_regs_base = bcm6368_regs_base;
bcm63xx_irqs = bcm6368_irqs;
break;
}
} }
break; break;
} }
......
...@@ -31,7 +31,7 @@ static struct resource voip_dsp_resources[] = { ...@@ -31,7 +31,7 @@ static struct resource voip_dsp_resources[] = {
static struct platform_device bcm63xx_voip_dsp_device = { static struct platform_device bcm63xx_voip_dsp_device = {
.name = "bcm63xx-voip-dsp", .name = "bcm63xx-voip-dsp",
.id = 0, .id = -1,
.num_resources = ARRAY_SIZE(voip_dsp_resources), .num_resources = ARRAY_SIZE(voip_dsp_resources),
.resource = voip_dsp_resources, .resource = voip_dsp_resources,
}; };
......
/*
* Broadcom BCM63xx flash registration
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
* Copyright (C) 2008 Florian Fainelli <florian@openwrt.org>
* Copyright (C) 2012 Jonas Gorski <jonas.gorski@gmail.com>
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_flash.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
static struct mtd_partition mtd_partitions[] = {
{
.name = "cfe",
.offset = 0x0,
.size = 0x40000,
}
};
static const char *bcm63xx_part_types[] = { "bcm63xxpart", NULL };
static struct physmap_flash_data flash_data = {
.width = 2,
.parts = mtd_partitions,
.part_probe_types = bcm63xx_part_types,
};
static struct resource mtd_resources[] = {
{
.start = 0, /* filled at runtime */
.end = 0, /* filled at runtime */
.flags = IORESOURCE_MEM,
}
};
static struct platform_device mtd_dev = {
.name = "physmap-flash",
.resource = mtd_resources,
.num_resources = ARRAY_SIZE(mtd_resources),
.dev = {
.platform_data = &flash_data,
},
};
static int __init bcm63xx_detect_flash_type(void)
{
u32 val;
switch (bcm63xx_get_cpu_id()) {
case BCM6328_CPU_ID:
val = bcm_misc_readl(MISC_STRAPBUS_6328_REG);
if (val & STRAPBUS_6328_BOOT_SEL_SERIAL)
return BCM63XX_FLASH_TYPE_SERIAL;
else
return BCM63XX_FLASH_TYPE_NAND;
case BCM6338_CPU_ID:
case BCM6345_CPU_ID:
case BCM6348_CPU_ID:
/* no way to auto detect so assume parallel */
return BCM63XX_FLASH_TYPE_PARALLEL;
case BCM6358_CPU_ID:
val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
if (val & STRAPBUS_6358_BOOT_SEL_PARALLEL)
return BCM63XX_FLASH_TYPE_PARALLEL;
else
return BCM63XX_FLASH_TYPE_SERIAL;
case BCM6368_CPU_ID:
val = bcm_gpio_readl(GPIO_STRAPBUS_REG);
switch (val & STRAPBUS_6368_BOOT_SEL_MASK) {
case STRAPBUS_6368_BOOT_SEL_NAND:
return BCM63XX_FLASH_TYPE_NAND;
case STRAPBUS_6368_BOOT_SEL_SERIAL:
return BCM63XX_FLASH_TYPE_SERIAL;
case STRAPBUS_6368_BOOT_SEL_PARALLEL:
return BCM63XX_FLASH_TYPE_PARALLEL;
}
default:
return -EINVAL;
}
}
int __init bcm63xx_flash_register(void)
{
int flash_type;
u32 val;
flash_type = bcm63xx_detect_flash_type();
switch (flash_type) {
case BCM63XX_FLASH_TYPE_PARALLEL:
/* read base address of boot chip select (0) */
val = bcm_mpi_readl(MPI_CSBASE_REG(0));
val &= MPI_CSBASE_BASE_MASK;
mtd_resources[0].start = val;
mtd_resources[0].end = 0x1FFFFFFF;
return platform_device_register(&mtd_dev);
case BCM63XX_FLASH_TYPE_SERIAL:
pr_warn("unsupported serial flash detected\n");
return -ENODEV;
case BCM63XX_FLASH_TYPE_NAND:
pr_warn("unsupported NAND flash detected\n");
return -ENODEV;
default:
pr_err("flash detection failed for BCM%x: %d\n",
bcm63xx_get_cpu_id(), flash_type);
return -ENODEV;
}
}
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2011 Florian Fainelli <florian@openwrt.org>
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <bcm63xx_cpu.h>
static struct resource rng_resources[] = {
{
.start = -1, /* filled at runtime */
.end = -1, /* filled at runtime */
.flags = IORESOURCE_MEM,
},
};
static struct platform_device bcm63xx_rng_device = {
.name = "bcm63xx-rng",
.id = -1,
.num_resources = ARRAY_SIZE(rng_resources),
.resource = rng_resources,
};
int __init bcm63xx_rng_register(void)
{
if (!BCMCPU_IS_6368())
return -ENODEV;
rng_resources[0].start = bcm63xx_regset_address(RSET_RNG);
rng_resources[0].end = rng_resources[0].start;
rng_resources[0].end += RSET_RNG_SIZE - 1;
return platform_device_register(&bcm63xx_rng_device);
}
arch_initcall(bcm63xx_rng_register);
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2009-2011 Florian Fainelli <florian@openwrt.org>
* Copyright (C) 2010 Tanguy Bouzeloc <tanguy.bouzeloc@efixo.com>
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_spi.h>
#include <bcm63xx_regs.h>
#ifdef BCMCPU_RUNTIME_DETECT
/*
* register offsets
*/
static const unsigned long bcm6338_regs_spi[] = {
__GEN_SPI_REGS_TABLE(6338)
};
static const unsigned long bcm6348_regs_spi[] = {
__GEN_SPI_REGS_TABLE(6348)
};
static const unsigned long bcm6358_regs_spi[] = {
__GEN_SPI_REGS_TABLE(6358)
};
static const unsigned long bcm6368_regs_spi[] = {
__GEN_SPI_REGS_TABLE(6368)
};
const unsigned long *bcm63xx_regs_spi;
EXPORT_SYMBOL(bcm63xx_regs_spi);
static __init void bcm63xx_spi_regs_init(void)
{
if (BCMCPU_IS_6338())
bcm63xx_regs_spi = bcm6338_regs_spi;
if (BCMCPU_IS_6348())
bcm63xx_regs_spi = bcm6348_regs_spi;
if (BCMCPU_IS_6358())
bcm63xx_regs_spi = bcm6358_regs_spi;
if (BCMCPU_IS_6368())
bcm63xx_regs_spi = bcm6368_regs_spi;
}
#else
static __init void bcm63xx_spi_regs_init(void) { }
#endif
static struct resource spi_resources[] = {
{
.start = -1, /* filled at runtime */
.end = -1, /* filled at runtime */
.flags = IORESOURCE_MEM,
},
{
.start = -1, /* filled at runtime */
.flags = IORESOURCE_IRQ,
},
};
static struct bcm63xx_spi_pdata spi_pdata = {
.bus_num = 0,
.num_chipselect = 8,
};
static struct platform_device bcm63xx_spi_device = {
.name = "bcm63xx-spi",
.id = -1,
.num_resources = ARRAY_SIZE(spi_resources),
.resource = spi_resources,
.dev = {
.platform_data = &spi_pdata,
},
};
int __init bcm63xx_spi_register(void)
{
struct clk *periph_clk;
if (BCMCPU_IS_6328() || BCMCPU_IS_6345())
return -ENODEV;
periph_clk = clk_get(NULL, "periph");
if (IS_ERR(periph_clk)) {
pr_err("unable to get periph clock\n");
return -ENODEV;
}
/* Set bus frequency */
spi_pdata.speed_hz = clk_get_rate(periph_clk);
spi_resources[0].start = bcm63xx_regset_address(RSET_SPI);
spi_resources[0].end = spi_resources[0].start;
spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI);
if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1;
spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE;
}
if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
}
bcm63xx_spi_regs_init();
return platform_device_register(&bcm63xx_spi_device);
}
...@@ -21,7 +21,7 @@ static struct resource wdt_resources[] = { ...@@ -21,7 +21,7 @@ static struct resource wdt_resources[] = {
static struct platform_device bcm63xx_wdt_device = { static struct platform_device bcm63xx_wdt_device = {
.name = "bcm63xx-wdt", .name = "bcm63xx-wdt",
.id = 0, .id = -1,
.num_resources = ARRAY_SIZE(wdt_resources), .num_resources = ARRAY_SIZE(wdt_resources),
.resource = wdt_resources, .resource = wdt_resources,
}; };
......
...@@ -27,6 +27,17 @@ static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused; ...@@ -27,6 +27,17 @@ static void __internal_irq_unmask_32(unsigned int irq) __maybe_unused;
static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused; static void __internal_irq_unmask_64(unsigned int irq) __maybe_unused;
#ifndef BCMCPU_RUNTIME_DETECT #ifndef BCMCPU_RUNTIME_DETECT
#ifdef CONFIG_BCM63XX_CPU_6328
#define irq_stat_reg PERF_IRQSTAT_6328_REG
#define irq_mask_reg PERF_IRQMASK_6328_REG
#define irq_bits 64
#define is_ext_irq_cascaded 1
#define ext_irq_start (BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE)
#define ext_irq_end (BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE)
#define ext_irq_count 4
#define ext_irq_cfg_reg1 PERF_EXTIRQ_CFG_REG_6328
#define ext_irq_cfg_reg2 0
#endif
#ifdef CONFIG_BCM63XX_CPU_6338 #ifdef CONFIG_BCM63XX_CPU_6338
#define irq_stat_reg PERF_IRQSTAT_6338_REG #define irq_stat_reg PERF_IRQSTAT_6338_REG
#define irq_mask_reg PERF_IRQMASK_6338_REG #define irq_mask_reg PERF_IRQMASK_6338_REG
...@@ -118,6 +129,16 @@ static void bcm63xx_init_irq(void) ...@@ -118,6 +129,16 @@ static void bcm63xx_init_irq(void)
irq_mask_addr = bcm63xx_regset_address(RSET_PERF); irq_mask_addr = bcm63xx_regset_address(RSET_PERF);
switch (bcm63xx_get_cpu_id()) { switch (bcm63xx_get_cpu_id()) {
case BCM6328_CPU_ID:
irq_stat_addr += PERF_IRQSTAT_6328_REG;
irq_mask_addr += PERF_IRQMASK_6328_REG;
irq_bits = 64;
ext_irq_count = 4;
is_ext_irq_cascaded = 1;
ext_irq_start = BCM_6328_EXT_IRQ0 - IRQ_INTERNAL_BASE;
ext_irq_end = BCM_6328_EXT_IRQ3 - IRQ_INTERNAL_BASE;
ext_irq_cfg_reg1 = PERF_EXTIRQ_CFG_REG_6328;
break;
case BCM6338_CPU_ID: case BCM6338_CPU_ID:
irq_stat_addr += PERF_IRQSTAT_6338_REG; irq_stat_addr += PERF_IRQSTAT_6338_REG;
irq_mask_addr += PERF_IRQMASK_6338_REG; irq_mask_addr += PERF_IRQMASK_6338_REG;
......
...@@ -26,7 +26,9 @@ void __init prom_init(void) ...@@ -26,7 +26,9 @@ void __init prom_init(void)
bcm_wdt_writel(WDT_STOP_2, WDT_CTL_REG); bcm_wdt_writel(WDT_STOP_2, WDT_CTL_REG);
/* disable all hardware blocks clock for now */ /* disable all hardware blocks clock for now */
if (BCMCPU_IS_6338()) if (BCMCPU_IS_6328())
mask = CKCTL_6328_ALL_SAFE_EN;
else if (BCMCPU_IS_6338())
mask = CKCTL_6338_ALL_SAFE_EN; mask = CKCTL_6338_ALL_SAFE_EN;
else if (BCMCPU_IS_6345()) else if (BCMCPU_IS_6345())
mask = CKCTL_6345_ALL_SAFE_EN; mask = CKCTL_6345_ALL_SAFE_EN;
......
...@@ -68,6 +68,9 @@ void bcm63xx_machine_reboot(void) ...@@ -68,6 +68,9 @@ void bcm63xx_machine_reboot(void)
/* mask and clear all external irq */ /* mask and clear all external irq */
switch (bcm63xx_get_cpu_id()) { switch (bcm63xx_get_cpu_id()) {
case BCM6328_CPU_ID:
perf_regs[0] = PERF_EXTIRQ_CFG_REG_6328;
break;
case BCM6338_CPU_ID: case BCM6338_CPU_ID:
perf_regs[0] = PERF_EXTIRQ_CFG_REG_6338; perf_regs[0] = PERF_EXTIRQ_CFG_REG_6338;
break; break;
...@@ -95,9 +98,13 @@ void bcm63xx_machine_reboot(void) ...@@ -95,9 +98,13 @@ void bcm63xx_machine_reboot(void)
bcm6348_a1_reboot(); bcm6348_a1_reboot();
printk(KERN_INFO "triggering watchdog soft-reset...\n"); printk(KERN_INFO "triggering watchdog soft-reset...\n");
reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG); if (BCMCPU_IS_6328()) {
reg |= SYS_PLL_SOFT_RESET; bcm_wdt_writel(1, WDT_SOFTRESET_REG);
bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG); } else {
reg = bcm_perf_readl(PERF_SYS_PLL_CTL_REG);
reg |= SYS_PLL_SOFT_RESET;
bcm_perf_writel(reg, PERF_SYS_PLL_CTL_REG);
}
while (1) while (1)
; ;
} }
......
...@@ -58,8 +58,12 @@ $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE ...@@ -58,8 +58,12 @@ $(obj)/piggy.o: $(obj)/dummy.o $(obj)/vmlinux.bin.z FORCE
# Calculate the load address of the compressed kernel image # Calculate the load address of the compressed kernel image
hostprogs-y := calc_vmlinuz_load_addr hostprogs-y := calc_vmlinuz_load_addr
ifeq ($(CONFIG_MACH_JZ4740),y)
VMLINUZ_LOAD_ADDRESS := 0x80600000
else
VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \ VMLINUZ_LOAD_ADDRESS = $(shell $(obj)/calc_vmlinuz_load_addr \
$(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS)) $(obj)/vmlinux.bin $(VMLINUX_LOAD_ADDRESS))
endif
vmlinuzobjs-y += $(obj)/piggy.o vmlinuzobjs-y += $(obj)/piggy.o
......
...@@ -18,6 +18,11 @@ ...@@ -18,6 +18,11 @@
#define PORT(offset) (CKSEG1ADDR(AR7_REGS_UART0) + (4 * offset)) #define PORT(offset) (CKSEG1ADDR(AR7_REGS_UART0) + (4 * offset))
#endif #endif
#ifdef CONFIG_MACH_JZ4740
#define UART0_BASE 0xB0030000
#define PORT(offset) (UART0_BASE + (4 * offset))
#endif
#ifndef PORT #ifndef PORT
#error please define the serial port address for your own machine #error please define the serial port address for your own machine
#endif #endif
......
...@@ -9,9 +9,25 @@ ...@@ -9,9 +9,25 @@
# Copyright (C) 2005-2009 Cavium Networks # Copyright (C) 2005-2009 Cavium Networks
# #
CFLAGS_octeon-platform.o = -I$(src)/../../../scripts/dtc/libfdt
CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
obj-y += dma-octeon.o flash_setup.o obj-y += dma-octeon.o flash_setup.o
obj-y += octeon-memcpy.o obj-y += octeon-memcpy.o
obj-y += executive/ obj-y += executive/
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
DTS_FILES = octeon_3xxx.dts octeon_68xx.dts
DTB_FILES = $(patsubst %.dts, %.dtb, $(DTS_FILES))
obj-y += $(patsubst %.dts, %.dtb.o, $(DTS_FILES))
$(obj)/%.dtb: $(src)/%.dts FORCE
$(call if_changed_dep,dtc)
# Let's keep the .dtb files around in case we want to look at them.
.SECONDARY: $(addprefix $(obj)/, $(DTB_FILES))
clean-files += $(DTB_FILES) $(patsubst %.dtb, %.dtb.S, $(DTB_FILES))
/***********************license start***************
* Author: Cavium Networks
*
* Contact: support@caviumnetworks.com
* This file is part of the OCTEON SDK
*
* Copyright (c) 2003-2008 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
*
* This file is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* or visit http://www.gnu.org/licenses/.
*
* This file may also be available under a different license from Cavium.
* Contact Cavium Networks for more information
***********************license end**************************************/
/**
* @file
*
* Support library for the hardware Free Pool Allocator.
*
*
*/
#include "cvmx-config.h"
#include "cvmx.h"
#include "cvmx-fpa.h"
#include "cvmx-ipd.h"
/**
* Current state of all the pools. Use access functions
* instead of using it directly.
*/
CVMX_SHARED cvmx_fpa_pool_info_t cvmx_fpa_pool_info[CVMX_FPA_NUM_POOLS];
/**
* Setup a FPA pool to control a new block of memory. The
* buffer pointer must be a physical address.
*
* @pool: Pool to initialize
* 0 <= pool < 8
* @name: Constant character string to name this pool.
* String is not copied.
* @buffer: Pointer to the block of memory to use. This must be
* accessible by all processors and external hardware.
* @block_size: Size for each block controlled by the FPA
* @num_blocks: Number of blocks
*
* Returns 0 on Success,
* -1 on failure
*/
int cvmx_fpa_setup_pool(uint64_t pool, const char *name, void *buffer,
uint64_t block_size, uint64_t num_blocks)
{
char *ptr;
if (!buffer) {
cvmx_dprintf
("ERROR: cvmx_fpa_setup_pool: NULL buffer pointer!\n");
return -1;
}
if (pool >= CVMX_FPA_NUM_POOLS) {
cvmx_dprintf("ERROR: cvmx_fpa_setup_pool: Illegal pool!\n");
return -1;
}
if (block_size < CVMX_FPA_MIN_BLOCK_SIZE) {
cvmx_dprintf
("ERROR: cvmx_fpa_setup_pool: Block size too small.\n");
return -1;
}
if (((unsigned long)buffer & (CVMX_FPA_ALIGNMENT - 1)) != 0) {
cvmx_dprintf
("ERROR: cvmx_fpa_setup_pool: Buffer not aligned properly.\n");
return -1;
}
cvmx_fpa_pool_info[pool].name = name;
cvmx_fpa_pool_info[pool].size = block_size;
cvmx_fpa_pool_info[pool].starting_element_count = num_blocks;
cvmx_fpa_pool_info[pool].base = buffer;
ptr = (char *)buffer;
while (num_blocks--) {
cvmx_fpa_free(ptr, pool, 0);
ptr += block_size;
}
return 0;
}
/**
* Shutdown a Memory pool and validate that it had all of
* the buffers originally placed in it.
*
* @pool: Pool to shutdown
* Returns Zero on success
* - Positive is count of missing buffers
* - Negative is too many buffers or corrupted pointers
*/
uint64_t cvmx_fpa_shutdown_pool(uint64_t pool)
{
uint64_t errors = 0;
uint64_t count = 0;
uint64_t base = cvmx_ptr_to_phys(cvmx_fpa_pool_info[pool].base);
uint64_t finish =
base +
cvmx_fpa_pool_info[pool].size *
cvmx_fpa_pool_info[pool].starting_element_count;
void *ptr;
uint64_t address;
count = 0;
do {
ptr = cvmx_fpa_alloc(pool);
if (ptr)
address = cvmx_ptr_to_phys(ptr);
else
address = 0;
if (address) {
if ((address >= base) && (address < finish) &&
(((address -
base) % cvmx_fpa_pool_info[pool].size) == 0)) {
count++;
} else {
cvmx_dprintf
("ERROR: cvmx_fpa_shutdown_pool: Illegal address 0x%llx in pool %s(%d)\n",
(unsigned long long)address,
cvmx_fpa_pool_info[pool].name, (int)pool);
errors++;
}
}
} while (address);
#ifdef CVMX_ENABLE_PKO_FUNCTIONS
if (pool == 0)
cvmx_ipd_free_ptr();
#endif
if (errors) {
cvmx_dprintf
("ERROR: cvmx_fpa_shutdown_pool: Pool %s(%d) started at 0x%llx, ended at 0x%llx, with a step of 0x%llx\n",
cvmx_fpa_pool_info[pool].name, (int)pool,
(unsigned long long)base, (unsigned long long)finish,
(unsigned long long)cvmx_fpa_pool_info[pool].size);
return -errors;
} else
return 0;
}
uint64_t cvmx_fpa_get_block_size(uint64_t pool)
{
switch (pool) {
case 0:
return CVMX_FPA_POOL_0_SIZE;
case 1:
return CVMX_FPA_POOL_1_SIZE;
case 2:
return CVMX_FPA_POOL_2_SIZE;
case 3:
return CVMX_FPA_POOL_3_SIZE;
case 4:
return CVMX_FPA_POOL_4_SIZE;
case 5:
return CVMX_FPA_POOL_5_SIZE;
case 6:
return CVMX_FPA_POOL_6_SIZE;
case 7:
return CVMX_FPA_POOL_7_SIZE;
default:
return 0;
}
}
/***********************license start***************
* Author: Cavium Networks
*
* Contact: support@caviumnetworks.com
* This file is part of the OCTEON SDK
*
* Copyright (c) 2003-2008 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
*
* This file is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* or visit http://www.gnu.org/licenses/.
*
* This file may also be available under a different license from Cavium.
* Contact Cavium Networks for more information
***********************license end**************************************/
/**
* @file
*
* Helper functions for FPA setup.
*
*/
#include "executive-config.h"
#include "cvmx-config.h"
#include "cvmx.h"
#include "cvmx-bootmem.h"
#include "cvmx-fpa.h"
#include "cvmx-helper-fpa.h"
/**
* Allocate memory for and initialize a single FPA pool.
*
* @pool: Pool to initialize
* @buffer_size: Size of buffers to allocate in bytes
* @buffers: Number of buffers to put in the pool. Zero is allowed
* @name: String name of the pool for debugging purposes
* Returns Zero on success, non-zero on failure
*/
static int __cvmx_helper_initialize_fpa_pool(int pool, uint64_t buffer_size,
uint64_t buffers, const char *name)
{
uint64_t current_num;
void *memory;
uint64_t align = CVMX_CACHE_LINE_SIZE;
/*
* Align the allocation so that power of 2 size buffers are
* naturally aligned.
*/
while (align < buffer_size)
align = align << 1;
if (buffers == 0)
return 0;
current_num = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(pool));
if (current_num) {
cvmx_dprintf("Fpa pool %d(%s) already has %llu buffers. "
"Skipping setup.\n",
pool, name, (unsigned long long)current_num);
return 0;
}
memory = cvmx_bootmem_alloc(buffer_size * buffers, align);
if (memory == NULL) {
cvmx_dprintf("Out of memory initializing fpa pool %d(%s).\n",
pool, name);
return -1;
}
cvmx_fpa_setup_pool(pool, name, memory, buffer_size, buffers);
return 0;
}
/**
* Allocate memory and initialize the FPA pools using memory
* from cvmx-bootmem. Specifying zero for the number of
* buffers will cause that FPA pool to not be setup. This is
* useful if you aren't using some of the hardware and want
* to save memory. Use cvmx_helper_initialize_fpa instead of
* this function directly.
*
* @pip_pool: Should always be CVMX_FPA_PACKET_POOL
* @pip_size: Should always be CVMX_FPA_PACKET_POOL_SIZE
* @pip_buffers:
* Number of packet buffers.
* @wqe_pool: Should always be CVMX_FPA_WQE_POOL
* @wqe_size: Should always be CVMX_FPA_WQE_POOL_SIZE
* @wqe_entries:
* Number of work queue entries
* @pko_pool: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL
* @pko_size: Should always be CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE
* @pko_buffers:
* PKO Command buffers. You should at minimum have two per
* each PKO queue.
* @tim_pool: Should always be CVMX_FPA_TIMER_POOL
* @tim_size: Should always be CVMX_FPA_TIMER_POOL_SIZE
* @tim_buffers:
* TIM ring buffer command queues. At least two per timer bucket
* is recommened.
* @dfa_pool: Should always be CVMX_FPA_DFA_POOL
* @dfa_size: Should always be CVMX_FPA_DFA_POOL_SIZE
* @dfa_buffers:
* DFA command buffer. A relatively small (32 for example)
* number should work.
* Returns Zero on success, non-zero if out of memory
*/
static int __cvmx_helper_initialize_fpa(int pip_pool, int pip_size,
int pip_buffers, int wqe_pool,
int wqe_size, int wqe_entries,
int pko_pool, int pko_size,
int pko_buffers, int tim_pool,
int tim_size, int tim_buffers,
int dfa_pool, int dfa_size,
int dfa_buffers)
{
int status;
cvmx_fpa_enable();
if ((pip_buffers > 0) && (pip_buffers <= 64))
cvmx_dprintf
("Warning: %d packet buffers may not be enough for hardware"
" prefetch. 65 or more is recommended.\n", pip_buffers);
if (pip_pool >= 0) {
status =
__cvmx_helper_initialize_fpa_pool(pip_pool, pip_size,
pip_buffers,
"Packet Buffers");
if (status)
return status;
}
if (wqe_pool >= 0) {
status =
__cvmx_helper_initialize_fpa_pool(wqe_pool, wqe_size,
wqe_entries,
"Work Queue Entries");
if (status)
return status;
}
if (pko_pool >= 0) {
status =
__cvmx_helper_initialize_fpa_pool(pko_pool, pko_size,
pko_buffers,
"PKO Command Buffers");
if (status)
return status;
}
if (tim_pool >= 0) {
status =
__cvmx_helper_initialize_fpa_pool(tim_pool, tim_size,
tim_buffers,
"TIM Command Buffers");
if (status)
return status;
}
if (dfa_pool >= 0) {
status =
__cvmx_helper_initialize_fpa_pool(dfa_pool, dfa_size,
dfa_buffers,
"DFA Command Buffers");
if (status)
return status;
}
return 0;
}
/**
* Allocate memory and initialize the FPA pools using memory
* from cvmx-bootmem. Sizes of each element in the pools is
* controlled by the cvmx-config.h header file. Specifying
* zero for any parameter will cause that FPA pool to not be
* setup. This is useful if you aren't using some of the
* hardware and want to save memory.
*
* @packet_buffers:
* Number of packet buffers to allocate
* @work_queue_entries:
* Number of work queue entries
* @pko_buffers:
* PKO Command buffers. You should at minimum have two per
* each PKO queue.
* @tim_buffers:
* TIM ring buffer command queues. At least two per timer bucket
* is recommened.
* @dfa_buffers:
* DFA command buffer. A relatively small (32 for example)
* number should work.
* Returns Zero on success, non-zero if out of memory
*/
int cvmx_helper_initialize_fpa(int packet_buffers, int work_queue_entries,
int pko_buffers, int tim_buffers,
int dfa_buffers)
{
#ifndef CVMX_FPA_PACKET_POOL
#define CVMX_FPA_PACKET_POOL -1
#define CVMX_FPA_PACKET_POOL_SIZE 0
#endif
#ifndef CVMX_FPA_WQE_POOL
#define CVMX_FPA_WQE_POOL -1
#define CVMX_FPA_WQE_POOL_SIZE 0
#endif
#ifndef CVMX_FPA_OUTPUT_BUFFER_POOL
#define CVMX_FPA_OUTPUT_BUFFER_POOL -1
#define CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE 0
#endif
#ifndef CVMX_FPA_TIMER_POOL
#define CVMX_FPA_TIMER_POOL -1
#define CVMX_FPA_TIMER_POOL_SIZE 0
#endif
#ifndef CVMX_FPA_DFA_POOL
#define CVMX_FPA_DFA_POOL -1
#define CVMX_FPA_DFA_POOL_SIZE 0
#endif
return __cvmx_helper_initialize_fpa(CVMX_FPA_PACKET_POOL,
CVMX_FPA_PACKET_POOL_SIZE,
packet_buffers, CVMX_FPA_WQE_POOL,
CVMX_FPA_WQE_POOL_SIZE,
work_queue_entries,
CVMX_FPA_OUTPUT_BUFFER_POOL,
CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE,
pko_buffers, CVMX_FPA_TIMER_POOL,
CVMX_FPA_TIMER_POOL_SIZE,
tim_buffers, CVMX_FPA_DFA_POOL,
CVMX_FPA_DFA_POOL_SIZE,
dfa_buffers);
}
...@@ -3,14 +3,17 @@ ...@@ -3,14 +3,17 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
* *
* Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks * Copyright (C) 2004-2012 Cavium, Inc.
*/ */
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <linux/slab.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/of.h>
#include <asm/octeon/octeon.h> #include <asm/octeon/octeon.h>
...@@ -42,9 +45,9 @@ struct octeon_core_chip_data { ...@@ -42,9 +45,9 @@ struct octeon_core_chip_data {
static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES]; static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES];
static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit, static void octeon_irq_set_ciu_mapping(int irq, int line, int bit,
struct irq_chip *chip, struct irq_chip *chip,
irq_flow_handler_t handler) irq_flow_handler_t handler)
{ {
union octeon_ciu_chip_data cd; union octeon_ciu_chip_data cd;
...@@ -505,6 +508,85 @@ static void octeon_irq_ciu_enable_all_v2(struct irq_data *data) ...@@ -505,6 +508,85 @@ static void octeon_irq_ciu_enable_all_v2(struct irq_data *data)
} }
} }
static void octeon_irq_gpio_setup(struct irq_data *data)
{
union cvmx_gpio_bit_cfgx cfg;
union octeon_ciu_chip_data cd;
u32 t = irqd_get_trigger_type(data);
cd.p = irq_data_get_irq_chip_data(data);
cfg.u64 = 0;
cfg.s.int_en = 1;
cfg.s.int_type = (t & IRQ_TYPE_EDGE_BOTH) != 0;
cfg.s.rx_xor = (t & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) != 0;
/* 140 nS glitch filter*/
cfg.s.fil_cnt = 7;
cfg.s.fil_sel = 3;
cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), cfg.u64);
}
static void octeon_irq_ciu_enable_gpio_v2(struct irq_data *data)
{
octeon_irq_gpio_setup(data);
octeon_irq_ciu_enable_v2(data);
}
static void octeon_irq_ciu_enable_gpio(struct irq_data *data)
{
octeon_irq_gpio_setup(data);
octeon_irq_ciu_enable(data);
}
static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t)
{
irqd_set_trigger_type(data, t);
octeon_irq_gpio_setup(data);
return IRQ_SET_MASK_OK;
}
static void octeon_irq_ciu_disable_gpio_v2(struct irq_data *data)
{
union octeon_ciu_chip_data cd;
cd.p = irq_data_get_irq_chip_data(data);
cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0);
octeon_irq_ciu_disable_all_v2(data);
}
static void octeon_irq_ciu_disable_gpio(struct irq_data *data)
{
union octeon_ciu_chip_data cd;
cd.p = irq_data_get_irq_chip_data(data);
cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0);
octeon_irq_ciu_disable_all(data);
}
static void octeon_irq_ciu_gpio_ack(struct irq_data *data)
{
union octeon_ciu_chip_data cd;
u64 mask;
cd.p = irq_data_get_irq_chip_data(data);
mask = 1ull << (cd.s.bit - 16);
cvmx_write_csr(CVMX_GPIO_INT_CLR, mask);
}
static void octeon_irq_handle_gpio(unsigned int irq, struct irq_desc *desc)
{
if (irqd_get_trigger_type(irq_desc_get_irq_data(desc)) & IRQ_TYPE_EDGE_BOTH)
handle_edge_irq(irq, desc);
else
handle_level_irq(irq, desc);
}
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static void octeon_irq_cpu_offline_ciu(struct irq_data *data) static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
...@@ -650,18 +732,6 @@ static struct irq_chip octeon_irq_chip_ciu_v2 = { ...@@ -650,18 +732,6 @@ static struct irq_chip octeon_irq_chip_ciu_v2 = {
.name = "CIU", .name = "CIU",
.irq_enable = octeon_irq_ciu_enable_v2, .irq_enable = octeon_irq_ciu_enable_v2,
.irq_disable = octeon_irq_ciu_disable_all_v2, .irq_disable = octeon_irq_ciu_disable_all_v2,
.irq_mask = octeon_irq_ciu_disable_local_v2,
.irq_unmask = octeon_irq_ciu_enable_v2,
#ifdef CONFIG_SMP
.irq_set_affinity = octeon_irq_ciu_set_affinity_v2,
.irq_cpu_offline = octeon_irq_cpu_offline_ciu,
#endif
};
static struct irq_chip octeon_irq_chip_ciu_edge_v2 = {
.name = "CIU-E",
.irq_enable = octeon_irq_ciu_enable_v2,
.irq_disable = octeon_irq_ciu_disable_all_v2,
.irq_ack = octeon_irq_ciu_ack, .irq_ack = octeon_irq_ciu_ack,
.irq_mask = octeon_irq_ciu_disable_local_v2, .irq_mask = octeon_irq_ciu_disable_local_v2,
.irq_unmask = octeon_irq_ciu_enable_v2, .irq_unmask = octeon_irq_ciu_enable_v2,
...@@ -675,19 +745,8 @@ static struct irq_chip octeon_irq_chip_ciu = { ...@@ -675,19 +745,8 @@ static struct irq_chip octeon_irq_chip_ciu = {
.name = "CIU", .name = "CIU",
.irq_enable = octeon_irq_ciu_enable, .irq_enable = octeon_irq_ciu_enable,
.irq_disable = octeon_irq_ciu_disable_all, .irq_disable = octeon_irq_ciu_disable_all,
.irq_mask = octeon_irq_dummy_mask,
#ifdef CONFIG_SMP
.irq_set_affinity = octeon_irq_ciu_set_affinity,
.irq_cpu_offline = octeon_irq_cpu_offline_ciu,
#endif
};
static struct irq_chip octeon_irq_chip_ciu_edge = {
.name = "CIU-E",
.irq_enable = octeon_irq_ciu_enable,
.irq_disable = octeon_irq_ciu_disable_all,
.irq_mask = octeon_irq_dummy_mask,
.irq_ack = octeon_irq_ciu_ack, .irq_ack = octeon_irq_ciu_ack,
.irq_mask = octeon_irq_dummy_mask,
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
.irq_set_affinity = octeon_irq_ciu_set_affinity, .irq_set_affinity = octeon_irq_ciu_set_affinity,
.irq_cpu_offline = octeon_irq_cpu_offline_ciu, .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
...@@ -717,6 +776,33 @@ static struct irq_chip octeon_irq_chip_ciu_mbox = { ...@@ -717,6 +776,33 @@ static struct irq_chip octeon_irq_chip_ciu_mbox = {
.flags = IRQCHIP_ONOFFLINE_ENABLED, .flags = IRQCHIP_ONOFFLINE_ENABLED,
}; };
static struct irq_chip octeon_irq_chip_ciu_gpio_v2 = {
.name = "CIU-GPIO",
.irq_enable = octeon_irq_ciu_enable_gpio_v2,
.irq_disable = octeon_irq_ciu_disable_gpio_v2,
.irq_ack = octeon_irq_ciu_gpio_ack,
.irq_mask = octeon_irq_ciu_disable_local_v2,
.irq_unmask = octeon_irq_ciu_enable_v2,
.irq_set_type = octeon_irq_ciu_gpio_set_type,
#ifdef CONFIG_SMP
.irq_set_affinity = octeon_irq_ciu_set_affinity_v2,
#endif
.flags = IRQCHIP_SET_TYPE_MASKED,
};
static struct irq_chip octeon_irq_chip_ciu_gpio = {
.name = "CIU-GPIO",
.irq_enable = octeon_irq_ciu_enable_gpio,
.irq_disable = octeon_irq_ciu_disable_gpio,
.irq_mask = octeon_irq_dummy_mask,
.irq_ack = octeon_irq_ciu_gpio_ack,
.irq_set_type = octeon_irq_ciu_gpio_set_type,
#ifdef CONFIG_SMP
.irq_set_affinity = octeon_irq_ciu_set_affinity,
#endif
.flags = IRQCHIP_SET_TYPE_MASKED,
};
/* /*
* Watchdog interrupts are special. They are associated with a single * Watchdog interrupts are special. They are associated with a single
* core, so we hardwire the affinity to that core. * core, so we hardwire the affinity to that core.
...@@ -764,6 +850,178 @@ static struct irq_chip octeon_irq_chip_ciu_wd = { ...@@ -764,6 +850,178 @@ static struct irq_chip octeon_irq_chip_ciu_wd = {
.irq_mask = octeon_irq_dummy_mask, .irq_mask = octeon_irq_dummy_mask,
}; };
static bool octeon_irq_ciu_is_edge(unsigned int line, unsigned int bit)
{
bool edge = false;
if (line == 0)
switch (bit) {
case 48 ... 49: /* GMX DRP */
case 50: /* IPD_DRP */
case 52 ... 55: /* Timers */
case 58: /* MPI */
edge = true;
break;
default:
break;
}
else /* line == 1 */
switch (bit) {
case 47: /* PTP */
edge = true;
break;
default:
break;
}
return edge;
}
struct octeon_irq_gpio_domain_data {
unsigned int base_hwirq;
};
static int octeon_irq_gpio_xlat(struct irq_domain *d,
struct device_node *node,
const u32 *intspec,
unsigned int intsize,
unsigned long *out_hwirq,
unsigned int *out_type)
{
unsigned int type;
unsigned int pin;
unsigned int trigger;
struct octeon_irq_gpio_domain_data *gpiod;
if (d->of_node != node)
return -EINVAL;
if (intsize < 2)
return -EINVAL;
pin = intspec[0];
if (pin >= 16)
return -EINVAL;
trigger = intspec[1];
switch (trigger) {
case 1:
type = IRQ_TYPE_EDGE_RISING;
break;
case 2:
type = IRQ_TYPE_EDGE_FALLING;
break;
case 4:
type = IRQ_TYPE_LEVEL_HIGH;
break;
case 8:
type = IRQ_TYPE_LEVEL_LOW;
break;
default:
pr_err("Error: (%s) Invalid irq trigger specification: %x\n",
node->name,
trigger);
type = IRQ_TYPE_LEVEL_LOW;
break;
}
*out_type = type;
gpiod = d->host_data;
*out_hwirq = gpiod->base_hwirq + pin;
return 0;
}
static int octeon_irq_ciu_xlat(struct irq_domain *d,
struct device_node *node,
const u32 *intspec,
unsigned int intsize,
unsigned long *out_hwirq,
unsigned int *out_type)
{
unsigned int ciu, bit;
ciu = intspec[0];
bit = intspec[1];
if (ciu > 1 || bit > 63)
return -EINVAL;
/* These are the GPIO lines */
if (ciu == 0 && bit >= 16 && bit < 32)
return -EINVAL;
*out_hwirq = (ciu << 6) | bit;
*out_type = 0;
return 0;
}
static struct irq_chip *octeon_irq_ciu_chip;
static struct irq_chip *octeon_irq_gpio_chip;
static bool octeon_irq_virq_in_range(unsigned int virq)
{
/* We cannot let it overflow the mapping array. */
if (virq < (1ul << 8 * sizeof(octeon_irq_ciu_to_irq[0][0])))
return true;
WARN_ONCE(true, "virq out of range %u.\n", virq);
return false;
}
static int octeon_irq_ciu_map(struct irq_domain *d,
unsigned int virq, irq_hw_number_t hw)
{
unsigned int line = hw >> 6;
unsigned int bit = hw & 63;
if (!octeon_irq_virq_in_range(virq))
return -EINVAL;
if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
return -EINVAL;
if (octeon_irq_ciu_is_edge(line, bit))
octeon_irq_set_ciu_mapping(virq, line, bit,
octeon_irq_ciu_chip,
handle_edge_irq);
else
octeon_irq_set_ciu_mapping(virq, line, bit,
octeon_irq_ciu_chip,
handle_level_irq);
return 0;
}
static int octeon_irq_gpio_map(struct irq_domain *d,
unsigned int virq, irq_hw_number_t hw)
{
unsigned int line = hw >> 6;
unsigned int bit = hw & 63;
if (!octeon_irq_virq_in_range(virq))
return -EINVAL;
if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
return -EINVAL;
octeon_irq_set_ciu_mapping(virq, line, bit,
octeon_irq_gpio_chip,
octeon_irq_handle_gpio);
return 0;
}
static struct irq_domain_ops octeon_irq_domain_ciu_ops = {
.map = octeon_irq_ciu_map,
.xlate = octeon_irq_ciu_xlat,
};
static struct irq_domain_ops octeon_irq_domain_gpio_ops = {
.map = octeon_irq_gpio_map,
.xlate = octeon_irq_gpio_xlat,
};
static void octeon_irq_ip2_v1(void) static void octeon_irq_ip2_v1(void)
{ {
const unsigned long core_id = cvmx_get_core_num(); const unsigned long core_id = cvmx_get_core_num();
...@@ -887,9 +1145,10 @@ static void __init octeon_irq_init_ciu(void) ...@@ -887,9 +1145,10 @@ static void __init octeon_irq_init_ciu(void)
{ {
unsigned int i; unsigned int i;
struct irq_chip *chip; struct irq_chip *chip;
struct irq_chip *chip_edge;
struct irq_chip *chip_mbox; struct irq_chip *chip_mbox;
struct irq_chip *chip_wd; struct irq_chip *chip_wd;
struct device_node *gpio_node;
struct device_node *ciu_node;
octeon_irq_init_ciu_percpu(); octeon_irq_init_ciu_percpu();
octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu; octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
...@@ -901,17 +1160,18 @@ static void __init octeon_irq_init_ciu(void) ...@@ -901,17 +1160,18 @@ static void __init octeon_irq_init_ciu(void)
octeon_irq_ip2 = octeon_irq_ip2_v2; octeon_irq_ip2 = octeon_irq_ip2_v2;
octeon_irq_ip3 = octeon_irq_ip3_v2; octeon_irq_ip3 = octeon_irq_ip3_v2;
chip = &octeon_irq_chip_ciu_v2; chip = &octeon_irq_chip_ciu_v2;
chip_edge = &octeon_irq_chip_ciu_edge_v2;
chip_mbox = &octeon_irq_chip_ciu_mbox_v2; chip_mbox = &octeon_irq_chip_ciu_mbox_v2;
chip_wd = &octeon_irq_chip_ciu_wd_v2; chip_wd = &octeon_irq_chip_ciu_wd_v2;
octeon_irq_gpio_chip = &octeon_irq_chip_ciu_gpio_v2;
} else { } else {
octeon_irq_ip2 = octeon_irq_ip2_v1; octeon_irq_ip2 = octeon_irq_ip2_v1;
octeon_irq_ip3 = octeon_irq_ip3_v1; octeon_irq_ip3 = octeon_irq_ip3_v1;
chip = &octeon_irq_chip_ciu; chip = &octeon_irq_chip_ciu;
chip_edge = &octeon_irq_chip_ciu_edge;
chip_mbox = &octeon_irq_chip_ciu_mbox; chip_mbox = &octeon_irq_chip_ciu_mbox;
chip_wd = &octeon_irq_chip_ciu_wd; chip_wd = &octeon_irq_chip_ciu_wd;
octeon_irq_gpio_chip = &octeon_irq_chip_ciu_gpio;
} }
octeon_irq_ciu_chip = chip;
octeon_irq_ip4 = octeon_irq_ip4_mask; octeon_irq_ip4 = octeon_irq_ip4_mask;
/* Mips internal */ /* Mips internal */
...@@ -920,80 +1180,49 @@ static void __init octeon_irq_init_ciu(void) ...@@ -920,80 +1180,49 @@ static void __init octeon_irq_init_ciu(void)
/* CIU_0 */ /* CIU_0 */
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq); octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
for (i = 0; i < 16; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35, chip, handle_level_irq);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq); octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq); octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47, chip, handle_level_irq);
for (i = 0; i < 2; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48, chip_edge, handle_edge_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50, chip_edge, handle_edge_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51, chip_edge, handle_edge_irq);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip_edge, handle_edge_irq); octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
/* CIU_1 */ /* CIU_1 */
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq); octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq); octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19, chip, handle_level_irq); gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20, chip, handle_level_irq); if (gpio_node) {
octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21, chip, handle_level_irq); struct octeon_irq_gpio_domain_data *gpiod;
octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23, chip, handle_level_irq); gpiod = kzalloc(sizeof(*gpiod), GFP_KERNEL);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24, chip, handle_level_irq); if (gpiod) {
octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25, chip, handle_level_irq); /* gpio domain host_data is the base hwirq number. */
octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26, chip, handle_level_irq); gpiod->base_hwirq = 16;
octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27, chip, handle_level_irq); irq_domain_add_linear(gpio_node, 16, &octeon_irq_domain_gpio_ops, gpiod);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28, chip, handle_level_irq); of_node_put(gpio_node);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29, chip, handle_level_irq); } else
octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30, chip, handle_level_irq); pr_warn("Cannot allocate memory for GPIO irq_domain.\n");
octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31, chip, handle_level_irq); } else
octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32, chip, handle_level_irq); pr_warn("Cannot find device node for cavium,octeon-3860-gpio.\n");
octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34, chip, handle_level_irq); ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu");
octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35, chip, handle_level_irq); if (ciu_node) {
irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36, chip, handle_level_irq); of_node_put(ciu_node);
} else
octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46, chip, handle_level_irq); pr_warn("Cannot find device node for cavium,octeon-3860-ciu.\n");
octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47, chip_edge, handle_edge_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56, chip, handle_level_irq);
octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63, chip, handle_level_irq);
/* Enable the CIU lines */ /* Enable the CIU lines */
set_c0_status(STATUSF_IP3 | STATUSF_IP2); set_c0_status(STATUSF_IP3 | STATUSF_IP2);
......
...@@ -163,6 +163,14 @@ ...@@ -163,6 +163,14 @@
.set noreorder .set noreorder
.set noat .set noat
/*
* t7 is used as a flag to note inatomic mode.
*/
LEAF(__copy_user_inatomic)
b __copy_user_common
li t7, 1
END(__copy_user_inatomic)
/* /*
* A combined memcpy/__copy_user * A combined memcpy/__copy_user
* __copy_user sets len to 0 for success; else to an upper bound of * __copy_user sets len to 0 for success; else to an upper bound of
...@@ -174,6 +182,8 @@ LEAF(memcpy) /* a0=dst a1=src a2=len */ ...@@ -174,6 +182,8 @@ LEAF(memcpy) /* a0=dst a1=src a2=len */
move v0, dst /* return value */ move v0, dst /* return value */
__memcpy: __memcpy:
FEXPORT(__copy_user) FEXPORT(__copy_user)
li t7, 0 /* not inatomic */
__copy_user_common:
/* /*
* Note: dst & src may be unaligned, len may be 0 * Note: dst & src may be unaligned, len may be 0
* Temps * Temps
...@@ -412,7 +422,6 @@ l_exc_copy: ...@@ -412,7 +422,6 @@ l_exc_copy:
* Assumes src < THREAD_BUADDR($28) * Assumes src < THREAD_BUADDR($28)
*/ */
LOAD t0, TI_TASK($28) LOAD t0, TI_TASK($28)
nop
LOAD t0, THREAD_BUADDR(t0) LOAD t0, THREAD_BUADDR(t0)
1: 1:
EXC( lb t1, 0(src), l_exc) EXC( lb t1, 0(src), l_exc)
...@@ -422,10 +431,9 @@ EXC( lb t1, 0(src), l_exc) ...@@ -422,10 +431,9 @@ EXC( lb t1, 0(src), l_exc)
ADD dst, dst, 1 ADD dst, dst, 1
l_exc: l_exc:
LOAD t0, TI_TASK($28) LOAD t0, TI_TASK($28)
nop
LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address
nop
SUB len, AT, t0 # len number of uncopied bytes SUB len, AT, t0 # len number of uncopied bytes
bnez t7, 2f /* Skip the zeroing out part if inatomic */
/* /*
* Here's where we rely on src and dst being incremented in tandem, * Here's where we rely on src and dst being incremented in tandem,
* See (3) above. * See (3) above.
...@@ -443,7 +451,7 @@ l_exc: ...@@ -443,7 +451,7 @@ l_exc:
ADD dst, dst, 1 ADD dst, dst, 1
bnez src, 1b bnez src, 1b
SUB src, src, 1 SUB src, src, 1
jr ra 2: jr ra
nop nop
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
* *
* Copyright (C) 2004-2010 Cavium Networks * Copyright (C) 2004-2011 Cavium Networks
* Copyright (C) 2008 Wind River Systems * Copyright (C) 2008 Wind River Systems
*/ */
...@@ -13,10 +13,16 @@ ...@@ -13,10 +13,16 @@
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of_platform.h>
#include <linux/of_fdt.h>
#include <linux/libfdt.h>
#include <asm/octeon/octeon.h> #include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-rnm-defs.h> #include <asm/octeon/cvmx-rnm-defs.h>
#include <asm/octeon/cvmx-helper.h>
#include <asm/octeon/cvmx-helper-board.h>
static struct octeon_cf_data octeon_cf_data; static struct octeon_cf_data octeon_cf_data;
...@@ -162,182 +168,6 @@ static int __init octeon_rng_device_init(void) ...@@ -162,182 +168,6 @@ static int __init octeon_rng_device_init(void)
} }
device_initcall(octeon_rng_device_init); device_initcall(octeon_rng_device_init);
static struct i2c_board_info __initdata octeon_i2c_devices[] = {
{
I2C_BOARD_INFO("ds1337", 0x68),
},
};
static int __init octeon_i2c_devices_init(void)
{
return i2c_register_board_info(0, octeon_i2c_devices,
ARRAY_SIZE(octeon_i2c_devices));
}
arch_initcall(octeon_i2c_devices_init);
#define OCTEON_I2C_IO_BASE 0x1180000001000ull
#define OCTEON_I2C_IO_UNIT_OFFSET 0x200
static struct octeon_i2c_data octeon_i2c_data[2];
static int __init octeon_i2c_device_init(void)
{
struct platform_device *pd;
int ret = 0;
int port, num_ports;
struct resource i2c_resources[] = {
{
.flags = IORESOURCE_MEM,
}, {
.flags = IORESOURCE_IRQ,
}
};
if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
num_ports = 2;
else
num_ports = 1;
for (port = 0; port < num_ports; port++) {
octeon_i2c_data[port].sys_freq = octeon_get_io_clock_rate();
/*FIXME: should be examined. At the moment is set for 100Khz */
octeon_i2c_data[port].i2c_freq = 100000;
pd = platform_device_alloc("i2c-octeon", port);
if (!pd) {
ret = -ENOMEM;
goto out;
}
pd->dev.platform_data = octeon_i2c_data + port;
i2c_resources[0].start =
OCTEON_I2C_IO_BASE + (port * OCTEON_I2C_IO_UNIT_OFFSET);
i2c_resources[0].end = i2c_resources[0].start + 0x1f;
switch (port) {
case 0:
i2c_resources[1].start = OCTEON_IRQ_TWSI;
i2c_resources[1].end = OCTEON_IRQ_TWSI;
break;
case 1:
i2c_resources[1].start = OCTEON_IRQ_TWSI2;
i2c_resources[1].end = OCTEON_IRQ_TWSI2;
break;
default:
BUG();
}
ret = platform_device_add_resources(pd,
i2c_resources,
ARRAY_SIZE(i2c_resources));
if (ret)
goto fail;
ret = platform_device_add(pd);
if (ret)
goto fail;
}
return ret;
fail:
platform_device_put(pd);
out:
return ret;
}
device_initcall(octeon_i2c_device_init);
/* Octeon SMI/MDIO interface. */
static int __init octeon_mdiobus_device_init(void)
{
struct platform_device *pd;
int ret = 0;
if (octeon_is_simulation())
return 0; /* No mdio in the simulator. */
/* The bus number is the platform_device id. */
pd = platform_device_alloc("mdio-octeon", 0);
if (!pd) {
ret = -ENOMEM;
goto out;
}
ret = platform_device_add(pd);
if (ret)
goto fail;
return ret;
fail:
platform_device_put(pd);
out:
return ret;
}
device_initcall(octeon_mdiobus_device_init);
/* Octeon mgmt port Ethernet interface. */
static int __init octeon_mgmt_device_init(void)
{
struct platform_device *pd;
int ret = 0;
int port, num_ports;
struct resource mgmt_port_resource = {
.flags = IORESOURCE_IRQ,
.start = -1,
.end = -1
};
if (!OCTEON_IS_MODEL(OCTEON_CN56XX) && !OCTEON_IS_MODEL(OCTEON_CN52XX))
return 0;
if (OCTEON_IS_MODEL(OCTEON_CN56XX))
num_ports = 1;
else
num_ports = 2;
for (port = 0; port < num_ports; port++) {
pd = platform_device_alloc("octeon_mgmt", port);
if (!pd) {
ret = -ENOMEM;
goto out;
}
/* No DMA restrictions */
pd->dev.coherent_dma_mask = DMA_BIT_MASK(64);
pd->dev.dma_mask = &pd->dev.coherent_dma_mask;
switch (port) {
case 0:
mgmt_port_resource.start = OCTEON_IRQ_MII0;
break;
case 1:
mgmt_port_resource.start = OCTEON_IRQ_MII1;
break;
default:
BUG();
}
mgmt_port_resource.end = mgmt_port_resource.start;
ret = platform_device_add_resources(pd, &mgmt_port_resource, 1);
if (ret)
goto fail;
ret = platform_device_add(pd);
if (ret)
goto fail;
}
return ret;
fail:
platform_device_put(pd);
out:
return ret;
}
device_initcall(octeon_mgmt_device_init);
#ifdef CONFIG_USB #ifdef CONFIG_USB
static int __init octeon_ehci_device_init(void) static int __init octeon_ehci_device_init(void)
...@@ -440,6 +270,521 @@ device_initcall(octeon_ohci_device_init); ...@@ -440,6 +270,521 @@ device_initcall(octeon_ohci_device_init);
#endif /* CONFIG_USB */ #endif /* CONFIG_USB */
static struct of_device_id __initdata octeon_ids[] = {
{ .compatible = "simple-bus", },
{ .compatible = "cavium,octeon-6335-uctl", },
{ .compatible = "cavium,octeon-3860-bootbus", },
{ .compatible = "cavium,mdio-mux", },
{ .compatible = "gpio-leds", },
{},
};
static bool __init octeon_has_88e1145(void)
{
return !OCTEON_IS_MODEL(OCTEON_CN52XX) &&
!OCTEON_IS_MODEL(OCTEON_CN6XXX) &&
!OCTEON_IS_MODEL(OCTEON_CN56XX);
}
static void __init octeon_fdt_set_phy(int eth, int phy_addr)
{
const __be32 *phy_handle;
const __be32 *alt_phy_handle;
const __be32 *reg;
u32 phandle;
int phy;
int alt_phy;
const char *p;
int current_len;
char new_name[20];
phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL);
if (!phy_handle)
return;
phandle = be32_to_cpup(phy_handle);
phy = fdt_node_offset_by_phandle(initial_boot_params, phandle);
alt_phy_handle = fdt_getprop(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
if (alt_phy_handle) {
u32 alt_phandle = be32_to_cpup(alt_phy_handle);
alt_phy = fdt_node_offset_by_phandle(initial_boot_params, alt_phandle);
} else {
alt_phy = -1;
}
if (phy_addr < 0 || phy < 0) {
/* Delete the PHY things */
fdt_nop_property(initial_boot_params, eth, "phy-handle");
/* This one may fail */
fdt_nop_property(initial_boot_params, eth, "cavium,alt-phy-handle");
if (phy >= 0)
fdt_nop_node(initial_boot_params, phy);
if (alt_phy >= 0)
fdt_nop_node(initial_boot_params, alt_phy);
return;
}
if (phy_addr >= 256 && alt_phy > 0) {
const struct fdt_property *phy_prop;
struct fdt_property *alt_prop;
u32 phy_handle_name;
/* Use the alt phy node instead.*/
phy_prop = fdt_get_property(initial_boot_params, eth, "phy-handle", NULL);
phy_handle_name = phy_prop->nameoff;
fdt_nop_node(initial_boot_params, phy);
fdt_nop_property(initial_boot_params, eth, "phy-handle");
alt_prop = fdt_get_property_w(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
alt_prop->nameoff = phy_handle_name;
phy = alt_phy;
}
phy_addr &= 0xff;
if (octeon_has_88e1145()) {
fdt_nop_property(initial_boot_params, phy, "marvell,reg-init");
memset(new_name, 0, sizeof(new_name));
strcpy(new_name, "marvell,88e1145");
p = fdt_getprop(initial_boot_params, phy, "compatible",
&current_len);
if (p && current_len >= strlen(new_name))
fdt_setprop_inplace(initial_boot_params, phy,
"compatible", new_name, current_len);
}
reg = fdt_getprop(initial_boot_params, phy, "reg", NULL);
if (phy_addr == be32_to_cpup(reg))
return;
fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr);
snprintf(new_name, sizeof(new_name), "ethernet-phy@%x", phy_addr);
p = fdt_get_name(initial_boot_params, phy, &current_len);
if (p && current_len == strlen(new_name))
fdt_set_name(initial_boot_params, phy, new_name);
else
pr_err("Error: could not rename ethernet phy: <%s>", p);
}
static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
{
u8 new_mac[6];
u64 mac = *pmac;
int r;
new_mac[0] = (mac >> 40) & 0xff;
new_mac[1] = (mac >> 32) & 0xff;
new_mac[2] = (mac >> 24) & 0xff;
new_mac[3] = (mac >> 16) & 0xff;
new_mac[4] = (mac >> 8) & 0xff;
new_mac[5] = mac & 0xff;
r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address",
new_mac, sizeof(new_mac));
if (r) {
pr_err("Setting \"local-mac-address\" failed %d", r);
return;
}
*pmac = mac + 1;
}
static void __init octeon_fdt_rm_ethernet(int node)
{
const __be32 *phy_handle;
phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL);
if (phy_handle) {
u32 ph = be32_to_cpup(phy_handle);
int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
if (p >= 0)
fdt_nop_node(initial_boot_params, p);
}
fdt_nop_node(initial_boot_params, node);
}
static void __init octeon_fdt_pip_port(int iface, int i, int p, int max, u64 *pmac)
{
char name_buffer[20];
int eth;
int phy_addr;
int ipd_port;
snprintf(name_buffer, sizeof(name_buffer), "ethernet@%x", p);
eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer);
if (eth < 0)
return;
if (p > max) {
pr_debug("Deleting port %x:%x\n", i, p);
octeon_fdt_rm_ethernet(eth);
return;
}
if (OCTEON_IS_MODEL(OCTEON_CN68XX))
ipd_port = (0x100 * i) + (0x10 * p) + 0x800;
else
ipd_port = 16 * i + p;
phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
octeon_fdt_set_phy(eth, phy_addr);
octeon_fdt_set_mac_addr(eth, pmac);
}
static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
{
char name_buffer[20];
int iface;
int p;
int count;
count = cvmx_helper_interface_enumerate(idx);
snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
if (iface < 0)
return;
for (p = 0; p < 16; p++)
octeon_fdt_pip_port(iface, idx, p, count - 1, pmac);
}
int __init octeon_prune_device_tree(void)
{
int i, max_port, uart_mask;
const char *pip_path;
const char *alias_prop;
char name_buffer[20];
int aliases;
u64 mac_addr_base;
if (fdt_check_header(initial_boot_params))
panic("Corrupt Device Tree.");
aliases = fdt_path_offset(initial_boot_params, "/aliases");
if (aliases < 0) {
pr_err("Error: No /aliases node in device tree.");
return -EINVAL;
}
mac_addr_base =
((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
(octeon_bootinfo->mac_addr_base[5] & 0xffull);
if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
max_port = 2;
else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX))
max_port = 1;
else
max_port = 0;
if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E)
max_port = 0;
for (i = 0; i < 2; i++) {
int mgmt;
snprintf(name_buffer, sizeof(name_buffer),
"mix%d", i);
alias_prop = fdt_getprop(initial_boot_params, aliases,
name_buffer, NULL);
if (alias_prop) {
mgmt = fdt_path_offset(initial_boot_params, alias_prop);
if (mgmt < 0)
continue;
if (i >= max_port) {
pr_debug("Deleting mix%d\n", i);
octeon_fdt_rm_ethernet(mgmt);
fdt_nop_property(initial_boot_params, aliases,
name_buffer);
} else {
int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i);
octeon_fdt_set_phy(mgmt, phy_addr);
octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
}
}
}
pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
if (pip_path) {
int pip = fdt_path_offset(initial_boot_params, pip_path);
if (pip >= 0)
for (i = 0; i <= 4; i++)
octeon_fdt_pip_iface(pip, i, &mac_addr_base);
}
/* I2C */
if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
OCTEON_IS_MODEL(OCTEON_CN63XX) ||
OCTEON_IS_MODEL(OCTEON_CN68XX) ||
OCTEON_IS_MODEL(OCTEON_CN56XX))
max_port = 2;
else
max_port = 1;
for (i = 0; i < 2; i++) {
int i2c;
snprintf(name_buffer, sizeof(name_buffer),
"twsi%d", i);
alias_prop = fdt_getprop(initial_boot_params, aliases,
name_buffer, NULL);
if (alias_prop) {
i2c = fdt_path_offset(initial_boot_params, alias_prop);
if (i2c < 0)
continue;
if (i >= max_port) {
pr_debug("Deleting twsi%d\n", i);
fdt_nop_node(initial_boot_params, i2c);
fdt_nop_property(initial_boot_params, aliases,
name_buffer);
}
}
}
/* SMI/MDIO */
if (OCTEON_IS_MODEL(OCTEON_CN68XX))
max_port = 4;
else if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
OCTEON_IS_MODEL(OCTEON_CN63XX) ||
OCTEON_IS_MODEL(OCTEON_CN56XX))
max_port = 2;
else
max_port = 1;
for (i = 0; i < 2; i++) {
int i2c;
snprintf(name_buffer, sizeof(name_buffer),
"smi%d", i);
alias_prop = fdt_getprop(initial_boot_params, aliases,
name_buffer, NULL);
if (alias_prop) {
i2c = fdt_path_offset(initial_boot_params, alias_prop);
if (i2c < 0)
continue;
if (i >= max_port) {
pr_debug("Deleting smi%d\n", i);
fdt_nop_node(initial_boot_params, i2c);
fdt_nop_property(initial_boot_params, aliases,
name_buffer);
}
}
}
/* Serial */
uart_mask = 3;
/* Right now CN52XX is the only chip with a third uart */
if (OCTEON_IS_MODEL(OCTEON_CN52XX))
uart_mask |= 4; /* uart2 */
for (i = 0; i < 3; i++) {
int uart;
snprintf(name_buffer, sizeof(name_buffer),
"uart%d", i);
alias_prop = fdt_getprop(initial_boot_params, aliases,
name_buffer, NULL);
if (alias_prop) {
uart = fdt_path_offset(initial_boot_params, alias_prop);
if (uart_mask & (1 << i))
continue;
pr_debug("Deleting uart%d\n", i);
fdt_nop_node(initial_boot_params, uart);
fdt_nop_property(initial_boot_params, aliases,
name_buffer);
}
}
/* Compact Flash */
alias_prop = fdt_getprop(initial_boot_params, aliases,
"cf0", NULL);
if (alias_prop) {
union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
unsigned long base_ptr, region_base, region_size;
unsigned long region1_base = 0;
unsigned long region1_size = 0;
int cs, bootbus;
bool is_16bit = false;
bool is_true_ide = false;
__be32 new_reg[6];
__be32 *ranges;
int len;
int cf = fdt_path_offset(initial_boot_params, alias_prop);
base_ptr = 0;
if (octeon_bootinfo->major_version == 1
&& octeon_bootinfo->minor_version >= 1) {
if (octeon_bootinfo->compact_flash_common_base_addr)
base_ptr = octeon_bootinfo->compact_flash_common_base_addr;
} else {
base_ptr = 0x1d000800;
}
if (!base_ptr)
goto no_cf;
/* Find CS0 region. */
for (cs = 0; cs < 8; cs++) {
mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
region_base = mio_boot_reg_cfg.s.base << 16;
region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
&& base_ptr < region_base + region_size) {
is_16bit = mio_boot_reg_cfg.s.width;
break;
}
}
if (cs >= 7) {
/* cs and cs + 1 are CS0 and CS1, both must be less than 8. */
goto no_cf;
}
if (!(base_ptr & 0xfffful)) {
/*
* Boot loader signals availability of DMA (true_ide
* mode) by setting low order bits of base_ptr to
* zero.
*/
/* Asume that CS1 immediately follows. */
mio_boot_reg_cfg.u64 =
cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs + 1));
region1_base = mio_boot_reg_cfg.s.base << 16;
region1_size = (mio_boot_reg_cfg.s.size + 1) << 16;
if (!mio_boot_reg_cfg.s.en)
goto no_cf;
is_true_ide = true;
} else {
fdt_nop_property(initial_boot_params, cf, "cavium,true-ide");
fdt_nop_property(initial_boot_params, cf, "cavium,dma-engine-handle");
if (!is_16bit) {
__be32 width = cpu_to_be32(8);
fdt_setprop_inplace(initial_boot_params, cf,
"cavium,bus-width", &width, sizeof(width));
}
}
new_reg[0] = cpu_to_be32(cs);
new_reg[1] = cpu_to_be32(0);
new_reg[2] = cpu_to_be32(0x10000);
new_reg[3] = cpu_to_be32(cs + 1);
new_reg[4] = cpu_to_be32(0);
new_reg[5] = cpu_to_be32(0x10000);
fdt_setprop_inplace(initial_boot_params, cf,
"reg", new_reg, sizeof(new_reg));
bootbus = fdt_parent_offset(initial_boot_params, cf);
if (bootbus < 0)
goto no_cf;
ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
if (!ranges || len < (5 * 8 * sizeof(__be32)))
goto no_cf;
ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
if (is_true_ide) {
cs++;
ranges[(cs * 5) + 2] = cpu_to_be32(region1_base >> 32);
ranges[(cs * 5) + 3] = cpu_to_be32(region1_base & 0xffffffff);
ranges[(cs * 5) + 4] = cpu_to_be32(region1_size);
}
goto end_cf;
no_cf:
fdt_nop_node(initial_boot_params, cf);
end_cf:
;
}
/* 8 char LED */
alias_prop = fdt_getprop(initial_boot_params, aliases,
"led0", NULL);
if (alias_prop) {
union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
unsigned long base_ptr, region_base, region_size;
int cs, bootbus;
__be32 new_reg[6];
__be32 *ranges;
int len;
int led = fdt_path_offset(initial_boot_params, alias_prop);
base_ptr = octeon_bootinfo->led_display_base_addr;
if (base_ptr == 0)
goto no_led;
/* Find CS0 region. */
for (cs = 0; cs < 8; cs++) {
mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
region_base = mio_boot_reg_cfg.s.base << 16;
region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
&& base_ptr < region_base + region_size)
break;
}
if (cs > 7)
goto no_led;
new_reg[0] = cpu_to_be32(cs);
new_reg[1] = cpu_to_be32(0x20);
new_reg[2] = cpu_to_be32(0x20);
new_reg[3] = cpu_to_be32(cs);
new_reg[4] = cpu_to_be32(0);
new_reg[5] = cpu_to_be32(0x20);
fdt_setprop_inplace(initial_boot_params, led,
"reg", new_reg, sizeof(new_reg));
bootbus = fdt_parent_offset(initial_boot_params, led);
if (bootbus < 0)
goto no_led;
ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
if (!ranges || len < (5 * 8 * sizeof(__be32)))
goto no_led;
ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
goto end_led;
no_led:
fdt_nop_node(initial_boot_params, led);
end_led:
;
}
/* OHCI/UHCI USB */
alias_prop = fdt_getprop(initial_boot_params, aliases,
"uctl", NULL);
if (alias_prop) {
int uctl = fdt_path_offset(initial_boot_params, alias_prop);
if (uctl >= 0 && (!OCTEON_IS_MODEL(OCTEON_CN6XXX) ||
octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC2E)) {
pr_debug("Deleting uctl\n");
fdt_nop_node(initial_boot_params, uctl);
fdt_nop_property(initial_boot_params, aliases, "uctl");
} else if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E ||
octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC4E) {
/* Missing "refclk-type" defaults to crystal. */
fdt_nop_property(initial_boot_params, uctl, "refclk-type");
}
}
return 0;
}
static int __init octeon_publish_devices(void)
{
return of_platform_bus_probe(NULL, octeon_ids, NULL);
}
device_initcall(octeon_publish_devices);
MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>"); MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Platform driver for Octeon SOC"); MODULE_DESCRIPTION("Platform driver for Octeon SOC");
/dts-v1/;
/*
* OCTEON 3XXX, 5XXX, 63XX device tree skeleton.
*
* This device tree is pruned and patched by early boot code before
* use. Because of this, it contains a super-set of the available
* devices and properties.
*/
/ {
compatible = "cavium,octeon-3860";
#address-cells = <2>;
#size-cells = <2>;
interrupt-parent = <&ciu>;
soc@0 {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges; /* Direct mapping */
ciu: interrupt-controller@1070000000000 {
compatible = "cavium,octeon-3860-ciu";
interrupt-controller;
/* Interrupts are specified by two parts:
* 1) Controller register (0 or 1)
* 2) Bit within the register (0..63)
*/
#interrupt-cells = <2>;
reg = <0x10700 0x00000000 0x0 0x7000>;
};
gpio: gpio-controller@1070000000800 {
#gpio-cells = <2>;
compatible = "cavium,octeon-3860-gpio";
reg = <0x10700 0x00000800 0x0 0x100>;
gpio-controller;
/* Interrupts are specified by two parts:
* 1) GPIO pin number (0..15)
* 2) Triggering (1 - edge rising
* 2 - edge falling
* 4 - level active high
* 8 - level active low)
*/
interrupt-controller;
#interrupt-cells = <2>;
/* The GPIO pin connect to 16 consecutive CUI bits */
interrupts = <0 16>, <0 17>, <0 18>, <0 19>,
<0 20>, <0 21>, <0 22>, <0 23>,
<0 24>, <0 25>, <0 26>, <0 27>,
<0 28>, <0 29>, <0 30>, <0 31>;
};
smi0: mdio@1180000001800 {
compatible = "cavium,octeon-3860-mdio";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11800 0x00001800 0x0 0x40>;
phy0: ethernet-phy@0 {
compatible = "marvell,88e1118";
marvell,reg-init =
/* Fix rx and tx clock transition timing */
<2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */
/* Adjust LED drive. */
<3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */
/* irq, blink-activity, blink-link */
<3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */
reg = <0>;
};
phy1: ethernet-phy@1 {
compatible = "marvell,88e1118";
marvell,reg-init =
/* Fix rx and tx clock transition timing */
<2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */
/* Adjust LED drive. */
<3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */
/* irq, blink-activity, blink-link */
<3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */
reg = <1>;
};
phy2: ethernet-phy@2 {
reg = <2>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy3: ethernet-phy@3 {
reg = <3>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy4: ethernet-phy@4 {
reg = <4>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy5: ethernet-phy@5 {
reg = <5>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy6: ethernet-phy@6 {
reg = <6>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy7: ethernet-phy@7 {
reg = <7>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy8: ethernet-phy@8 {
reg = <8>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy9: ethernet-phy@9 {
reg = <9>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
};
smi1: mdio@1180000001900 {
compatible = "cavium,octeon-3860-mdio";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11800 0x00001900 0x0 0x40>;
phy100: ethernet-phy@1 {
reg = <1>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <12 8>; /* Pin 12, active low */
};
phy101: ethernet-phy@2 {
reg = <2>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <12 8>; /* Pin 12, active low */
};
phy102: ethernet-phy@3 {
reg = <3>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <12 8>; /* Pin 12, active low */
};
phy103: ethernet-phy@4 {
reg = <4>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
interrupt-parent = <&gpio>;
interrupts = <12 8>; /* Pin 12, active low */
};
};
mix0: ethernet@1070000100000 {
compatible = "cavium,octeon-5750-mix";
reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
<0x11800 0xE0000000 0x0 0x300>, /* AGL */
<0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
<0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */
cell-index = <0>;
interrupts = <0 62>, <1 46>;
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy0>;
};
mix1: ethernet@1070000100800 {
compatible = "cavium,octeon-5750-mix";
reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */
<0x11800 0xE0000800 0x0 0x300>, /* AGL */
<0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
<0x11800 0xE0002008 0x0 0x8>; /* AGL_PRT_CTL */
cell-index = <1>;
interrupts = <1 18>, < 1 46>;
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy1>;
};
pip: pip@11800a0000000 {
compatible = "cavium,octeon-3860-pip";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11800 0xa0000000 0x0 0x2000>;
interface@0 {
compatible = "cavium,octeon-3860-pip-interface";
#address-cells = <1>;
#size-cells = <0>;
reg = <0>; /* interface */
ethernet@0 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x0>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy2>;
cavium,alt-phy-handle = <&phy100>;
};
ethernet@1 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x1>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy3>;
cavium,alt-phy-handle = <&phy101>;
};
ethernet@2 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x2>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy4>;
cavium,alt-phy-handle = <&phy102>;
};
ethernet@3 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x3>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy5>;
cavium,alt-phy-handle = <&phy103>;
};
ethernet@4 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x4>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@5 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x5>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@6 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x6>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@7 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x7>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@8 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x8>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@9 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x9>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@a {
compatible = "cavium,octeon-3860-pip-port";
reg = <0xa>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@b {
compatible = "cavium,octeon-3860-pip-port";
reg = <0xb>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@c {
compatible = "cavium,octeon-3860-pip-port";
reg = <0xc>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@d {
compatible = "cavium,octeon-3860-pip-port";
reg = <0xd>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@e {
compatible = "cavium,octeon-3860-pip-port";
reg = <0xe>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
ethernet@f {
compatible = "cavium,octeon-3860-pip-port";
reg = <0xf>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
};
interface@1 {
compatible = "cavium,octeon-3860-pip-interface";
#address-cells = <1>;
#size-cells = <0>;
reg = <1>; /* interface */
ethernet@0 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x0>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy6>;
};
ethernet@1 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x1>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy7>;
};
ethernet@2 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x2>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy8>;
};
ethernet@3 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x3>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy9>;
};
};
};
twsi0: i2c@1180000001000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "cavium,octeon-3860-twsi";
reg = <0x11800 0x00001000 0x0 0x200>;
interrupts = <0 45>;
clock-frequency = <100000>;
rtc@68 {
compatible = "dallas,ds1337";
reg = <0x68>;
};
tmp@4c {
compatible = "ti,tmp421";
reg = <0x4c>;
};
};
twsi1: i2c@1180000001200 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "cavium,octeon-3860-twsi";
reg = <0x11800 0x00001200 0x0 0x200>;
interrupts = <0 59>;
clock-frequency = <100000>;
};
uart0: serial@1180000000800 {
compatible = "cavium,octeon-3860-uart","ns16550";
reg = <0x11800 0x00000800 0x0 0x400>;
clock-frequency = <0>;
current-speed = <115200>;
reg-shift = <3>;
interrupts = <0 34>;
};
uart1: serial@1180000000c00 {
compatible = "cavium,octeon-3860-uart","ns16550";
reg = <0x11800 0x00000c00 0x0 0x400>;
clock-frequency = <0>;
current-speed = <115200>;
reg-shift = <3>;
interrupts = <0 35>;
};
uart2: serial@1180000000400 {
compatible = "cavium,octeon-3860-uart","ns16550";
reg = <0x11800 0x00000400 0x0 0x400>;
clock-frequency = <0>;
current-speed = <115200>;
reg-shift = <3>;
interrupts = <1 16>;
};
bootbus: bootbus@1180000000000 {
compatible = "cavium,octeon-3860-bootbus";
reg = <0x11800 0x00000000 0x0 0x200>;
/* The chip select number and offset */
#address-cells = <2>;
/* The size of the chip select region */
#size-cells = <1>;
ranges = <0 0 0x0 0x1f400000 0xc00000>,
<1 0 0x10000 0x30000000 0>,
<2 0 0x10000 0x40000000 0>,
<3 0 0x10000 0x50000000 0>,
<4 0 0x0 0x1d020000 0x10000>,
<5 0 0x0 0x1d040000 0x10000>,
<6 0 0x0 0x1d050000 0x10000>,
<7 0 0x10000 0x90000000 0>;
cavium,cs-config@0 {
compatible = "cavium,octeon-3860-bootbus-config";
cavium,cs-index = <0>;
cavium,t-adr = <20>;
cavium,t-ce = <60>;
cavium,t-oe = <60>;
cavium,t-we = <45>;
cavium,t-rd-hld = <35>;
cavium,t-wr-hld = <45>;
cavium,t-pause = <0>;
cavium,t-wait = <0>;
cavium,t-page = <35>;
cavium,t-rd-dly = <0>;
cavium,pages = <0>;
cavium,bus-width = <8>;
};
cavium,cs-config@4 {
compatible = "cavium,octeon-3860-bootbus-config";
cavium,cs-index = <4>;
cavium,t-adr = <320>;
cavium,t-ce = <320>;
cavium,t-oe = <320>;
cavium,t-we = <320>;
cavium,t-rd-hld = <320>;
cavium,t-wr-hld = <320>;
cavium,t-pause = <320>;
cavium,t-wait = <320>;
cavium,t-page = <320>;
cavium,t-rd-dly = <0>;
cavium,pages = <0>;
cavium,bus-width = <8>;
};
cavium,cs-config@5 {
compatible = "cavium,octeon-3860-bootbus-config";
cavium,cs-index = <5>;
cavium,t-adr = <5>;
cavium,t-ce = <300>;
cavium,t-oe = <125>;
cavium,t-we = <150>;
cavium,t-rd-hld = <100>;
cavium,t-wr-hld = <30>;
cavium,t-pause = <0>;
cavium,t-wait = <30>;
cavium,t-page = <320>;
cavium,t-rd-dly = <0>;
cavium,pages = <0>;
cavium,bus-width = <16>;
};
cavium,cs-config@6 {
compatible = "cavium,octeon-3860-bootbus-config";
cavium,cs-index = <6>;
cavium,t-adr = <5>;
cavium,t-ce = <300>;
cavium,t-oe = <270>;
cavium,t-we = <150>;
cavium,t-rd-hld = <100>;
cavium,t-wr-hld = <70>;
cavium,t-pause = <0>;
cavium,t-wait = <0>;
cavium,t-page = <320>;
cavium,t-rd-dly = <0>;
cavium,pages = <0>;
cavium,wait-mode;
cavium,bus-width = <16>;
};
flash0: nor@0,0 {
compatible = "cfi-flash";
reg = <0 0 0x800000>;
#address-cells = <1>;
#size-cells = <1>;
};
led0: led-display@4,0 {
compatible = "avago,hdsp-253x";
reg = <4 0x20 0x20>, <4 0 0x20>;
};
cf0: compact-flash@5,0 {
compatible = "cavium,ebt3000-compact-flash";
reg = <5 0 0x10000>, <6 0 0x10000>;
cavium,bus-width = <16>;
cavium,true-ide;
cavium,dma-engine-handle = <&dma0>;
};
};
dma0: dma-engine@1180000000100 {
compatible = "cavium,octeon-5750-bootbus-dma";
reg = <0x11800 0x00000100 0x0 0x8>;
interrupts = <0 63>;
};
dma1: dma-engine@1180000000108 {
compatible = "cavium,octeon-5750-bootbus-dma";
reg = <0x11800 0x00000108 0x0 0x8>;
interrupts = <0 63>;
};
uctl: uctl@118006f000000 {
compatible = "cavium,octeon-6335-uctl";
reg = <0x11800 0x6f000000 0x0 0x100>;
ranges; /* Direct mapping */
#address-cells = <2>;
#size-cells = <2>;
/* 12MHz, 24MHz and 48MHz allowed */
refclk-frequency = <12000000>;
/* Either "crystal" or "external" */
refclk-type = "crystal";
ehci@16f0000000000 {
compatible = "cavium,octeon-6335-ehci","usb-ehci";
reg = <0x16f00 0x00000000 0x0 0x100>;
interrupts = <0 56>;
big-endian-regs;
};
ohci@16f0000000400 {
compatible = "cavium,octeon-6335-ohci","usb-ohci";
reg = <0x16f00 0x00000400 0x0 0x100>;
interrupts = <0 56>;
big-endian-regs;
};
};
};
aliases {
mix0 = &mix0;
mix1 = &mix1;
pip = &pip;
smi0 = &smi0;
smi1 = &smi1;
twsi0 = &twsi0;
twsi1 = &twsi1;
uart0 = &uart0;
uart1 = &uart1;
uart2 = &uart2;
flash0 = &flash0;
cf0 = &cf0;
uctl = &uctl;
led0 = &led0;
};
};
/dts-v1/;
/*
* OCTEON 68XX device tree skeleton.
*
* This device tree is pruned and patched by early boot code before
* use. Because of this, it contains a super-set of the available
* devices and properties.
*/
/ {
compatible = "cavium,octeon-6880";
#address-cells = <2>;
#size-cells = <2>;
interrupt-parent = <&ciu2>;
soc@0 {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges; /* Direct mapping */
ciu2: interrupt-controller@1070100000000 {
compatible = "cavium,octeon-6880-ciu2";
interrupt-controller;
/* Interrupts are specified by two parts:
* 1) Controller register (0 or 7)
* 2) Bit within the register (0..63)
*/
#address-cells = <0>;
#interrupt-cells = <2>;
reg = <0x10701 0x00000000 0x0 0x4000000>;
};
gpio: gpio-controller@1070000000800 {
#gpio-cells = <2>;
compatible = "cavium,octeon-3860-gpio";
reg = <0x10700 0x00000800 0x0 0x100>;
gpio-controller;
/* Interrupts are specified by two parts:
* 1) GPIO pin number (0..15)
* 2) Triggering (1 - edge rising
* 2 - edge falling
* 4 - level active high
* 8 - level active low)
*/
interrupt-controller;
#interrupt-cells = <2>;
/* The GPIO pins connect to 16 consecutive CUI bits */
interrupts = <7 0>, <7 1>, <7 2>, <7 3>,
<7 4>, <7 5>, <7 6>, <7 7>,
<7 8>, <7 9>, <7 10>, <7 11>,
<7 12>, <7 13>, <7 14>, <7 15>;
};
smi0: mdio@1180000003800 {
compatible = "cavium,octeon-3860-mdio";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11800 0x00003800 0x0 0x40>;
phy0: ethernet-phy@6 {
compatible = "marvell,88e1118";
marvell,reg-init =
/* Fix rx and tx clock transition timing */
<2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */
/* Adjust LED drive. */
<3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */
/* irq, blink-activity, blink-link */
<3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */
reg = <6>;
};
phy1: ethernet-phy@1 {
cavium,qlm-trim = "4,sgmii";
reg = <1>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy2: ethernet-phy@2 {
cavium,qlm-trim = "4,sgmii";
reg = <2>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy3: ethernet-phy@3 {
cavium,qlm-trim = "4,sgmii";
reg = <3>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy4: ethernet-phy@4 {
cavium,qlm-trim = "4,sgmii";
reg = <4>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
};
smi1: mdio@1180000003880 {
compatible = "cavium,octeon-3860-mdio";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11800 0x00003880 0x0 0x40>;
phy41: ethernet-phy@1 {
cavium,qlm-trim = "0,sgmii";
reg = <1>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy42: ethernet-phy@2 {
cavium,qlm-trim = "0,sgmii";
reg = <2>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy43: ethernet-phy@3 {
cavium,qlm-trim = "0,sgmii";
reg = <3>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy44: ethernet-phy@4 {
cavium,qlm-trim = "0,sgmii";
reg = <4>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
};
smi2: mdio@1180000003900 {
compatible = "cavium,octeon-3860-mdio";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11800 0x00003900 0x0 0x40>;
phy21: ethernet-phy@1 {
cavium,qlm-trim = "2,sgmii";
reg = <1>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy22: ethernet-phy@2 {
cavium,qlm-trim = "2,sgmii";
reg = <2>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy23: ethernet-phy@3 {
cavium,qlm-trim = "2,sgmii";
reg = <3>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy24: ethernet-phy@4 {
cavium,qlm-trim = "2,sgmii";
reg = <4>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
};
smi3: mdio@1180000003980 {
compatible = "cavium,octeon-3860-mdio";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11800 0x00003980 0x0 0x40>;
phy11: ethernet-phy@1 {
cavium,qlm-trim = "3,sgmii";
reg = <1>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy12: ethernet-phy@2 {
cavium,qlm-trim = "3,sgmii";
reg = <2>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy13: ethernet-phy@3 {
cavium,qlm-trim = "3,sgmii";
reg = <3>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
phy14: ethernet-phy@4 {
cavium,qlm-trim = "3,sgmii";
reg = <4>;
compatible = "marvell,88e1149r";
marvell,reg-init = <3 0x10 0 0x5777>,
<3 0x11 0 0x00aa>,
<3 0x12 0 0x4105>,
<3 0x13 0 0x0a60>;
};
};
mix0: ethernet@1070000100000 {
compatible = "cavium,octeon-5750-mix";
reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
<0x11800 0xE0000000 0x0 0x300>, /* AGL */
<0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED */
<0x11800 0xE0002000 0x0 0x8>; /* AGL_PRT_CTL */
cell-index = <0>;
interrupts = <6 40>, <6 32>;
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy0>;
};
pip: pip@11800a0000000 {
compatible = "cavium,octeon-3860-pip";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x11800 0xa0000000 0x0 0x2000>;
interface@4 {
compatible = "cavium,octeon-3860-pip-interface";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x4>; /* interface */
ethernet@0 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x0>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy1>;
};
ethernet@1 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x1>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy2>;
};
ethernet@2 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x2>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy3>;
};
ethernet@3 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x3>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy4>;
};
};
interface@3 {
compatible = "cavium,octeon-3860-pip-interface";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x3>; /* interface */
ethernet@0 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x0>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy11>;
};
ethernet@1 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x1>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy12>;
};
ethernet@2 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x2>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy13>;
};
ethernet@3 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x3>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy14>;
};
};
interface@2 {
compatible = "cavium,octeon-3860-pip-interface";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x2>; /* interface */
ethernet@0 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x0>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy21>;
};
ethernet@1 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x1>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy22>;
};
ethernet@2 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x2>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy23>;
};
ethernet@3 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x3>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy24>;
};
};
interface@1 {
compatible = "cavium,octeon-3860-pip-interface";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x1>; /* interface */
ethernet@0 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x0>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
};
};
interface@0 {
compatible = "cavium,octeon-3860-pip-interface";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x0>; /* interface */
ethernet@0 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x0>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy41>;
};
ethernet@1 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x1>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy42>;
};
ethernet@2 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x2>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy43>;
};
ethernet@3 {
compatible = "cavium,octeon-3860-pip-port";
reg = <0x3>; /* Port */
local-mac-address = [ 00 00 00 00 00 00 ];
phy-handle = <&phy44>;
};
};
};
twsi0: i2c@1180000001000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "cavium,octeon-3860-twsi";
reg = <0x11800 0x00001000 0x0 0x200>;
interrupts = <3 32>;
clock-frequency = <100000>;
rtc@68 {
compatible = "dallas,ds1337";
reg = <0x68>;
};
tmp@4c {
compatible = "ti,tmp421";
reg = <0x4c>;
};
};
twsi1: i2c@1180000001200 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "cavium,octeon-3860-twsi";
reg = <0x11800 0x00001200 0x0 0x200>;
interrupts = <3 33>;
clock-frequency = <100000>;
};
uart0: serial@1180000000800 {
compatible = "cavium,octeon-3860-uart","ns16550";
reg = <0x11800 0x00000800 0x0 0x400>;
clock-frequency = <0>;
current-speed = <115200>;
reg-shift = <3>;
interrupts = <3 36>;
};
uart1: serial@1180000000c00 {
compatible = "cavium,octeon-3860-uart","ns16550";
reg = <0x11800 0x00000c00 0x0 0x400>;
clock-frequency = <0>;
current-speed = <115200>;
reg-shift = <3>;
interrupts = <3 37>;
};
bootbus: bootbus@1180000000000 {
compatible = "cavium,octeon-3860-bootbus";
reg = <0x11800 0x00000000 0x0 0x200>;
/* The chip select number and offset */
#address-cells = <2>;
/* The size of the chip select region */
#size-cells = <1>;
ranges = <0 0 0 0x1f400000 0xc00000>,
<1 0 0x10000 0x30000000 0>,
<2 0 0x10000 0x40000000 0>,
<3 0 0x10000 0x50000000 0>,
<4 0 0 0x1d020000 0x10000>,
<5 0 0 0x1d040000 0x10000>,
<6 0 0 0x1d050000 0x10000>,
<7 0 0x10000 0x90000000 0>;
cavium,cs-config@0 {
compatible = "cavium,octeon-3860-bootbus-config";
cavium,cs-index = <0>;
cavium,t-adr = <10>;
cavium,t-ce = <50>;
cavium,t-oe = <50>;
cavium,t-we = <35>;
cavium,t-rd-hld = <25>;
cavium,t-wr-hld = <35>;
cavium,t-pause = <0>;
cavium,t-wait = <300>;
cavium,t-page = <25>;
cavium,t-rd-dly = <0>;
cavium,pages = <0>;
cavium,bus-width = <8>;
};
cavium,cs-config@4 {
compatible = "cavium,octeon-3860-bootbus-config";
cavium,cs-index = <4>;
cavium,t-adr = <320>;
cavium,t-ce = <320>;
cavium,t-oe = <320>;
cavium,t-we = <320>;
cavium,t-rd-hld = <320>;
cavium,t-wr-hld = <320>;
cavium,t-pause = <320>;
cavium,t-wait = <320>;
cavium,t-page = <320>;
cavium,t-rd-dly = <0>;
cavium,pages = <0>;
cavium,bus-width = <8>;
};
cavium,cs-config@5 {
compatible = "cavium,octeon-3860-bootbus-config";
cavium,cs-index = <5>;
cavium,t-adr = <0>;
cavium,t-ce = <300>;
cavium,t-oe = <125>;
cavium,t-we = <150>;
cavium,t-rd-hld = <100>;
cavium,t-wr-hld = <300>;
cavium,t-pause = <0>;
cavium,t-wait = <300>;
cavium,t-page = <310>;
cavium,t-rd-dly = <0>;
cavium,pages = <0>;
cavium,bus-width = <16>;
};
cavium,cs-config@6 {
compatible = "cavium,octeon-3860-bootbus-config";
cavium,cs-index = <6>;
cavium,t-adr = <0>;
cavium,t-ce = <30>;
cavium,t-oe = <125>;
cavium,t-we = <150>;
cavium,t-rd-hld = <100>;
cavium,t-wr-hld = <30>;
cavium,t-pause = <0>;
cavium,t-wait = <30>;
cavium,t-page = <310>;
cavium,t-rd-dly = <0>;
cavium,pages = <0>;
cavium,wait-mode;
cavium,bus-width = <16>;
};
flash0: nor@0,0 {
compatible = "cfi-flash";
reg = <0 0 0x800000>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "bootloader";
reg = <0 0x200000>;
read-only;
};
partition@200000 {
label = "kernel";
reg = <0x200000 0x200000>;
};
partition@400000 {
label = "cramfs";
reg = <0x400000 0x3fe000>;
};
partition@7fe000 {
label = "environment";
reg = <0x7fe000 0x2000>;
read-only;
};
};
led0: led-display@4,0 {
compatible = "avago,hdsp-253x";
reg = <4 0x20 0x20>, <4 0 0x20>;
};
compact-flash@5,0 {
compatible = "cavium,ebt3000-compact-flash";
reg = <5 0 0x10000>, <6 0 0x10000>;
cavium,bus-width = <16>;
cavium,true-ide;
cavium,dma-engine-handle = <&dma0>;
};
};
dma0: dma-engine@1180000000100 {
compatible = "cavium,octeon-5750-bootbus-dma";
reg = <0x11800 0x00000100 0x0 0x8>;
interrupts = <0 63>;
};
dma1: dma-engine@1180000000108 {
compatible = "cavium,octeon-5750-bootbus-dma";
reg = <0x11800 0x00000108 0x0 0x8>;
interrupts = <0 63>;
};
uctl: uctl@118006f000000 {
compatible = "cavium,octeon-6335-uctl";
reg = <0x11800 0x6f000000 0x0 0x100>;
ranges; /* Direct mapping */
#address-cells = <2>;
#size-cells = <2>;
/* 12MHz, 24MHz and 48MHz allowed */
refclk-frequency = <12000000>;
/* Either "crystal" or "external" */
refclk-type = "crystal";
ehci@16f0000000000 {
compatible = "cavium,octeon-6335-ehci","usb-ehci";
reg = <0x16f00 0x00000000 0x0 0x100>;
interrupts = <3 44>;
big-endian-regs;
};
ohci@16f0000000400 {
compatible = "cavium,octeon-6335-ohci","usb-ohci";
reg = <0x16f00 0x00000400 0x0 0x100>;
interrupts = <3 44>;
big-endian-regs;
};
};
};
aliases {
mix0 = &mix0;
pip = &pip;
smi0 = &smi0;
smi1 = &smi1;
smi2 = &smi2;
smi3 = &smi3;
twsi0 = &twsi0;
twsi1 = &twsi1;
uart0 = &uart0;
uart1 = &uart1;
uctl = &uctl;
led0 = &led0;
flash0 = &flash0;
};
};
...@@ -43,95 +43,67 @@ void octeon_serial_out(struct uart_port *up, int offset, int value) ...@@ -43,95 +43,67 @@ void octeon_serial_out(struct uart_port *up, int offset, int value)
cvmx_write_csr((uint64_t)(up->membase + (offset << 3)), (u8)value); cvmx_write_csr((uint64_t)(up->membase + (offset << 3)), (u8)value);
} }
/* static int __devinit octeon_serial_probe(struct platform_device *pdev)
* Allocated in .bss, so it is all zeroed.
*/
#define OCTEON_MAX_UARTS 3
static struct plat_serial8250_port octeon_uart8250_data[OCTEON_MAX_UARTS + 1];
static struct platform_device octeon_uart8250_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = octeon_uart8250_data,
},
};
static void __init octeon_uart_set_common(struct plat_serial8250_port *p)
{ {
p->flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE; int irq, res;
p->type = PORT_OCTEON; struct resource *res_mem;
p->iotype = UPIO_MEM; struct uart_port port;
p->regshift = 3; /* I/O addresses are every 8 bytes */
/* All adaptors have an irq. */
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
memset(&port, 0, sizeof(port));
port.flags = ASYNC_SKIP_TEST | UPF_SHARE_IRQ | UPF_FIXED_TYPE;
port.type = PORT_OCTEON;
port.iotype = UPIO_MEM;
port.regshift = 3;
port.dev = &pdev->dev;
if (octeon_is_simulation()) if (octeon_is_simulation())
/* Make simulator output fast*/ /* Make simulator output fast*/
p->uartclk = 115200 * 16; port.uartclk = 115200 * 16;
else else
p->uartclk = octeon_get_io_clock_rate(); port.uartclk = octeon_get_io_clock_rate();
p->serial_in = octeon_serial_in;
p->serial_out = octeon_serial_out;
}
static int __init octeon_serial_init(void) port.serial_in = octeon_serial_in;
{ port.serial_out = octeon_serial_out;
int enable_uart0; port.irq = irq;
int enable_uart1;
int enable_uart2;
struct plat_serial8250_port *p;
#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
/*
* If we are configured to run as the second of two kernels,
* disable uart0 and enable uart1. Uart0 is owned by the first
* kernel
*/
enable_uart0 = 0;
enable_uart1 = 1;
#else
/*
* We are configured for the first kernel. We'll enable uart0
* if the bootloader told us to use 0, otherwise will enable
* uart 1.
*/
enable_uart0 = (octeon_get_boot_uart() == 0);
enable_uart1 = (octeon_get_boot_uart() == 1);
#ifdef CONFIG_KGDB
enable_uart1 = 1;
#endif
#endif
/* Right now CN52XX is the only chip with a third uart */
enable_uart2 = OCTEON_IS_MODEL(OCTEON_CN52XX);
p = octeon_uart8250_data;
if (enable_uart0) {
/* Add a ttyS device for hardware uart 0 */
octeon_uart_set_common(p);
p->membase = (void *) CVMX_MIO_UARTX_RBR(0);
p->mapbase = CVMX_MIO_UARTX_RBR(0) & ((1ull << 49) - 1);
p->irq = OCTEON_IRQ_UART0;
p++;
}
if (enable_uart1) { res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
/* Add a ttyS device for hardware uart 1 */ if (res_mem == NULL) {
octeon_uart_set_common(p); dev_err(&pdev->dev, "found no memory resource\n");
p->membase = (void *) CVMX_MIO_UARTX_RBR(1); return -ENXIO;
p->mapbase = CVMX_MIO_UARTX_RBR(1) & ((1ull << 49) - 1);
p->irq = OCTEON_IRQ_UART1;
p++;
}
if (enable_uart2) {
/* Add a ttyS device for hardware uart 2 */
octeon_uart_set_common(p);
p->membase = (void *) CVMX_MIO_UART2_RBR;
p->mapbase = CVMX_MIO_UART2_RBR & ((1ull << 49) - 1);
p->irq = OCTEON_IRQ_UART2;
p++;
} }
port.mapbase = res_mem->start;
port.membase = ioremap(res_mem->start, resource_size(res_mem));
BUG_ON(p > &octeon_uart8250_data[OCTEON_MAX_UARTS]); res = serial8250_register_port(&port);
return platform_device_register(&octeon_uart8250_device); return res >= 0 ? 0 : res;
} }
device_initcall(octeon_serial_init); static struct of_device_id octeon_serial_match[] = {
{
.compatible = "cavium,octeon-3860-uart",
},
{},
};
MODULE_DEVICE_TABLE(of, octeon_serial_match);
static struct platform_driver octeon_serial_driver = {
.probe = octeon_serial_probe,
.driver = {
.owner = THIS_MODULE,
.name = "octeon_serial",
.of_match_table = octeon_serial_match,
},
};
static int __init octeon_serial_init(void)
{
return platform_driver_register(&octeon_serial_driver);
}
late_initcall(octeon_serial_init);
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/of_fdt.h>
#include <linux/libfdt.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/reboot.h> #include <asm/reboot.h>
...@@ -775,3 +777,46 @@ void prom_free_prom_memory(void) ...@@ -775,3 +777,46 @@ void prom_free_prom_memory(void)
} }
#endif #endif
} }
int octeon_prune_device_tree(void);
extern const char __dtb_octeon_3xxx_begin;
extern const char __dtb_octeon_3xxx_end;
extern const char __dtb_octeon_68xx_begin;
extern const char __dtb_octeon_68xx_end;
void __init device_tree_init(void)
{
int dt_size;
struct boot_param_header *fdt;
bool do_prune;
if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) {
fdt = phys_to_virt(octeon_bootinfo->fdt_addr);
if (fdt_check_header(fdt))
panic("Corrupt Device Tree passed to kernel.");
dt_size = be32_to_cpu(fdt->totalsize);
do_prune = false;
} else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
fdt = (struct boot_param_header *)&__dtb_octeon_68xx_begin;
dt_size = &__dtb_octeon_68xx_end - &__dtb_octeon_68xx_begin;
do_prune = true;
} else {
fdt = (struct boot_param_header *)&__dtb_octeon_3xxx_begin;
dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin;
do_prune = true;
}
/* Copy the default tree from init memory. */
initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8);
if (initial_boot_params == NULL)
panic("Could not allocate initial_boot_params\n");
memcpy(initial_boot_params, fdt, dt_size);
if (do_prune) {
octeon_prune_device_tree();
pr_info("Using internal Device Tree.\n");
} else {
pr_info("Using passed Device Tree.\n");
}
unflatten_device_tree();
}
CONFIG_MACH_LOONGSON1=y
CONFIG_PREEMPT=y
# CONFIG_SECCOMP is not set
CONFIG_EXPERIMENTAL=y
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=16
CONFIG_NAMESPACES=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
CONFIG_EXPERT=y
CONFIG_PERF_EVENTS=y
# CONFIG_COMPAT_BRK is not set
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
# CONFIG_LBDAF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
# CONFIG_SUSPEND is not set
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_SYN_COOKIES=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_DIAG is not set
# CONFIG_IPV6 is not set
# CONFIG_WIRELESS is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_STANDALONE is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_SCSI=m
# CONFIG_SCSI_PROC_FS is not set
CONFIG_BLK_DEV_SD=m
# CONFIG_SCSI_LOWLEVEL is not set
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CHELSIO is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_SEEQ is not set
# CONFIG_NET_VENDOR_SMSC is not set
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_DA=y
# CONFIG_NET_VENDOR_WIZNET is not set
# CONFIG_WLAN is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_SERIO is not set
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_LEGACY_PTY_COUNT=8
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
# CONFIG_HW_RANDOM is not set
# CONFIG_HWMON is not set
# CONFIG_VGA_CONSOLE is not set
CONFIG_USB_HID=m
CONFIG_HID_GENERIC=m
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_TT_NEWSCHED is not set
CONFIG_USB_STORAGE=m
CONFIG_USB_SERIAL=m
CONFIG_USB_SERIAL_PL2303=m
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_LOONGSON1=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
CONFIG_EXT2_FS_SECURITY=y
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
# CONFIG_DNOTIFY is not set
CONFIG_VFAT_FS=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
# CONFIG_MISC_FILESYSTEMS is not set
CONFIG_NFS_FS=y
CONFIG_ROOT_NFS=y
CONFIG_NLS_CODEPAGE_437=m
CONFIG_NLS_ISO8859_1=m
# CONFIG_ENABLE_WARN_DEPRECATED is not set
# CONFIG_ENABLE_MUST_CHECK is not set
CONFIG_MAGIC_SYSRQ=y
# CONFIG_SCHED_DEBUG is not set
# CONFIG_DEBUG_PREEMPT is not set
# CONFIG_FTRACE is not set
# CONFIG_EARLY_PRINTK is not set
...@@ -367,6 +367,10 @@ CONFIG_SERIAL_8250_RSA=y ...@@ -367,6 +367,10 @@ CONFIG_SERIAL_8250_RSA=y
CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_TIMERIOMEM=m CONFIG_HW_RANDOM_TIMERIOMEM=m
CONFIG_RAW_DRIVER=m CONFIG_RAW_DRIVER=m
CONFIG_I2C=y
CONFIG_I2C_XLR=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_DS1374=y
# CONFIG_HWMON is not set # CONFIG_HWMON is not set
# CONFIG_VGA_CONSOLE is not set # CONFIG_VGA_CONSOLE is not set
# CONFIG_HID_SUPPORT is not set # CONFIG_HID_SUPPORT is not set
......
...@@ -101,7 +101,7 @@ void __init prom_free_prom_memory(void) ...@@ -101,7 +101,7 @@ void __init prom_free_prom_memory(void)
* the first page reserved for the exception handlers. * the first page reserved for the exception handlers.
*/ */
#if defined(CONFIG_DECLANCE) || defined(CONFIG_DECLANCE_MODULE) #if IS_ENABLED(CONFIG_DECLANCE)
/* /*
* Leave 128 KB reserved for Lance memory for * Leave 128 KB reserved for Lance memory for
* IOASIC DECstations. * IOASIC DECstations.
......
...@@ -197,6 +197,7 @@ ...@@ -197,6 +197,7 @@
#define PRID_REV_VR4181A 0x0070 /* Same as VR4122 */ #define PRID_REV_VR4181A 0x0070 /* Same as VR4122 */
#define PRID_REV_VR4130 0x0080 #define PRID_REV_VR4130 0x0080
#define PRID_REV_34K_V1_0_2 0x0022 #define PRID_REV_34K_V1_0_2 0x0022
#define PRID_REV_LOONGSON1B 0x0020
#define PRID_REV_LOONGSON2E 0x0002 #define PRID_REV_LOONGSON2E 0x0002
#define PRID_REV_LOONGSON2F 0x0003 #define PRID_REV_LOONGSON2F 0x0003
...@@ -261,7 +262,7 @@ enum cpu_type_enum { ...@@ -261,7 +262,7 @@ enum cpu_type_enum {
*/ */
CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K, CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_M14KC, CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC,
/* /*
* MIPS64 class processors * MIPS64 class processors
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* compile time if only one CPU support is enabled (idea stolen from * compile time if only one CPU support is enabled (idea stolen from
* arm mach-types) * arm mach-types)
*/ */
#define BCM6328_CPU_ID 0x6328
#define BCM6338_CPU_ID 0x6338 #define BCM6338_CPU_ID 0x6338
#define BCM6345_CPU_ID 0x6345 #define BCM6345_CPU_ID 0x6345
#define BCM6348_CPU_ID 0x6348 #define BCM6348_CPU_ID 0x6348
...@@ -20,6 +21,19 @@ u16 __bcm63xx_get_cpu_id(void); ...@@ -20,6 +21,19 @@ u16 __bcm63xx_get_cpu_id(void);
u16 bcm63xx_get_cpu_rev(void); u16 bcm63xx_get_cpu_rev(void);
unsigned int bcm63xx_get_cpu_freq(void); unsigned int bcm63xx_get_cpu_freq(void);
#ifdef CONFIG_BCM63XX_CPU_6328
# ifdef bcm63xx_get_cpu_id
# undef bcm63xx_get_cpu_id
# define bcm63xx_get_cpu_id() __bcm63xx_get_cpu_id()
# define BCMCPU_RUNTIME_DETECT
# else
# define bcm63xx_get_cpu_id() BCM6328_CPU_ID
# endif
# define BCMCPU_IS_6328() (bcm63xx_get_cpu_id() == BCM6328_CPU_ID)
#else
# define BCMCPU_IS_6328() (0)
#endif
#ifdef CONFIG_BCM63XX_CPU_6338 #ifdef CONFIG_BCM63XX_CPU_6338
# ifdef bcm63xx_get_cpu_id # ifdef bcm63xx_get_cpu_id
# undef bcm63xx_get_cpu_id # undef bcm63xx_get_cpu_id
...@@ -102,13 +116,13 @@ enum bcm63xx_regs_set { ...@@ -102,13 +116,13 @@ enum bcm63xx_regs_set {
RSET_UART1, RSET_UART1,
RSET_GPIO, RSET_GPIO,
RSET_SPI, RSET_SPI,
RSET_SPI2,
RSET_UDC0, RSET_UDC0,
RSET_OHCI0, RSET_OHCI0,
RSET_OHCI_PRIV, RSET_OHCI_PRIV,
RSET_USBH_PRIV, RSET_USBH_PRIV,
RSET_MPI, RSET_MPI,
RSET_PCMCIA, RSET_PCMCIA,
RSET_PCIE,
RSET_DSL, RSET_DSL,
RSET_ENET0, RSET_ENET0,
RSET_ENET1, RSET_ENET1,
...@@ -130,11 +144,17 @@ enum bcm63xx_regs_set { ...@@ -130,11 +144,17 @@ enum bcm63xx_regs_set {
RSET_PCMDMA, RSET_PCMDMA,
RSET_PCMDMAC, RSET_PCMDMAC,
RSET_PCMDMAS, RSET_PCMDMAS,
RSET_RNG,
RSET_MISC
}; };
#define RSET_DSL_LMEM_SIZE (64 * 1024 * 4) #define RSET_DSL_LMEM_SIZE (64 * 1024 * 4)
#define RSET_DSL_SIZE 4096 #define RSET_DSL_SIZE 4096
#define RSET_WDT_SIZE 12 #define RSET_WDT_SIZE 12
#define BCM_6338_RSET_SPI_SIZE 64
#define BCM_6348_RSET_SPI_SIZE 64
#define BCM_6358_RSET_SPI_SIZE 1804
#define BCM_6368_RSET_SPI_SIZE 1804
#define RSET_ENET_SIZE 2048 #define RSET_ENET_SIZE 2048
#define RSET_ENETDMA_SIZE 2048 #define RSET_ENETDMA_SIZE 2048
#define RSET_ENETSW_SIZE 65536 #define RSET_ENETSW_SIZE 65536
...@@ -149,7 +169,52 @@ enum bcm63xx_regs_set { ...@@ -149,7 +169,52 @@ enum bcm63xx_regs_set {
#define RSET_XTMDMA_SIZE 256 #define RSET_XTMDMA_SIZE 256
#define RSET_XTMDMAC_SIZE(chans) (16 * (chans)) #define RSET_XTMDMAC_SIZE(chans) (16 * (chans))
#define RSET_XTMDMAS_SIZE(chans) (16 * (chans)) #define RSET_XTMDMAS_SIZE(chans) (16 * (chans))
#define RSET_RNG_SIZE 20
/*
* 6328 register sets base address
*/
#define BCM_6328_DSL_LMEM_BASE (0xdeadbeef)
#define BCM_6328_PERF_BASE (0xb0000000)
#define BCM_6328_TIMER_BASE (0xb0000040)
#define BCM_6328_WDT_BASE (0xb000005c)
#define BCM_6328_UART0_BASE (0xb0000100)
#define BCM_6328_UART1_BASE (0xb0000120)
#define BCM_6328_GPIO_BASE (0xb0000080)
#define BCM_6328_SPI_BASE (0xdeadbeef)
#define BCM_6328_UDC0_BASE (0xdeadbeef)
#define BCM_6328_USBDMA_BASE (0xdeadbeef)
#define BCM_6328_OHCI0_BASE (0xdeadbeef)
#define BCM_6328_OHCI_PRIV_BASE (0xdeadbeef)
#define BCM_6328_USBH_PRIV_BASE (0xdeadbeef)
#define BCM_6328_MPI_BASE (0xdeadbeef)
#define BCM_6328_PCMCIA_BASE (0xdeadbeef)
#define BCM_6328_PCIE_BASE (0xb0e40000)
#define BCM_6328_SDRAM_REGS_BASE (0xdeadbeef)
#define BCM_6328_DSL_BASE (0xb0001900)
#define BCM_6328_UBUS_BASE (0xdeadbeef)
#define BCM_6328_ENET0_BASE (0xdeadbeef)
#define BCM_6328_ENET1_BASE (0xdeadbeef)
#define BCM_6328_ENETDMA_BASE (0xb000d800)
#define BCM_6328_ENETDMAC_BASE (0xb000da00)
#define BCM_6328_ENETDMAS_BASE (0xb000dc00)
#define BCM_6328_ENETSW_BASE (0xb0e00000)
#define BCM_6328_EHCI0_BASE (0x10002500)
#define BCM_6328_SDRAM_BASE (0xdeadbeef)
#define BCM_6328_MEMC_BASE (0xdeadbeef)
#define BCM_6328_DDR_BASE (0xb0003000)
#define BCM_6328_M2M_BASE (0xdeadbeef)
#define BCM_6328_ATM_BASE (0xdeadbeef)
#define BCM_6328_XTM_BASE (0xdeadbeef)
#define BCM_6328_XTMDMA_BASE (0xb000b800)
#define BCM_6328_XTMDMAC_BASE (0xdeadbeef)
#define BCM_6328_XTMDMAS_BASE (0xdeadbeef)
#define BCM_6328_PCM_BASE (0xb000a800)
#define BCM_6328_PCMDMA_BASE (0xdeadbeef)
#define BCM_6328_PCMDMAC_BASE (0xdeadbeef)
#define BCM_6328_PCMDMAS_BASE (0xdeadbeef)
#define BCM_6328_RNG_BASE (0xdeadbeef)
#define BCM_6328_MISC_BASE (0xb0001800)
/* /*
* 6338 register sets base address * 6338 register sets base address
*/ */
...@@ -162,7 +227,6 @@ enum bcm63xx_regs_set { ...@@ -162,7 +227,6 @@ enum bcm63xx_regs_set {
#define BCM_6338_UART1_BASE (0xdeadbeef) #define BCM_6338_UART1_BASE (0xdeadbeef)
#define BCM_6338_GPIO_BASE (0xfffe0400) #define BCM_6338_GPIO_BASE (0xfffe0400)
#define BCM_6338_SPI_BASE (0xfffe0c00) #define BCM_6338_SPI_BASE (0xfffe0c00)
#define BCM_6338_SPI2_BASE (0xdeadbeef)
#define BCM_6338_UDC0_BASE (0xdeadbeef) #define BCM_6338_UDC0_BASE (0xdeadbeef)
#define BCM_6338_USBDMA_BASE (0xfffe2400) #define BCM_6338_USBDMA_BASE (0xfffe2400)
#define BCM_6338_OHCI0_BASE (0xdeadbeef) #define BCM_6338_OHCI0_BASE (0xdeadbeef)
...@@ -170,6 +234,7 @@ enum bcm63xx_regs_set { ...@@ -170,6 +234,7 @@ enum bcm63xx_regs_set {
#define BCM_6338_USBH_PRIV_BASE (0xdeadbeef) #define BCM_6338_USBH_PRIV_BASE (0xdeadbeef)
#define BCM_6338_MPI_BASE (0xfffe3160) #define BCM_6338_MPI_BASE (0xfffe3160)
#define BCM_6338_PCMCIA_BASE (0xdeadbeef) #define BCM_6338_PCMCIA_BASE (0xdeadbeef)
#define BCM_6338_PCIE_BASE (0xdeadbeef)
#define BCM_6338_SDRAM_REGS_BASE (0xfffe3100) #define BCM_6338_SDRAM_REGS_BASE (0xfffe3100)
#define BCM_6338_DSL_BASE (0xfffe1000) #define BCM_6338_DSL_BASE (0xfffe1000)
#define BCM_6338_UBUS_BASE (0xdeadbeef) #define BCM_6338_UBUS_BASE (0xdeadbeef)
...@@ -193,6 +258,8 @@ enum bcm63xx_regs_set { ...@@ -193,6 +258,8 @@ enum bcm63xx_regs_set {
#define BCM_6338_PCMDMA_BASE (0xdeadbeef) #define BCM_6338_PCMDMA_BASE (0xdeadbeef)
#define BCM_6338_PCMDMAC_BASE (0xdeadbeef) #define BCM_6338_PCMDMAC_BASE (0xdeadbeef)
#define BCM_6338_PCMDMAS_BASE (0xdeadbeef) #define BCM_6338_PCMDMAS_BASE (0xdeadbeef)
#define BCM_6338_RNG_BASE (0xdeadbeef)
#define BCM_6338_MISC_BASE (0xdeadbeef)
/* /*
* 6345 register sets base address * 6345 register sets base address
...@@ -206,7 +273,6 @@ enum bcm63xx_regs_set { ...@@ -206,7 +273,6 @@ enum bcm63xx_regs_set {
#define BCM_6345_UART1_BASE (0xdeadbeef) #define BCM_6345_UART1_BASE (0xdeadbeef)
#define BCM_6345_GPIO_BASE (0xfffe0400) #define BCM_6345_GPIO_BASE (0xfffe0400)
#define BCM_6345_SPI_BASE (0xdeadbeef) #define BCM_6345_SPI_BASE (0xdeadbeef)
#define BCM_6345_SPI2_BASE (0xdeadbeef)
#define BCM_6345_UDC0_BASE (0xdeadbeef) #define BCM_6345_UDC0_BASE (0xdeadbeef)
#define BCM_6345_USBDMA_BASE (0xfffe2800) #define BCM_6345_USBDMA_BASE (0xfffe2800)
#define BCM_6345_ENET0_BASE (0xfffe1800) #define BCM_6345_ENET0_BASE (0xfffe1800)
...@@ -216,6 +282,7 @@ enum bcm63xx_regs_set { ...@@ -216,6 +282,7 @@ enum bcm63xx_regs_set {
#define BCM_6345_ENETSW_BASE (0xdeadbeef) #define BCM_6345_ENETSW_BASE (0xdeadbeef)
#define BCM_6345_PCMCIA_BASE (0xfffe2028) #define BCM_6345_PCMCIA_BASE (0xfffe2028)
#define BCM_6345_MPI_BASE (0xfffe2000) #define BCM_6345_MPI_BASE (0xfffe2000)
#define BCM_6345_PCIE_BASE (0xdeadbeef)
#define BCM_6345_OHCI0_BASE (0xfffe2100) #define BCM_6345_OHCI0_BASE (0xfffe2100)
#define BCM_6345_OHCI_PRIV_BASE (0xfffe2200) #define BCM_6345_OHCI_PRIV_BASE (0xfffe2200)
#define BCM_6345_USBH_PRIV_BASE (0xdeadbeef) #define BCM_6345_USBH_PRIV_BASE (0xdeadbeef)
...@@ -237,6 +304,8 @@ enum bcm63xx_regs_set { ...@@ -237,6 +304,8 @@ enum bcm63xx_regs_set {
#define BCM_6345_PCMDMA_BASE (0xdeadbeef) #define BCM_6345_PCMDMA_BASE (0xdeadbeef)
#define BCM_6345_PCMDMAC_BASE (0xdeadbeef) #define BCM_6345_PCMDMAC_BASE (0xdeadbeef)
#define BCM_6345_PCMDMAS_BASE (0xdeadbeef) #define BCM_6345_PCMDMAS_BASE (0xdeadbeef)
#define BCM_6345_RNG_BASE (0xdeadbeef)
#define BCM_6345_MISC_BASE (0xdeadbeef)
/* /*
* 6348 register sets base address * 6348 register sets base address
...@@ -249,13 +318,13 @@ enum bcm63xx_regs_set { ...@@ -249,13 +318,13 @@ enum bcm63xx_regs_set {
#define BCM_6348_UART1_BASE (0xdeadbeef) #define BCM_6348_UART1_BASE (0xdeadbeef)
#define BCM_6348_GPIO_BASE (0xfffe0400) #define BCM_6348_GPIO_BASE (0xfffe0400)
#define BCM_6348_SPI_BASE (0xfffe0c00) #define BCM_6348_SPI_BASE (0xfffe0c00)
#define BCM_6348_SPI2_BASE (0xdeadbeef)
#define BCM_6348_UDC0_BASE (0xfffe1000) #define BCM_6348_UDC0_BASE (0xfffe1000)
#define BCM_6348_OHCI0_BASE (0xfffe1b00) #define BCM_6348_OHCI0_BASE (0xfffe1b00)
#define BCM_6348_OHCI_PRIV_BASE (0xfffe1c00) #define BCM_6348_OHCI_PRIV_BASE (0xfffe1c00)
#define BCM_6348_USBH_PRIV_BASE (0xdeadbeef) #define BCM_6348_USBH_PRIV_BASE (0xdeadbeef)
#define BCM_6348_MPI_BASE (0xfffe2000) #define BCM_6348_MPI_BASE (0xfffe2000)
#define BCM_6348_PCMCIA_BASE (0xfffe2054) #define BCM_6348_PCMCIA_BASE (0xfffe2054)
#define BCM_6348_PCIE_BASE (0xdeadbeef)
#define BCM_6348_SDRAM_REGS_BASE (0xfffe2300) #define BCM_6348_SDRAM_REGS_BASE (0xfffe2300)
#define BCM_6348_M2M_BASE (0xfffe2800) #define BCM_6348_M2M_BASE (0xfffe2800)
#define BCM_6348_DSL_BASE (0xfffe3000) #define BCM_6348_DSL_BASE (0xfffe3000)
...@@ -278,6 +347,8 @@ enum bcm63xx_regs_set { ...@@ -278,6 +347,8 @@ enum bcm63xx_regs_set {
#define BCM_6348_PCMDMA_BASE (0xdeadbeef) #define BCM_6348_PCMDMA_BASE (0xdeadbeef)
#define BCM_6348_PCMDMAC_BASE (0xdeadbeef) #define BCM_6348_PCMDMAC_BASE (0xdeadbeef)
#define BCM_6348_PCMDMAS_BASE (0xdeadbeef) #define BCM_6348_PCMDMAS_BASE (0xdeadbeef)
#define BCM_6348_RNG_BASE (0xdeadbeef)
#define BCM_6348_MISC_BASE (0xdeadbeef)
/* /*
* 6358 register sets base address * 6358 register sets base address
...@@ -289,14 +360,14 @@ enum bcm63xx_regs_set { ...@@ -289,14 +360,14 @@ enum bcm63xx_regs_set {
#define BCM_6358_UART0_BASE (0xfffe0100) #define BCM_6358_UART0_BASE (0xfffe0100)
#define BCM_6358_UART1_BASE (0xfffe0120) #define BCM_6358_UART1_BASE (0xfffe0120)
#define BCM_6358_GPIO_BASE (0xfffe0080) #define BCM_6358_GPIO_BASE (0xfffe0080)
#define BCM_6358_SPI_BASE (0xdeadbeef) #define BCM_6358_SPI_BASE (0xfffe0800)
#define BCM_6358_SPI2_BASE (0xfffe0800)
#define BCM_6358_UDC0_BASE (0xfffe0800) #define BCM_6358_UDC0_BASE (0xfffe0800)
#define BCM_6358_OHCI0_BASE (0xfffe1400) #define BCM_6358_OHCI0_BASE (0xfffe1400)
#define BCM_6358_OHCI_PRIV_BASE (0xdeadbeef) #define BCM_6358_OHCI_PRIV_BASE (0xdeadbeef)
#define BCM_6358_USBH_PRIV_BASE (0xfffe1500) #define BCM_6358_USBH_PRIV_BASE (0xfffe1500)
#define BCM_6358_MPI_BASE (0xfffe1000) #define BCM_6358_MPI_BASE (0xfffe1000)
#define BCM_6358_PCMCIA_BASE (0xfffe1054) #define BCM_6358_PCMCIA_BASE (0xfffe1054)
#define BCM_6358_PCIE_BASE (0xdeadbeef)
#define BCM_6358_SDRAM_REGS_BASE (0xfffe2300) #define BCM_6358_SDRAM_REGS_BASE (0xfffe2300)
#define BCM_6358_M2M_BASE (0xdeadbeef) #define BCM_6358_M2M_BASE (0xdeadbeef)
#define BCM_6358_DSL_BASE (0xfffe3000) #define BCM_6358_DSL_BASE (0xfffe3000)
...@@ -319,6 +390,8 @@ enum bcm63xx_regs_set { ...@@ -319,6 +390,8 @@ enum bcm63xx_regs_set {
#define BCM_6358_PCMDMA_BASE (0xfffe1800) #define BCM_6358_PCMDMA_BASE (0xfffe1800)
#define BCM_6358_PCMDMAC_BASE (0xfffe1900) #define BCM_6358_PCMDMAC_BASE (0xfffe1900)
#define BCM_6358_PCMDMAS_BASE (0xfffe1a00) #define BCM_6358_PCMDMAS_BASE (0xfffe1a00)
#define BCM_6358_RNG_BASE (0xdeadbeef)
#define BCM_6358_MISC_BASE (0xdeadbeef)
/* /*
...@@ -331,14 +404,14 @@ enum bcm63xx_regs_set { ...@@ -331,14 +404,14 @@ enum bcm63xx_regs_set {
#define BCM_6368_UART0_BASE (0xb0000100) #define BCM_6368_UART0_BASE (0xb0000100)
#define BCM_6368_UART1_BASE (0xb0000120) #define BCM_6368_UART1_BASE (0xb0000120)
#define BCM_6368_GPIO_BASE (0xb0000080) #define BCM_6368_GPIO_BASE (0xb0000080)
#define BCM_6368_SPI_BASE (0xdeadbeef) #define BCM_6368_SPI_BASE (0xb0000800)
#define BCM_6368_SPI2_BASE (0xb0000800)
#define BCM_6368_UDC0_BASE (0xdeadbeef) #define BCM_6368_UDC0_BASE (0xdeadbeef)
#define BCM_6368_OHCI0_BASE (0xb0001600) #define BCM_6368_OHCI0_BASE (0xb0001600)
#define BCM_6368_OHCI_PRIV_BASE (0xdeadbeef) #define BCM_6368_OHCI_PRIV_BASE (0xdeadbeef)
#define BCM_6368_USBH_PRIV_BASE (0xb0001700) #define BCM_6368_USBH_PRIV_BASE (0xb0001700)
#define BCM_6368_MPI_BASE (0xb0001000) #define BCM_6368_MPI_BASE (0xb0001000)
#define BCM_6368_PCMCIA_BASE (0xb0001054) #define BCM_6368_PCMCIA_BASE (0xb0001054)
#define BCM_6368_PCIE_BASE (0xdeadbeef)
#define BCM_6368_SDRAM_REGS_BASE (0xdeadbeef) #define BCM_6368_SDRAM_REGS_BASE (0xdeadbeef)
#define BCM_6368_M2M_BASE (0xdeadbeef) #define BCM_6368_M2M_BASE (0xdeadbeef)
#define BCM_6368_DSL_BASE (0xdeadbeef) #define BCM_6368_DSL_BASE (0xdeadbeef)
...@@ -361,6 +434,8 @@ enum bcm63xx_regs_set { ...@@ -361,6 +434,8 @@ enum bcm63xx_regs_set {
#define BCM_6368_PCMDMA_BASE (0xb0005800) #define BCM_6368_PCMDMA_BASE (0xb0005800)
#define BCM_6368_PCMDMAC_BASE (0xb0005a00) #define BCM_6368_PCMDMAC_BASE (0xb0005a00)
#define BCM_6368_PCMDMAS_BASE (0xb0005c00) #define BCM_6368_PCMDMAS_BASE (0xb0005c00)
#define BCM_6368_RNG_BASE (0xb0004180)
#define BCM_6368_MISC_BASE (0xdeadbeef)
extern const unsigned long *bcm63xx_regs_base; extern const unsigned long *bcm63xx_regs_base;
...@@ -379,13 +454,13 @@ extern const unsigned long *bcm63xx_regs_base; ...@@ -379,13 +454,13 @@ extern const unsigned long *bcm63xx_regs_base;
__GEN_RSET_BASE(__cpu, UART1) \ __GEN_RSET_BASE(__cpu, UART1) \
__GEN_RSET_BASE(__cpu, GPIO) \ __GEN_RSET_BASE(__cpu, GPIO) \
__GEN_RSET_BASE(__cpu, SPI) \ __GEN_RSET_BASE(__cpu, SPI) \
__GEN_RSET_BASE(__cpu, SPI2) \
__GEN_RSET_BASE(__cpu, UDC0) \ __GEN_RSET_BASE(__cpu, UDC0) \
__GEN_RSET_BASE(__cpu, OHCI0) \ __GEN_RSET_BASE(__cpu, OHCI0) \
__GEN_RSET_BASE(__cpu, OHCI_PRIV) \ __GEN_RSET_BASE(__cpu, OHCI_PRIV) \
__GEN_RSET_BASE(__cpu, USBH_PRIV) \ __GEN_RSET_BASE(__cpu, USBH_PRIV) \
__GEN_RSET_BASE(__cpu, MPI) \ __GEN_RSET_BASE(__cpu, MPI) \
__GEN_RSET_BASE(__cpu, PCMCIA) \ __GEN_RSET_BASE(__cpu, PCMCIA) \
__GEN_RSET_BASE(__cpu, PCIE) \
__GEN_RSET_BASE(__cpu, DSL) \ __GEN_RSET_BASE(__cpu, DSL) \
__GEN_RSET_BASE(__cpu, ENET0) \ __GEN_RSET_BASE(__cpu, ENET0) \
__GEN_RSET_BASE(__cpu, ENET1) \ __GEN_RSET_BASE(__cpu, ENET1) \
...@@ -407,6 +482,8 @@ extern const unsigned long *bcm63xx_regs_base; ...@@ -407,6 +482,8 @@ extern const unsigned long *bcm63xx_regs_base;
__GEN_RSET_BASE(__cpu, PCMDMA) \ __GEN_RSET_BASE(__cpu, PCMDMA) \
__GEN_RSET_BASE(__cpu, PCMDMAC) \ __GEN_RSET_BASE(__cpu, PCMDMAC) \
__GEN_RSET_BASE(__cpu, PCMDMAS) \ __GEN_RSET_BASE(__cpu, PCMDMAS) \
__GEN_RSET_BASE(__cpu, RNG) \
__GEN_RSET_BASE(__cpu, MISC) \
} }
#define __GEN_CPU_REGS_TABLE(__cpu) \ #define __GEN_CPU_REGS_TABLE(__cpu) \
...@@ -418,13 +495,13 @@ extern const unsigned long *bcm63xx_regs_base; ...@@ -418,13 +495,13 @@ extern const unsigned long *bcm63xx_regs_base;
[RSET_UART1] = BCM_## __cpu ##_UART1_BASE, \ [RSET_UART1] = BCM_## __cpu ##_UART1_BASE, \
[RSET_GPIO] = BCM_## __cpu ##_GPIO_BASE, \ [RSET_GPIO] = BCM_## __cpu ##_GPIO_BASE, \
[RSET_SPI] = BCM_## __cpu ##_SPI_BASE, \ [RSET_SPI] = BCM_## __cpu ##_SPI_BASE, \
[RSET_SPI2] = BCM_## __cpu ##_SPI2_BASE, \
[RSET_UDC0] = BCM_## __cpu ##_UDC0_BASE, \ [RSET_UDC0] = BCM_## __cpu ##_UDC0_BASE, \
[RSET_OHCI0] = BCM_## __cpu ##_OHCI0_BASE, \ [RSET_OHCI0] = BCM_## __cpu ##_OHCI0_BASE, \
[RSET_OHCI_PRIV] = BCM_## __cpu ##_OHCI_PRIV_BASE, \ [RSET_OHCI_PRIV] = BCM_## __cpu ##_OHCI_PRIV_BASE, \
[RSET_USBH_PRIV] = BCM_## __cpu ##_USBH_PRIV_BASE, \ [RSET_USBH_PRIV] = BCM_## __cpu ##_USBH_PRIV_BASE, \
[RSET_MPI] = BCM_## __cpu ##_MPI_BASE, \ [RSET_MPI] = BCM_## __cpu ##_MPI_BASE, \
[RSET_PCMCIA] = BCM_## __cpu ##_PCMCIA_BASE, \ [RSET_PCMCIA] = BCM_## __cpu ##_PCMCIA_BASE, \
[RSET_PCIE] = BCM_## __cpu ##_PCIE_BASE, \
[RSET_DSL] = BCM_## __cpu ##_DSL_BASE, \ [RSET_DSL] = BCM_## __cpu ##_DSL_BASE, \
[RSET_ENET0] = BCM_## __cpu ##_ENET0_BASE, \ [RSET_ENET0] = BCM_## __cpu ##_ENET0_BASE, \
[RSET_ENET1] = BCM_## __cpu ##_ENET1_BASE, \ [RSET_ENET1] = BCM_## __cpu ##_ENET1_BASE, \
...@@ -446,6 +523,8 @@ extern const unsigned long *bcm63xx_regs_base; ...@@ -446,6 +523,8 @@ extern const unsigned long *bcm63xx_regs_base;
[RSET_PCMDMA] = BCM_## __cpu ##_PCMDMA_BASE, \ [RSET_PCMDMA] = BCM_## __cpu ##_PCMDMA_BASE, \
[RSET_PCMDMAC] = BCM_## __cpu ##_PCMDMAC_BASE, \ [RSET_PCMDMAC] = BCM_## __cpu ##_PCMDMAC_BASE, \
[RSET_PCMDMAS] = BCM_## __cpu ##_PCMDMAS_BASE, \ [RSET_PCMDMAS] = BCM_## __cpu ##_PCMDMAS_BASE, \
[RSET_RNG] = BCM_## __cpu ##_RNG_BASE, \
[RSET_MISC] = BCM_## __cpu ##_MISC_BASE, \
static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set) static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
...@@ -453,6 +532,9 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set) ...@@ -453,6 +532,9 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
#ifdef BCMCPU_RUNTIME_DETECT #ifdef BCMCPU_RUNTIME_DETECT
return bcm63xx_regs_base[set]; return bcm63xx_regs_base[set];
#else #else
#ifdef CONFIG_BCM63XX_CPU_6328
__GEN_RSET(6328)
#endif
#ifdef CONFIG_BCM63XX_CPU_6338 #ifdef CONFIG_BCM63XX_CPU_6338
__GEN_RSET(6338) __GEN_RSET(6338)
#endif #endif
...@@ -478,6 +560,7 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set) ...@@ -478,6 +560,7 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
*/ */
enum bcm63xx_irq { enum bcm63xx_irq {
IRQ_TIMER = 0, IRQ_TIMER = 0,
IRQ_SPI,
IRQ_UART0, IRQ_UART0,
IRQ_UART1, IRQ_UART1,
IRQ_DSL, IRQ_DSL,
...@@ -505,10 +588,52 @@ enum bcm63xx_irq { ...@@ -505,10 +588,52 @@ enum bcm63xx_irq {
IRQ_XTM_DMA0, IRQ_XTM_DMA0,
}; };
/*
* 6328 irqs
*/
#define BCM_6328_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32)
#define BCM_6328_TIMER_IRQ (IRQ_INTERNAL_BASE + 31)
#define BCM_6328_SPI_IRQ 0
#define BCM_6328_UART0_IRQ (IRQ_INTERNAL_BASE + 28)
#define BCM_6328_UART1_IRQ (BCM_6328_HIGH_IRQ_BASE + 7)
#define BCM_6328_DSL_IRQ (IRQ_INTERNAL_BASE + 4)
#define BCM_6328_UDC0_IRQ 0
#define BCM_6328_ENET0_IRQ 0
#define BCM_6328_ENET1_IRQ 0
#define BCM_6328_ENET_PHY_IRQ (IRQ_INTERNAL_BASE + 12)
#define BCM_6328_OHCI0_IRQ (IRQ_INTERNAL_BASE + 9)
#define BCM_6328_EHCI0_IRQ (IRQ_INTERNAL_BASE + 10)
#define BCM_6328_PCMCIA_IRQ 0
#define BCM_6328_ENET0_RXDMA_IRQ 0
#define BCM_6328_ENET0_TXDMA_IRQ 0
#define BCM_6328_ENET1_RXDMA_IRQ 0
#define BCM_6328_ENET1_TXDMA_IRQ 0
#define BCM_6328_PCI_IRQ (IRQ_INTERNAL_BASE + 23)
#define BCM_6328_ATM_IRQ 0
#define BCM_6328_ENETSW_RXDMA0_IRQ (BCM_6328_HIGH_IRQ_BASE + 0)
#define BCM_6328_ENETSW_RXDMA1_IRQ (BCM_6328_HIGH_IRQ_BASE + 1)
#define BCM_6328_ENETSW_RXDMA2_IRQ (BCM_6328_HIGH_IRQ_BASE + 2)
#define BCM_6328_ENETSW_RXDMA3_IRQ (BCM_6328_HIGH_IRQ_BASE + 3)
#define BCM_6328_ENETSW_TXDMA0_IRQ (BCM_6328_HIGH_IRQ_BASE + 4)
#define BCM_6328_ENETSW_TXDMA1_IRQ (BCM_6328_HIGH_IRQ_BASE + 5)
#define BCM_6328_ENETSW_TXDMA2_IRQ (BCM_6328_HIGH_IRQ_BASE + 6)
#define BCM_6328_ENETSW_TXDMA3_IRQ (BCM_6328_HIGH_IRQ_BASE + 7)
#define BCM_6328_XTM_IRQ (BCM_6328_HIGH_IRQ_BASE + 31)
#define BCM_6328_XTM_DMA0_IRQ (BCM_6328_HIGH_IRQ_BASE + 11)
#define BCM_6328_PCM_DMA0_IRQ (IRQ_INTERNAL_BASE + 2)
#define BCM_6328_PCM_DMA1_IRQ (IRQ_INTERNAL_BASE + 3)
#define BCM_6328_EXT_IRQ0 (IRQ_INTERNAL_BASE + 24)
#define BCM_6328_EXT_IRQ1 (IRQ_INTERNAL_BASE + 25)
#define BCM_6328_EXT_IRQ2 (IRQ_INTERNAL_BASE + 26)
#define BCM_6328_EXT_IRQ3 (IRQ_INTERNAL_BASE + 27)
/* /*
* 6338 irqs * 6338 irqs
*/ */
#define BCM_6338_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) #define BCM_6338_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
#define BCM_6338_SPI_IRQ (IRQ_INTERNAL_BASE + 1)
#define BCM_6338_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6338_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
#define BCM_6338_UART1_IRQ 0 #define BCM_6338_UART1_IRQ 0
#define BCM_6338_DSL_IRQ (IRQ_INTERNAL_BASE + 5) #define BCM_6338_DSL_IRQ (IRQ_INTERNAL_BASE + 5)
...@@ -539,6 +664,7 @@ enum bcm63xx_irq { ...@@ -539,6 +664,7 @@ enum bcm63xx_irq {
* 6345 irqs * 6345 irqs
*/ */
#define BCM_6345_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) #define BCM_6345_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
#define BCM_6345_SPI_IRQ 0
#define BCM_6345_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6345_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
#define BCM_6345_UART1_IRQ 0 #define BCM_6345_UART1_IRQ 0
#define BCM_6345_DSL_IRQ (IRQ_INTERNAL_BASE + 3) #define BCM_6345_DSL_IRQ (IRQ_INTERNAL_BASE + 3)
...@@ -569,6 +695,7 @@ enum bcm63xx_irq { ...@@ -569,6 +695,7 @@ enum bcm63xx_irq {
* 6348 irqs * 6348 irqs
*/ */
#define BCM_6348_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) #define BCM_6348_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
#define BCM_6348_SPI_IRQ (IRQ_INTERNAL_BASE + 1)
#define BCM_6348_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6348_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
#define BCM_6348_UART1_IRQ 0 #define BCM_6348_UART1_IRQ 0
#define BCM_6348_DSL_IRQ (IRQ_INTERNAL_BASE + 4) #define BCM_6348_DSL_IRQ (IRQ_INTERNAL_BASE + 4)
...@@ -599,6 +726,7 @@ enum bcm63xx_irq { ...@@ -599,6 +726,7 @@ enum bcm63xx_irq {
* 6358 irqs * 6358 irqs
*/ */
#define BCM_6358_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) #define BCM_6358_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
#define BCM_6358_SPI_IRQ (IRQ_INTERNAL_BASE + 1)
#define BCM_6358_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6358_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
#define BCM_6358_UART1_IRQ (IRQ_INTERNAL_BASE + 3) #define BCM_6358_UART1_IRQ (IRQ_INTERNAL_BASE + 3)
#define BCM_6358_DSL_IRQ (IRQ_INTERNAL_BASE + 29) #define BCM_6358_DSL_IRQ (IRQ_INTERNAL_BASE + 29)
...@@ -638,6 +766,7 @@ enum bcm63xx_irq { ...@@ -638,6 +766,7 @@ enum bcm63xx_irq {
#define BCM_6368_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32) #define BCM_6368_HIGH_IRQ_BASE (IRQ_INTERNAL_BASE + 32)
#define BCM_6368_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) #define BCM_6368_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
#define BCM_6368_SPI_IRQ (IRQ_INTERNAL_BASE + 1)
#define BCM_6368_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6368_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
#define BCM_6368_UART1_IRQ (IRQ_INTERNAL_BASE + 3) #define BCM_6368_UART1_IRQ (IRQ_INTERNAL_BASE + 3)
#define BCM_6368_DSL_IRQ (IRQ_INTERNAL_BASE + 4) #define BCM_6368_DSL_IRQ (IRQ_INTERNAL_BASE + 4)
...@@ -677,6 +806,7 @@ extern const int *bcm63xx_irqs; ...@@ -677,6 +806,7 @@ extern const int *bcm63xx_irqs;
#define __GEN_CPU_IRQ_TABLE(__cpu) \ #define __GEN_CPU_IRQ_TABLE(__cpu) \
[IRQ_TIMER] = BCM_## __cpu ##_TIMER_IRQ, \ [IRQ_TIMER] = BCM_## __cpu ##_TIMER_IRQ, \
[IRQ_SPI] = BCM_## __cpu ##_SPI_IRQ, \
[IRQ_UART0] = BCM_## __cpu ##_UART0_IRQ, \ [IRQ_UART0] = BCM_## __cpu ##_UART0_IRQ, \
[IRQ_UART1] = BCM_## __cpu ##_UART1_IRQ, \ [IRQ_UART1] = BCM_## __cpu ##_UART1_IRQ, \
[IRQ_DSL] = BCM_## __cpu ##_DSL_IRQ, \ [IRQ_DSL] = BCM_## __cpu ##_DSL_IRQ, \
......
#ifndef __BCM63XX_FLASH_H
#define __BCM63XX_FLASH_H
enum {
BCM63XX_FLASH_TYPE_PARALLEL,
BCM63XX_FLASH_TYPE_SERIAL,
BCM63XX_FLASH_TYPE_NAND,
};
int __init bcm63xx_flash_register(void);
#endif /* __BCM63XX_FLASH_H */
#ifndef BCM63XX_DEV_SPI_H
#define BCM63XX_DEV_SPI_H
#include <linux/types.h>
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
int __init bcm63xx_spi_register(void);
struct bcm63xx_spi_pdata {
unsigned int fifo_size;
int bus_num;
int num_chipselect;
u32 speed_hz;
};
enum bcm63xx_regs_spi {
SPI_CMD,
SPI_INT_STATUS,
SPI_INT_MASK_ST,
SPI_INT_MASK,
SPI_ST,
SPI_CLK_CFG,
SPI_FILL_BYTE,
SPI_MSG_TAIL,
SPI_RX_TAIL,
SPI_MSG_CTL,
SPI_MSG_DATA,
SPI_RX_DATA,
};
#define __GEN_SPI_RSET_BASE(__cpu, __rset) \
case SPI_## __rset: \
return SPI_## __cpu ##_## __rset;
#define __GEN_SPI_RSET(__cpu) \
switch (reg) { \
__GEN_SPI_RSET_BASE(__cpu, CMD) \
__GEN_SPI_RSET_BASE(__cpu, INT_STATUS) \
__GEN_SPI_RSET_BASE(__cpu, INT_MASK_ST) \
__GEN_SPI_RSET_BASE(__cpu, INT_MASK) \
__GEN_SPI_RSET_BASE(__cpu, ST) \
__GEN_SPI_RSET_BASE(__cpu, CLK_CFG) \
__GEN_SPI_RSET_BASE(__cpu, FILL_BYTE) \
__GEN_SPI_RSET_BASE(__cpu, MSG_TAIL) \
__GEN_SPI_RSET_BASE(__cpu, RX_TAIL) \
__GEN_SPI_RSET_BASE(__cpu, MSG_CTL) \
__GEN_SPI_RSET_BASE(__cpu, MSG_DATA) \
__GEN_SPI_RSET_BASE(__cpu, RX_DATA) \
}
#define __GEN_SPI_REGS_TABLE(__cpu) \
[SPI_CMD] = SPI_## __cpu ##_CMD, \
[SPI_INT_STATUS] = SPI_## __cpu ##_INT_STATUS, \
[SPI_INT_MASK_ST] = SPI_## __cpu ##_INT_MASK_ST, \
[SPI_INT_MASK] = SPI_## __cpu ##_INT_MASK, \
[SPI_ST] = SPI_## __cpu ##_ST, \
[SPI_CLK_CFG] = SPI_## __cpu ##_CLK_CFG, \
[SPI_FILL_BYTE] = SPI_## __cpu ##_FILL_BYTE, \
[SPI_MSG_TAIL] = SPI_## __cpu ##_MSG_TAIL, \
[SPI_RX_TAIL] = SPI_## __cpu ##_RX_TAIL, \
[SPI_MSG_CTL] = SPI_## __cpu ##_MSG_CTL, \
[SPI_MSG_DATA] = SPI_## __cpu ##_MSG_DATA, \
[SPI_RX_DATA] = SPI_## __cpu ##_RX_DATA,
static inline unsigned long bcm63xx_spireg(enum bcm63xx_regs_spi reg)
{
#ifdef BCMCPU_RUNTIME_DETECT
extern const unsigned long *bcm63xx_regs_spi;
return bcm63xx_regs_spi[reg];
#else
#ifdef CONFIG_BCM63XX_CPU_6338
__GEN_SPI_RSET(6338)
#endif
#ifdef CONFIG_BCM63XX_CPU_6348
__GEN_SPI_RSET(6348)
#endif
#ifdef CONFIG_BCM63XX_CPU_6358
__GEN_SPI_RSET(6358)
#endif
#ifdef CONFIG_BCM63XX_CPU_6368
__GEN_SPI_RSET(6368)
#endif
#endif
return 0;
}
#endif /* BCM63XX_DEV_SPI_H */
...@@ -9,6 +9,8 @@ int __init bcm63xx_gpio_init(void); ...@@ -9,6 +9,8 @@ int __init bcm63xx_gpio_init(void);
static inline unsigned long bcm63xx_gpio_count(void) static inline unsigned long bcm63xx_gpio_count(void)
{ {
switch (bcm63xx_get_cpu_id()) { switch (bcm63xx_get_cpu_id()) {
case BCM6328_CPU_ID:
return 32;
case BCM6358_CPU_ID: case BCM6358_CPU_ID:
return 40; return 40;
case BCM6338_CPU_ID: case BCM6338_CPU_ID:
......
...@@ -40,6 +40,10 @@ ...@@ -40,6 +40,10 @@
#define BCM_CB_MEM_END_PA (BCM_CB_MEM_BASE_PA + \ #define BCM_CB_MEM_END_PA (BCM_CB_MEM_BASE_PA + \
BCM_CB_MEM_SIZE - 1) BCM_CB_MEM_SIZE - 1)
#define BCM_PCIE_MEM_BASE_PA 0x10f00000
#define BCM_PCIE_MEM_SIZE (16 * 1024 * 1024)
#define BCM_PCIE_MEM_END_PA (BCM_PCIE_MEM_BASE_PA + \
BCM_PCIE_MEM_SIZE - 1)
/* /*
* Internal registers are accessed through KSEG3 * Internal registers are accessed through KSEG3
...@@ -85,11 +89,15 @@ ...@@ -85,11 +89,15 @@
#define bcm_mpi_writel(v, o) bcm_rset_writel(RSET_MPI, (v), (o)) #define bcm_mpi_writel(v, o) bcm_rset_writel(RSET_MPI, (v), (o))
#define bcm_pcmcia_readl(o) bcm_rset_readl(RSET_PCMCIA, (o)) #define bcm_pcmcia_readl(o) bcm_rset_readl(RSET_PCMCIA, (o))
#define bcm_pcmcia_writel(v, o) bcm_rset_writel(RSET_PCMCIA, (v), (o)) #define bcm_pcmcia_writel(v, o) bcm_rset_writel(RSET_PCMCIA, (v), (o))
#define bcm_pcie_readl(o) bcm_rset_readl(RSET_PCIE, (o))
#define bcm_pcie_writel(v, o) bcm_rset_writel(RSET_PCIE, (v), (o))
#define bcm_sdram_readl(o) bcm_rset_readl(RSET_SDRAM, (o)) #define bcm_sdram_readl(o) bcm_rset_readl(RSET_SDRAM, (o))
#define bcm_sdram_writel(v, o) bcm_rset_writel(RSET_SDRAM, (v), (o)) #define bcm_sdram_writel(v, o) bcm_rset_writel(RSET_SDRAM, (v), (o))
#define bcm_memc_readl(o) bcm_rset_readl(RSET_MEMC, (o)) #define bcm_memc_readl(o) bcm_rset_readl(RSET_MEMC, (o))
#define bcm_memc_writel(v, o) bcm_rset_writel(RSET_MEMC, (v), (o)) #define bcm_memc_writel(v, o) bcm_rset_writel(RSET_MEMC, (v), (o))
#define bcm_ddr_readl(o) bcm_rset_readl(RSET_DDR, (o)) #define bcm_ddr_readl(o) bcm_rset_readl(RSET_DDR, (o))
#define bcm_ddr_writel(v, o) bcm_rset_writel(RSET_DDR, (v), (o)) #define bcm_ddr_writel(v, o) bcm_rset_writel(RSET_DDR, (v), (o))
#define bcm_misc_readl(o) bcm_rset_readl(RSET_MISC, (o))
#define bcm_misc_writel(v, o) bcm_rset_writel(RSET_MISC, (v), (o))
#endif /* ! BCM63XX_IO_H_ */ #endif /* ! BCM63XX_IO_H_ */
...@@ -15,6 +15,30 @@ ...@@ -15,6 +15,30 @@
/* Clock Control register */ /* Clock Control register */
#define PERF_CKCTL_REG 0x4 #define PERF_CKCTL_REG 0x4
#define CKCTL_6328_PHYMIPS_EN (1 << 0)
#define CKCTL_6328_ADSL_QPROC_EN (1 << 1)
#define CKCTL_6328_ADSL_AFE_EN (1 << 2)
#define CKCTL_6328_ADSL_EN (1 << 3)
#define CKCTL_6328_MIPS_EN (1 << 4)
#define CKCTL_6328_SAR_EN (1 << 5)
#define CKCTL_6328_PCM_EN (1 << 6)
#define CKCTL_6328_USBD_EN (1 << 7)
#define CKCTL_6328_USBH_EN (1 << 8)
#define CKCTL_6328_HSSPI_EN (1 << 9)
#define CKCTL_6328_PCIE_EN (1 << 10)
#define CKCTL_6328_ROBOSW_EN (1 << 11)
#define CKCTL_6328_ALL_SAFE_EN (CKCTL_6328_PHYMIPS_EN | \
CKCTL_6328_ADSL_QPROC_EN | \
CKCTL_6328_ADSL_AFE_EN | \
CKCTL_6328_ADSL_EN | \
CKCTL_6328_SAR_EN | \
CKCTL_6328_PCM_EN | \
CKCTL_6328_USBD_EN | \
CKCTL_6328_USBH_EN | \
CKCTL_6328_ROBOSW_EN | \
CKCTL_6328_PCIE_EN)
#define CKCTL_6338_ADSLPHY_EN (1 << 0) #define CKCTL_6338_ADSLPHY_EN (1 << 0)
#define CKCTL_6338_MPI_EN (1 << 1) #define CKCTL_6338_MPI_EN (1 << 1)
#define CKCTL_6338_DRAM_EN (1 << 2) #define CKCTL_6338_DRAM_EN (1 << 2)
...@@ -90,35 +114,36 @@ ...@@ -90,35 +114,36 @@
#define CKCTL_6368_PHYMIPS_EN (1 << 6) #define CKCTL_6368_PHYMIPS_EN (1 << 6)
#define CKCTL_6368_SWPKT_USB_EN (1 << 7) #define CKCTL_6368_SWPKT_USB_EN (1 << 7)
#define CKCTL_6368_SWPKT_SAR_EN (1 << 8) #define CKCTL_6368_SWPKT_SAR_EN (1 << 8)
#define CKCTL_6368_SPI_CLK_EN (1 << 9) #define CKCTL_6368_SPI_EN (1 << 9)
#define CKCTL_6368_USBD_CLK_EN (1 << 10) #define CKCTL_6368_USBD_EN (1 << 10)
#define CKCTL_6368_SAR_CLK_EN (1 << 11) #define CKCTL_6368_SAR_EN (1 << 11)
#define CKCTL_6368_ROBOSW_CLK_EN (1 << 12) #define CKCTL_6368_ROBOSW_EN (1 << 12)
#define CKCTL_6368_UTOPIA_CLK_EN (1 << 13) #define CKCTL_6368_UTOPIA_EN (1 << 13)
#define CKCTL_6368_PCM_CLK_EN (1 << 14) #define CKCTL_6368_PCM_EN (1 << 14)
#define CKCTL_6368_USBH_CLK_EN (1 << 15) #define CKCTL_6368_USBH_EN (1 << 15)
#define CKCTL_6368_DISABLE_GLESS_EN (1 << 16) #define CKCTL_6368_DISABLE_GLESS_EN (1 << 16)
#define CKCTL_6368_NAND_CLK_EN (1 << 17) #define CKCTL_6368_NAND_EN (1 << 17)
#define CKCTL_6368_IPSEC_CLK_EN (1 << 18) #define CKCTL_6368_IPSEC_EN (1 << 18)
#define CKCTL_6368_ALL_SAFE_EN (CKCTL_6368_SWPKT_USB_EN | \ #define CKCTL_6368_ALL_SAFE_EN (CKCTL_6368_SWPKT_USB_EN | \
CKCTL_6368_SWPKT_SAR_EN | \ CKCTL_6368_SWPKT_SAR_EN | \
CKCTL_6368_SPI_CLK_EN | \ CKCTL_6368_SPI_EN | \
CKCTL_6368_USBD_CLK_EN | \ CKCTL_6368_USBD_EN | \
CKCTL_6368_SAR_CLK_EN | \ CKCTL_6368_SAR_EN | \
CKCTL_6368_ROBOSW_CLK_EN | \ CKCTL_6368_ROBOSW_EN | \
CKCTL_6368_UTOPIA_CLK_EN | \ CKCTL_6368_UTOPIA_EN | \
CKCTL_6368_PCM_CLK_EN | \ CKCTL_6368_PCM_EN | \
CKCTL_6368_USBH_CLK_EN | \ CKCTL_6368_USBH_EN | \
CKCTL_6368_DISABLE_GLESS_EN | \ CKCTL_6368_DISABLE_GLESS_EN | \
CKCTL_6368_NAND_CLK_EN | \ CKCTL_6368_NAND_EN | \
CKCTL_6368_IPSEC_CLK_EN) CKCTL_6368_IPSEC_EN)
/* System PLL Control register */ /* System PLL Control register */
#define PERF_SYS_PLL_CTL_REG 0x8 #define PERF_SYS_PLL_CTL_REG 0x8
#define SYS_PLL_SOFT_RESET 0x1 #define SYS_PLL_SOFT_RESET 0x1
/* Interrupt Mask register */ /* Interrupt Mask register */
#define PERF_IRQMASK_6328_REG 0x20
#define PERF_IRQMASK_6338_REG 0xc #define PERF_IRQMASK_6338_REG 0xc
#define PERF_IRQMASK_6345_REG 0xc #define PERF_IRQMASK_6345_REG 0xc
#define PERF_IRQMASK_6348_REG 0xc #define PERF_IRQMASK_6348_REG 0xc
...@@ -126,6 +151,7 @@ ...@@ -126,6 +151,7 @@
#define PERF_IRQMASK_6368_REG 0x20 #define PERF_IRQMASK_6368_REG 0x20
/* Interrupt Status register */ /* Interrupt Status register */
#define PERF_IRQSTAT_6328_REG 0x28
#define PERF_IRQSTAT_6338_REG 0x10 #define PERF_IRQSTAT_6338_REG 0x10
#define PERF_IRQSTAT_6345_REG 0x10 #define PERF_IRQSTAT_6345_REG 0x10
#define PERF_IRQSTAT_6348_REG 0x10 #define PERF_IRQSTAT_6348_REG 0x10
...@@ -133,6 +159,7 @@ ...@@ -133,6 +159,7 @@
#define PERF_IRQSTAT_6368_REG 0x28 #define PERF_IRQSTAT_6368_REG 0x28
/* External Interrupt Configuration register */ /* External Interrupt Configuration register */
#define PERF_EXTIRQ_CFG_REG_6328 0x18
#define PERF_EXTIRQ_CFG_REG_6338 0x14 #define PERF_EXTIRQ_CFG_REG_6338 0x14
#define PERF_EXTIRQ_CFG_REG_6348 0x14 #define PERF_EXTIRQ_CFG_REG_6348 0x14
#define PERF_EXTIRQ_CFG_REG_6358 0x14 #define PERF_EXTIRQ_CFG_REG_6358 0x14
...@@ -162,8 +189,21 @@ ...@@ -162,8 +189,21 @@
/* Soft Reset register */ /* Soft Reset register */
#define PERF_SOFTRESET_REG 0x28 #define PERF_SOFTRESET_REG 0x28
#define PERF_SOFTRESET_6328_REG 0x10
#define PERF_SOFTRESET_6368_REG 0x10 #define PERF_SOFTRESET_6368_REG 0x10
#define SOFTRESET_6328_SPI_MASK (1 << 0)
#define SOFTRESET_6328_EPHY_MASK (1 << 1)
#define SOFTRESET_6328_SAR_MASK (1 << 2)
#define SOFTRESET_6328_ENETSW_MASK (1 << 3)
#define SOFTRESET_6328_USBS_MASK (1 << 4)
#define SOFTRESET_6328_USBH_MASK (1 << 5)
#define SOFTRESET_6328_PCM_MASK (1 << 6)
#define SOFTRESET_6328_PCIE_CORE_MASK (1 << 7)
#define SOFTRESET_6328_PCIE_MASK (1 << 8)
#define SOFTRESET_6328_PCIE_EXT_MASK (1 << 9)
#define SOFTRESET_6328_PCIE_HARD_MASK (1 << 10)
#define SOFTRESET_6338_SPI_MASK (1 << 0) #define SOFTRESET_6338_SPI_MASK (1 << 0)
#define SOFTRESET_6338_ENET_MASK (1 << 2) #define SOFTRESET_6338_ENET_MASK (1 << 2)
#define SOFTRESET_6338_USBH_MASK (1 << 3) #define SOFTRESET_6338_USBH_MASK (1 << 3)
...@@ -307,6 +347,8 @@ ...@@ -307,6 +347,8 @@
/* Watchdog reset length register */ /* Watchdog reset length register */
#define WDT_RSTLEN_REG 0x8 #define WDT_RSTLEN_REG 0x8
/* Watchdog soft reset register (BCM6328 only) */
#define WDT_SOFTRESET_REG 0xc
/************************************************************************* /*************************************************************************
* _REG relative to RSET_UARTx * _REG relative to RSET_UARTx
...@@ -507,6 +549,15 @@ ...@@ -507,6 +549,15 @@
#define GPIO_BASEMODE_6368_MASK 0x7 #define GPIO_BASEMODE_6368_MASK 0x7
/* those bits must be kept as read in gpio basemode register*/ /* those bits must be kept as read in gpio basemode register*/
#define GPIO_STRAPBUS_REG 0x40
#define STRAPBUS_6358_BOOT_SEL_PARALLEL (1 << 1)
#define STRAPBUS_6358_BOOT_SEL_SERIAL (0 << 1)
#define STRAPBUS_6368_BOOT_SEL_MASK 0x3
#define STRAPBUS_6368_BOOT_SEL_NAND 0
#define STRAPBUS_6368_BOOT_SEL_SERIAL 1
#define STRAPBUS_6368_BOOT_SEL_PARALLEL 3
/************************************************************************* /*************************************************************************
* _REG relative to RSET_ENET * _REG relative to RSET_ENET
*************************************************************************/ *************************************************************************/
...@@ -924,6 +975,8 @@ ...@@ -924,6 +975,8 @@
* _REG relative to RSET_DDR * _REG relative to RSET_DDR
*************************************************************************/ *************************************************************************/
#define DDR_CSEND_REG 0x8
#define DDR_DMIPSPLLCFG_REG 0x18 #define DDR_DMIPSPLLCFG_REG 0x18
#define DMIPSPLLCFG_M1_SHIFT 0 #define DMIPSPLLCFG_M1_SHIFT 0
#define DMIPSPLLCFG_M1_MASK (0xff << DMIPSPLLCFG_M1_SHIFT) #define DMIPSPLLCFG_M1_MASK (0xff << DMIPSPLLCFG_M1_SHIFT)
...@@ -973,4 +1026,201 @@ ...@@ -973,4 +1026,201 @@
#define M2M_SRCID_REG(x) ((x) * 0x40 + 0x14) #define M2M_SRCID_REG(x) ((x) * 0x40 + 0x14)
#define M2M_DSTID_REG(x) ((x) * 0x40 + 0x18) #define M2M_DSTID_REG(x) ((x) * 0x40 + 0x18)
/*************************************************************************
* _REG relative to RSET_RNG
*************************************************************************/
#define RNG_CTRL 0x00
#define RNG_EN (1 << 0)
#define RNG_STAT 0x04
#define RNG_AVAIL_MASK (0xff000000)
#define RNG_DATA 0x08
#define RNG_THRES 0x0c
#define RNG_MASK 0x10
/*************************************************************************
* _REG relative to RSET_SPI
*************************************************************************/
/* BCM 6338 SPI core */
#define SPI_6338_CMD 0x00 /* 16-bits register */
#define SPI_6338_INT_STATUS 0x02
#define SPI_6338_INT_MASK_ST 0x03
#define SPI_6338_INT_MASK 0x04
#define SPI_6338_ST 0x05
#define SPI_6338_CLK_CFG 0x06
#define SPI_6338_FILL_BYTE 0x07
#define SPI_6338_MSG_TAIL 0x09
#define SPI_6338_RX_TAIL 0x0b
#define SPI_6338_MSG_CTL 0x40
#define SPI_6338_MSG_DATA 0x41
#define SPI_6338_MSG_DATA_SIZE 0x3f
#define SPI_6338_RX_DATA 0x80
#define SPI_6338_RX_DATA_SIZE 0x3f
/* BCM 6348 SPI core */
#define SPI_6348_CMD 0x00 /* 16-bits register */
#define SPI_6348_INT_STATUS 0x02
#define SPI_6348_INT_MASK_ST 0x03
#define SPI_6348_INT_MASK 0x04
#define SPI_6348_ST 0x05
#define SPI_6348_CLK_CFG 0x06
#define SPI_6348_FILL_BYTE 0x07
#define SPI_6348_MSG_TAIL 0x09
#define SPI_6348_RX_TAIL 0x0b
#define SPI_6348_MSG_CTL 0x40
#define SPI_6348_MSG_DATA 0x41
#define SPI_6348_MSG_DATA_SIZE 0x3f
#define SPI_6348_RX_DATA 0x80
#define SPI_6348_RX_DATA_SIZE 0x3f
/* BCM 6358 SPI core */
#define SPI_6358_MSG_CTL 0x00 /* 16-bits register */
#define SPI_6358_MSG_DATA 0x02
#define SPI_6358_MSG_DATA_SIZE 0x21e
#define SPI_6358_RX_DATA 0x400
#define SPI_6358_RX_DATA_SIZE 0x220
#define SPI_6358_CMD 0x700 /* 16-bits register */
#define SPI_6358_INT_STATUS 0x702
#define SPI_6358_INT_MASK_ST 0x703
#define SPI_6358_INT_MASK 0x704
#define SPI_6358_ST 0x705
#define SPI_6358_CLK_CFG 0x706
#define SPI_6358_FILL_BYTE 0x707
#define SPI_6358_MSG_TAIL 0x709
#define SPI_6358_RX_TAIL 0x70B
/* BCM 6358 SPI core */
#define SPI_6368_MSG_CTL 0x00 /* 16-bits register */
#define SPI_6368_MSG_DATA 0x02
#define SPI_6368_MSG_DATA_SIZE 0x21e
#define SPI_6368_RX_DATA 0x400
#define SPI_6368_RX_DATA_SIZE 0x220
#define SPI_6368_CMD 0x700 /* 16-bits register */
#define SPI_6368_INT_STATUS 0x702
#define SPI_6368_INT_MASK_ST 0x703
#define SPI_6368_INT_MASK 0x704
#define SPI_6368_ST 0x705
#define SPI_6368_CLK_CFG 0x706
#define SPI_6368_FILL_BYTE 0x707
#define SPI_6368_MSG_TAIL 0x709
#define SPI_6368_RX_TAIL 0x70B
/* Shared SPI definitions */
/* Message configuration */
#define SPI_FD_RW 0x00
#define SPI_HD_W 0x01
#define SPI_HD_R 0x02
#define SPI_BYTE_CNT_SHIFT 0
#define SPI_MSG_TYPE_SHIFT 14
/* Command */
#define SPI_CMD_NOOP 0x00
#define SPI_CMD_SOFT_RESET 0x01
#define SPI_CMD_HARD_RESET 0x02
#define SPI_CMD_START_IMMEDIATE 0x03
#define SPI_CMD_COMMAND_SHIFT 0
#define SPI_CMD_COMMAND_MASK 0x000f
#define SPI_CMD_DEVICE_ID_SHIFT 4
#define SPI_CMD_PREPEND_BYTE_CNT_SHIFT 8
#define SPI_CMD_ONE_BYTE_SHIFT 11
#define SPI_CMD_ONE_WIRE_SHIFT 12
#define SPI_DEV_ID_0 0
#define SPI_DEV_ID_1 1
#define SPI_DEV_ID_2 2
#define SPI_DEV_ID_3 3
/* Interrupt mask */
#define SPI_INTR_CMD_DONE 0x01
#define SPI_INTR_RX_OVERFLOW 0x02
#define SPI_INTR_TX_UNDERFLOW 0x04
#define SPI_INTR_TX_OVERFLOW 0x08
#define SPI_INTR_RX_UNDERFLOW 0x10
#define SPI_INTR_CLEAR_ALL 0x1f
/* Status */
#define SPI_RX_EMPTY 0x02
#define SPI_CMD_BUSY 0x04
#define SPI_SERIAL_BUSY 0x08
/* Clock configuration */
#define SPI_CLK_20MHZ 0x00
#define SPI_CLK_0_391MHZ 0x01
#define SPI_CLK_0_781MHZ 0x02 /* default */
#define SPI_CLK_1_563MHZ 0x03
#define SPI_CLK_3_125MHZ 0x04
#define SPI_CLK_6_250MHZ 0x05
#define SPI_CLK_12_50MHZ 0x06
#define SPI_CLK_MASK 0x07
#define SPI_SSOFFTIME_MASK 0x38
#define SPI_SSOFFTIME_SHIFT 3
#define SPI_BYTE_SWAP 0x80
/*************************************************************************
* _REG relative to RSET_MISC
*************************************************************************/
#define MISC_SERDES_CTRL_REG 0x0
#define SERDES_PCIE_EN (1 << 0)
#define SERDES_PCIE_EXD_EN (1 << 15)
#define MISC_STRAPBUS_6328_REG 0x240
#define STRAPBUS_6328_FCVO_SHIFT 7
#define STRAPBUS_6328_FCVO_MASK (0x1f << STRAPBUS_6328_FCVO_SHIFT)
#define STRAPBUS_6328_BOOT_SEL_SERIAL (1 << 28)
#define STRAPBUS_6328_BOOT_SEL_NAND (0 << 28)
/*************************************************************************
* _REG relative to RSET_PCIE
*************************************************************************/
#define PCIE_CONFIG2_REG 0x408
#define CONFIG2_BAR1_SIZE_EN 1
#define CONFIG2_BAR1_SIZE_MASK 0xf
#define PCIE_IDVAL3_REG 0x43c
#define IDVAL3_CLASS_CODE_MASK 0xffffff
#define IDVAL3_SUBCLASS_SHIFT 8
#define IDVAL3_CLASS_SHIFT 16
#define PCIE_DLSTATUS_REG 0x1048
#define DLSTATUS_PHYLINKUP (1 << 13)
#define PCIE_BRIDGE_OPT1_REG 0x2820
#define OPT1_RD_BE_OPT_EN (1 << 7)
#define OPT1_RD_REPLY_BE_FIX_EN (1 << 9)
#define OPT1_PCIE_BRIDGE_HOLE_DET_EN (1 << 11)
#define OPT1_L1_INT_STATUS_MASK_POL (1 << 12)
#define PCIE_BRIDGE_OPT2_REG 0x2824
#define OPT2_UBUS_UR_DECODE_DIS (1 << 2)
#define OPT2_TX_CREDIT_CHK_EN (1 << 4)
#define OPT2_CFG_TYPE1_BD_SEL (1 << 7)
#define OPT2_CFG_TYPE1_BUS_NO_SHIFT 16
#define OPT2_CFG_TYPE1_BUS_NO_MASK (0xff << OPT2_CFG_TYPE1_BUS_NO_SHIFT)
#define PCIE_BRIDGE_BAR0_BASEMASK_REG 0x2828
#define PCIE_BRIDGE_BAR1_BASEMASK_REG 0x2830
#define BASEMASK_REMAP_EN (1 << 0)
#define BASEMASK_SWAP_EN (1 << 1)
#define BASEMASK_MASK_SHIFT 4
#define BASEMASK_MASK_MASK (0xfff << BASEMASK_MASK_SHIFT)
#define BASEMASK_BASE_SHIFT 20
#define BASEMASK_BASE_MASK (0xfff << BASEMASK_BASE_SHIFT)
#define PCIE_BRIDGE_BAR0_REBASE_ADDR_REG 0x282c
#define PCIE_BRIDGE_BAR1_REBASE_ADDR_REG 0x2834
#define REBASE_ADDR_BASE_SHIFT 20
#define REBASE_ADDR_BASE_MASK (0xfff << REBASE_ADDR_BASE_SHIFT)
#define PCIE_BRIDGE_RC_INT_MASK_REG 0x2854
#define PCIE_RC_INT_A (1 << 0)
#define PCIE_RC_INT_B (1 << 1)
#define PCIE_RC_INT_C (1 << 2)
#define PCIE_RC_INT_D (1 << 3)
#define PCIE_DEVICE_OFFSET 0x8000
#endif /* BCM63XX_REGS_H_ */ #endif /* BCM63XX_REGS_H_ */
...@@ -18,6 +18,7 @@ static inline int is_bcm63xx_internal_registers(phys_t offset) ...@@ -18,6 +18,7 @@ static inline int is_bcm63xx_internal_registers(phys_t offset)
if (offset >= 0xfff00000) if (offset >= 0xfff00000)
return 1; return 1;
break; break;
case BCM6328_CPU_ID:
case BCM6368_CPU_ID: case BCM6368_CPU_ID:
if (offset >= 0xb0000000 && offset < 0xb1000000) if (offset >= 0xb0000000 && offset < 0xb1000000)
return 1; return 1;
......
...@@ -41,61 +41,26 @@ enum octeon_irq { ...@@ -41,61 +41,26 @@ enum octeon_irq {
OCTEON_IRQ_TWSI, OCTEON_IRQ_TWSI,
OCTEON_IRQ_TWSI2, OCTEON_IRQ_TWSI2,
OCTEON_IRQ_RML, OCTEON_IRQ_RML,
OCTEON_IRQ_TRACE0,
OCTEON_IRQ_GMX_DRP0 = OCTEON_IRQ_TRACE0 + 4,
OCTEON_IRQ_IPD_DRP = OCTEON_IRQ_GMX_DRP0 + 5,
OCTEON_IRQ_KEY_ZERO,
OCTEON_IRQ_TIMER0, OCTEON_IRQ_TIMER0,
OCTEON_IRQ_TIMER1, OCTEON_IRQ_TIMER1,
OCTEON_IRQ_TIMER2, OCTEON_IRQ_TIMER2,
OCTEON_IRQ_TIMER3, OCTEON_IRQ_TIMER3,
OCTEON_IRQ_USB0, OCTEON_IRQ_USB0,
OCTEON_IRQ_USB1, OCTEON_IRQ_USB1,
OCTEON_IRQ_PCM,
OCTEON_IRQ_MPI,
OCTEON_IRQ_POWIQ,
OCTEON_IRQ_IPDPPTHR,
OCTEON_IRQ_MII0, OCTEON_IRQ_MII0,
OCTEON_IRQ_MII1, OCTEON_IRQ_MII1,
OCTEON_IRQ_BOOTDMA, OCTEON_IRQ_BOOTDMA,
#ifndef CONFIG_PCI_MSI
OCTEON_IRQ_NAND, OCTEON_IRQ_LAST = 127
OCTEON_IRQ_MIO, /* Summary of MIO_BOOT_ERR */ #endif
OCTEON_IRQ_IOB, /* Summary of IOB_INT_SUM */
OCTEON_IRQ_FPA, /* Summary of FPA_INT_SUM */
OCTEON_IRQ_POW, /* Summary of POW_ECC_ERR */
OCTEON_IRQ_L2C, /* Summary of L2C_INT_STAT */
OCTEON_IRQ_IPD, /* Summary of IPD_INT_SUM */
OCTEON_IRQ_PIP, /* Summary of PIP_INT_REG */
OCTEON_IRQ_PKO, /* Summary of PKO_REG_ERROR */
OCTEON_IRQ_ZIP, /* Summary of ZIP_ERROR */
OCTEON_IRQ_TIM, /* Summary of TIM_REG_ERROR */
OCTEON_IRQ_RAD, /* Summary of RAD_REG_ERROR */
OCTEON_IRQ_KEY, /* Summary of KEY_INT_SUM */
OCTEON_IRQ_DFA, /* Summary of DFA */
OCTEON_IRQ_USBCTL, /* Summary of USBN0_INT_SUM */
OCTEON_IRQ_SLI, /* Summary of SLI_INT_SUM */
OCTEON_IRQ_DPI, /* Summary of DPI_INT_SUM */
OCTEON_IRQ_AGX0, /* Summary of GMX0*+PCS0_INT*_REG */
OCTEON_IRQ_AGL = OCTEON_IRQ_AGX0 + 5,
OCTEON_IRQ_PTP,
OCTEON_IRQ_PEM0,
OCTEON_IRQ_PEM1,
OCTEON_IRQ_SRIO0,
OCTEON_IRQ_SRIO1,
OCTEON_IRQ_LMC0,
OCTEON_IRQ_DFM = OCTEON_IRQ_LMC0 + 4, /* Summary of DFM */
OCTEON_IRQ_RST,
}; };
#ifdef CONFIG_PCI_MSI #ifdef CONFIG_PCI_MSI
/* 152 - 407 represent the MSI interrupts 0-255 */ /* 256 - 511 represent the MSI interrupts 0-255 */
#define OCTEON_IRQ_MSI_BIT0 (OCTEON_IRQ_RST + 1) #define OCTEON_IRQ_MSI_BIT0 (256)
#define OCTEON_IRQ_MSI_LAST (OCTEON_IRQ_MSI_BIT0 + 255) #define OCTEON_IRQ_MSI_LAST (OCTEON_IRQ_MSI_BIT0 + 255)
#define OCTEON_IRQ_LAST (OCTEON_IRQ_MSI_LAST + 1) #define OCTEON_IRQ_LAST (OCTEON_IRQ_MSI_LAST + 1)
#else
#define OCTEON_IRQ_LAST (OCTEON_IRQ_RST + 1)
#endif #endif
#endif #endif
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <linux/mtd/nand.h> #include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h> #include <linux/mtd/partitions.h>
#define JZ_NAND_NUM_BANKS 4
struct jz_nand_platform_data { struct jz_nand_platform_data {
int num_partitions; int num_partitions;
struct mtd_partition *partitions; struct mtd_partition *partitions;
...@@ -27,6 +29,8 @@ struct jz_nand_platform_data { ...@@ -27,6 +29,8 @@ struct jz_nand_platform_data {
unsigned int busy_gpio; unsigned int busy_gpio;
unsigned char banks[JZ_NAND_NUM_BANKS];
void (*ident_callback)(struct platform_device *, struct nand_chip *, void (*ident_callback)(struct platform_device *, struct nand_chip *,
struct mtd_partition **, int *num_partitions); struct mtd_partition **, int *num_partitions);
}; };
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/kconfig.h>
/* loongson internal northbridge initialization */ /* loongson internal northbridge initialization */
extern void bonito_irq_init(void); extern void bonito_irq_init(void);
...@@ -66,7 +67,7 @@ extern int mach_i8259_irq(void); ...@@ -66,7 +67,7 @@ extern int mach_i8259_irq(void);
#include <linux/interrupt.h> #include <linux/interrupt.h>
static inline void do_perfcnt_IRQ(void) static inline void do_perfcnt_IRQ(void)
{ {
#if defined(CONFIG_OPROFILE) || defined(CONFIG_OPROFILE_MODULE) #if IS_ENABLED(CONFIG_OPROFILE)
do_IRQ(LOONGSON2_PERFCNT_IRQ); do_IRQ(LOONGSON2_PERFCNT_IRQ);
#endif #endif
} }
......
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
*
* IRQ mappings for Loongson 1
*
* 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_MACH_LOONGSON1_IRQ_H
#define __ASM_MACH_LOONGSON1_IRQ_H
/*
* CPU core Interrupt Numbers
*/
#define MIPS_CPU_IRQ_BASE 0
#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x))
#define SOFTINT0_IRQ MIPS_CPU_IRQ(0)
#define SOFTINT1_IRQ MIPS_CPU_IRQ(1)
#define INT0_IRQ MIPS_CPU_IRQ(2)
#define INT1_IRQ MIPS_CPU_IRQ(3)
#define INT2_IRQ MIPS_CPU_IRQ(4)
#define INT3_IRQ MIPS_CPU_IRQ(5)
#define INT4_IRQ MIPS_CPU_IRQ(6)
#define TIMER_IRQ MIPS_CPU_IRQ(7) /* cpu timer */
#define MIPS_CPU_IRQS (MIPS_CPU_IRQ(7) + 1 - MIPS_CPU_IRQ_BASE)
/*
* INT0~3 Interrupt Numbers
*/
#define LS1X_IRQ_BASE MIPS_CPU_IRQS
#define LS1X_IRQ(n, x) (LS1X_IRQ_BASE + (n << 5) + (x))
#define LS1X_UART0_IRQ LS1X_IRQ(0, 2)
#define LS1X_UART1_IRQ LS1X_IRQ(0, 3)
#define LS1X_UART2_IRQ LS1X_IRQ(0, 4)
#define LS1X_UART3_IRQ LS1X_IRQ(0, 5)
#define LS1X_CAN0_IRQ LS1X_IRQ(0, 6)
#define LS1X_CAN1_IRQ LS1X_IRQ(0, 7)
#define LS1X_SPI0_IRQ LS1X_IRQ(0, 8)
#define LS1X_SPI1_IRQ LS1X_IRQ(0, 9)
#define LS1X_AC97_IRQ LS1X_IRQ(0, 10)
#define LS1X_DMA0_IRQ LS1X_IRQ(0, 13)
#define LS1X_DMA1_IRQ LS1X_IRQ(0, 14)
#define LS1X_DMA2_IRQ LS1X_IRQ(0, 15)
#define LS1X_PWM0_IRQ LS1X_IRQ(0, 17)
#define LS1X_PWM1_IRQ LS1X_IRQ(0, 18)
#define LS1X_PWM2_IRQ LS1X_IRQ(0, 19)
#define LS1X_PWM3_IRQ LS1X_IRQ(0, 20)
#define LS1X_RTC_INT0_IRQ LS1X_IRQ(0, 21)
#define LS1X_RTC_INT1_IRQ LS1X_IRQ(0, 22)
#define LS1X_RTC_INT2_IRQ LS1X_IRQ(0, 23)
#define LS1X_TOY_INT0_IRQ LS1X_IRQ(0, 24)
#define LS1X_TOY_INT1_IRQ LS1X_IRQ(0, 25)
#define LS1X_TOY_INT2_IRQ LS1X_IRQ(0, 26)
#define LS1X_RTC_TICK_IRQ LS1X_IRQ(0, 27)
#define LS1X_TOY_TICK_IRQ LS1X_IRQ(0, 28)
#define LS1X_EHCI_IRQ LS1X_IRQ(1, 0)
#define LS1X_OHCI_IRQ LS1X_IRQ(1, 1)
#define LS1X_GMAC0_IRQ LS1X_IRQ(1, 2)
#define LS1X_GMAC1_IRQ LS1X_IRQ(1, 3)
#define LS1X_IRQS (LS1X_IRQ(4, 31) + 1 - LS1X_IRQ_BASE)
#define NR_IRQS (MIPS_CPU_IRQS + LS1X_IRQS)
#endif /* __ASM_MACH_LOONGSON1_IRQ_H */
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
*
* Register mappings for Loongson 1
*
* 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_MACH_LOONGSON1_LOONGSON1_H
#define __ASM_MACH_LOONGSON1_LOONGSON1_H
#define DEFAULT_MEMSIZE 256 /* If no memsize provided */
/* Loongson 1 Register Bases */
#define LS1X_INTC_BASE 0x1fd01040
#define LS1X_EHCI_BASE 0x1fe00000
#define LS1X_OHCI_BASE 0x1fe08000
#define LS1X_GMAC0_BASE 0x1fe10000
#define LS1X_GMAC1_BASE 0x1fe20000
#define LS1X_UART0_BASE 0x1fe40000
#define LS1X_UART1_BASE 0x1fe44000
#define LS1X_UART2_BASE 0x1fe48000
#define LS1X_UART3_BASE 0x1fe4c000
#define LS1X_CAN0_BASE 0x1fe50000
#define LS1X_CAN1_BASE 0x1fe54000
#define LS1X_I2C0_BASE 0x1fe58000
#define LS1X_I2C1_BASE 0x1fe68000
#define LS1X_I2C2_BASE 0x1fe70000
#define LS1X_PWM_BASE 0x1fe5c000
#define LS1X_WDT_BASE 0x1fe5c060
#define LS1X_RTC_BASE 0x1fe64000
#define LS1X_AC97_BASE 0x1fe74000
#define LS1X_NAND_BASE 0x1fe78000
#define LS1X_CLK_BASE 0x1fe78030
#include <regs-clk.h>
#include <regs-wdt.h>
#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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_MACH_LOONGSON1_PLATFORM_H
#define __ASM_MACH_LOONGSON1_PLATFORM_H
#include <linux/platform_device.h>
extern struct platform_device ls1x_uart_device;
extern struct platform_device ls1x_eth0_device;
extern struct platform_device ls1x_ehci_device;
extern struct platform_device ls1x_rtc_device;
void ls1x_serial_setup(void);
#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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_MACH_LOONGSON1_PROM_H
#define __ASM_MACH_LOONGSON1_PROM_H
#include <linux/io.h>
#include <linux/init.h>
#include <linux/irq.h>
/* environment arguments from bootloader */
extern unsigned long memsize, highmemsize;
/* loongson-specific command line, env and memory initialization */
extern char *prom_getenv(char *name);
extern void __init prom_init_cmdline(void);
#endif /* __ASM_MACH_LOONGSON1_PROM_H */
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
*
* Loongson 1 Clock Register Definitions.
*
* 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_MACH_LOONGSON1_REGS_CLK_H
#define __ASM_MACH_LOONGSON1_REGS_CLK_H
#define LS1X_CLK_REG(x) \
((void __iomem *)KSEG1ADDR(LS1X_CLK_BASE + (x)))
#define LS1X_CLK_PLL_FREQ LS1X_CLK_REG(0x0)
#define LS1X_CLK_PLL_DIV LS1X_CLK_REG(0x4)
/* Clock PLL Divisor Register Bits */
#define DIV_DC_EN (0x1 << 31)
#define DIV_DC (0x1f << 26)
#define DIV_CPU_EN (0x1 << 25)
#define DIV_CPU (0x1f << 20)
#define DIV_DDR_EN (0x1 << 19)
#define DIV_DDR (0x1f << 14)
#define DIV_DC_SHIFT 26
#define DIV_CPU_SHIFT 20
#define DIV_DDR_SHIFT 14
#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
*
* Loongson 1 watchdog register definitions.
*
* 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_MACH_LOONGSON1_REGS_WDT_H
#define __ASM_MACH_LOONGSON1_REGS_WDT_H
#define LS1X_WDT_REG(x) \
((void __iomem *)KSEG1ADDR(LS1X_WDT_BASE + (x)))
#define LS1X_WDT_EN LS1X_WDT_REG(0x0)
#define LS1X_WDT_SET LS1X_WDT_REG(0x4)
#define LS1X_WDT_TIMER LS1X_WDT_REG(0x8)
#endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
*/
#ifndef __ASM_MACH_LOONGSON1_WAR_H
#define __ASM_MACH_LOONGSON1_WAR_H
#define R4600_V1_INDEX_ICACHEOP_WAR 0
#define R4600_V1_HIT_CACHEOP_WAR 0
#define R4600_V2_HIT_CACHEOP_WAR 0
#define R5432_CP0_INTERRUPT_WAR 0
#define BCM1250_M3_WAR 0
#define SIBYTE_1956_WAR 0
#define MIPS4K_ICACHE_REFILL_WAR 0
#define MIPS_CACHE_SYNC_WAR 0
#define TX49XX_ICACHE_INDEX_INV_WAR 0
#define RM9000_CDEX_SMP_WAR 0
#define ICACHE_REFILLS_WORKAROUND_WAR 0
#define R10000_LLSC_WAR 0
#define MIPS34K_MISSED_ITLB_WAR 0
#endif /* __ASM_MACH_LOONGSON1_WAR_H */
...@@ -48,7 +48,6 @@ ...@@ -48,7 +48,6 @@
#define cpu_has_userlocal 1 #define cpu_has_userlocal 1
#define cpu_has_mips32r2 1 #define cpu_has_mips32r2 1
#define cpu_has_mips64r2 1 #define cpu_has_mips64r2 1
#define cpu_has_dc_aliases 1
#else #else
#error "Unknown Netlogic CPU" #error "Unknown Netlogic CPU"
#endif #endif
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
#define ioswabb(a, x) (x) #define ioswabb(a, x) (x)
#define __mem_ioswabb(a, x) (x) #define __mem_ioswabb(a, x) (x)
#if defined(CONFIG_TOSHIBA_RBTX4939) && \ #if defined(CONFIG_TOSHIBA_RBTX4939) && \
(defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE)) && \ IS_ENABLED(CONFIG_SMC91X) && \
defined(__BIG_ENDIAN) defined(__BIG_ENDIAN)
#define NEEDS_TXX9_IOSWABW #define NEEDS_TXX9_IOSWABW
extern u16 (*ioswabw)(volatile u16 *a, u16 x); extern u16 (*ioswabw)(volatile u16 *a, u16 x);
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#define read_c0_vpeconf0() __read_32bit_c0_register($1, 2) #define read_c0_vpeconf0() __read_32bit_c0_register($1, 2)
#define write_c0_vpeconf0(val) __write_32bit_c0_register($1, 2, val) #define write_c0_vpeconf0(val) __write_32bit_c0_register($1, 2, val)
#define read_c0_vpeconf1() __read_32bit_c0_register($1, 3)
#define write_c0_vpeconf1(val) __write_32bit_c0_register($1, 3, val)
#define read_c0_tcstatus() __read_32bit_c0_register($2, 1) #define read_c0_tcstatus() __read_32bit_c0_register($2, 1)
#define write_c0_tcstatus(val) __write_32bit_c0_register($2, 1, val) #define write_c0_tcstatus(val) __write_32bit_c0_register($2, 1, val)
...@@ -124,6 +127,14 @@ ...@@ -124,6 +127,14 @@
#define VPECONF0_XTC_SHIFT 21 #define VPECONF0_XTC_SHIFT 21
#define VPECONF0_XTC (_ULCAST_(0xff) << VPECONF0_XTC_SHIFT) #define VPECONF0_XTC (_ULCAST_(0xff) << VPECONF0_XTC_SHIFT)
/* VPEConf1 fields (per VPE) */
#define VPECONF1_NCP1_SHIFT 0
#define VPECONF1_NCP1 (_ULCAST_(0xff) << VPECONF1_NCP1_SHIFT)
#define VPECONF1_NCP2_SHIFT 10
#define VPECONF1_NCP2 (_ULCAST_(0xff) << VPECONF1_NCP2_SHIFT)
#define VPECONF1_NCX_SHIFT 20
#define VPECONF1_NCX (_ULCAST_(0xff) << VPECONF1_NCX_SHIFT)
/* TCStatus fields (per TC) */ /* TCStatus fields (per TC) */
#define TCSTATUS_TASID (_ULCAST_(0xff)) #define TCSTATUS_TASID (_ULCAST_(0xff))
#define TCSTATUS_IXMT_SHIFT 10 #define TCSTATUS_IXMT_SHIFT 10
...@@ -350,6 +361,8 @@ do { \ ...@@ -350,6 +361,8 @@ do { \
#define write_vpe_c0_vpecontrol(val) mttc0(1, 1, val) #define write_vpe_c0_vpecontrol(val) mttc0(1, 1, val)
#define read_vpe_c0_vpeconf0() mftc0(1, 2) #define read_vpe_c0_vpeconf0() mftc0(1, 2)
#define write_vpe_c0_vpeconf0(val) mttc0(1, 2, val) #define write_vpe_c0_vpeconf0(val) mttc0(1, 2, val)
#define read_vpe_c0_vpeconf1() mftc0(1, 3)
#define write_vpe_c0_vpeconf1(val) mttc0(1, 3, val)
#define read_vpe_c0_count() mftc0(9, 0) #define read_vpe_c0_count() mftc0(9, 0)
#define write_vpe_c0_count(val) mttc0(9, 0, val) #define write_vpe_c0_count(val) mttc0(9, 0, val)
#define read_vpe_c0_status() mftc0(12, 0) #define read_vpe_c0_status() mftc0(12, 0)
......
...@@ -117,6 +117,8 @@ search_module_dbetables(unsigned long addr) ...@@ -117,6 +117,8 @@ search_module_dbetables(unsigned long addr)
#define MODULE_PROC_FAMILY "RM9000 " #define MODULE_PROC_FAMILY "RM9000 "
#elif defined CONFIG_CPU_SB1 #elif defined CONFIG_CPU_SB1
#define MODULE_PROC_FAMILY "SB1 " #define MODULE_PROC_FAMILY "SB1 "
#elif defined CONFIG_CPU_LOONGSON1
#define MODULE_PROC_FAMILY "LOONGSON1 "
#elif defined CONFIG_CPU_LOONGSON2 #elif defined CONFIG_CPU_LOONGSON2
#define MODULE_PROC_FAMILY "LOONGSON2 " #define MODULE_PROC_FAMILY "LOONGSON2 "
#elif defined CONFIG_CPU_CAVIUM_OCTEON #elif defined CONFIG_CPU_CAVIUM_OCTEON
......
...@@ -47,7 +47,9 @@ ...@@ -47,7 +47,9 @@
#define CPU_BLOCKID_MAP 10 #define CPU_BLOCKID_MAP 10
#define LSU_DEFEATURE 0x304 #define LSU_DEFEATURE 0x304
#define LSU_CERRLOG_REGID 0x09 #define LSU_DEBUG_ADDR 0x305
#define LSU_DEBUG_DATA0 0x306
#define LSU_CERRLOG_REGID 0x309
#define SCHED_DEFEATURE 0x700 #define SCHED_DEFEATURE 0x700
/* Offsets of interest from the 'MAP' Block */ /* Offsets of interest from the 'MAP' Block */
......
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
#define __NLM_HAL_IOMAP_H__ #define __NLM_HAL_IOMAP_H__
#define XLP_DEFAULT_IO_BASE 0x18000000 #define XLP_DEFAULT_IO_BASE 0x18000000
#define XLP_DEFAULT_PCI_ECFG_BASE XLP_DEFAULT_IO_BASE
#define XLP_DEFAULT_PCI_CFG_BASE 0x1c000000
#define NMI_BASE 0xbfc00000 #define NMI_BASE 0xbfc00000
#define XLP_IO_CLK 133333333 #define XLP_IO_CLK 133333333
...@@ -129,7 +132,7 @@ ...@@ -129,7 +132,7 @@
#define PCI_DEVICE_ID_NLM_PIC 0x1003 #define PCI_DEVICE_ID_NLM_PIC 0x1003
#define PCI_DEVICE_ID_NLM_PCIE 0x1004 #define PCI_DEVICE_ID_NLM_PCIE 0x1004
#define PCI_DEVICE_ID_NLM_EHCI 0x1007 #define PCI_DEVICE_ID_NLM_EHCI 0x1007
#define PCI_DEVICE_ID_NLM_ILK 0x1008 #define PCI_DEVICE_ID_NLM_OHCI 0x1008
#define PCI_DEVICE_ID_NLM_NAE 0x1009 #define PCI_DEVICE_ID_NLM_NAE 0x1009
#define PCI_DEVICE_ID_NLM_POE 0x100A #define PCI_DEVICE_ID_NLM_POE 0x100A
#define PCI_DEVICE_ID_NLM_FMN 0x100B #define PCI_DEVICE_ID_NLM_FMN 0x100B
......
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NLM_HAL_PCIBUS_H__
#define __NLM_HAL_PCIBUS_H__
/* PCIE Memory and IO regions */
#define PCIE_MEM_BASE 0xd0000000ULL
#define PCIE_MEM_LIMIT 0xdfffffffULL
#define PCIE_IO_BASE 0x14000000ULL
#define PCIE_IO_LIMIT 0x15ffffffULL
#define PCIE_BRIDGE_CMD 0x1
#define PCIE_BRIDGE_MSI_CAP 0x14
#define PCIE_BRIDGE_MSI_ADDRL 0x15
#define PCIE_BRIDGE_MSI_ADDRH 0x16
#define PCIE_BRIDGE_MSI_DATA 0x17
/* XLP Global PCIE configuration space registers */
#define PCIE_BYTE_SWAP_MEM_BASE 0x247
#define PCIE_BYTE_SWAP_MEM_LIM 0x248
#define PCIE_BYTE_SWAP_IO_BASE 0x249
#define PCIE_BYTE_SWAP_IO_LIM 0x24A
#define PCIE_MSI_STATUS 0x25A
#define PCIE_MSI_EN 0x25B
#define PCIE_INT_EN0 0x261
/* PCIE_MSI_EN */
#define PCIE_MSI_VECTOR_INT_EN 0xFFFFFFFF
/* PCIE_INT_EN0 */
#define PCIE_MSI_INT_EN (1 << 9)
#ifndef __ASSEMBLY__
#define nlm_read_pcie_reg(b, r) nlm_read_reg(b, r)
#define nlm_write_pcie_reg(b, r, v) nlm_write_reg(b, r, v)
#define nlm_get_pcie_base(node, inst) \
nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, inst))
#define nlm_get_pcie_regbase(node, inst) \
(nlm_get_pcie_base(node, inst) + XLP_IO_PCI_HDRSZ)
int xlp_pcie_link_irt(int link);
#endif
#endif /* __NLM_HAL_PCIBUS_H__ */
...@@ -201,7 +201,11 @@ ...@@ -201,7 +201,11 @@
#define PIC_NUM_USB_IRTS 6 #define PIC_NUM_USB_IRTS 6
#define PIC_IRT_USB_0_INDEX 115 #define PIC_IRT_USB_0_INDEX 115
#define PIC_IRT_EHCI_0_INDEX 115 #define PIC_IRT_EHCI_0_INDEX 115
#define PIC_IRT_OHCI_0_INDEX 116
#define PIC_IRT_OHCI_1_INDEX 117
#define PIC_IRT_EHCI_1_INDEX 118 #define PIC_IRT_EHCI_1_INDEX 118
#define PIC_IRT_OHCI_2_INDEX 119
#define PIC_IRT_OHCI_3_INDEX 120
#define PIC_IRT_USB_INDEX(num) ((num) + PIC_IRT_USB_0_INDEX) #define PIC_IRT_USB_INDEX(num) ((num) + PIC_IRT_USB_0_INDEX)
/* 115 to 120 */ /* 115 to 120 */
#define PIC_IRT_GDX_INDEX 121 #define PIC_IRT_GDX_INDEX 121
......
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __NLM_HAL_USB_H__
#define __NLM_HAL_USB_H__
#define USB_CTL_0 0x01
#define USB_PHY_0 0x0A
#define USB_PHY_RESET 0x01
#define USB_PHY_PORT_RESET_0 0x10
#define USB_PHY_PORT_RESET_1 0x20
#define USB_CONTROLLER_RESET 0x01
#define USB_INT_STATUS 0x0E
#define USB_INT_EN 0x0F
#define USB_PHY_INTERRUPT_EN 0x01
#define USB_OHCI_INTERRUPT_EN 0x02
#define USB_OHCI_INTERRUPT1_EN 0x04
#define USB_OHCI_INTERRUPT2_EN 0x08
#define USB_CTRL_INTERRUPT_EN 0x10
#ifndef __ASSEMBLY__
#define nlm_read_usb_reg(b, r) nlm_read_reg(b, r)
#define nlm_write_usb_reg(b, r, v) nlm_write_reg(b, r, v)
#define nlm_get_usb_pcibase(node, inst) \
nlm_pcicfg_base(XLP_IO_USB_OFFSET(node, inst))
#define nlm_get_usb_hcd_base(node, inst) \
nlm_xkphys_map_pcibar0(nlm_get_usb_pcibase(node, inst))
#define nlm_get_usb_regbase(node, inst) \
(nlm_get_usb_pcibase(node, inst) + XLP_IO_PCI_HDRSZ)
#endif
#endif /* __NLM_HAL_USB_H__ */
...@@ -35,8 +35,21 @@ ...@@ -35,8 +35,21 @@
#ifndef _NLM_HAL_XLP_H #ifndef _NLM_HAL_XLP_H
#define _NLM_HAL_XLP_H #define _NLM_HAL_XLP_H
#define PIC_UART_0_IRQ 17 #define PIC_UART_0_IRQ 17
#define PIC_UART_1_IRQ 18 #define PIC_UART_1_IRQ 18
#define PIC_PCIE_LINK_0_IRQ 19
#define PIC_PCIE_LINK_1_IRQ 20
#define PIC_PCIE_LINK_2_IRQ 21
#define PIC_PCIE_LINK_3_IRQ 22
#define PIC_EHCI_0_IRQ 23
#define PIC_EHCI_1_IRQ 24
#define PIC_OHCI_0_IRQ 25
#define PIC_OHCI_1_IRQ 26
#define PIC_OHCI_2_IRQ 27
#define PIC_OHCI_3_IRQ 28
#define PIC_MMC_IRQ 29
#define PIC_I2C_0_IRQ 30
#define PIC_I2C_1_IRQ 31
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
......
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _ASM_NLM_BRIDGE_H_
#define _ASM_NLM_BRIDGE_H_
#define BRIDGE_DRAM_0_BAR 0
#define BRIDGE_DRAM_1_BAR 1
#define BRIDGE_DRAM_2_BAR 2
#define BRIDGE_DRAM_3_BAR 3
#define BRIDGE_DRAM_4_BAR 4
#define BRIDGE_DRAM_5_BAR 5
#define BRIDGE_DRAM_6_BAR 6
#define BRIDGE_DRAM_7_BAR 7
#define BRIDGE_DRAM_CHN_0_MTR_0_BAR 8
#define BRIDGE_DRAM_CHN_0_MTR_1_BAR 9
#define BRIDGE_DRAM_CHN_0_MTR_2_BAR 10
#define BRIDGE_DRAM_CHN_0_MTR_3_BAR 11
#define BRIDGE_DRAM_CHN_0_MTR_4_BAR 12
#define BRIDGE_DRAM_CHN_0_MTR_5_BAR 13
#define BRIDGE_DRAM_CHN_0_MTR_6_BAR 14
#define BRIDGE_DRAM_CHN_0_MTR_7_BAR 15
#define BRIDGE_DRAM_CHN_1_MTR_0_BAR 16
#define BRIDGE_DRAM_CHN_1_MTR_1_BAR 17
#define BRIDGE_DRAM_CHN_1_MTR_2_BAR 18
#define BRIDGE_DRAM_CHN_1_MTR_3_BAR 19
#define BRIDGE_DRAM_CHN_1_MTR_4_BAR 20
#define BRIDGE_DRAM_CHN_1_MTR_5_BAR 21
#define BRIDGE_DRAM_CHN_1_MTR_6_BAR 22
#define BRIDGE_DRAM_CHN_1_MTR_7_BAR 23
#define BRIDGE_CFG_BAR 24
#define BRIDGE_PHNX_IO_BAR 25
#define BRIDGE_FLASH_BAR 26
#define BRIDGE_SRAM_BAR 27
#define BRIDGE_HTMEM_BAR 28
#define BRIDGE_HTINT_BAR 29
#define BRIDGE_HTPIC_BAR 30
#define BRIDGE_HTSM_BAR 31
#define BRIDGE_HTIO_BAR 32
#define BRIDGE_HTCFG_BAR 33
#define BRIDGE_PCIXCFG_BAR 34
#define BRIDGE_PCIXMEM_BAR 35
#define BRIDGE_PCIXIO_BAR 36
#define BRIDGE_DEVICE_MASK 37
#define BRIDGE_AERR_INTR_LOG1 38
#define BRIDGE_AERR_INTR_LOG2 39
#define BRIDGE_AERR_INTR_LOG3 40
#define BRIDGE_AERR_DEV_STAT 41
#define BRIDGE_AERR1_LOG1 42
#define BRIDGE_AERR1_LOG2 43
#define BRIDGE_AERR1_LOG3 44
#define BRIDGE_AERR1_DEV_STAT 45
#define BRIDGE_AERR_INTR_EN 46
#define BRIDGE_AERR_UPG 47
#define BRIDGE_AERR_CLEAR 48
#define BRIDGE_AERR1_CLEAR 49
#define BRIDGE_SBE_COUNTS 50
#define BRIDGE_DBE_COUNTS 51
#define BRIDGE_BITERR_INT_EN 52
#define BRIDGE_SYS2IO_CREDITS 53
#define BRIDGE_EVNT_CNT_CTRL1 54
#define BRIDGE_EVNT_COUNTER1 55
#define BRIDGE_EVNT_CNT_CTRL2 56
#define BRIDGE_EVNT_COUNTER2 57
#define BRIDGE_RESERVED1 58
#define BRIDGE_DEFEATURE 59
#define BRIDGE_SCRATCH0 60
#define BRIDGE_SCRATCH1 61
#define BRIDGE_SCRATCH2 62
#define BRIDGE_SCRATCH3 63
#endif
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _ASM_NLM_FLASH_H_
#define _ASM_NLM_FLASH_H_
#define FLASH_CSBASE_ADDR(cs) (cs)
#define FLASH_CSADDR_MASK(cs) (0x10 + (cs))
#define FLASH_CSDEV_PARM(cs) (0x20 + (cs))
#define FLASH_CSTIME_PARMA(cs) (0x30 + (cs))
#define FLASH_CSTIME_PARMB(cs) (0x40 + (cs))
#define FLASH_INT_MASK 0x50
#define FLASH_INT_STATUS 0x60
#define FLASH_ERROR_STATUS 0x70
#define FLASH_ERROR_ADDR 0x80
#define FLASH_NAND_CLE(cs) (0x90 + (cs))
#define FLASH_NAND_ALE(cs) (0xa0 + (cs))
#define FLASH_NAND_CSDEV_PARAM 0x000041e6
#define FLASH_NAND_CSTIME_PARAMA 0x4f400e22
#define FLASH_NAND_CSTIME_PARAMB 0x000083cf
#endif
...@@ -35,39 +35,40 @@ ...@@ -35,39 +35,40 @@
#ifndef _ASM_NLM_GPIO_H #ifndef _ASM_NLM_GPIO_H
#define _ASM_NLM_GPIO_H #define _ASM_NLM_GPIO_H
#define NETLOGIC_GPIO_INT_EN_REG 0 #define GPIO_INT_EN_REG 0
#define NETLOGIC_GPIO_INPUT_INVERSION_REG 1 #define GPIO_INPUT_INVERSION_REG 1
#define NETLOGIC_GPIO_IO_DIR_REG 2 #define GPIO_IO_DIR_REG 2
#define NETLOGIC_GPIO_IO_DATA_WR_REG 3 #define GPIO_IO_DATA_WR_REG 3
#define NETLOGIC_GPIO_IO_DATA_RD_REG 4 #define GPIO_IO_DATA_RD_REG 4
#define NETLOGIC_GPIO_SWRESET_REG 8 #define GPIO_SWRESET_REG 8
#define NETLOGIC_GPIO_DRAM1_CNTRL_REG 9 #define GPIO_DRAM1_CNTRL_REG 9
#define NETLOGIC_GPIO_DRAM1_RATIO_REG 10 #define GPIO_DRAM1_RATIO_REG 10
#define NETLOGIC_GPIO_DRAM1_RESET_REG 11 #define GPIO_DRAM1_RESET_REG 11
#define NETLOGIC_GPIO_DRAM1_STATUS_REG 12 #define GPIO_DRAM1_STATUS_REG 12
#define NETLOGIC_GPIO_DRAM2_CNTRL_REG 13 #define GPIO_DRAM2_CNTRL_REG 13
#define NETLOGIC_GPIO_DRAM2_RATIO_REG 14 #define GPIO_DRAM2_RATIO_REG 14
#define NETLOGIC_GPIO_DRAM2_RESET_REG 15 #define GPIO_DRAM2_RESET_REG 15
#define NETLOGIC_GPIO_DRAM2_STATUS_REG 16 #define GPIO_DRAM2_STATUS_REG 16
#define NETLOGIC_GPIO_PWRON_RESET_CFG_REG 21 #define GPIO_PWRON_RESET_CFG_REG 21
#define NETLOGIC_GPIO_BIST_ALL_GO_STATUS_REG 24 #define GPIO_BIST_ALL_GO_STATUS_REG 24
#define NETLOGIC_GPIO_BIST_CPU_GO_STATUS_REG 25 #define GPIO_BIST_CPU_GO_STATUS_REG 25
#define NETLOGIC_GPIO_BIST_DEV_GO_STATUS_REG 26 #define GPIO_BIST_DEV_GO_STATUS_REG 26
#define NETLOGIC_GPIO_FUSE_BANK_REG 35 #define GPIO_FUSE_BANK_REG 35
#define NETLOGIC_GPIO_CPU_RESET_REG 40 #define GPIO_CPU_RESET_REG 40
#define NETLOGIC_GPIO_RNG_REG 43 #define GPIO_RNG_REG 43
#define NETLOGIC_PWRON_RESET_PCMCIA_BOOT 17 #define PWRON_RESET_PCMCIA_BOOT 17
#define NETLOGIC_GPIO_LED_BITMAP 0x1700000
#define NETLOGIC_GPIO_LED_0_SHIFT 20
#define NETLOGIC_GPIO_LED_1_SHIFT 24
#define NETLOGIC_GPIO_LED_OUTPUT_CODE_RESET 0x01 #define GPIO_LED_BITMAP 0x1700000
#define NETLOGIC_GPIO_LED_OUTPUT_CODE_HARD_RESET 0x02 #define GPIO_LED_0_SHIFT 20
#define NETLOGIC_GPIO_LED_OUTPUT_CODE_SOFT_RESET 0x03 #define GPIO_LED_1_SHIFT 24
#define NETLOGIC_GPIO_LED_OUTPUT_CODE_MAIN 0x04
#define GPIO_LED_OUTPUT_CODE_RESET 0x01
#define GPIO_LED_OUTPUT_CODE_HARD_RESET 0x02
#define GPIO_LED_OUTPUT_CODE_SOFT_RESET 0x03
#define GPIO_LED_OUTPUT_CODE_MAIN 0x04
#endif #endif
/***********************license start***************
* Author: Cavium Networks
*
* Contact: support@caviumnetworks.com
* This file is part of the OCTEON SDK
*
* Copyright (c) 2003-2008 Cavium Networks
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, Version 2, as
* published by the Free Software Foundation.
*
* This file is distributed in the hope that it will be useful, but
* AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
* NONINFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* or visit http://www.gnu.org/licenses/.
*
* This file may also be available under a different license from Cavium.
* Contact Cavium Networks for more information
***********************license end**************************************/
/**
* @file
*
* Helper functions for FPA setup.
*
*/
#ifndef __CVMX_HELPER_H_FPA__
#define __CVMX_HELPER_H_FPA__
/**
* Allocate memory and initialize the FPA pools using memory
* from cvmx-bootmem. Sizes of each element in the pools is
* controlled by the cvmx-config.h header file. Specifying
* zero for any parameter will cause that FPA pool to not be
* setup. This is useful if you aren't using some of the
* hardware and want to save memory.
*
* @packet_buffers:
* Number of packet buffers to allocate
* @work_queue_entries:
* Number of work queue entries
* @pko_buffers:
* PKO Command buffers. You should at minimum have two per
* each PKO queue.
* @tim_buffers:
* TIM ring buffer command queues. At least two per timer bucket
* is recommened.
* @dfa_buffers:
* DFA command buffer. A relatively small (32 for example)
* number should work.
* Returns Zero on success, non-zero if out of memory
*/
extern int cvmx_helper_initialize_fpa(int packet_buffers,
int work_queue_entries, int pko_buffers,
int tim_buffers, int dfa_buffers);
#endif /* __CVMX_HELPER_H__ */
...@@ -61,8 +61,6 @@ typedef union { ...@@ -61,8 +61,6 @@ typedef union {
} s; } s;
} cvmx_helper_link_info_t; } cvmx_helper_link_info_t;
#include "cvmx-helper-fpa.h"
#include <asm/octeon/cvmx-helper-errata.h> #include <asm/octeon/cvmx-helper-errata.h>
#include "cvmx-helper-loop.h" #include "cvmx-helper-loop.h"
#include "cvmx-helper-npi.h" #include "cvmx-helper-npi.h"
......
...@@ -215,11 +215,6 @@ struct octeon_cf_data { ...@@ -215,11 +215,6 @@ struct octeon_cf_data {
int dma_engine; /* -1 for no DMA */ int dma_engine; /* -1 for no DMA */
}; };
struct octeon_i2c_data {
unsigned int sys_freq;
unsigned int i2c_freq;
};
extern void octeon_write_lcd(const char *s); extern void octeon_write_lcd(const char *s);
extern void octeon_check_cpu_bist(void); extern void octeon_check_cpu_bist(void);
extern int octeon_get_boot_debug_flag(void); extern int octeon_get_boot_debug_flag(void);
......
...@@ -20,9 +20,6 @@ ...@@ -20,9 +20,6 @@
extern int early_init_dt_scan_memory_arch(unsigned long node, extern int early_init_dt_scan_memory_arch(unsigned long node,
const char *uname, int depth, void *data); const char *uname, int depth, void *data);
extern int reserve_mem_mach(unsigned long addr, unsigned long size);
extern void free_mem_mach(unsigned long addr, unsigned long size);
extern void device_tree_init(void); extern void device_tree_init(void);
static inline unsigned long pci_address_to_pio(phys_addr_t address) static inline unsigned long pci_address_to_pio(phys_addr_t address)
......
...@@ -33,6 +33,12 @@ typedef long asiduse; ...@@ -33,6 +33,12 @@ typedef long asiduse;
#endif #endif
#endif #endif
/*
* VPE Management information
*/
#define MAX_SMTC_VPES MAX_SMTC_TLBS /* FIXME: May not always be true. */
extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS]; extern asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
struct mm_struct; struct mm_struct;
......
...@@ -687,7 +687,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n); ...@@ -687,7 +687,7 @@ extern size_t __copy_user(void *__to, const void *__from, size_t __n);
__MODULE_JAL(__copy_user) \ __MODULE_JAL(__copy_user) \
: "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \
: \ : \
: "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \
DADDI_SCRATCH, "memory"); \ DADDI_SCRATCH, "memory"); \
__cu_len_r; \ __cu_len_r; \
}) })
...@@ -797,7 +797,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); ...@@ -797,7 +797,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
".set\treorder" \ ".set\treorder" \
: "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \
: \ : \
: "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \
DADDI_SCRATCH, "memory"); \ DADDI_SCRATCH, "memory"); \
__cu_len_r; \ __cu_len_r; \
}) })
...@@ -820,7 +820,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n); ...@@ -820,7 +820,7 @@ extern size_t __copy_user_inatomic(void *__to, const void *__from, size_t __n);
".set\treorder" \ ".set\treorder" \
: "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \ : "+r" (__cu_to_r), "+r" (__cu_from_r), "+r" (__cu_len_r) \
: \ : \
: "$8", "$9", "$10", "$11", "$12", "$15", "$24", "$31", \ : "$8", "$9", "$10", "$11", "$12", "$14", "$15", "$24", "$31", \
DADDI_SCRATCH, "memory"); \ DADDI_SCRATCH, "memory"); \
__cu_len_r; \ __cu_len_r; \
}) })
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer * Copyright (C) 2004, 2005, 2006, 2008 Thiemo Seufer
* Copyright (C) 2005 Maciej W. Rozycki * Copyright (C) 2005 Maciej W. Rozycki
* Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 2006 Ralf Baechle (ralf@linux-mips.org)
* Copyright (C) 2012 MIPS Technologies, Inc.
*/ */
#include <linux/types.h> #include <linux/types.h>
...@@ -62,8 +63,10 @@ void __uasminit uasm_i##op(u32 **buf, unsigned int a, signed int b) ...@@ -62,8 +63,10 @@ void __uasminit uasm_i##op(u32 **buf, unsigned int a, signed int b)
Ip_u2u1s3(_addiu); Ip_u2u1s3(_addiu);
Ip_u3u1u2(_addu); Ip_u3u1u2(_addu);
Ip_u2u1u3(_andi);
Ip_u3u1u2(_and); Ip_u3u1u2(_and);
Ip_u2u1u3(_andi);
Ip_u1u2s3(_bbit0);
Ip_u1u2s3(_bbit1);
Ip_u1u2s3(_beq); Ip_u1u2s3(_beq);
Ip_u1u2s3(_beql); Ip_u1u2s3(_beql);
Ip_u1s2(_bgez); Ip_u1s2(_bgez);
...@@ -72,55 +75,54 @@ Ip_u1s2(_bltz); ...@@ -72,55 +75,54 @@ Ip_u1s2(_bltz);
Ip_u1s2(_bltzl); Ip_u1s2(_bltzl);
Ip_u1u2s3(_bne); Ip_u1u2s3(_bne);
Ip_u2s3u1(_cache); Ip_u2s3u1(_cache);
Ip_u1u2u3(_dmfc0);
Ip_u1u2u3(_dmtc0);
Ip_u2u1s3(_daddiu); Ip_u2u1s3(_daddiu);
Ip_u3u1u2(_daddu); Ip_u3u1u2(_daddu);
Ip_u2u1msbu3(_dins);
Ip_u2u1msbu3(_dinsm);
Ip_u1u2u3(_dmfc0);
Ip_u1u2u3(_dmtc0);
Ip_u2u1u3(_drotr);
Ip_u2u1u3(_drotr32);
Ip_u2u1u3(_dsll); Ip_u2u1u3(_dsll);
Ip_u2u1u3(_dsll32); Ip_u2u1u3(_dsll32);
Ip_u2u1u3(_dsra); Ip_u2u1u3(_dsra);
Ip_u2u1u3(_dsrl); Ip_u2u1u3(_dsrl);
Ip_u2u1u3(_dsrl32); Ip_u2u1u3(_dsrl32);
Ip_u2u1u3(_drotr);
Ip_u2u1u3(_drotr32);
Ip_u3u1u2(_dsubu); Ip_u3u1u2(_dsubu);
Ip_0(_eret); Ip_0(_eret);
Ip_u1(_j); Ip_u1(_j);
Ip_u1(_jal); Ip_u1(_jal);
Ip_u1(_jr); Ip_u1(_jr);
Ip_u2s3u1(_ld); Ip_u2s3u1(_ld);
Ip_u3u1u2(_ldx);
Ip_u2s3u1(_ll); Ip_u2s3u1(_ll);
Ip_u2s3u1(_lld); Ip_u2s3u1(_lld);
Ip_u1s2(_lui); Ip_u1s2(_lui);
Ip_u2s3u1(_lw); Ip_u2s3u1(_lw);
Ip_u3u1u2(_lwx);
Ip_u1u2u3(_mfc0); Ip_u1u2u3(_mfc0);
Ip_u1u2u3(_mtc0); Ip_u1u2u3(_mtc0);
Ip_u2u1u3(_ori);
Ip_u3u1u2(_or); Ip_u3u1u2(_or);
Ip_u2u1u3(_ori);
Ip_u2s3u1(_pref); Ip_u2s3u1(_pref);
Ip_0(_rfe); Ip_0(_rfe);
Ip_u2u1u3(_rotr);
Ip_u2s3u1(_sc); Ip_u2s3u1(_sc);
Ip_u2s3u1(_scd); Ip_u2s3u1(_scd);
Ip_u2s3u1(_sd); Ip_u2s3u1(_sd);
Ip_u2u1u3(_sll); Ip_u2u1u3(_sll);
Ip_u2u1u3(_sra); Ip_u2u1u3(_sra);
Ip_u2u1u3(_srl); Ip_u2u1u3(_srl);
Ip_u2u1u3(_rotr);
Ip_u3u1u2(_subu); Ip_u3u1u2(_subu);
Ip_u2s3u1(_sw); Ip_u2s3u1(_sw);
Ip_u1(_syscall);
Ip_0(_tlbp); Ip_0(_tlbp);
Ip_0(_tlbr); Ip_0(_tlbr);
Ip_0(_tlbwi); Ip_0(_tlbwi);
Ip_0(_tlbwr); Ip_0(_tlbwr);
Ip_u3u1u2(_xor); Ip_u3u1u2(_xor);
Ip_u2u1u3(_xori); Ip_u2u1u3(_xori);
Ip_u2u1msbu3(_dins);
Ip_u2u1msbu3(_dinsm);
Ip_u1(_syscall);
Ip_u1u2s3(_bbit0);
Ip_u1u2s3(_bbit1);
Ip_u3u1u2(_lwx);
Ip_u3u1u2(_ldx);
/* Handle labels. */ /* Handle labels. */
struct uasm_label { struct uasm_label {
...@@ -145,37 +147,37 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ ...@@ -145,37 +147,37 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
/* convenience macros for instructions */ /* convenience macros for instructions */
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
# define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_daddiu(buf, rs, rt, val)
# define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_daddu(buf, rs, rt, rd)
# define UASM_i_LL(buf, rs, rt, off) uasm_i_lld(buf, rs, rt, off)
# define UASM_i_LW(buf, rs, rt, off) uasm_i_ld(buf, rs, rt, off) # define UASM_i_LW(buf, rs, rt, off) uasm_i_ld(buf, rs, rt, off)
# define UASM_i_SW(buf, rs, rt, off) uasm_i_sd(buf, rs, rt, off) # define UASM_i_LWX(buf, rs, rt, rd) uasm_i_ldx(buf, rs, rt, rd)
# define UASM_i_MFC0(buf, rt, rd...) uasm_i_dmfc0(buf, rt, rd)
# define UASM_i_MTC0(buf, rt, rd...) uasm_i_dmtc0(buf, rt, rd)
# define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_drotr(buf, rs, rt, sh)
# define UASM_i_SC(buf, rs, rt, off) uasm_i_scd(buf, rs, rt, off)
# define UASM_i_SLL(buf, rs, rt, sh) uasm_i_dsll(buf, rs, rt, sh) # define UASM_i_SLL(buf, rs, rt, sh) uasm_i_dsll(buf, rs, rt, sh)
# define UASM_i_SRA(buf, rs, rt, sh) uasm_i_dsra(buf, rs, rt, sh) # define UASM_i_SRA(buf, rs, rt, sh) uasm_i_dsra(buf, rs, rt, sh)
# define UASM_i_SRL(buf, rs, rt, sh) uasm_i_dsrl(buf, rs, rt, sh) # define UASM_i_SRL(buf, rs, rt, sh) uasm_i_dsrl(buf, rs, rt, sh)
# define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_dsrl_safe(buf, rs, rt, sh) # define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_dsrl_safe(buf, rs, rt, sh)
# define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_drotr(buf, rs, rt, sh)
# define UASM_i_MFC0(buf, rt, rd...) uasm_i_dmfc0(buf, rt, rd)
# define UASM_i_MTC0(buf, rt, rd...) uasm_i_dmtc0(buf, rt, rd)
# define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_daddiu(buf, rs, rt, val)
# define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_daddu(buf, rs, rt, rd)
# define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_dsubu(buf, rs, rt, rd) # define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_dsubu(buf, rs, rt, rd)
# define UASM_i_LL(buf, rs, rt, off) uasm_i_lld(buf, rs, rt, off) # define UASM_i_SW(buf, rs, rt, off) uasm_i_sd(buf, rs, rt, off)
# define UASM_i_SC(buf, rs, rt, off) uasm_i_scd(buf, rs, rt, off)
# define UASM_i_LWX(buf, rs, rt, rd) uasm_i_ldx(buf, rs, rt, rd)
#else #else
# define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_addiu(buf, rs, rt, val)
# define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_addu(buf, rs, rt, rd)
# define UASM_i_LL(buf, rs, rt, off) uasm_i_ll(buf, rs, rt, off)
# define UASM_i_LW(buf, rs, rt, off) uasm_i_lw(buf, rs, rt, off) # define UASM_i_LW(buf, rs, rt, off) uasm_i_lw(buf, rs, rt, off)
# define UASM_i_SW(buf, rs, rt, off) uasm_i_sw(buf, rs, rt, off) # define UASM_i_LWX(buf, rs, rt, rd) uasm_i_lwx(buf, rs, rt, rd)
# define UASM_i_MFC0(buf, rt, rd...) uasm_i_mfc0(buf, rt, rd)
# define UASM_i_MTC0(buf, rt, rd...) uasm_i_mtc0(buf, rt, rd)
# define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_rotr(buf, rs, rt, sh)
# define UASM_i_SC(buf, rs, rt, off) uasm_i_sc(buf, rs, rt, off)
# define UASM_i_SLL(buf, rs, rt, sh) uasm_i_sll(buf, rs, rt, sh) # define UASM_i_SLL(buf, rs, rt, sh) uasm_i_sll(buf, rs, rt, sh)
# define UASM_i_SRA(buf, rs, rt, sh) uasm_i_sra(buf, rs, rt, sh) # define UASM_i_SRA(buf, rs, rt, sh) uasm_i_sra(buf, rs, rt, sh)
# define UASM_i_SRL(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh) # define UASM_i_SRL(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh)
# define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh) # define UASM_i_SRL_SAFE(buf, rs, rt, sh) uasm_i_srl(buf, rs, rt, sh)
# define UASM_i_ROTR(buf, rs, rt, sh) uasm_i_rotr(buf, rs, rt, sh)
# define UASM_i_MFC0(buf, rt, rd...) uasm_i_mfc0(buf, rt, rd)
# define UASM_i_MTC0(buf, rt, rd...) uasm_i_mtc0(buf, rt, rd)
# define UASM_i_ADDIU(buf, rs, rt, val) uasm_i_addiu(buf, rs, rt, val)
# define UASM_i_ADDU(buf, rs, rt, rd) uasm_i_addu(buf, rs, rt, rd)
# define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_subu(buf, rs, rt, rd) # define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_subu(buf, rs, rt, rd)
# define UASM_i_LL(buf, rs, rt, off) uasm_i_ll(buf, rs, rt, off) # define UASM_i_SW(buf, rs, rt, off) uasm_i_sw(buf, rs, rt, off)
# define UASM_i_SC(buf, rs, rt, off) uasm_i_sc(buf, rs, rt, off)
# define UASM_i_LWX(buf, rs, rt, rd) uasm_i_lwx(buf, rs, rt, rd)
#endif #endif
#define uasm_i_b(buf, off) uasm_i_beq(buf, 0, 0, off) #define uasm_i_b(buf, off) uasm_i_beq(buf, 0, 0, off)
...@@ -183,19 +185,10 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \ ...@@ -183,19 +185,10 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
#define uasm_i_beqzl(buf, rs, off) uasm_i_beql(buf, rs, 0, off) #define uasm_i_beqzl(buf, rs, off) uasm_i_beql(buf, rs, 0, off)
#define uasm_i_bnez(buf, rs, off) uasm_i_bne(buf, rs, 0, off) #define uasm_i_bnez(buf, rs, off) uasm_i_bne(buf, rs, 0, off)
#define uasm_i_bnezl(buf, rs, off) uasm_i_bnel(buf, rs, 0, off) #define uasm_i_bnezl(buf, rs, off) uasm_i_bnel(buf, rs, 0, off)
#define uasm_i_ehb(buf) uasm_i_sll(buf, 0, 0, 3)
#define uasm_i_move(buf, a, b) UASM_i_ADDU(buf, a, 0, b) #define uasm_i_move(buf, a, b) UASM_i_ADDU(buf, a, 0, b)
#define uasm_i_nop(buf) uasm_i_sll(buf, 0, 0, 0) #define uasm_i_nop(buf) uasm_i_sll(buf, 0, 0, 0)
#define uasm_i_ssnop(buf) uasm_i_sll(buf, 0, 0, 1) #define uasm_i_ssnop(buf) uasm_i_sll(buf, 0, 0, 1)
#define uasm_i_ehb(buf) uasm_i_sll(buf, 0, 0, 3)
static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1,
unsigned int a2, unsigned int a3)
{
if (a3 < 32)
uasm_i_dsrl(p, a1, a2, a3);
else
uasm_i_dsrl32(p, a1, a2, a3 - 32);
}
static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1, static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1,
unsigned int a2, unsigned int a3) unsigned int a2, unsigned int a3)
...@@ -215,6 +208,15 @@ static inline void uasm_i_dsll_safe(u32 **p, unsigned int a1, ...@@ -215,6 +208,15 @@ static inline void uasm_i_dsll_safe(u32 **p, unsigned int a1,
uasm_i_dsll32(p, a1, a2, a3 - 32); uasm_i_dsll32(p, a1, a2, a3 - 32);
} }
static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1,
unsigned int a2, unsigned int a3)
{
if (a3 < 32)
uasm_i_dsrl(p, a1, a2, a3);
else
uasm_i_dsrl32(p, a1, a2, a3 - 32);
}
/* Handle relocations. */ /* Handle relocations. */
struct uasm_reloc { struct uasm_reloc {
u32 *addr; u32 *addr;
...@@ -234,16 +236,16 @@ void uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab, ...@@ -234,16 +236,16 @@ void uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab,
int uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr); int uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr);
/* Convenience functions for labeled branches. */ /* Convenience functions for labeled branches. */
void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_b(u32 **p, struct uasm_reloc **r, int lid); void uasm_il_b(u32 **p, struct uasm_reloc **r, int lid);
void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg,
unsigned int bit, int lid);
void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg,
unsigned int bit, int lid);
void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1, void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1,
unsigned int reg2, int lid); unsigned int reg2, int lid);
void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid); void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg, int lid);
void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg,
unsigned int bit, int lid);
void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg,
unsigned int bit, int lid);
...@@ -140,6 +140,7 @@ static void qi_lb60_nand_ident(struct platform_device *pdev, ...@@ -140,6 +140,7 @@ static void qi_lb60_nand_ident(struct platform_device *pdev,
static struct jz_nand_platform_data qi_lb60_nand_pdata = { static struct jz_nand_platform_data qi_lb60_nand_pdata = {
.ident_callback = qi_lb60_nand_ident, .ident_callback = qi_lb60_nand_ident,
.busy_gpio = 94, .busy_gpio = 94,
.banks = { 1 },
}; };
/* Keyboard*/ /* Keyboard*/
......
...@@ -157,11 +157,29 @@ static struct resource jz4740_nand_resources[] = { ...@@ -157,11 +157,29 @@ static struct resource jz4740_nand_resources[] = {
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
{ {
.name = "bank", .name = "bank1",
.start = 0x18000000, .start = 0x18000000,
.end = 0x180C0000 - 1, .end = 0x180C0000 - 1,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
{
.name = "bank2",
.start = 0x14000000,
.end = 0x140C0000 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "bank3",
.start = 0x0C000000,
.end = 0x0C0C0000 - 1,
.flags = IORESOURCE_MEM,
},
{
.name = "bank4",
.start = 0x08000000,
.end = 0x080C0000 - 1,
.flags = IORESOURCE_MEM,
},
}; };
struct platform_device jz4740_nand_device = { struct platform_device jz4740_nand_device = {
......
...@@ -21,6 +21,9 @@ ...@@ -21,6 +21,9 @@
#include <asm/mach-jz4740/base.h> #include <asm/mach-jz4740/base.h>
#include <asm/mach-jz4740/timer.h> #include <asm/mach-jz4740/timer.h>
#include "reset.h"
#include "clock.h"
static void jz4740_halt(void) static void jz4740_halt(void)
{ {
while (1) { while (1) {
...@@ -53,21 +56,57 @@ static void jz4740_restart(char *command) ...@@ -53,21 +56,57 @@ static void jz4740_restart(char *command)
jz4740_halt(); jz4740_halt();
} }
#define JZ_REG_RTC_CTRL 0x00 #define JZ_REG_RTC_CTRL 0x00
#define JZ_REG_RTC_HIBERNATE 0x20 #define JZ_REG_RTC_HIBERNATE 0x20
#define JZ_REG_RTC_WAKEUP_FILTER 0x24
#define JZ_REG_RTC_RESET_COUNTER 0x28
#define JZ_RTC_CTRL_WRDY BIT(7) #define JZ_RTC_CTRL_WRDY BIT(7)
#define JZ_RTC_WAKEUP_FILTER_MASK 0x0000FFE0
#define JZ_RTC_RESET_COUNTER_MASK 0x00000FE0
static void jz4740_power_off(void) static inline void jz4740_rtc_wait_ready(void __iomem *rtc_base)
{ {
void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x24);
uint32_t ctrl; uint32_t ctrl;
do { do {
ctrl = readl(rtc_base + JZ_REG_RTC_CTRL); ctrl = readl(rtc_base + JZ_REG_RTC_CTRL);
} while (!(ctrl & JZ_RTC_CTRL_WRDY)); } while (!(ctrl & JZ_RTC_CTRL_WRDY));
}
static void jz4740_power_off(void)
{
void __iomem *rtc_base = ioremap(JZ4740_RTC_BASE_ADDR, 0x38);
unsigned long wakeup_filter_ticks;
unsigned long reset_counter_ticks;
/*
* Set minimum wakeup pin assertion time: 100 ms.
* Range is 0 to 2 sec if RTC is clocked at 32 kHz.
*/
wakeup_filter_ticks = (100 * jz4740_clock_bdata.rtc_rate) / 1000;
if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
else
wakeup_filter_ticks = JZ_RTC_WAKEUP_FILTER_MASK;
jz4740_rtc_wait_ready(rtc_base);
writel(wakeup_filter_ticks, rtc_base + JZ_REG_RTC_WAKEUP_FILTER);
/*
* Set reset pin low-level assertion time after wakeup: 60 ms.
* Range is 0 to 125 ms if RTC is clocked at 32 kHz.
*/
reset_counter_ticks = (60 * jz4740_clock_bdata.rtc_rate) / 1000;
if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK)
reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK;
else
reset_counter_ticks = JZ_RTC_RESET_COUNTER_MASK;
jz4740_rtc_wait_ready(rtc_base);
writel(reset_counter_ticks, rtc_base + JZ_REG_RTC_RESET_COUNTER);
jz4740_rtc_wait_ready(rtc_base);
writel(1, rtc_base + JZ_REG_RTC_HIBERNATE); writel(1, rtc_base + JZ_REG_RTC_HIBERNATE);
jz4740_halt(); jz4740_halt();
} }
......
...@@ -190,6 +190,7 @@ void __init check_wait(void) ...@@ -190,6 +190,7 @@ void __init check_wait(void)
case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON_PLUS:
case CPU_CAVIUM_OCTEON2: case CPU_CAVIUM_OCTEON2:
case CPU_JZRISC: case CPU_JZRISC:
case CPU_LOONGSON1:
case CPU_XLR: case CPU_XLR:
case CPU_XLP: case CPU_XLP:
cpu_wait = r4k_wait; cpu_wait = r4k_wait;
...@@ -330,6 +331,154 @@ static inline void cpu_probe_vmbits(struct cpuinfo_mips *c) ...@@ -330,6 +331,154 @@ static inline void cpu_probe_vmbits(struct cpuinfo_mips *c)
#endif #endif
} }
static char unknown_isa[] __cpuinitdata = KERN_ERR \
"Unsupported ISA type, c0.config0: %d.";
static inline unsigned int decode_config0(struct cpuinfo_mips *c)
{
unsigned int config0;
int isa;
config0 = read_c0_config();
if (((config0 & MIPS_CONF_MT) >> 7) == 1)
c->options |= MIPS_CPU_TLB;
isa = (config0 & MIPS_CONF_AT) >> 13;
switch (isa) {
case 0:
switch ((config0 & MIPS_CONF_AR) >> 10) {
case 0:
c->isa_level = MIPS_CPU_ISA_M32R1;
break;
case 1:
c->isa_level = MIPS_CPU_ISA_M32R2;
break;
default:
goto unknown;
}
break;
case 2:
switch ((config0 & MIPS_CONF_AR) >> 10) {
case 0:
c->isa_level = MIPS_CPU_ISA_M64R1;
break;
case 1:
c->isa_level = MIPS_CPU_ISA_M64R2;
break;
default:
goto unknown;
}
break;
default:
goto unknown;
}
return config0 & MIPS_CONF_M;
unknown:
panic(unknown_isa, config0);
}
static inline unsigned int decode_config1(struct cpuinfo_mips *c)
{
unsigned int config1;
config1 = read_c0_config1();
if (config1 & MIPS_CONF1_MD)
c->ases |= MIPS_ASE_MDMX;
if (config1 & MIPS_CONF1_WR)
c->options |= MIPS_CPU_WATCH;
if (config1 & MIPS_CONF1_CA)
c->ases |= MIPS_ASE_MIPS16;
if (config1 & MIPS_CONF1_EP)
c->options |= MIPS_CPU_EJTAG;
if (config1 & MIPS_CONF1_FP) {
c->options |= MIPS_CPU_FPU;
c->options |= MIPS_CPU_32FPR;
}
if (cpu_has_tlb)
c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1;
return config1 & MIPS_CONF_M;
}
static inline unsigned int decode_config2(struct cpuinfo_mips *c)
{
unsigned int config2;
config2 = read_c0_config2();
if (config2 & MIPS_CONF2_SL)
c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
return config2 & MIPS_CONF_M;
}
static inline unsigned int decode_config3(struct cpuinfo_mips *c)
{
unsigned int config3;
config3 = read_c0_config3();
if (config3 & MIPS_CONF3_SM)
c->ases |= MIPS_ASE_SMARTMIPS;
if (config3 & MIPS_CONF3_DSP)
c->ases |= MIPS_ASE_DSP;
if (config3 & MIPS_CONF3_VINT)
c->options |= MIPS_CPU_VINT;
if (config3 & MIPS_CONF3_VEIC)
c->options |= MIPS_CPU_VEIC;
if (config3 & MIPS_CONF3_MT)
c->ases |= MIPS_ASE_MIPSMT;
if (config3 & MIPS_CONF3_ULRI)
c->options |= MIPS_CPU_ULRI;
return config3 & MIPS_CONF_M;
}
static inline unsigned int decode_config4(struct cpuinfo_mips *c)
{
unsigned int config4;
config4 = read_c0_config4();
if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT
&& cpu_has_tlb)
c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
c->kscratch_mask = (config4 >> 16) & 0xff;
return config4 & MIPS_CONF_M;
}
static void __cpuinit decode_configs(struct cpuinfo_mips *c)
{
int ok;
/* MIPS32 or MIPS64 compliant CPU. */
c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
c->scache.flags = MIPS_CACHE_NOT_PRESENT;
ok = decode_config0(c); /* Read Config registers. */
BUG_ON(!ok); /* Arch spec violation! */
if (ok)
ok = decode_config1(c);
if (ok)
ok = decode_config2(c);
if (ok)
ok = decode_config3(c);
if (ok)
ok = decode_config4(c);
mips_probe_watch_registers(c);
if (cpu_has_mips_r2)
c->core = read_c0_ebase() & 0x3ff;
}
#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \ #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \
| MIPS_CPU_COUNTER) | MIPS_CPU_COUNTER)
...@@ -638,155 +787,19 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) ...@@ -638,155 +787,19 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
MIPS_CPU_32FPR; MIPS_CPU_32FPR;
c->tlbsize = 64; c->tlbsize = 64;
break; break;
} case PRID_IMP_LOONGSON1:
} decode_configs(c);
static char unknown_isa[] __cpuinitdata = KERN_ERR \
"Unsupported ISA type, c0.config0: %d.";
static inline unsigned int decode_config0(struct cpuinfo_mips *c) c->cputype = CPU_LOONGSON1;
{
unsigned int config0;
int isa;
config0 = read_c0_config(); switch (c->processor_id & PRID_REV_MASK) {
case PRID_REV_LOONGSON1B:
if (((config0 & MIPS_CONF_MT) >> 7) == 1) __cpu_name[cpu] = "Loongson 1B";
c->options |= MIPS_CPU_TLB;
isa = (config0 & MIPS_CONF_AT) >> 13;
switch (isa) {
case 0:
switch ((config0 & MIPS_CONF_AR) >> 10) {
case 0:
c->isa_level = MIPS_CPU_ISA_M32R1;
break;
case 1:
c->isa_level = MIPS_CPU_ISA_M32R2;
break; break;
default:
goto unknown;
} }
break;
case 2:
switch ((config0 & MIPS_CONF_AR) >> 10) {
case 0:
c->isa_level = MIPS_CPU_ISA_M64R1;
break;
case 1:
c->isa_level = MIPS_CPU_ISA_M64R2;
break;
default:
goto unknown;
}
break;
default:
goto unknown;
}
return config0 & MIPS_CONF_M;
unknown:
panic(unknown_isa, config0);
}
static inline unsigned int decode_config1(struct cpuinfo_mips *c) break;
{
unsigned int config1;
config1 = read_c0_config1();
if (config1 & MIPS_CONF1_MD)
c->ases |= MIPS_ASE_MDMX;
if (config1 & MIPS_CONF1_WR)
c->options |= MIPS_CPU_WATCH;
if (config1 & MIPS_CONF1_CA)
c->ases |= MIPS_ASE_MIPS16;
if (config1 & MIPS_CONF1_EP)
c->options |= MIPS_CPU_EJTAG;
if (config1 & MIPS_CONF1_FP) {
c->options |= MIPS_CPU_FPU;
c->options |= MIPS_CPU_32FPR;
} }
if (cpu_has_tlb)
c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1;
return config1 & MIPS_CONF_M;
}
static inline unsigned int decode_config2(struct cpuinfo_mips *c)
{
unsigned int config2;
config2 = read_c0_config2();
if (config2 & MIPS_CONF2_SL)
c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
return config2 & MIPS_CONF_M;
}
static inline unsigned int decode_config3(struct cpuinfo_mips *c)
{
unsigned int config3;
config3 = read_c0_config3();
if (config3 & MIPS_CONF3_SM)
c->ases |= MIPS_ASE_SMARTMIPS;
if (config3 & MIPS_CONF3_DSP)
c->ases |= MIPS_ASE_DSP;
if (config3 & MIPS_CONF3_VINT)
c->options |= MIPS_CPU_VINT;
if (config3 & MIPS_CONF3_VEIC)
c->options |= MIPS_CPU_VEIC;
if (config3 & MIPS_CONF3_MT)
c->ases |= MIPS_ASE_MIPSMT;
if (config3 & MIPS_CONF3_ULRI)
c->options |= MIPS_CPU_ULRI;
return config3 & MIPS_CONF_M;
}
static inline unsigned int decode_config4(struct cpuinfo_mips *c)
{
unsigned int config4;
config4 = read_c0_config4();
if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT
&& cpu_has_tlb)
c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
c->kscratch_mask = (config4 >> 16) & 0xff;
return config4 & MIPS_CONF_M;
}
static void __cpuinit decode_configs(struct cpuinfo_mips *c)
{
int ok;
/* MIPS32 or MIPS64 compliant CPU. */
c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER |
MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK;
c->scache.flags = MIPS_CACHE_NOT_PRESENT;
ok = decode_config0(c); /* Read Config registers. */
BUG_ON(!ok); /* Arch spec violation! */
if (ok)
ok = decode_config1(c);
if (ok)
ok = decode_config2(c);
if (ok)
ok = decode_config3(c);
if (ok)
ok = decode_config4(c);
mips_probe_watch_registers(c);
if (cpu_has_mips_r2)
c->core = read_c0_ebase() & 0x3ff;
} }
static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
......
...@@ -1559,6 +1559,11 @@ init_hw_perf_events(void) ...@@ -1559,6 +1559,11 @@ init_hw_perf_events(void)
mipspmu.general_event_map = &mipsxxcore_event_map; mipspmu.general_event_map = &mipsxxcore_event_map;
mipspmu.cache_event_map = &mipsxxcore_cache_map; mipspmu.cache_event_map = &mipsxxcore_cache_map;
break; break;
case CPU_LOONGSON1:
mipspmu.name = "mips/loongson1";
mipspmu.general_event_map = &mipsxxcore_event_map;
mipspmu.cache_event_map = &mipsxxcore_cache_map;
break;
case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON:
case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON_PLUS:
case CPU_CAVIUM_OCTEON2: case CPU_CAVIUM_OCTEON2:
......
...@@ -35,16 +35,6 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) ...@@ -35,16 +35,6 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
return add_memory_region(base, size, BOOT_MEM_RAM); return add_memory_region(base, size, BOOT_MEM_RAM);
} }
int __init reserve_mem_mach(unsigned long addr, unsigned long size)
{
return reserve_bootmem(addr, size, BOOTMEM_DEFAULT);
}
void __init free_mem_mach(unsigned long addr, unsigned long size)
{
return free_bootmem(addr, size);
}
void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
{ {
return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS)); return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
...@@ -77,25 +67,6 @@ void __init early_init_devtree(void *params) ...@@ -77,25 +67,6 @@ void __init early_init_devtree(void *params)
of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL); of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
} }
void __init device_tree_init(void)
{
unsigned long base, size;
if (!initial_boot_params)
return;
base = virt_to_phys((void *)initial_boot_params);
size = be32_to_cpu(initial_boot_params->totalsize);
/* Before we do anything, lets reserve the dt blob */
reserve_mem_mach(base, size);
unflatten_device_tree();
/* free the space reserved for the dt blob */
free_mem_mach(base, size);
}
void __init __dt_setup_arch(struct boot_param_header *bph) void __init __dt_setup_arch(struct boot_param_header *bph)
{ {
if (be32_to_cpu(bph->magic) != OF_DT_HEADER) { if (be32_to_cpu(bph->magic) != OF_DT_HEADER) {
......
...@@ -102,7 +102,9 @@ asmlinkage __cpuinit void start_secondary(void) ...@@ -102,7 +102,9 @@ asmlinkage __cpuinit void start_secondary(void)
#ifdef CONFIG_MIPS_MT_SMTC #ifdef CONFIG_MIPS_MT_SMTC
/* Only do cpu_probe for first TC of CPU */ /* Only do cpu_probe for first TC of CPU */
if ((read_c0_tcbind() & TCBIND_CURTC) == 0) if ((read_c0_tcbind() & TCBIND_CURTC) != 0)
__cpu_name[smp_processor_id()] = __cpu_name[0];
else
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
cpu_probe(); cpu_probe();
cpu_report(); cpu_report();
......
...@@ -86,6 +86,13 @@ struct smtc_ipi_q IPIQ[NR_CPUS]; ...@@ -86,6 +86,13 @@ struct smtc_ipi_q IPIQ[NR_CPUS];
static struct smtc_ipi_q freeIPIq; static struct smtc_ipi_q freeIPIq;
/*
* Number of FPU contexts for each VPE
*/
static int smtc_nconf1[MAX_SMTC_VPES];
/* Forward declarations */ /* Forward declarations */
void ipi_decode(struct smtc_ipi *); void ipi_decode(struct smtc_ipi *);
...@@ -174,9 +181,9 @@ static int __init tintq(char *str) ...@@ -174,9 +181,9 @@ static int __init tintq(char *str)
__setup("tintq=", tintq); __setup("tintq=", tintq);
static int imstuckcount[2][8]; static int imstuckcount[MAX_SMTC_VPES][8];
/* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */ /* vpemask represents IM/IE bits of per-VPE Status registers, low-to-high */
static int vpemask[2][8] = { static int vpemask[MAX_SMTC_VPES][8] = {
{0, 0, 1, 0, 0, 0, 0, 1}, {0, 0, 1, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 1} {0, 0, 0, 0, 0, 0, 0, 1}
}; };
...@@ -331,6 +338,22 @@ int __init smtc_build_cpu_map(int start_cpu_slot) ...@@ -331,6 +338,22 @@ int __init smtc_build_cpu_map(int start_cpu_slot)
static void smtc_tc_setup(int vpe, int tc, int cpu) static void smtc_tc_setup(int vpe, int tc, int cpu)
{ {
static int cp1contexts[MAX_SMTC_VPES];
/*
* Make a local copy of the available FPU contexts in order
* to keep track of TCs that can have one.
*/
if (tc == 1)
{
/*
* FIXME: Multi-core SMTC hasn't been tested and the
* maximum number of VPEs may change.
*/
cp1contexts[0] = smtc_nconf1[0] - 1;
cp1contexts[1] = smtc_nconf1[1];
}
settc(tc); settc(tc);
write_tc_c0_tchalt(TCHALT_H); write_tc_c0_tchalt(TCHALT_H);
mips_ihb(); mips_ihb();
...@@ -343,22 +366,29 @@ static void smtc_tc_setup(int vpe, int tc, int cpu) ...@@ -343,22 +366,29 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
* an active IPI queue. * an active IPI queue.
*/ */
write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16); write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16);
/* Bind tc to vpe */
/* Bind TC to VPE. */
write_tc_c0_tcbind(vpe); write_tc_c0_tcbind(vpe);
/* In general, all TCs should have the same cpu_data indications. */ /* In general, all TCs should have the same cpu_data indications. */
memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips)); memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
/* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
if (cpu_data[0].cputype == CPU_34K || /* Check to see if there is a FPU context available for this TC. */
cpu_data[0].cputype == CPU_1004K) if (!cp1contexts[vpe])
cpu_data[cpu].options &= ~MIPS_CPU_FPU; cpu_data[cpu].options &= ~MIPS_CPU_FPU;
else
cp1contexts[vpe]--;
/* Store the TC and VPE into the cpu_data structure. */
cpu_data[cpu].vpe_id = vpe; cpu_data[cpu].vpe_id = vpe;
cpu_data[cpu].tc_id = tc; cpu_data[cpu].tc_id = tc;
/* Multi-core SMTC hasn't been tested, but be prepared */
/* FIXME: Multi-core SMTC hasn't been tested, but be prepared. */
cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff; cpu_data[cpu].core = (read_vpe_c0_ebase() >> 1) & 0xff;
} }
/* /*
* Tweak to get Count registes in as close a sync as possible. The * Tweak to get Count registers synced as closely as possible. The
* value seems good for 34K-class cores. * value seems good for 34K-class cores.
*/ */
...@@ -466,6 +496,24 @@ void smtc_prepare_cpus(int cpus) ...@@ -466,6 +496,24 @@ void smtc_prepare_cpus(int cpus)
smtc_configure_tlb(); smtc_configure_tlb();
for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) { for (tc = 0, vpe = 0 ; (vpe < nvpe) && (tc < ntc) ; vpe++) {
/* Get number of CP1 contexts for each VPE. */
if (tc == 0)
{
/*
* Do not call settc() for TC0 or the FPU context
* value will be incorrect. Besides, we know that
* we are TC0 anyway.
*/
smtc_nconf1[0] = ((read_vpe_c0_vpeconf1() &
VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT);
if (nvpe == 2)
{
settc(1);
smtc_nconf1[1] = ((read_vpe_c0_vpeconf1() &
VPECONF1_NCP1) >> VPECONF1_NCP1_SHIFT);
settc(0);
}
}
if (tcpervpe[vpe] == 0) if (tcpervpe[vpe] == 0)
continue; continue;
if (vpe != 0) if (vpe != 0)
...@@ -479,6 +527,18 @@ void smtc_prepare_cpus(int cpus) ...@@ -479,6 +527,18 @@ void smtc_prepare_cpus(int cpus)
*/ */
if (tc != 0) { if (tc != 0) {
smtc_tc_setup(vpe, tc, cpu); smtc_tc_setup(vpe, tc, cpu);
if (vpe != 0) {
/*
* Set MVP bit (possibly again). Do it
* here to catch CPUs that have no TCs
* bound to the VPE at reset. In that
* case, a TC must be bound to the VPE
* before we can set VPEControl[MVP]
*/
write_vpe_c0_vpeconf0(
read_vpe_c0_vpeconf0() |
VPECONF0_MVP);
}
cpu++; cpu++;
} }
printk(" %d", tc); printk(" %d", tc);
......
...@@ -1253,6 +1253,7 @@ static inline void parity_protection_init(void) ...@@ -1253,6 +1253,7 @@ static inline void parity_protection_init(void)
case CPU_5KC: case CPU_5KC:
case CPU_5KE: case CPU_5KE:
case CPU_LOONGSON1:
write_c0_ecc(0x80000000); write_c0_ecc(0x80000000);
back_to_back_c0_hazard(); back_to_back_c0_hazard();
/* Set the PE bit (bit 31) in the c0_errctl register. */ /* Set the PE bit (bit 31) in the c0_errctl register. */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Makefile for MIPS-specific library files.. # Makefile for MIPS-specific library files..
# #
lib-y += csum_partial.o delay.o memcpy.o memcpy-inatomic.o memset.o \ lib-y += csum_partial.o delay.o memcpy.o memset.o \
strlen_user.o strncpy_user.o strnlen_user.o uncached.o strlen_user.o strncpy_user.o strnlen_user.o uncached.o
obj-y += iomap.o obj-y += iomap.o
......
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Unified implementation of memcpy, memmove and the __copy_user backend.
*
* Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@gnu.org)
* Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc.
* Copyright (C) 2002 Broadcom, Inc.
* memcpy/copy_user author: Mark Vandevoorde
* Copyright (C) 2007 Maciej W. Rozycki
*
* Mnemonic names for arguments to memcpy/__copy_user
*/
/*
* Hack to resolve longstanding prefetch issue
*
* Prefetching may be fatal on some systems if we're prefetching beyond the
* end of memory on some systems. It's also a seriously bad idea on non
* dma-coherent systems.
*/
#ifdef CONFIG_DMA_NONCOHERENT
#undef CONFIG_CPU_HAS_PREFETCH
#endif
#ifdef CONFIG_MIPS_MALTA
#undef CONFIG_CPU_HAS_PREFETCH
#endif
#include <asm/asm.h>
#include <asm/asm-offsets.h>
#include <asm/regdef.h>
#define dst a0
#define src a1
#define len a2
/*
* Spec
*
* memcpy copies len bytes from src to dst and sets v0 to dst.
* It assumes that
* - src and dst don't overlap
* - src is readable
* - dst is writable
* memcpy uses the standard calling convention
*
* __copy_user copies up to len bytes from src to dst and sets a2 (len) to
* the number of uncopied bytes due to an exception caused by a read or write.
* __copy_user assumes that src and dst don't overlap, and that the call is
* implementing one of the following:
* copy_to_user
* - src is readable (no exceptions when reading src)
* copy_from_user
* - dst is writable (no exceptions when writing dst)
* __copy_user uses a non-standard calling convention; see
* include/asm-mips/uaccess.h
*
* When an exception happens on a load, the handler must
# ensure that all of the destination buffer is overwritten to prevent
* leaking information to user mode programs.
*/
/*
* Implementation
*/
/*
* The exception handler for loads requires that:
* 1- AT contain the address of the byte just past the end of the source
* of the copy,
* 2- src_entry <= src < AT, and
* 3- (dst - src) == (dst_entry - src_entry),
* The _entry suffix denotes values when __copy_user was called.
*
* (1) is set up up by uaccess.h and maintained by not writing AT in copy_user
* (2) is met by incrementing src by the number of bytes copied
* (3) is met by not doing loads between a pair of increments of dst and src
*
* The exception handlers for stores adjust len (if necessary) and return.
* These handlers do not need to overwrite any data.
*
* For __rmemcpy and memmove an exception is always a kernel bug, therefore
* they're not protected.
*/
#define EXC(inst_reg,addr,handler) \
9: inst_reg, addr; \
.section __ex_table,"a"; \
PTR 9b, handler; \
.previous
/*
* Only on the 64-bit kernel we can made use of 64-bit registers.
*/
#ifdef CONFIG_64BIT
#define USE_DOUBLE
#endif
#ifdef USE_DOUBLE
#define LOAD ld
#define LOADL ldl
#define LOADR ldr
#define STOREL sdl
#define STORER sdr
#define STORE sd
#define ADD daddu
#define SUB dsubu
#define SRL dsrl
#define SRA dsra
#define SLL dsll
#define SLLV dsllv
#define SRLV dsrlv
#define NBYTES 8
#define LOG_NBYTES 3
/*
* As we are sharing code base with the mips32 tree (which use the o32 ABI
* register definitions). We need to redefine the register definitions from
* the n64 ABI register naming to the o32 ABI register naming.
*/
#undef t0
#undef t1
#undef t2
#undef t3
#define t0 $8
#define t1 $9
#define t2 $10
#define t3 $11
#define t4 $12
#define t5 $13
#define t6 $14
#define t7 $15
#else
#define LOAD lw
#define LOADL lwl
#define LOADR lwr
#define STOREL swl
#define STORER swr
#define STORE sw
#define ADD addu
#define SUB subu
#define SRL srl
#define SLL sll
#define SRA sra
#define SLLV sllv
#define SRLV srlv
#define NBYTES 4
#define LOG_NBYTES 2
#endif /* USE_DOUBLE */
#ifdef CONFIG_CPU_LITTLE_ENDIAN
#define LDFIRST LOADR
#define LDREST LOADL
#define STFIRST STORER
#define STREST STOREL
#define SHIFT_DISCARD SLLV
#else
#define LDFIRST LOADL
#define LDREST LOADR
#define STFIRST STOREL
#define STREST STORER
#define SHIFT_DISCARD SRLV
#endif
#define FIRST(unit) ((unit)*NBYTES)
#define REST(unit) (FIRST(unit)+NBYTES-1)
#define UNIT(unit) FIRST(unit)
#define ADDRMASK (NBYTES-1)
.text
.set noreorder
#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
.set noat
#else
.set at=v1
#endif
/*
* A combined memcpy/__copy_user
* __copy_user sets len to 0 for success; else to an upper bound of
* the number of uncopied bytes.
* memcpy sets v0 to dst.
*/
.align 5
LEAF(__copy_user_inatomic)
/*
* Note: dst & src may be unaligned, len may be 0
* Temps
*/
#define rem t8
/*
* The "issue break"s below are very approximate.
* Issue delays for dcache fills will perturb the schedule, as will
* load queue full replay traps, etc.
*
* If len < NBYTES use byte operations.
*/
PREF( 0, 0(src) )
PREF( 1, 0(dst) )
sltu t2, len, NBYTES
and t1, dst, ADDRMASK
PREF( 0, 1*32(src) )
PREF( 1, 1*32(dst) )
bnez t2, .Lcopy_bytes_checklen
and t0, src, ADDRMASK
PREF( 0, 2*32(src) )
PREF( 1, 2*32(dst) )
bnez t1, .Ldst_unaligned
nop
bnez t0, .Lsrc_unaligned_dst_aligned
/*
* use delay slot for fall-through
* src and dst are aligned; need to compute rem
*/
.Lboth_aligned:
SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter
beqz t0, .Lcleanup_both_aligned # len < 8*NBYTES
and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES)
PREF( 0, 3*32(src) )
PREF( 1, 3*32(dst) )
.align 4
1:
EXC( LOAD t0, UNIT(0)(src), .Ll_exc)
EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy)
EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy)
EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy)
SUB len, len, 8*NBYTES
EXC( LOAD t4, UNIT(4)(src), .Ll_exc_copy)
EXC( LOAD t7, UNIT(5)(src), .Ll_exc_copy)
STORE t0, UNIT(0)(dst)
STORE t1, UNIT(1)(dst)
EXC( LOAD t0, UNIT(6)(src), .Ll_exc_copy)
EXC( LOAD t1, UNIT(7)(src), .Ll_exc_copy)
ADD src, src, 8*NBYTES
ADD dst, dst, 8*NBYTES
STORE t2, UNIT(-6)(dst)
STORE t3, UNIT(-5)(dst)
STORE t4, UNIT(-4)(dst)
STORE t7, UNIT(-3)(dst)
STORE t0, UNIT(-2)(dst)
STORE t1, UNIT(-1)(dst)
PREF( 0, 8*32(src) )
PREF( 1, 8*32(dst) )
bne len, rem, 1b
nop
/*
* len == rem == the number of bytes left to copy < 8*NBYTES
*/
.Lcleanup_both_aligned:
beqz len, .Ldone
sltu t0, len, 4*NBYTES
bnez t0, .Lless_than_4units
and rem, len, (NBYTES-1) # rem = len % NBYTES
/*
* len >= 4*NBYTES
*/
EXC( LOAD t0, UNIT(0)(src), .Ll_exc)
EXC( LOAD t1, UNIT(1)(src), .Ll_exc_copy)
EXC( LOAD t2, UNIT(2)(src), .Ll_exc_copy)
EXC( LOAD t3, UNIT(3)(src), .Ll_exc_copy)
SUB len, len, 4*NBYTES
ADD src, src, 4*NBYTES
STORE t0, UNIT(0)(dst)
STORE t1, UNIT(1)(dst)
STORE t2, UNIT(2)(dst)
STORE t3, UNIT(3)(dst)
.set reorder /* DADDI_WAR */
ADD dst, dst, 4*NBYTES
beqz len, .Ldone
.set noreorder
.Lless_than_4units:
/*
* rem = len % NBYTES
*/
beq rem, len, .Lcopy_bytes
nop
1:
EXC( LOAD t0, 0(src), .Ll_exc)
ADD src, src, NBYTES
SUB len, len, NBYTES
STORE t0, 0(dst)
.set reorder /* DADDI_WAR */
ADD dst, dst, NBYTES
bne rem, len, 1b
.set noreorder
/*
* src and dst are aligned, need to copy rem bytes (rem < NBYTES)
* A loop would do only a byte at a time with possible branch
* mispredicts. Can't do an explicit LOAD dst,mask,or,STORE
* because can't assume read-access to dst. Instead, use
* STREST dst, which doesn't require read access to dst.
*
* This code should perform better than a simple loop on modern,
* wide-issue mips processors because the code has fewer branches and
* more instruction-level parallelism.
*/
#define bits t2
beqz len, .Ldone
ADD t1, dst, len # t1 is just past last byte of dst
li bits, 8*NBYTES
SLL rem, len, 3 # rem = number of bits to keep
EXC( LOAD t0, 0(src), .Ll_exc)
SUB bits, bits, rem # bits = number of bits to discard
SHIFT_DISCARD t0, t0, bits
STREST t0, -1(t1)
jr ra
move len, zero
.Ldst_unaligned:
/*
* dst is unaligned
* t0 = src & ADDRMASK
* t1 = dst & ADDRMASK; T1 > 0
* len >= NBYTES
*
* Copy enough bytes to align dst
* Set match = (src and dst have same alignment)
*/
#define match rem
EXC( LDFIRST t3, FIRST(0)(src), .Ll_exc)
ADD t2, zero, NBYTES
EXC( LDREST t3, REST(0)(src), .Ll_exc_copy)
SUB t2, t2, t1 # t2 = number of bytes copied
xor match, t0, t1
STFIRST t3, FIRST(0)(dst)
beq len, t2, .Ldone
SUB len, len, t2
ADD dst, dst, t2
beqz match, .Lboth_aligned
ADD src, src, t2
.Lsrc_unaligned_dst_aligned:
SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter
PREF( 0, 3*32(src) )
beqz t0, .Lcleanup_src_unaligned
and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES
PREF( 1, 3*32(dst) )
1:
/*
* Avoid consecutive LD*'s to the same register since some mips
* implementations can't issue them in the same cycle.
* It's OK to load FIRST(N+1) before REST(N) because the two addresses
* are to the same unit (unless src is aligned, but it's not).
*/
EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc)
EXC( LDFIRST t1, FIRST(1)(src), .Ll_exc_copy)
SUB len, len, 4*NBYTES
EXC( LDREST t0, REST(0)(src), .Ll_exc_copy)
EXC( LDREST t1, REST(1)(src), .Ll_exc_copy)
EXC( LDFIRST t2, FIRST(2)(src), .Ll_exc_copy)
EXC( LDFIRST t3, FIRST(3)(src), .Ll_exc_copy)
EXC( LDREST t2, REST(2)(src), .Ll_exc_copy)
EXC( LDREST t3, REST(3)(src), .Ll_exc_copy)
PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed)
ADD src, src, 4*NBYTES
#ifdef CONFIG_CPU_SB1
nop # improves slotting
#endif
STORE t0, UNIT(0)(dst)
STORE t1, UNIT(1)(dst)
STORE t2, UNIT(2)(dst)
STORE t3, UNIT(3)(dst)
PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed)
.set reorder /* DADDI_WAR */
ADD dst, dst, 4*NBYTES
bne len, rem, 1b
.set noreorder
.Lcleanup_src_unaligned:
beqz len, .Ldone
and rem, len, NBYTES-1 # rem = len % NBYTES
beq rem, len, .Lcopy_bytes
nop
1:
EXC( LDFIRST t0, FIRST(0)(src), .Ll_exc)
EXC( LDREST t0, REST(0)(src), .Ll_exc_copy)
ADD src, src, NBYTES
SUB len, len, NBYTES
STORE t0, 0(dst)
.set reorder /* DADDI_WAR */
ADD dst, dst, NBYTES
bne len, rem, 1b
.set noreorder
.Lcopy_bytes_checklen:
beqz len, .Ldone
nop
.Lcopy_bytes:
/* 0 < len < NBYTES */
#define COPY_BYTE(N) \
EXC( lb t0, N(src), .Ll_exc); \
SUB len, len, 1; \
beqz len, .Ldone; \
sb t0, N(dst)
COPY_BYTE(0)
COPY_BYTE(1)
#ifdef USE_DOUBLE
COPY_BYTE(2)
COPY_BYTE(3)
COPY_BYTE(4)
COPY_BYTE(5)
#endif
EXC( lb t0, NBYTES-2(src), .Ll_exc)
SUB len, len, 1
jr ra
sb t0, NBYTES-2(dst)
.Ldone:
jr ra
nop
END(__copy_user_inatomic)
.Ll_exc_copy:
/*
* Copy bytes from src until faulting load address (or until a
* lb faults)
*
* When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28)
* may be more than a byte beyond the last address.
* Hence, the lb below may get an exception.
*
* Assumes src < THREAD_BUADDR($28)
*/
LOAD t0, TI_TASK($28)
nop
LOAD t0, THREAD_BUADDR(t0)
1:
EXC( lb t1, 0(src), .Ll_exc)
ADD src, src, 1
sb t1, 0(dst) # can't fault -- we're copy_from_user
.set reorder /* DADDI_WAR */
ADD dst, dst, 1
bne src, t0, 1b
.set noreorder
.Ll_exc:
LOAD t0, TI_TASK($28)
nop
LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address
nop
SUB len, AT, t0 # len number of uncopied bytes
jr ra
nop
...@@ -182,6 +182,14 @@ ...@@ -182,6 +182,14 @@
.set at=v1 .set at=v1
#endif #endif
/*
* t6 is used as a flag to note inatomic mode.
*/
LEAF(__copy_user_inatomic)
b __copy_user_common
li t6, 1
END(__copy_user_inatomic)
/* /*
* A combined memcpy/__copy_user * A combined memcpy/__copy_user
* __copy_user sets len to 0 for success; else to an upper bound of * __copy_user sets len to 0 for success; else to an upper bound of
...@@ -193,6 +201,8 @@ LEAF(memcpy) /* a0=dst a1=src a2=len */ ...@@ -193,6 +201,8 @@ LEAF(memcpy) /* a0=dst a1=src a2=len */
move v0, dst /* return value */ move v0, dst /* return value */
.L__memcpy: .L__memcpy:
FEXPORT(__copy_user) FEXPORT(__copy_user)
li t6, 0 /* not inatomic */
__copy_user_common:
/* /*
* Note: dst & src may be unaligned, len may be 0 * Note: dst & src may be unaligned, len may be 0
* Temps * Temps
...@@ -458,6 +468,7 @@ EXC( lb t1, 0(src), .Ll_exc) ...@@ -458,6 +468,7 @@ EXC( lb t1, 0(src), .Ll_exc)
LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address LOAD t0, THREAD_BUADDR(t0) # t0 is just past last good address
nop nop
SUB len, AT, t0 # len number of uncopied bytes SUB len, AT, t0 # len number of uncopied bytes
bnez t6, .Ldone /* Skip the zeroing part if inatomic */
/* /*
* Here's where we rely on src and dst being incremented in tandem, * Here's where we rely on src and dst being incremented in tandem,
* See (3) above. * See (3) above.
......
if MACH_LOONGSON1
choice
prompt "Machine Type"
config LOONGSON1_LS1B
bool "Loongson LS1B board"
select CEVT_R4K
select CSRC_R4K
select SYS_HAS_CPU_LOONGSON1B
select DMA_NONCOHERENT
select BOOT_ELF32
select IRQ_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_HIGHMEM
select SYS_HAS_EARLY_PRINTK
endchoice
endif # MACH_LOONGSON1
#
# Common code for all Loongson 1 based systems
#
obj-$(CONFIG_MACH_LOONGSON1) += common/
#
# Loongson LS1B board
#
obj-$(CONFIG_LOONGSON1_LS1B) += ls1b/
cflags-$(CONFIG_CPU_LOONGSON1) += \
$(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
-Wa,-mips32r2 -Wa,--trap
platform-$(CONFIG_MACH_LOONGSON1) += loongson1/
cflags-$(CONFIG_MACH_LOONGSON1) += -I$(srctree)/arch/mips/include/asm/mach-loongson1
load-$(CONFIG_LOONGSON1_LS1B) += 0xffffffff80100000
#
# Makefile for common code of loongson1 based machines.
#
obj-y += clock.o irq.o platform.o prom.o reset.o setup.o
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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/module.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <asm/clock.h>
#include <asm/time.h>
#include <loongson1.h>
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
struct clk *clk_get(struct device *dev, const char *name)
{
struct clk *c;
struct clk *ret = NULL;
mutex_lock(&clocks_mutex);
list_for_each_entry(c, &clocks, node) {
if (!strcmp(c->name, name)) {
ret = c;
break;
}
}
mutex_unlock(&clocks_mutex);
return ret;
}
EXPORT_SYMBOL(clk_get);
unsigned long clk_get_rate(struct clk *clk)
{
return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);
static void pll_clk_init(struct clk *clk)
{
u32 pll;
pll = __raw_readl(LS1X_CLK_PLL_FREQ);
clk->rate = (12 + (pll & 0x3f)) * 33 / 2
+ ((pll >> 8) & 0x3ff) * 33 / 1024 / 2;
clk->rate *= 1000000;
}
static void cpu_clk_init(struct clk *clk)
{
u32 pll, ctrl;
pll = clk_get_rate(clk->parent);
ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_CPU;
clk->rate = pll / (ctrl >> DIV_CPU_SHIFT);
}
static void ddr_clk_init(struct clk *clk)
{
u32 pll, ctrl;
pll = clk_get_rate(clk->parent);
ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DDR;
clk->rate = pll / (ctrl >> DIV_DDR_SHIFT);
}
static void dc_clk_init(struct clk *clk)
{
u32 pll, ctrl;
pll = clk_get_rate(clk->parent);
ctrl = __raw_readl(LS1X_CLK_PLL_DIV) & DIV_DC;
clk->rate = pll / (ctrl >> DIV_DC_SHIFT);
}
static struct clk_ops pll_clk_ops = {
.init = pll_clk_init,
};
static struct clk_ops cpu_clk_ops = {
.init = cpu_clk_init,
};
static struct clk_ops ddr_clk_ops = {
.init = ddr_clk_init,
};
static struct clk_ops dc_clk_ops = {
.init = dc_clk_init,
};
static struct clk pll_clk = {
.name = "pll",
.ops = &pll_clk_ops,
};
static struct clk cpu_clk = {
.name = "cpu",
.parent = &pll_clk,
.ops = &cpu_clk_ops,
};
static struct clk ddr_clk = {
.name = "ddr",
.parent = &pll_clk,
.ops = &ddr_clk_ops,
};
static struct clk dc_clk = {
.name = "dc",
.parent = &pll_clk,
.ops = &dc_clk_ops,
};
int clk_register(struct clk *clk)
{
mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
if (clk->ops->init)
clk->ops->init(clk);
mutex_unlock(&clocks_mutex);
return 0;
}
EXPORT_SYMBOL(clk_register);
static struct clk *ls1x_clks[] = {
&pll_clk,
&cpu_clk,
&ddr_clk,
&dc_clk,
};
int __init ls1x_clock_init(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(ls1x_clks); i++)
clk_register(ls1x_clks[i]);
return 0;
}
void __init plat_time_init(void)
{
struct clk *clk;
/* Initialize LS1X clocks */
ls1x_clock_init();
/* setup mips r4k timer */
clk = clk_get(NULL, "cpu");
if (IS_ERR(clk))
panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
mips_hpt_frequency = clk_get_rate(clk) / 2;
}
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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/interrupt.h>
#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <loongson1.h>
#include <irq.h>
#define LS1X_INTC_REG(n, x) \
((void __iomem *)KSEG1ADDR(LS1X_INTC_BASE + (n * 0x18) + (x)))
#define LS1X_INTC_INTISR(n) LS1X_INTC_REG(n, 0x0)
#define LS1X_INTC_INTIEN(n) LS1X_INTC_REG(n, 0x4)
#define LS1X_INTC_INTSET(n) LS1X_INTC_REG(n, 0x8)
#define LS1X_INTC_INTCLR(n) LS1X_INTC_REG(n, 0xc)
#define LS1X_INTC_INTPOL(n) LS1X_INTC_REG(n, 0x10)
#define LS1X_INTC_INTEDGE(n) LS1X_INTC_REG(n, 0x14)
static void ls1x_irq_ack(struct irq_data *d)
{
unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
__raw_writel(__raw_readl(LS1X_INTC_INTCLR(n))
| (1 << bit), LS1X_INTC_INTCLR(n));
}
static void ls1x_irq_mask(struct irq_data *d)
{
unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
__raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
& ~(1 << bit), LS1X_INTC_INTIEN(n));
}
static void ls1x_irq_mask_ack(struct irq_data *d)
{
unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
__raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
& ~(1 << bit), LS1X_INTC_INTIEN(n));
__raw_writel(__raw_readl(LS1X_INTC_INTCLR(n))
| (1 << bit), LS1X_INTC_INTCLR(n));
}
static void ls1x_irq_unmask(struct irq_data *d)
{
unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f;
unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5;
__raw_writel(__raw_readl(LS1X_INTC_INTIEN(n))
| (1 << bit), LS1X_INTC_INTIEN(n));
}
static struct irq_chip ls1x_irq_chip = {
.name = "LS1X-INTC",
.irq_ack = ls1x_irq_ack,
.irq_mask = ls1x_irq_mask,
.irq_mask_ack = ls1x_irq_mask_ack,
.irq_unmask = ls1x_irq_unmask,
};
static void ls1x_irq_dispatch(int n)
{
u32 int_status, irq;
/* Get pending sources, masked by current enables */
int_status = __raw_readl(LS1X_INTC_INTISR(n)) &
__raw_readl(LS1X_INTC_INTIEN(n));
if (int_status) {
irq = LS1X_IRQ(n, __ffs(int_status));
do_IRQ(irq);
}
}
asmlinkage void plat_irq_dispatch(void)
{
unsigned int pending;
pending = read_c0_cause() & read_c0_status() & ST0_IM;
if (pending & CAUSEF_IP7)
do_IRQ(TIMER_IRQ);
else if (pending & CAUSEF_IP2)
ls1x_irq_dispatch(0); /* INT0 */
else if (pending & CAUSEF_IP3)
ls1x_irq_dispatch(1); /* INT1 */
else if (pending & CAUSEF_IP4)
ls1x_irq_dispatch(2); /* INT2 */
else if (pending & CAUSEF_IP5)
ls1x_irq_dispatch(3); /* INT3 */
else if (pending & CAUSEF_IP6)
ls1x_irq_dispatch(4); /* INT4 */
else
spurious_interrupt();
}
struct irqaction cascade_irqaction = {
.handler = no_action,
.name = "cascade",
.flags = IRQF_NO_THREAD,
};
static void __init ls1x_irq_init(int base)
{
int n;
/* Disable interrupts and clear pending,
* setup all IRQs as high level triggered
*/
for (n = 0; n < 4; n++) {
__raw_writel(0x0, LS1X_INTC_INTIEN(n));
__raw_writel(0xffffffff, LS1X_INTC_INTCLR(n));
__raw_writel(0xffffffff, LS1X_INTC_INTPOL(n));
/* set DMA0, DMA1 and DMA2 to edge trigger */
__raw_writel(n ? 0x0 : 0xe000, LS1X_INTC_INTEDGE(n));
}
for (n = base; n < LS1X_IRQS; n++) {
irq_set_chip_and_handler(n, &ls1x_irq_chip,
handle_level_irq);
}
setup_irq(INT0_IRQ, &cascade_irqaction);
setup_irq(INT1_IRQ, &cascade_irqaction);
setup_irq(INT2_IRQ, &cascade_irqaction);
setup_irq(INT3_IRQ, &cascade_irqaction);
}
void __init arch_init_irq(void)
{
mips_cpu_irq_init();
ls1x_irq_init(LS1X_IRQ_BASE);
}
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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/clk.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/phy.h>
#include <linux/serial_8250.h>
#include <linux/stmmac.h>
#include <asm-generic/sizes.h>
#include <loongson1.h>
#define LS1X_UART(_id) \
{ \
.mapbase = LS1X_UART ## _id ## _BASE, \
.irq = LS1X_UART ## _id ## _IRQ, \
.iotype = UPIO_MEM, \
.flags = UPF_IOREMAP | UPF_FIXED_TYPE, \
.type = PORT_16550A, \
}
static struct plat_serial8250_port ls1x_serial8250_port[] = {
LS1X_UART(0),
LS1X_UART(1),
LS1X_UART(2),
LS1X_UART(3),
{},
};
struct platform_device ls1x_uart_device = {
.name = "serial8250",
.id = PLAT8250_DEV_PLATFORM,
.dev = {
.platform_data = ls1x_serial8250_port,
},
};
void __init ls1x_serial_setup(void)
{
struct clk *clk;
struct plat_serial8250_port *p;
clk = clk_get(NULL, "dc");
if (IS_ERR(clk))
panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
for (p = ls1x_serial8250_port; p->flags != 0; ++p)
p->uartclk = clk_get_rate(clk);
}
/* Synopsys Ethernet GMAC */
static struct resource ls1x_eth0_resources[] = {
[0] = {
.start = LS1X_GMAC0_BASE,
.end = LS1X_GMAC0_BASE + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.name = "macirq",
.start = LS1X_GMAC0_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = {
.bus_id = 0,
.phy_mask = 0,
};
static struct plat_stmmacenet_data ls1x_eth_data = {
.bus_id = 0,
.phy_addr = -1,
.mdio_bus_data = &ls1x_mdio_bus_data,
.has_gmac = 1,
.tx_coe = 1,
};
struct platform_device ls1x_eth0_device = {
.name = "stmmaceth",
.id = 0,
.num_resources = ARRAY_SIZE(ls1x_eth0_resources),
.resource = ls1x_eth0_resources,
.dev = {
.platform_data = &ls1x_eth_data,
},
};
/* USB EHCI */
static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32);
static struct resource ls1x_ehci_resources[] = {
[0] = {
.start = LS1X_EHCI_BASE,
.end = LS1X_EHCI_BASE + SZ_32K - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = LS1X_EHCI_IRQ,
.flags = IORESOURCE_IRQ,
},
};
struct platform_device ls1x_ehci_device = {
.name = "ls1x-ehci",
.id = -1,
.num_resources = ARRAY_SIZE(ls1x_ehci_resources),
.resource = ls1x_ehci_resources,
.dev = {
.dma_mask = &ls1x_ehci_dmamask,
},
};
/* Real Time Clock */
struct platform_device ls1x_rtc_device = {
.name = "ls1x-rtc",
.id = -1,
};
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
*
* Modified from arch/mips/pnx833x/common/prom.c.
*
* 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/serial_reg.h>
#include <asm/bootinfo.h>
#include <loongson1.h>
#include <prom.h>
int prom_argc;
char **prom_argv, **prom_envp;
unsigned long memsize, highmemsize;
char *prom_getenv(char *envname)
{
char **env = prom_envp;
int i;
i = strlen(envname);
while (*env) {
if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=')
return *env + i + 1;
env++;
}
return 0;
}
static inline unsigned long env_or_default(char *env, unsigned long dfl)
{
char *str = prom_getenv(env);
return str ? simple_strtol(str, 0, 0) : dfl;
}
void __init prom_init_cmdline(void)
{
char *c = &(arcs_cmdline[0]);
int i;
for (i = 1; i < prom_argc; i++) {
strcpy(c, prom_argv[i]);
c += strlen(prom_argv[i]);
if (i < prom_argc-1)
*c++ = ' ';
}
*c = 0;
}
void __init prom_init(void)
{
prom_argc = fw_arg0;
prom_argv = (char **)fw_arg1;
prom_envp = (char **)fw_arg2;
prom_init_cmdline();
memsize = env_or_default("memsize", DEFAULT_MEMSIZE);
highmemsize = env_or_default("highmemsize", 0x0);
}
void __init prom_free_prom_memory(void)
{
}
#define PORT(offset) (u8 *)(KSEG1ADDR(LS1X_UART0_BASE + offset))
void __init prom_putchar(char c)
{
int timeout;
timeout = 1024;
while (((readb(PORT(UART_LSR)) & UART_LSR_THRE) == 0)
&& (timeout-- > 0))
;
writeb(c, PORT(UART_TX));
}
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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/io.h>
#include <linux/pm.h>
#include <asm/reboot.h>
#include <loongson1.h>
static void ls1x_restart(char *command)
{
__raw_writel(0x1, LS1X_WDT_EN);
__raw_writel(0x5000000, LS1X_WDT_TIMER);
__raw_writel(0x1, LS1X_WDT_SET);
}
static void ls1x_halt(void)
{
while (1) {
if (cpu_wait)
cpu_wait();
}
}
static void ls1x_power_off(void)
{
ls1x_halt();
}
static int __init ls1x_reboot_setup(void)
{
_machine_restart = ls1x_restart;
_machine_halt = ls1x_halt;
pm_power_off = ls1x_power_off;
return 0;
}
arch_initcall(ls1x_reboot_setup);
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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 <asm/bootinfo.h>
#include <prom.h>
void __init plat_mem_setup(void)
{
add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
}
const char *get_system_type(void)
{
unsigned int processor_id = (&current_cpu_data)->processor_id;
switch (processor_id & PRID_REV_MASK) {
case PRID_REV_LOONGSON1B:
return "LOONGSON LS1B";
default:
return "LOONGSON (unknown)";
}
}
#
# Makefile for loongson1B based machines.
#
obj-y += board.o
/*
* Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.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 <platform.h>
#include <linux/serial_8250.h>
#include <loongson1.h>
static struct platform_device *ls1b_platform_devices[] __initdata = {
&ls1x_uart_device,
&ls1x_eth0_device,
&ls1x_ehci_device,
&ls1x_rtc_device,
};
static int __init ls1b_platform_init(void)
{
int err;
ls1x_serial_setup();
err = platform_add_devices(ls1b_platform_devices,
ARRAY_SIZE(ls1b_platform_devices));
return err;
}
arch_initcall(ls1b_platform_init);
...@@ -58,18 +58,16 @@ enum fields { ...@@ -58,18 +58,16 @@ enum fields {
enum opcode { enum opcode {
insn_invalid, insn_invalid,
insn_addu, insn_addiu, insn_and, insn_andi, insn_beq, insn_addiu, insn_addu, insn_and, insn_andi, insn_bbit0, insn_bbit1,
insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl, insn_beq, insn_beql, insn_bgez, insn_bgezl, insn_bltz, insn_bltzl,
insn_bne, insn_cache, insn_daddu, insn_daddiu, insn_dmfc0, insn_bne, insn_cache, insn_daddiu, insn_daddu, insn_dins, insn_dinsm,
insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dmfc0, insn_dmtc0, insn_drotr, insn_drotr32, insn_dsll,
insn_dsrl32, insn_drotr, insn_drotr32, insn_dsubu, insn_eret, insn_dsll32, insn_dsra, insn_dsrl, insn_dsrl32, insn_dsubu, insn_eret,
insn_j, insn_jal, insn_jr, insn_ld, insn_ll, insn_lld, insn_j, insn_jal, insn_jr, insn_ld, insn_ldx, insn_ll, insn_lld,
insn_lui, insn_lw, insn_mfc0, insn_mtc0, insn_or, insn_ori, insn_lui, insn_lw, insn_lwx, insn_mfc0, insn_mtc0, insn_or, insn_ori,
insn_pref, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, insn_pref, insn_rfe, insn_rotr, insn_sc, insn_scd, insn_sd, insn_sll,
insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, insn_tlbp, insn_sra, insn_srl, insn_subu, insn_sw, insn_syscall, insn_tlbp,
insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori,
insn_dins, insn_dinsm, insn_syscall, insn_bbit0, insn_bbit1,
insn_lwx, insn_ldx
}; };
struct insn { struct insn {
...@@ -90,65 +88,65 @@ struct insn { ...@@ -90,65 +88,65 @@ struct insn {
static struct insn insn_table[] __uasminitdata = { static struct insn insn_table[] __uasminitdata = {
{ insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_addiu, M(addiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD }, { insn_addu, M(spec_op, 0, 0, 0, 0, addu_op), RS | RT | RD },
{ insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
{ insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_andi, M(andi_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
{ insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, { insn_and, M(spec_op, 0, 0, 0, 0, and_op), RS | RT | RD },
{ insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
{ insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
{ insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, { insn_beql, M(beql_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
{ insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM }, { insn_beq, M(beq_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
{ insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM }, { insn_bgezl, M(bcond_op, 0, bgezl_op, 0, 0, 0), RS | BIMM },
{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM }, { insn_bgez, M(bcond_op, 0, bgez_op, 0, 0, 0), RS | BIMM },
{ insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM }, { insn_bltzl, M(bcond_op, 0, bltzl_op, 0, 0, 0), RS | BIMM },
{ insn_bltz, M(bcond_op, 0, bltz_op, 0, 0, 0), RS | BIMM },
{ insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, { insn_bne, M(bne_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
{ insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_cache, M(cache_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_daddiu, M(daddiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD }, { insn_daddu, M(spec_op, 0, 0, 0, 0, daddu_op), RS | RT | RD },
{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
{ insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
{ insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_dmfc0, M(cop0_op, dmfc_op, 0, 0, 0, 0), RT | RD | SET},
{ insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_dmtc0, M(cop0_op, dmtc_op, 0, 0, 0, 0), RT | RD | SET},
{ insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE }, { insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE },
{ insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE },
{ insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE }, { insn_dsll32, M(spec_op, 0, 0, 0, 0, dsll32_op), RT | RD | RE },
{ insn_dsll, M(spec_op, 0, 0, 0, 0, dsll_op), RT | RD | RE },
{ insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE }, { insn_dsra, M(spec_op, 0, 0, 0, 0, dsra_op), RT | RD | RE },
{ insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
{ insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE }, { insn_dsrl32, M(spec_op, 0, 0, 0, 0, dsrl32_op), RT | RD | RE },
{ insn_drotr, M(spec_op, 1, 0, 0, 0, dsrl_op), RT | RD | RE }, { insn_dsrl, M(spec_op, 0, 0, 0, 0, dsrl_op), RT | RD | RE },
{ insn_drotr32, M(spec_op, 1, 0, 0, 0, dsrl32_op), RT | RD | RE },
{ insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD }, { insn_dsubu, M(spec_op, 0, 0, 0, 0, dsubu_op), RS | RT | RD },
{ insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 }, { insn_eret, M(cop0_op, cop_op, 0, 0, 0, eret_op), 0 },
{ insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
{ insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM }, { insn_jal, M(jal_op, 0, 0, 0, 0, 0), JIMM },
{ insn_j, M(j_op, 0, 0, 0, 0, 0), JIMM },
{ insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS }, { insn_jr, M(spec_op, 0, 0, 0, 0, jr_op), RS },
{ insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_ld, M(ld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
{ insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_lld, M(lld_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_ll, M(ll_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM }, { insn_lui, M(lui_op, 0, 0, 0, 0, 0), RT | SIMM },
{ insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
{ insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
{ insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
{ insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
{ insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
{ insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
{ insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 }, { insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 },
{ insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE },
{ insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_scd, M(scd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_sc, M(sc_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_sd, M(sd_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE }, { insn_sll, M(spec_op, 0, 0, 0, 0, sll_op), RT | RD | RE },
{ insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE }, { insn_sra, M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE },
{ insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE }, { insn_srl, M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE },
{ insn_rotr, M(spec_op, 1, 0, 0, 0, srl_op), RT | RD | RE },
{ insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD }, { insn_subu, M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD },
{ insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_sw, M(sw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
{ insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 }, { insn_tlbp, M(cop0_op, cop_op, 0, 0, 0, tlbp_op), 0 },
{ insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 }, { insn_tlbr, M(cop0_op, cop_op, 0, 0, 0, tlbr_op), 0 },
{ insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 }, { insn_tlbwi, M(cop0_op, cop_op, 0, 0, 0, tlbwi_op), 0 },
{ insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 }, { insn_tlbwr, M(cop0_op, cop_op, 0, 0, 0, tlbwr_op), 0 },
{ insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
{ insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
{ insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
{ insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
{ insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
{ insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
{ insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
{ insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
{ insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
{ insn_invalid, 0, 0 } { insn_invalid, 0, 0 }
}; };
......
...@@ -54,7 +54,7 @@ void prom_putchar(char c) ...@@ -54,7 +54,7 @@ void prom_putchar(char c)
#elif defined(CONFIG_CPU_XLR) #elif defined(CONFIG_CPU_XLR)
uartbase = nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET); uartbase = nlm_mmio_base(NETLOGIC_IO_UART_0_OFFSET);
#endif #endif
while (nlm_read_reg(uartbase, UART_LSR) == 0) while ((nlm_read_reg(uartbase, UART_LSR) & UART_LSR_THRE) == 0)
; ;
nlm_write_reg(uartbase, UART_TX, c); nlm_write_reg(uartbase, UART_TX, c);
} }
...@@ -54,28 +54,68 @@ ...@@ -54,28 +54,68 @@
XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \ XLP_IO_SYS_OFFSET(node) + XLP_IO_PCI_HDRSZ + \
SYS_CPU_NONCOHERENT_MODE * 4 SYS_CPU_NONCOHERENT_MODE * 4
.macro __config_lsu #define XLP_AX_WORKAROUND /* enable Ax silicon workarounds */
li t0, LSU_DEFEATURE
mfcr t1, t0
lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */ /* Enable XLP features and workarounds in the LSU */
or t1, t1, t2 .macro xlp_config_lsu
li t2, ~0xe /* S1RCM */ li t0, LSU_DEFEATURE
mfcr t1, t0
lui t2, 0x4080 /* Enable Unaligned Access, L2HPE */
or t1, t1, t2
#ifdef XLP_AX_WORKAROUND
li t2, ~0xe /* S1RCM */
and t1, t1, t2 and t1, t1, t2
mtcr t1, t0 #endif
mtcr t1, t0
li t0, SCHED_DEFEATURE #ifdef XLP_AX_WORKAROUND
lui t1, 0x0100 /* Experimental: Disable BRU accepting ALU ops */ li t0, SCHED_DEFEATURE
mtcr t1, t0 lui t1, 0x0100 /* Disable BRU accepting ALU ops */
mtcr t1, t0
#endif
.endm
/*
* This is the code that will be copied to the reset entry point for
* XLR and XLP. The XLP cores start here when they are woken up. This
* is also the NMI entry point.
*/
.macro xlp_flush_l1_dcache
li t0, LSU_DEBUG_DATA0
li t1, LSU_DEBUG_ADDR
li t2, 0 /* index */
li t3, 0x1000 /* loop count */
1:
sll v0, t2, 5
mtcr zero, t0
ori v1, v0, 0x3 /* way0 | write_enable | write_active */
mtcr v1, t1
2:
mfcr v1, t1
andi v1, 0x1 /* wait for write_active == 0 */
bnez v1, 2b
nop
mtcr zero, t0
ori v1, v0, 0x7 /* way1 | write_enable | write_active */
mtcr v1, t1
3:
mfcr v1, t1
andi v1, 0x1 /* wait for write_active == 0 */
bnez v1, 3b
nop
addi t2, 1
bne t3, t2, 1b
nop
.endm .endm
/* /*
* The cores can come start when they are woken up. This is also the NMI * The cores can come start when they are woken up. This is also the NMI
* entry, so check that first. * entry, so check that first.
* *
* The data corresponding to reset is stored at RESET_DATA_PHYS location, * The data corresponding to reset/NMI is stored at RESET_DATA_PHYS
* this will have the thread mask (used when core is woken up) and the * location, this will have the thread mask (used when core is woken up)
* current NMI handler in case we reached here for an NMI. * and the current NMI handler in case we reached here for an NMI.
* *
* When a core or thread is newly woken up, it loops in a 'wait'. When * When a core or thread is newly woken up, it loops in a 'wait'. When
* the CPU really needs waking up, we send an NMI to it, with the NMI * the CPU really needs waking up, we send an NMI to it, with the NMI
...@@ -89,12 +129,12 @@ ...@@ -89,12 +129,12 @@
FEXPORT(nlm_reset_entry) FEXPORT(nlm_reset_entry)
dmtc0 k0, $22, 6 dmtc0 k0, $22, 6
dmtc0 k1, $22, 7 dmtc0 k1, $22, 7
mfc0 k0, CP0_STATUS mfc0 k0, CP0_STATUS
li k1, 0x80000 li k1, 0x80000
and k1, k0, k1 and k1, k0, k1
beqz k1, 1f /* go to real reset entry */ beqz k1, 1f /* go to real reset entry */
nop nop
li k1, CKSEG1ADDR(RESET_DATA_PHYS) /* NMI */ li k1, CKSEG1ADDR(RESET_DATA_PHYS) /* NMI */
ld k0, BOOT_NMI_HANDLER(k1) ld k0, BOOT_NMI_HANDLER(k1)
jr k0 jr k0
nop nop
...@@ -114,21 +154,25 @@ FEXPORT(nlm_reset_entry) ...@@ -114,21 +154,25 @@ FEXPORT(nlm_reset_entry)
li t2, SYS_CPU_COHERENT_BASE(0) li t2, SYS_CPU_COHERENT_BASE(0)
add t2, t2, t3 /* t2 <- SYS offset for node */ add t2, t2, t3 /* t2 <- SYS offset for node */
lw t1, 0(t2) lw t1, 0(t2)
and t1, t1, t0 and t1, t1, t0
sw t1, 0(t2) sw t1, 0(t2)
/* read back to ensure complete */ /* read back to ensure complete */
lw t1, 0(t2) lw t1, 0(t2)
sync sync
/* Configure LSU on Non-0 Cores. */ /* Configure LSU on Non-0 Cores. */
__config_lsu xlp_config_lsu
/* FALL THROUGH */
/* /*
* Wake up sibling threads from the initial thread in * Wake up sibling threads from the initial thread in
* a core. * a core.
*/ */
EXPORT(nlm_boot_siblings) EXPORT(nlm_boot_siblings)
/* core L1D flush before enable threads */
xlp_flush_l1_dcache
/* Enable hw threads by writing to MAP_THREADMODE of the core */
li t0, CKSEG1ADDR(RESET_DATA_PHYS) li t0, CKSEG1ADDR(RESET_DATA_PHYS)
lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */ lw t1, BOOT_THREAD_MODE(t0) /* t1 <- thread mode */
li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE) li t0, ((CPU_BLOCKID_MAP << 8) | MAP_THREADMODE)
...@@ -139,31 +183,28 @@ EXPORT(nlm_boot_siblings) ...@@ -139,31 +183,28 @@ EXPORT(nlm_boot_siblings)
/* /*
* The new hardware thread starts at the next instruction * The new hardware thread starts at the next instruction
* For all the cases other than core 0 thread 0, we will * For all the cases other than core 0 thread 0, we will
* jump to the secondary wait function. * jump to the secondary wait function.
*/ */
mfc0 v0, CP0_EBASE, 1 mfc0 v0, CP0_EBASE, 1
andi v0, 0x7f /* v0 <- node/core */ andi v0, 0x7f /* v0 <- node/core */
#if 1 /* Init MMU in the first thread after changing THREAD_MODE
/* A0 errata - Write MMU_SETUP after changing thread mode register. */ * register (Ax Errata?)
*/
andi v1, v0, 0x3 /* v1 <- thread id */ andi v1, v0, 0x3 /* v1 <- thread id */
bnez v1, 2f bnez v1, 2f
nop nop
li t0, MMU_SETUP li t0, MMU_SETUP
li t1, 0 li t1, 0
mtcr t1, t0 mtcr t1, t0
ehb _ehb
#endif
2: beqz v0, 4f 2: beqz v0, 4f /* boot cpu (cpuid == 0)? */
nop nop
/* setup status reg */ /* setup status reg */
mfc0 t1, CP0_STATUS move t1, zero
li t0, ST0_BEV
or t1, t0
xor t1, t0
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
ori t1, ST0_KX ori t1, ST0_KX
#endif #endif
...@@ -183,9 +224,9 @@ EXPORT(nlm_boot_siblings) ...@@ -183,9 +224,9 @@ EXPORT(nlm_boot_siblings)
* For the boot CPU, we have to restore registers and * For the boot CPU, we have to restore registers and
* return * return
*/ */
4: dmfc0 t0, $4, 2 /* restore SP from UserLocal */ 4: dmfc0 t0, $4, 2 /* restore SP from UserLocal */
li t1, 0xfadebeef li t1, 0xfadebeef
dmtc0 t1, $4, 2 /* restore SP from UserLocal */ dmtc0 t1, $4, 2 /* restore SP from UserLocal */
PTR_SUBU sp, t0, PT_SIZE PTR_SUBU sp, t0, PT_SIZE
RESTORE_ALL RESTORE_ALL
jr ra jr ra
...@@ -193,7 +234,7 @@ EXPORT(nlm_boot_siblings) ...@@ -193,7 +234,7 @@ EXPORT(nlm_boot_siblings)
EXPORT(nlm_reset_entry_end) EXPORT(nlm_reset_entry_end)
FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */ FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */
__config_lsu xlp_config_lsu
dmtc0 sp, $4, 2 /* SP saved in UserLocal */ dmtc0 sp, $4, 2 /* SP saved in UserLocal */
SAVE_ALL SAVE_ALL
sync sync
...@@ -210,6 +251,12 @@ FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */ ...@@ -210,6 +251,12 @@ FEXPORT(xlp_boot_core0_siblings) /* "Master" cpu starts from here */
__CPUINIT __CPUINIT
NESTED(nlm_boot_secondary_cpus, 16, sp) NESTED(nlm_boot_secondary_cpus, 16, sp)
/* Initialize CP0 Status */
move t1, zero
#ifdef CONFIG_64BIT
ori t1, ST0_KX
#endif
mtc0 t1, CP0_STATUS
PTR_LA t1, nlm_next_sp PTR_LA t1, nlm_next_sp
PTR_L sp, 0(t1) PTR_L sp, 0(t1)
PTR_LA t1, nlm_next_gp PTR_LA t1, nlm_next_gp
...@@ -234,36 +281,36 @@ END(nlm_boot_secondary_cpus) ...@@ -234,36 +281,36 @@ END(nlm_boot_secondary_cpus)
*/ */
__CPUINIT __CPUINIT
NESTED(nlm_rmiboot_preboot, 16, sp) NESTED(nlm_rmiboot_preboot, 16, sp)
mfc0 t0, $15, 1 # read ebase mfc0 t0, $15, 1 /* read ebase */
andi t0, 0x1f # t0 has the processor_id() andi t0, 0x1f /* t0 has the processor_id() */
andi t2, t0, 0x3 # thread no andi t2, t0, 0x3 /* thread num */
sll t0, 2 # offset in cpu array sll t0, 2 /* offset in cpu array */
PTR_LA t1, nlm_cpu_ready # mark CPU ready PTR_LA t1, nlm_cpu_ready /* mark CPU ready */
PTR_ADDU t1, t0 PTR_ADDU t1, t0
li t3, 1 li t3, 1
sw t3, 0(t1) sw t3, 0(t1)
bnez t2, 1f # skip thread programming bnez t2, 1f /* skip thread programming */
nop # for non zero hw threads nop /* for thread id != 0 */
/* /*
* MMU setup only for first thread in core * XLR MMU setup only for first thread in core
*/ */
li t0, 0x400 li t0, 0x400
mfcr t1, t0 mfcr t1, t0
li t2, 6 # XLR thread mode mask li t2, 6 /* XLR thread mode mask */
nor t3, t2, zero nor t3, t2, zero
and t2, t1, t2 # t2 - current thread mode and t2, t1, t2 /* t2 - current thread mode */
li v0, CKSEG1ADDR(RESET_DATA_PHYS) li v0, CKSEG1ADDR(RESET_DATA_PHYS)
lw v1, BOOT_THREAD_MODE(v0) # v1 - new thread mode lw v1, BOOT_THREAD_MODE(v0) /* v1 - new thread mode */
sll v1, 1 sll v1, 1
beq v1, t2, 1f # same as request value beq v1, t2, 1f /* same as request value */
nop # nothing to do */ nop /* nothing to do */
and t2, t1, t3 # mask out old thread mode and t2, t1, t3 /* mask out old thread mode */
or t1, t2, v1 # put in new value or t1, t2, v1 /* put in new value */
mtcr t1, t0 # update core control mtcr t1, t0 /* update core control */
1: wait 1: wait
j 1b j 1b
......
obj-y += setup.o platform.o nlm_hal.o obj-y += setup.o platform.o nlm_hal.o
obj-$(CONFIG_OF) += of.o
obj-$(CONFIG_SMP) += wakeup.o obj-$(CONFIG_SMP) += wakeup.o
obj-$(CONFIG_USB) += usb-init.o
...@@ -69,6 +69,32 @@ int nlm_irq_to_irt(int irq) ...@@ -69,6 +69,32 @@ int nlm_irq_to_irt(int irq)
return PIC_IRT_UART_0_INDEX; return PIC_IRT_UART_0_INDEX;
case PIC_UART_1_IRQ: case PIC_UART_1_IRQ:
return PIC_IRT_UART_1_INDEX; return PIC_IRT_UART_1_INDEX;
case PIC_PCIE_LINK_0_IRQ:
return PIC_IRT_PCIE_LINK_0_INDEX;
case PIC_PCIE_LINK_1_IRQ:
return PIC_IRT_PCIE_LINK_1_INDEX;
case PIC_PCIE_LINK_2_IRQ:
return PIC_IRT_PCIE_LINK_2_INDEX;
case PIC_PCIE_LINK_3_IRQ:
return PIC_IRT_PCIE_LINK_3_INDEX;
case PIC_EHCI_0_IRQ:
return PIC_IRT_EHCI_0_INDEX;
case PIC_EHCI_1_IRQ:
return PIC_IRT_EHCI_1_INDEX;
case PIC_OHCI_0_IRQ:
return PIC_IRT_OHCI_0_INDEX;
case PIC_OHCI_1_IRQ:
return PIC_IRT_OHCI_1_INDEX;
case PIC_OHCI_2_IRQ:
return PIC_IRT_OHCI_2_INDEX;
case PIC_OHCI_3_IRQ:
return PIC_IRT_OHCI_3_INDEX;
case PIC_MMC_IRQ:
return PIC_IRT_MMC_INDEX;
case PIC_I2C_0_IRQ:
return PIC_IRT_I2C_0_INDEX;
case PIC_I2C_1_IRQ:
return PIC_IRT_I2C_1_INDEX;
default: default:
return -1; return -1;
} }
...@@ -81,6 +107,32 @@ int nlm_irt_to_irq(int irt) ...@@ -81,6 +107,32 @@ int nlm_irt_to_irq(int irt)
return PIC_UART_0_IRQ; return PIC_UART_0_IRQ;
case PIC_IRT_UART_1_INDEX: case PIC_IRT_UART_1_INDEX:
return PIC_UART_1_IRQ; return PIC_UART_1_IRQ;
case PIC_IRT_PCIE_LINK_0_INDEX:
return PIC_PCIE_LINK_0_IRQ;
case PIC_IRT_PCIE_LINK_1_INDEX:
return PIC_PCIE_LINK_1_IRQ;
case PIC_IRT_PCIE_LINK_2_INDEX:
return PIC_PCIE_LINK_2_IRQ;
case PIC_IRT_PCIE_LINK_3_INDEX:
return PIC_PCIE_LINK_3_IRQ;
case PIC_IRT_EHCI_0_INDEX:
return PIC_EHCI_0_IRQ;
case PIC_IRT_EHCI_1_INDEX:
return PIC_EHCI_1_IRQ;
case PIC_IRT_OHCI_0_INDEX:
return PIC_OHCI_0_IRQ;
case PIC_IRT_OHCI_1_INDEX:
return PIC_OHCI_1_IRQ;
case PIC_IRT_OHCI_2_INDEX:
return PIC_OHCI_2_IRQ;
case PIC_IRT_OHCI_3_INDEX:
return PIC_OHCI_3_IRQ;
case PIC_IRT_MMC_INDEX:
return PIC_MMC_IRQ;
case PIC_IRT_I2C_0_INDEX:
return PIC_I2C_0_IRQ;
case PIC_IRT_I2C_1_INDEX:
return PIC_I2C_1_IRQ;
default: default:
return -1; return -1;
} }
......
#include <linux/bootmem.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/of_fdt.h>
#include <asm/byteorder.h>
static int __init reserve_mem_mach(unsigned long addr, unsigned long size)
{
return reserve_bootmem(addr, size, BOOTMEM_DEFAULT);
}
void __init free_mem_mach(unsigned long addr, unsigned long size)
{
return free_bootmem(addr, size);
}
void __init device_tree_init(void)
{
unsigned long base, size;
if (!initial_boot_params)
return;
base = virt_to_phys((void *)initial_boot_params);
size = be32_to_cpu(initial_boot_params->totalsize);
/* Before we do anything, lets reserve the dt blob */
reserve_mem_mach(base, size);
unflatten_device_tree();
/* free the space reserved for the dt blob */
free_mem_mach(base, size);
}
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
static unsigned int nlm_xlp_uart_in(struct uart_port *p, int offset) static unsigned int nlm_xlp_uart_in(struct uart_port *p, int offset)
{ {
return nlm_read_reg(p->iobase, offset); return nlm_read_reg(p->iobase, offset);
} }
static void nlm_xlp_uart_out(struct uart_port *p, int offset, int value) static void nlm_xlp_uart_out(struct uart_port *p, int offset, int value)
......
...@@ -41,6 +41,8 @@ ...@@ -41,6 +41,8 @@
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <linux/of_fdt.h> #include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
#include <asm/netlogic/haldefs.h> #include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h> #include <asm/netlogic/common.h>
...@@ -109,3 +111,17 @@ void __init prom_init(void) ...@@ -109,3 +111,17 @@ void __init prom_init(void)
register_smp_ops(&nlm_smp_ops); register_smp_ops(&nlm_smp_ops);
#endif #endif
} }
static struct of_device_id __initdata xlp_ids[] = {
{ .compatible = "simple-bus", },
{},
};
int __init xlp8xx_ds_publish_devices(void)
{
if (!of_have_populated_dt())
return 0;
return of_platform_bus_probe(NULL, xlp_ids, NULL);
}
device_initcall(xlp8xx_ds_publish_devices);
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/usb.h>
static void nlm_usb_intr_en(int node, int port)
{
uint32_t val;
uint64_t port_addr;
port_addr = nlm_get_usb_regbase(node, port);
val = nlm_read_usb_reg(port_addr, USB_INT_EN);
val = USB_CTRL_INTERRUPT_EN | USB_OHCI_INTERRUPT_EN |
USB_OHCI_INTERRUPT1_EN | USB_CTRL_INTERRUPT_EN |
USB_OHCI_INTERRUPT_EN | USB_OHCI_INTERRUPT2_EN;
nlm_write_usb_reg(port_addr, USB_INT_EN, val);
}
static void nlm_usb_hw_reset(int node, int port)
{
uint64_t port_addr;
uint32_t val;
/* reset USB phy */
port_addr = nlm_get_usb_regbase(node, port);
val = nlm_read_usb_reg(port_addr, USB_PHY_0);
val &= ~(USB_PHY_RESET | USB_PHY_PORT_RESET_0 | USB_PHY_PORT_RESET_1);
nlm_write_usb_reg(port_addr, USB_PHY_0, val);
mdelay(100);
val = nlm_read_usb_reg(port_addr, USB_CTL_0);
val &= ~(USB_CONTROLLER_RESET);
val |= 0x4;
nlm_write_usb_reg(port_addr, USB_CTL_0, val);
}
static int __init nlm_platform_usb_init(void)
{
pr_info("Initializing USB Interface\n");
nlm_usb_hw_reset(0, 0);
nlm_usb_hw_reset(0, 3);
/* Enable PHY interrupts */
nlm_usb_intr_en(0, 0);
nlm_usb_intr_en(0, 3);
return 0;
}
arch_initcall(nlm_platform_usb_init);
static u64 xlp_usb_dmamask = ~(u32)0;
/* Fixup the IRQ for USB devices which is exist on XLP SOC PCIE bus */
static void nlm_usb_fixup_final(struct pci_dev *dev)
{
dev->dev.dma_mask = &xlp_usb_dmamask;
dev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
switch (dev->devfn) {
case 0x10:
dev->irq = PIC_EHCI_0_IRQ;
break;
case 0x11:
dev->irq = PIC_OHCI_0_IRQ;
break;
case 0x12:
dev->irq = PIC_OHCI_1_IRQ;
break;
case 0x13:
dev->irq = PIC_EHCI_1_IRQ;
break;
case 0x14:
dev->irq = PIC_OHCI_2_IRQ;
break;
case 0x15:
dev->irq = PIC_OHCI_3_IRQ;
break;
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_EHCI,
nlm_usb_fixup_final);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_NETLOGIC, PCI_DEVICE_ID_NLM_OHCI,
nlm_usb_fixup_final);
obj-y += setup.o platform.o obj-y += setup.o platform.o platform-flash.o
obj-$(CONFIG_SMP) += wakeup.o obj-$(CONFIG_SMP) += wakeup.o
/*
* Copyright 2011, Netlogic Microsystems.
* Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/resource.h>
#include <linux/spi/flash.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/xlr/iomap.h>
#include <asm/netlogic/xlr/flash.h>
#include <asm/netlogic/xlr/bridge.h>
#include <asm/netlogic/xlr/gpio.h>
#include <asm/netlogic/xlr/xlr.h>
/*
* Default NOR partition layout
*/
static struct mtd_partition xlr_nor_parts[] = {
{
.name = "User FS",
.offset = 0x800000,
.size = MTDPART_SIZ_FULL,
}
};
/*
* Default NAND partition layout
*/
static struct mtd_partition xlr_nand_parts[] = {
{
.name = "Root Filesystem",
.offset = 64 * 64 * 2048,
.size = 432 * 64 * 2048,
},
{
.name = "Home Filesystem",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
},
};
/* Use PHYSMAP flash for NOR */
struct physmap_flash_data xlr_nor_data = {
.width = 2,
.parts = xlr_nor_parts,
.nr_parts = ARRAY_SIZE(xlr_nor_parts),
};
static struct resource xlr_nor_res[] = {
{
.flags = IORESOURCE_MEM,
},
};
static struct platform_device xlr_nor_dev = {
.name = "physmap-flash",
.dev = {
.platform_data = &xlr_nor_data,
},
.num_resources = ARRAY_SIZE(xlr_nor_res),
.resource = xlr_nor_res,
};
const char *xlr_part_probes[] = { "cmdlinepart", NULL };
/*
* Use "gen_nand" driver for NAND flash
*
* There seems to be no way to store a private pointer containing
* platform specific info in gen_nand drivier. We will use a global
* struct for now, since we currently have only one NAND chip per board.
*/
struct xlr_nand_flash_priv {
int cs;
uint64_t flash_mmio;
};
static struct xlr_nand_flash_priv nand_priv;
static void xlr_nand_ctrl(struct mtd_info *mtd, int cmd,
unsigned int ctrl)
{
if (ctrl & NAND_CLE)
nlm_write_reg(nand_priv.flash_mmio,
FLASH_NAND_CLE(nand_priv.cs), cmd);
else if (ctrl & NAND_ALE)
nlm_write_reg(nand_priv.flash_mmio,
FLASH_NAND_ALE(nand_priv.cs), cmd);
}
struct platform_nand_data xlr_nand_data = {
.chip = {
.nr_chips = 1,
.nr_partitions = ARRAY_SIZE(xlr_nand_parts),
.chip_delay = 50,
.partitions = xlr_nand_parts,
.part_probe_types = xlr_part_probes,
},
.ctrl = {
.cmd_ctrl = xlr_nand_ctrl,
},
};
static struct resource xlr_nand_res[] = {
{
.flags = IORESOURCE_MEM,
},
};
static struct platform_device xlr_nand_dev = {
.name = "gen_nand",
.id = -1,
.num_resources = ARRAY_SIZE(xlr_nand_res),
.resource = xlr_nand_res,
.dev = {
.platform_data = &xlr_nand_data,
}
};
/*
* XLR/XLS supports upto 8 devices on its FLASH interface. The value in
* FLASH_BAR (on the MEM/IO bridge) gives the base for mapping all the
* flash devices.
* Under this, each flash device has an offset and size given by the
* CSBASE_ADDR and CSBASE_MASK registers for the device.
*
* The CSBASE_ registers are expected to be setup by the bootloader.
*/
static void setup_flash_resource(uint64_t flash_mmio,
uint64_t flash_map_base, int cs, struct resource *res)
{
u32 base, mask;
base = nlm_read_reg(flash_mmio, FLASH_CSBASE_ADDR(cs));
mask = nlm_read_reg(flash_mmio, FLASH_CSADDR_MASK(cs));
res->start = flash_map_base + ((unsigned long)base << 16);
res->end = res->start + (mask + 1) * 64 * 1024;
}
static int __init xlr_flash_init(void)
{
uint64_t gpio_mmio, flash_mmio, flash_map_base;
u32 gpio_resetcfg, flash_bar;
int cs, boot_nand, boot_nor;
/* Flash address bits 39:24 is in bridge flash BAR */
flash_bar = nlm_read_reg(nlm_io_base, BRIDGE_FLASH_BAR);
flash_map_base = (flash_bar & 0xffff0000) << 8;
gpio_mmio = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET);
flash_mmio = nlm_mmio_base(NETLOGIC_IO_FLASH_OFFSET);
/* Get the chip reset config */
gpio_resetcfg = nlm_read_reg(gpio_mmio, GPIO_PWRON_RESET_CFG_REG);
/* Check for boot flash type */
boot_nor = boot_nand = 0;
if (nlm_chip_is_xls()) {
/* On XLS, check boot from NAND bit (GPIO reset reg bit 16) */
if (gpio_resetcfg & (1 << 16))
boot_nand = 1;
/* check boot from PCMCIA, (GPIO reset reg bit 15 */
if ((gpio_resetcfg & (1 << 15)) == 0)
boot_nor = 1; /* not set, booted from NOR */
} else { /* XLR */
/* check boot from PCMCIA (bit 16 in GPIO reset on XLR) */
if ((gpio_resetcfg & (1 << 16)) == 0)
boot_nor = 1; /* not set, booted from NOR */
}
/* boot flash at chip select 0 */
cs = 0;
if (boot_nand) {
nand_priv.cs = cs;
nand_priv.flash_mmio = flash_mmio;
setup_flash_resource(flash_mmio, flash_map_base, cs,
xlr_nand_res);
/* Initialize NAND flash at CS 0 */
nlm_write_reg(flash_mmio, FLASH_CSDEV_PARM(cs),
FLASH_NAND_CSDEV_PARAM);
nlm_write_reg(flash_mmio, FLASH_CSTIME_PARMA(cs),
FLASH_NAND_CSTIME_PARAMA);
nlm_write_reg(flash_mmio, FLASH_CSTIME_PARMB(cs),
FLASH_NAND_CSTIME_PARAMB);
pr_info("ChipSelect %d: NAND Flash %pR\n", cs, xlr_nand_res);
return platform_device_register(&xlr_nand_dev);
}
if (boot_nor) {
setup_flash_resource(flash_mmio, flash_map_base, cs,
xlr_nor_res);
pr_info("ChipSelect %d: NOR Flash %pR\n", cs, xlr_nor_res);
return platform_device_register(&xlr_nor_dev);
}
return 0;
}
arch_initcall(xlr_flash_init);
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/resource.h> #include <linux/resource.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
#include <linux/i2c.h>
#include <asm/netlogic/haldefs.h> #include <asm/netlogic/haldefs.h>
#include <asm/netlogic/xlr/iomap.h> #include <asm/netlogic/xlr/iomap.h>
...@@ -97,3 +98,142 @@ static int __init nlm_uart_init(void) ...@@ -97,3 +98,142 @@ static int __init nlm_uart_init(void)
} }
arch_initcall(nlm_uart_init); arch_initcall(nlm_uart_init);
#ifdef CONFIG_USB
/* Platform USB devices, only on XLS chips */
static u64 xls_usb_dmamask = ~(u32)0;
#define USB_PLATFORM_DEV(n, i, irq) \
{ \
.name = n, \
.id = i, \
.num_resources = 2, \
.dev = { \
.dma_mask = &xls_usb_dmamask, \
.coherent_dma_mask = 0xffffffff, \
}, \
.resource = (struct resource[]) { \
{ \
.flags = IORESOURCE_MEM, \
}, \
{ \
.start = irq, \
.end = irq, \
.flags = IORESOURCE_IRQ, \
}, \
}, \
}
static struct platform_device xls_usb_ehci_device =
USB_PLATFORM_DEV("ehci-xls", 0, PIC_USB_IRQ);
static struct platform_device xls_usb_ohci_device_0 =
USB_PLATFORM_DEV("ohci-xls-0", 1, PIC_USB_IRQ);
static struct platform_device xls_usb_ohci_device_1 =
USB_PLATFORM_DEV("ohci-xls-1", 2, PIC_USB_IRQ);
static struct platform_device *xls_platform_devices[] = {
&xls_usb_ehci_device,
&xls_usb_ohci_device_0,
&xls_usb_ohci_device_1,
};
int xls_platform_usb_init(void)
{
uint64_t usb_mmio, gpio_mmio;
unsigned long memres;
uint32_t val;
if (!nlm_chip_is_xls())
return 0;
gpio_mmio = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET);
usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_1_OFFSET);
/* Clear Rogue Phy INTs */
nlm_write_reg(usb_mmio, 49, 0x10000000);
/* Enable all interrupts */
nlm_write_reg(usb_mmio, 50, 0x1f000000);
/* Enable ports */
nlm_write_reg(usb_mmio, 1, 0x07000500);
val = nlm_read_reg(gpio_mmio, 21);
if (((val >> 22) & 0x01) == 0) {
pr_info("Detected USB Device mode - Not supported!\n");
nlm_write_reg(usb_mmio, 0, 0x01000000);
return 0;
}
pr_info("Detected USB Host mode - Adding XLS USB devices.\n");
/* Clear reset, host mode */
nlm_write_reg(usb_mmio, 0, 0x02000000);
/* Memory resource for various XLS usb ports */
usb_mmio = nlm_mmio_base(NETLOGIC_IO_USB_0_OFFSET);
memres = CPHYSADDR((unsigned long)usb_mmio);
xls_usb_ehci_device.resource[0].start = memres;
xls_usb_ehci_device.resource[0].end = memres + 0x400 - 1;
memres += 0x400;
xls_usb_ohci_device_0.resource[0].start = memres;
xls_usb_ohci_device_0.resource[0].end = memres + 0x400 - 1;
memres += 0x400;
xls_usb_ohci_device_1.resource[0].start = memres;
xls_usb_ohci_device_1.resource[0].end = memres + 0x400 - 1;
return platform_add_devices(xls_platform_devices,
ARRAY_SIZE(xls_platform_devices));
}
arch_initcall(xls_platform_usb_init);
#endif
#ifdef CONFIG_I2C
static struct i2c_board_info nlm_i2c_board_info1[] __initdata = {
/* All XLR boards have this RTC and Max6657 Temp Chip */
[0] = {
.type = "ds1374",
.addr = 0x68
},
[1] = {
.type = "lm90",
.addr = 0x4c
},
};
static struct resource i2c_resources[] = {
[0] = {
.start = 0, /* filled at init */
.end = 0,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device nlm_xlr_i2c_1 = {
.name = "xlr-i2cbus",
.id = 1,
.num_resources = 1,
.resource = i2c_resources,
};
static int __init nlm_i2c_init(void)
{
int err = 0;
unsigned int offset;
/* I2C bus 0 does not have any useful devices, configure only bus 1 */
offset = NETLOGIC_IO_I2C_1_OFFSET;
nlm_xlr_i2c_1.resource[0].start = CPHYSADDR(nlm_mmio_base(offset));
nlm_xlr_i2c_1.resource[0].end = nlm_xlr_i2c_1.resource[0].start + 0xfff;
platform_device_register(&nlm_xlr_i2c_1);
err = i2c_register_board_info(1, nlm_i2c_board_info1,
ARRAY_SIZE(nlm_i2c_board_info1));
if (err < 0)
pr_err("nlm-i2c: cannot register board I2C devices\n");
return err;
}
arch_initcall(nlm_i2c_init);
#endif
...@@ -85,7 +85,7 @@ static void nlm_linux_exit(void) ...@@ -85,7 +85,7 @@ static void nlm_linux_exit(void)
gpiobase = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET); gpiobase = nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET);
/* trigger a chip reset by writing 1 to GPIO_SWRESET_REG */ /* trigger a chip reset by writing 1 to GPIO_SWRESET_REG */
nlm_write_reg(gpiobase, NETLOGIC_GPIO_SWRESET_REG, 1); nlm_write_reg(gpiobase, GPIO_SWRESET_REG, 1);
for ( ; ; ) for ( ; ; )
cpu_wait(); cpu_wait();
} }
......
...@@ -85,6 +85,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) ...@@ -85,6 +85,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
case CPU_34K: case CPU_34K:
case CPU_1004K: case CPU_1004K:
case CPU_74K: case CPU_74K:
case CPU_LOONGSON1:
case CPU_SB1: case CPU_SB1:
case CPU_SB1A: case CPU_SB1A:
case CPU_R10000: case CPU_R10000:
......
...@@ -339,12 +339,6 @@ static int __init mipsxx_init(void) ...@@ -339,12 +339,6 @@ static int __init mipsxx_init(void)
break; break;
case CPU_1004K: case CPU_1004K:
#if 0
/* FIXME: report as 34K for now */
op_model_mipsxx_ops.cpu_type = "mips/1004K";
break;
#endif
case CPU_34K: case CPU_34K:
op_model_mipsxx_ops.cpu_type = "mips/34K"; op_model_mipsxx_ops.cpu_type = "mips/34K";
break; break;
...@@ -374,6 +368,10 @@ static int __init mipsxx_init(void) ...@@ -374,6 +368,10 @@ static int __init mipsxx_init(void)
op_model_mipsxx_ops.cpu_type = "mips/sb1"; op_model_mipsxx_ops.cpu_type = "mips/sb1";
break; break;
case CPU_LOONGSON1:
op_model_mipsxx_ops.cpu_type = "mips/loongson1";
break;
default: default:
printk(KERN_ERR "Profiling unsupported for this CPU\n"); printk(KERN_ERR "Profiling unsupported for this CPU\n");
......
...@@ -59,6 +59,7 @@ obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o ...@@ -59,6 +59,7 @@ obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o
obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o
obj-$(CONFIG_CPU_CAVIUM_OCTEON) += pci-octeon.o pcie-octeon.o obj-$(CONFIG_CPU_CAVIUM_OCTEON) += pci-octeon.o pcie-octeon.o
obj-$(CONFIG_CPU_XLR) += pci-xlr.o obj-$(CONFIG_CPU_XLR) += pci-xlr.o
obj-$(CONFIG_CPU_XLP) += pci-xlp.o
ifdef CONFIG_PCI_MSI ifdef CONFIG_PCI_MSI
obj-$(CONFIG_CPU_CAVIUM_OCTEON) += msi-octeon.o obj-$(CONFIG_CPU_CAVIUM_OCTEON) += msi-octeon.o
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#define VIA_COBALT_BRD_ID_REG 0x94 #define VIA_COBALT_BRD_ID_REG 0x94
#define VIA_COBALT_BRD_REG_to_ID(reg) ((unsigned char)(reg) >> 4) #define VIA_COBALT_BRD_REG_to_ID(reg) ((unsigned char)(reg) >> 4)
static void qube_raq_galileo_early_fixup(struct pci_dev *dev) static void __devinit qube_raq_galileo_early_fixup(struct pci_dev *dev)
{ {
if (dev->devfn == PCI_DEVFN(0, 0) && if (dev->devfn == PCI_DEVFN(0, 0) &&
(dev->class >> 8) == PCI_CLASS_MEMORY_OTHER) { (dev->class >> 8) == PCI_CLASS_MEMORY_OTHER) {
...@@ -51,7 +51,7 @@ static void qube_raq_galileo_early_fixup(struct pci_dev *dev) ...@@ -51,7 +51,7 @@ static void qube_raq_galileo_early_fixup(struct pci_dev *dev)
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111, DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
qube_raq_galileo_early_fixup); qube_raq_galileo_early_fixup);
static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) static void __devinit qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
{ {
unsigned short cfgword; unsigned short cfgword;
unsigned char lt; unsigned char lt;
...@@ -74,7 +74,7 @@ static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) ...@@ -74,7 +74,7 @@ static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1,
qube_raq_via_bmIDE_fixup); qube_raq_via_bmIDE_fixup);
static void qube_raq_galileo_fixup(struct pci_dev *dev) static void __devinit qube_raq_galileo_fixup(struct pci_dev *dev)
{ {
if (dev->devfn != PCI_DEVFN(0, 0)) if (dev->devfn != PCI_DEVFN(0, 0))
return; return;
...@@ -129,7 +129,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111, ...@@ -129,7 +129,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
int cobalt_board_id; int cobalt_board_id;
static void qube_raq_via_board_id_fixup(struct pci_dev *dev) static void __devinit qube_raq_via_board_id_fixup(struct pci_dev *dev)
{ {
u8 id; u8 id;
int retval; int retval;
......
...@@ -101,3 +101,17 @@ static void __devinit malta_piix_func1_fixup(struct pci_dev *pdev) ...@@ -101,3 +101,17 @@ static void __devinit malta_piix_func1_fixup(struct pci_dev *pdev)
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB, DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB,
malta_piix_func1_fixup); malta_piix_func1_fixup);
/* Enable PCI 2.1 compatibility in PIIX4 */
static void __devinit quirk_dlcsetup(struct pci_dev *dev)
{
u8 odlc, ndlc;
(void) pci_read_config_byte(dev, 0x82, &odlc);
/* Enable passive releases and delayed transaction */
ndlc = odlc | 7;
(void) pci_write_config_byte(dev, 0x82, ndlc);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
quirk_dlcsetup);
...@@ -47,7 +47,7 @@ int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ...@@ -47,7 +47,7 @@ int __devinit pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
return irq + GROUP4_IRQ_BASE + 4; return irq + GROUP4_IRQ_BASE + 4;
} }
static void rc32434_pci_early_fixup(struct pci_dev *dev) static void __devinit rc32434_pci_early_fixup(struct pci_dev *dev)
{ {
if (PCI_SLOT(dev->devfn) == 6 && dev->bus->number == 0) { if (PCI_SLOT(dev->devfn) == 6 && dev->bus->number == 0) {
/* disable prefetched memory range */ /* disable prefetched memory range */
......
...@@ -411,7 +411,7 @@ struct pci_ops bcm63xx_cb_ops = { ...@@ -411,7 +411,7 @@ struct pci_ops bcm63xx_cb_ops = {
* only one IO window, so it cannot be shared by PCI and cardbus, use * only one IO window, so it cannot be shared by PCI and cardbus, use
* fixup to choose and detect unhandled configuration * fixup to choose and detect unhandled configuration
*/ */
static void bcm63xx_fixup(struct pci_dev *dev) static void __devinit bcm63xx_fixup(struct pci_dev *dev)
{ {
static int io_window = -1; static int io_window = -1;
int i, found, new_io_window; int i, found, new_io_window;
...@@ -465,3 +465,64 @@ static void bcm63xx_fixup(struct pci_dev *dev) ...@@ -465,3 +465,64 @@ static void bcm63xx_fixup(struct pci_dev *dev)
DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup); DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup);
#endif #endif
static int bcm63xx_pcie_can_access(struct pci_bus *bus, int devfn)
{
switch (bus->number) {
case PCIE_BUS_BRIDGE:
return (PCI_SLOT(devfn) == 0);
case PCIE_BUS_DEVICE:
if (PCI_SLOT(devfn) == 0)
return bcm_pcie_readl(PCIE_DLSTATUS_REG)
& DLSTATUS_PHYLINKUP;
default:
return false;
}
}
static int bcm63xx_pcie_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
u32 data;
u32 reg = where & ~3;
if (!bcm63xx_pcie_can_access(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
if (bus->number == PCIE_BUS_DEVICE)
reg += PCIE_DEVICE_OFFSET;
data = bcm_pcie_readl(reg);
*val = postprocess_read(data, where, size);
return PCIBIOS_SUCCESSFUL;
}
static int bcm63xx_pcie_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
u32 data;
u32 reg = where & ~3;
if (!bcm63xx_pcie_can_access(bus, devfn))
return PCIBIOS_DEVICE_NOT_FOUND;
if (bus->number == PCIE_BUS_DEVICE)
reg += PCIE_DEVICE_OFFSET;
data = bcm_pcie_readl(reg);
data = preprocess_write(data, val, where, size);
bcm_pcie_writel(data, reg);
return PCIBIOS_SUCCESSFUL;
}
struct pci_ops bcm63xx_pcie_ops = {
.read = bcm63xx_pcie_read,
.write = bcm63xx_pcie_write
};
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include "pci-bcm63xx.h" #include "pci-bcm63xx.h"
...@@ -71,6 +72,26 @@ struct pci_controller bcm63xx_cb_controller = { ...@@ -71,6 +72,26 @@ struct pci_controller bcm63xx_cb_controller = {
}; };
#endif #endif
static struct resource bcm_pcie_mem_resource = {
.name = "bcm63xx PCIe memory space",
.start = BCM_PCIE_MEM_BASE_PA,
.end = BCM_PCIE_MEM_END_PA,
.flags = IORESOURCE_MEM,
};
static struct resource bcm_pcie_io_resource = {
.name = "bcm63xx PCIe IO space",
.start = 0,
.end = 0,
.flags = 0,
};
struct pci_controller bcm63xx_pcie_controller = {
.pci_ops = &bcm63xx_pcie_ops,
.io_resource = &bcm_pcie_io_resource,
.mem_resource = &bcm_pcie_mem_resource,
};
static u32 bcm63xx_int_cfg_readl(u32 reg) static u32 bcm63xx_int_cfg_readl(u32 reg)
{ {
u32 tmp; u32 tmp;
...@@ -94,17 +115,99 @@ static void bcm63xx_int_cfg_writel(u32 val, u32 reg) ...@@ -94,17 +115,99 @@ static void bcm63xx_int_cfg_writel(u32 val, u32 reg)
void __iomem *pci_iospace_start; void __iomem *pci_iospace_start;
static int __init bcm63xx_pci_init(void) static void __init bcm63xx_reset_pcie(void)
{ {
unsigned int mem_size;
u32 val; u32 val;
if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358() && !BCMCPU_IS_6368()) /* enable clock */
return -ENODEV; val = bcm_perf_readl(PERF_CKCTL_REG);
val |= CKCTL_6328_PCIE_EN;
bcm_perf_writel(val, PERF_CKCTL_REG);
/* enable SERDES */
val = bcm_misc_readl(MISC_SERDES_CTRL_REG);
val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN;
bcm_misc_writel(val, MISC_SERDES_CTRL_REG);
/* reset the PCIe core */
val = bcm_perf_readl(PERF_SOFTRESET_6328_REG);
val &= ~SOFTRESET_6328_PCIE_MASK;
val &= ~SOFTRESET_6328_PCIE_CORE_MASK;
val &= ~SOFTRESET_6328_PCIE_HARD_MASK;
val &= ~SOFTRESET_6328_PCIE_EXT_MASK;
bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
mdelay(10);
val |= SOFTRESET_6328_PCIE_MASK;
val |= SOFTRESET_6328_PCIE_CORE_MASK;
val |= SOFTRESET_6328_PCIE_HARD_MASK;
bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
mdelay(10);
val |= SOFTRESET_6328_PCIE_EXT_MASK;
bcm_perf_writel(val, PERF_SOFTRESET_6328_REG);
mdelay(200);
}
if (!bcm63xx_pci_enabled) static int __init bcm63xx_register_pcie(void)
return -ENODEV; {
u32 val;
bcm63xx_reset_pcie();
/* configure the PCIe bridge */
val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG);
val |= OPT1_RD_BE_OPT_EN;
val |= OPT1_RD_REPLY_BE_FIX_EN;
val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN;
val |= OPT1_L1_INT_STATUS_MASK_POL;
bcm_pcie_writel(val, PCIE_BRIDGE_OPT1_REG);
/* setup the interrupts */
val = bcm_pcie_readl(PCIE_BRIDGE_RC_INT_MASK_REG);
val |= PCIE_RC_INT_A | PCIE_RC_INT_B | PCIE_RC_INT_C | PCIE_RC_INT_D;
bcm_pcie_writel(val, PCIE_BRIDGE_RC_INT_MASK_REG);
val = bcm_pcie_readl(PCIE_BRIDGE_OPT2_REG);
/* enable credit checking and error checking */
val |= OPT2_TX_CREDIT_CHK_EN;
val |= OPT2_UBUS_UR_DECODE_DIS;
/* set device bus/func for the pcie device */
val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT);
val |= OPT2_CFG_TYPE1_BD_SEL;
bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG);
/* setup class code as bridge */
val = bcm_pcie_readl(PCIE_IDVAL3_REG);
val &= ~IDVAL3_CLASS_CODE_MASK;
val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT);
bcm_pcie_writel(val, PCIE_IDVAL3_REG);
/* disable bar1 size */
val = bcm_pcie_readl(PCIE_CONFIG2_REG);
val &= ~CONFIG2_BAR1_SIZE_MASK;
bcm_pcie_writel(val, PCIE_CONFIG2_REG);
/* set bar0 to little endian */
val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT;
val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT;
val |= BASEMASK_REMAP_EN;
bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG);
val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT;
bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG);
register_pci_controller(&bcm63xx_pcie_controller);
return 0;
}
static int __init bcm63xx_register_pci(void)
{
unsigned int mem_size;
u32 val;
/* /*
* configuration access are done through IO space, remap 4 * configuration access are done through IO space, remap 4
* first bytes to access it from CPU. * first bytes to access it from CPU.
...@@ -221,4 +324,22 @@ static int __init bcm63xx_pci_init(void) ...@@ -221,4 +324,22 @@ static int __init bcm63xx_pci_init(void)
return 0; return 0;
} }
static int __init bcm63xx_pci_init(void)
{
if (!bcm63xx_pci_enabled)
return -ENODEV;
switch (bcm63xx_get_cpu_id()) {
case BCM6328_CPU_ID:
return bcm63xx_register_pcie();
case BCM6348_CPU_ID:
case BCM6358_CPU_ID:
case BCM6368_CPU_ID:
return bcm63xx_register_pci();
default:
return -ENODEV;
}
}
arch_initcall(bcm63xx_pci_init); arch_initcall(bcm63xx_pci_init);
...@@ -13,11 +13,16 @@ ...@@ -13,11 +13,16 @@
*/ */
#define CARDBUS_PCI_IDSEL 0x8 #define CARDBUS_PCI_IDSEL 0x8
#define PCIE_BUS_BRIDGE 0
#define PCIE_BUS_DEVICE 1
/* /*
* defined in ops-bcm63xx.c * defined in ops-bcm63xx.c
*/ */
extern struct pci_ops bcm63xx_pci_ops; extern struct pci_ops bcm63xx_pci_ops;
extern struct pci_ops bcm63xx_cb_ops; extern struct pci_ops bcm63xx_cb_ops;
extern struct pci_ops bcm63xx_pcie_ops;
/* /*
* defined in pci-bcm63xx.c * defined in pci-bcm63xx.c
......
/*
* Copyright (c) 2003-2012 Broadcom Corporation
* All Rights Reserved
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the Broadcom
* license below:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/msi.h>
#include <linux/mm.h>
#include <linux/irq.h>
#include <linux/irqdesc.h>
#include <linux/console.h>
#include <asm/io.h>
#include <asm/netlogic/interrupt.h>
#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/xlp-hal/iomap.h>
#include <asm/netlogic/xlp-hal/pic.h>
#include <asm/netlogic/xlp-hal/xlp.h>
#include <asm/netlogic/xlp-hal/pcibus.h>
#include <asm/netlogic/xlp-hal/bridge.h>
static void *pci_config_base;
#define pci_cfg_addr(bus, devfn, off) (((bus) << 20) | ((devfn) << 12) | (off))
/* PCI ops */
static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn,
int where)
{
u32 data;
u32 *cfgaddr;
cfgaddr = (u32 *)(pci_config_base +
pci_cfg_addr(bus->number, devfn, where & ~3));
data = *cfgaddr;
return data;
}
static inline void pci_cfg_write_32bit(struct pci_bus *bus, unsigned int devfn,
int where, u32 data)
{
u32 *cfgaddr;
cfgaddr = (u32 *)(pci_config_base +
pci_cfg_addr(bus->number, devfn, where & ~3));
*cfgaddr = data;
}
static int nlm_pcibios_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
u32 data;
if ((size == 2) && (where & 1))
return PCIBIOS_BAD_REGISTER_NUMBER;
else if ((size == 4) && (where & 3))
return PCIBIOS_BAD_REGISTER_NUMBER;
data = pci_cfg_read_32bit(bus, devfn, where);
if (size == 1)
*val = (data >> ((where & 3) << 3)) & 0xff;
else if (size == 2)
*val = (data >> ((where & 3) << 3)) & 0xffff;
else
*val = data;
return PCIBIOS_SUCCESSFUL;
}
static int nlm_pcibios_write(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 val)
{
u32 data;
if ((size == 2) && (where & 1))
return PCIBIOS_BAD_REGISTER_NUMBER;
else if ((size == 4) && (where & 3))
return PCIBIOS_BAD_REGISTER_NUMBER;
data = pci_cfg_read_32bit(bus, devfn, where);
if (size == 1)
data = (data & ~(0xff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
else if (size == 2)
data = (data & ~(0xffff << ((where & 3) << 3))) |
(val << ((where & 3) << 3));
else
data = val;
pci_cfg_write_32bit(bus, devfn, where, data);
return PCIBIOS_SUCCESSFUL;
}
struct pci_ops nlm_pci_ops = {
.read = nlm_pcibios_read,
.write = nlm_pcibios_write
};
static struct resource nlm_pci_mem_resource = {
.name = "XLP PCI MEM",
.start = 0xd0000000UL, /* 256MB PCI mem @ 0xd000_0000 */
.end = 0xdfffffffUL,
.flags = IORESOURCE_MEM,
};
static struct resource nlm_pci_io_resource = {
.name = "XLP IO MEM",
.start = 0x14000000UL, /* 64MB PCI IO @ 0x1000_0000 */
.end = 0x17ffffffUL,
.flags = IORESOURCE_IO,
};
struct pci_controller nlm_pci_controller = {
.index = 0,
.pci_ops = &nlm_pci_ops,
.mem_resource = &nlm_pci_mem_resource,
.mem_offset = 0x00000000UL,
.io_resource = &nlm_pci_io_resource,
.io_offset = 0x00000000UL,
};
static int get_irq_vector(const struct pci_dev *dev)
{
/*
* For XLP PCIe, there is an IRQ per Link, find out which
* link the device is on to assign interrupts
*/
if (dev->bus->self == NULL)
return 0;
switch (dev->bus->self->devfn) {
case 0x8:
return PIC_PCIE_LINK_0_IRQ;
case 0x9:
return PIC_PCIE_LINK_1_IRQ;
case 0xa:
return PIC_PCIE_LINK_2_IRQ;
case 0xb:
return PIC_PCIE_LINK_3_IRQ;
}
WARN(1, "Unexpected devfn %d\n", dev->bus->self->devfn);
return 0;
}
int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return get_irq_vector(dev);
}
/* Do platform specific device initialization at pci_enable_device() time */
int pcibios_plat_dev_init(struct pci_dev *dev)
{
return 0;
}
static int xlp_enable_pci_bswap(void)
{
uint64_t pciebase, sysbase;
int node, i;
u32 reg;
/* Chip-0 so node set to 0 */
node = 0;
sysbase = nlm_get_bridge_regbase(node);
/*
* Enable byte swap in hardware. Program each link's PCIe SWAP regions
* from the link's address ranges.
*/
for (i = 0; i < 4; i++) {
pciebase = nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, i));
if (nlm_read_pci_reg(pciebase, 0) == 0xffffffff)
continue;
reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEMEM_BASE0 + i);
nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_MEM_BASE, reg);
reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEMEM_LIMIT0 + i);
nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_MEM_LIM,
reg | 0xfff);
reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEIO_BASE0 + i);
nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_IO_BASE, reg);
reg = nlm_read_bridge_reg(sysbase, BRIDGE_PCIEIO_LIMIT0 + i);
nlm_write_pci_reg(pciebase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff);
}
return 0;
}
static int __init pcibios_init(void)
{
/* Firmware assigns PCI resources */
pci_set_flags(PCI_PROBE_ONLY);
pci_config_base = ioremap(XLP_DEFAULT_PCI_ECFG_BASE, 64 << 20);
/* Extend IO port for memory mapped io */
ioport_resource.start = 0;
ioport_resource.end = ~0;
xlp_enable_pci_bswap();
set_io_port_base(CKSEG1);
nlm_pci_controller.io_map_base = CKSEG1;
register_pci_controller(&nlm_pci_controller);
pr_info("XLP PCIe Controller %pR%pR.\n", &nlm_pci_io_resource,
&nlm_pci_mem_resource);
return 0;
}
arch_initcall(pcibios_init);
...@@ -375,7 +375,3 @@ static int __init pcibios_init(void) ...@@ -375,7 +375,3 @@ static int __init pcibios_init(void)
} }
arch_initcall(pcibios_init); arch_initcall(pcibios_init);
struct pci_fixup pcibios_fixups[] = {
{0}
};
...@@ -91,7 +91,7 @@ void __init pnx833x_board_setup(void) ...@@ -91,7 +91,7 @@ void __init pnx833x_board_setup(void)
pnx833x_gpio_select_function_alt(32); pnx833x_gpio_select_function_alt(32);
pnx833x_gpio_select_function_alt(33); pnx833x_gpio_select_function_alt(33);
#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE) #if IS_ENABLED(CONFIG_MTD_NAND_PLATFORM)
/* Setup MIU for NAND access on CS0... /* Setup MIU for NAND access on CS0...
* *
* (it seems that we must also configure CS1 for reliable operation, * (it seems that we must also configure CS1 for reliable operation,
...@@ -117,7 +117,7 @@ void __init pnx833x_board_setup(void) ...@@ -117,7 +117,7 @@ void __init pnx833x_board_setup(void)
pnx833x_gpio_select_output(5); pnx833x_gpio_select_output(5);
pnx833x_gpio_write(1, 5); pnx833x_gpio_write(1, 5);
#elif defined(CONFIG_MTD_CFI) || defined(CONFIG_MTD_CFI_MODULE) #elif IS_ENABLED(CONFIG_MTD_CFI)
/* Set up MIU for 16-bit NOR access on CS0 and CS1... */ /* Set up MIU for 16-bit NOR access on CS0 and CS1... */
......
...@@ -304,7 +304,7 @@ static void __devinit quirk_slc90e66_bridge(struct pci_dev *dev) ...@@ -304,7 +304,7 @@ static void __devinit quirk_slc90e66_bridge(struct pci_dev *dev)
smsc_fdc37m81x_config_end(); smsc_fdc37m81x_config_end();
} }
static void quirk_slc90e66_ide(struct pci_dev *dev) static void __devinit quirk_slc90e66_ide(struct pci_dev *dev)
{ {
unsigned char dat; unsigned char dat;
int regs[2] = {0x41, 0x43}; int regs[2] = {0x41, 0x43};
...@@ -339,7 +339,7 @@ static void quirk_slc90e66_ide(struct pci_dev *dev) ...@@ -339,7 +339,7 @@ static void quirk_slc90e66_ide(struct pci_dev *dev)
} }
#endif /* CONFIG_TOSHIBA_FPCIB0 */ #endif /* CONFIG_TOSHIBA_FPCIB0 */
static void tc35815_fixup(struct pci_dev *dev) static void __devinit tc35815_fixup(struct pci_dev *dev)
{ {
/* This device may have PM registers but not they are not suported. */ /* This device may have PM registers but not they are not suported. */
if (dev->pm_cap) { if (dev->pm_cap) {
...@@ -348,7 +348,7 @@ static void tc35815_fixup(struct pci_dev *dev) ...@@ -348,7 +348,7 @@ static void tc35815_fixup(struct pci_dev *dev)
} }
} }
static void final_fixup(struct pci_dev *dev) static void __devinit final_fixup(struct pci_dev *dev)
{ {
unsigned char bist; unsigned char bist;
......
...@@ -632,7 +632,7 @@ void __init txx9_physmap_flash_init(int no, unsigned long addr, ...@@ -632,7 +632,7 @@ void __init txx9_physmap_flash_init(int no, unsigned long addr,
unsigned long size, unsigned long size,
const struct physmap_flash_data *pdata) const struct physmap_flash_data *pdata)
{ {
#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE) #if IS_ENABLED(CONFIG_MTD_PHYSMAP)
struct resource res = { struct resource res = {
.start = addr, .start = addr,
.end = addr + size - 1, .end = addr + size - 1,
...@@ -670,8 +670,7 @@ void __init txx9_physmap_flash_init(int no, unsigned long addr, ...@@ -670,8 +670,7 @@ void __init txx9_physmap_flash_init(int no, unsigned long addr,
void __init txx9_ndfmc_init(unsigned long baseaddr, void __init txx9_ndfmc_init(unsigned long baseaddr,
const struct txx9ndfmc_platform_data *pdata) const struct txx9ndfmc_platform_data *pdata)
{ {
#if defined(CONFIG_MTD_NAND_TXX9NDFMC) || \ #if IS_ENABLED(CONFIG_MTD_NAND_TXX9NDFMC)
defined(CONFIG_MTD_NAND_TXX9NDFMC_MODULE)
struct resource res = { struct resource res = {
.start = baseaddr, .start = baseaddr,
.end = baseaddr + 0x1000 - 1, .end = baseaddr + 0x1000 - 1,
...@@ -687,7 +686,7 @@ void __init txx9_ndfmc_init(unsigned long baseaddr, ...@@ -687,7 +686,7 @@ void __init txx9_ndfmc_init(unsigned long baseaddr,
#endif #endif
} }
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE) #if IS_ENABLED(CONFIG_LEDS_GPIO)
static DEFINE_SPINLOCK(txx9_iocled_lock); static DEFINE_SPINLOCK(txx9_iocled_lock);
#define TXX9_IOCLED_MAXLEDS 8 #define TXX9_IOCLED_MAXLEDS 8
...@@ -810,7 +809,7 @@ void __init txx9_iocled_init(unsigned long baseaddr, ...@@ -810,7 +809,7 @@ void __init txx9_iocled_init(unsigned long baseaddr,
void __init txx9_dmac_init(int id, unsigned long baseaddr, int irq, void __init txx9_dmac_init(int id, unsigned long baseaddr, int irq,
const struct txx9dmac_platform_data *pdata) const struct txx9dmac_platform_data *pdata)
{ {
#if defined(CONFIG_TXX9_DMAC) || defined(CONFIG_TXX9_DMAC_MODULE) #if IS_ENABLED(CONFIG_TXX9_DMAC)
struct resource res[] = { struct resource res[] = {
{ {
.start = baseaddr, .start = baseaddr,
...@@ -866,8 +865,7 @@ void __init txx9_aclc_init(unsigned long baseaddr, int irq, ...@@ -866,8 +865,7 @@ void __init txx9_aclc_init(unsigned long baseaddr, int irq,
unsigned int dma_chan_out, unsigned int dma_chan_out,
unsigned int dma_chan_in) unsigned int dma_chan_in)
{ {
#if defined(CONFIG_SND_SOC_TXX9ACLC) || \ #if IS_ENABLED(CONFIG_SND_SOC_TXX9ACLC)
defined(CONFIG_SND_SOC_TXX9ACLC_MODULE)
unsigned int dma_base = dmac_id * TXX9_DMA_MAX_NR_CHANNELS; unsigned int dma_base = dmac_id * TXX9_DMA_MAX_NR_CHANNELS;
struct resource res[] = { struct resource res[] = {
{ {
......
...@@ -317,7 +317,7 @@ void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask) ...@@ -317,7 +317,7 @@ void __init tx4939_sio_init(unsigned int sclk, unsigned int cts_mask)
} }
} }
#if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE) #if IS_ENABLED(CONFIG_TC35815)
static u32 tx4939_get_eth_speed(struct net_device *dev) static u32 tx4939_get_eth_speed(struct net_device *dev)
{ {
struct ethtool_cmd cmd; struct ethtool_cmd cmd;
......
...@@ -40,8 +40,7 @@ static void __init rbtx4939_time_init(void) ...@@ -40,8 +40,7 @@ static void __init rbtx4939_time_init(void)
tx4939_time_init(0); tx4939_time_init(0);
} }
#if defined(__BIG_ENDIAN) && \ #if defined(__BIG_ENDIAN) && IS_ENABLED(CONFIG_SMC91X)
(defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE))
#define HAVE_RBTX4939_IOSWAB #define HAVE_RBTX4939_IOSWAB
#define IS_CE1_ADDR(addr) \ #define IS_CE1_ADDR(addr) \
((((unsigned long)(addr) - IO_BASE) & 0xfff00000) == TXX9_CE(1)) ((((unsigned long)(addr) - IO_BASE) & 0xfff00000) == TXX9_CE(1))
...@@ -187,7 +186,7 @@ static void __init rbtx4939_update_ioc_pen(void) ...@@ -187,7 +186,7 @@ static void __init rbtx4939_update_ioc_pen(void)
#define RBTX4939_MAX_7SEGLEDS 8 #define RBTX4939_MAX_7SEGLEDS 8
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) #if IS_ENABLED(CONFIG_LEDS_CLASS)
static u8 led_val[RBTX4939_MAX_7SEGLEDS]; static u8 led_val[RBTX4939_MAX_7SEGLEDS];
struct rbtx4939_led_data { struct rbtx4939_led_data {
struct led_classdev cdev; struct led_classdev cdev;
...@@ -263,7 +262,7 @@ static inline void rbtx4939_led_setup(void) ...@@ -263,7 +262,7 @@ static inline void rbtx4939_led_setup(void)
static void __rbtx4939_7segled_putc(unsigned int pos, unsigned char val) static void __rbtx4939_7segled_putc(unsigned int pos, unsigned char val)
{ {
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) #if IS_ENABLED(CONFIG_LEDS_CLASS)
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
/* bit7: reserved for LED class */ /* bit7: reserved for LED class */
...@@ -287,7 +286,7 @@ static void rbtx4939_7segled_putc(unsigned int pos, unsigned char val) ...@@ -287,7 +286,7 @@ static void rbtx4939_7segled_putc(unsigned int pos, unsigned char val)
__rbtx4939_7segled_putc(pos, val); __rbtx4939_7segled_putc(pos, val);
} }
#if defined(CONFIG_MTD_RBTX4939) || defined(CONFIG_MTD_RBTX4939_MODULE) #if IS_ENABLED(CONFIG_MTD_RBTX4939)
/* special mapping for boot rom */ /* special mapping for boot rom */
static unsigned long rbtx4939_flash_fixup_ofs(unsigned long ofs) static unsigned long rbtx4939_flash_fixup_ofs(unsigned long ofs)
{ {
...@@ -463,7 +462,7 @@ static void __init rbtx4939_device_init(void) ...@@ -463,7 +462,7 @@ static void __init rbtx4939_device_init(void)
.flags = SMC91X_USE_16BIT, .flags = SMC91X_USE_16BIT,
}; };
struct platform_device *pdev; struct platform_device *pdev;
#if defined(CONFIG_TC35815) || defined(CONFIG_TC35815_MODULE) #if IS_ENABLED(CONFIG_TC35815)
int i, j; int i, j;
unsigned char ethaddr[2][6]; unsigned char ethaddr[2][6];
u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f; u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
......
...@@ -73,6 +73,20 @@ config HW_RANDOM_ATMEL ...@@ -73,6 +73,20 @@ config HW_RANDOM_ATMEL
If unsure, say Y. If unsure, say Y.
config HW_RANDOM_BCM63XX
tristate "Broadcom BCM63xx Random Number Generator support"
depends on HW_RANDOM && BCM63XX
default HW_RANDOM
---help---
This driver provides kernel-side support for the Random Number
Generator hardware found on the Broadcom BCM63xx SoCs.
To compile this driver as a module, choose M here: the
module will be called bcm63xx-rng
If unusure, say Y.
config HW_RANDOM_GEODE config HW_RANDOM_GEODE
tristate "AMD Geode HW Random Number Generator support" tristate "AMD Geode HW Random Number Generator support"
depends on HW_RANDOM && X86_32 && PCI depends on HW_RANDOM && X86_32 && PCI
......
...@@ -8,6 +8,7 @@ obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o ...@@ -8,6 +8,7 @@ obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
obj-$(CONFIG_HW_RANDOM_BCM63XX) += bcm63xx-rng.o
obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
n2-rng-y := n2-drv.o n2-asm.o n2-rng-y := n2-drv.o n2-asm.o
......
/*
* Broadcom BCM63xx Random Number Generator support
*
* Copyright (C) 2011, Florian Fainelli <florian@openwrt.org>
* Copyright (C) 2009, Broadcom Corporation
*
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/hw_random.h>
#include <bcm63xx_io.h>
#include <bcm63xx_regs.h>
struct bcm63xx_rng_priv {
struct clk *clk;
void __iomem *regs;
};
#define to_rng_priv(rng) ((struct bcm63xx_rng_priv *)rng->priv)
static int bcm63xx_rng_init(struct hwrng *rng)
{
struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
u32 val;
val = bcm_readl(priv->regs + RNG_CTRL);
val |= RNG_EN;
bcm_writel(val, priv->regs + RNG_CTRL);
return 0;
}
static void bcm63xx_rng_cleanup(struct hwrng *rng)
{
struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
u32 val;
val = bcm_readl(priv->regs + RNG_CTRL);
val &= ~RNG_EN;
bcm_writel(val, priv->regs + RNG_CTRL);
}
static int bcm63xx_rng_data_present(struct hwrng *rng, int wait)
{
struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
return bcm_readl(priv->regs + RNG_STAT) & RNG_AVAIL_MASK;
}
static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data)
{
struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
*data = bcm_readl(priv->regs + RNG_DATA);
return 4;
}
static int __devinit bcm63xx_rng_probe(struct platform_device *pdev)
{
struct resource *r;
struct clk *clk;
int ret;
struct bcm63xx_rng_priv *priv;
struct hwrng *rng;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r) {
dev_err(&pdev->dev, "no iomem resource\n");
ret = -ENXIO;
goto out;
}
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "no memory for private structure\n");
ret = -ENOMEM;
goto out;
}
rng = kzalloc(sizeof(*rng), GFP_KERNEL);
if (!rng) {
dev_err(&pdev->dev, "no memory for rng structure\n");
ret = -ENOMEM;
goto out_free_priv;
}
platform_set_drvdata(pdev, rng);
rng->priv = (unsigned long)priv;
rng->name = pdev->name;
rng->init = bcm63xx_rng_init;
rng->cleanup = bcm63xx_rng_cleanup;
rng->data_present = bcm63xx_rng_data_present;
rng->data_read = bcm63xx_rng_data_read;
clk = clk_get(&pdev->dev, "ipsec");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "no clock for device\n");
ret = PTR_ERR(clk);
goto out_free_rng;
}
priv->clk = clk;
if (!devm_request_mem_region(&pdev->dev, r->start,
resource_size(r), pdev->name)) {
dev_err(&pdev->dev, "request mem failed");
ret = -ENOMEM;
goto out_free_rng;
}
priv->regs = devm_ioremap_nocache(&pdev->dev, r->start,
resource_size(r));
if (!priv->regs) {
dev_err(&pdev->dev, "ioremap failed");
ret = -ENOMEM;
goto out_free_rng;
}
clk_enable(clk);
ret = hwrng_register(rng);
if (ret) {
dev_err(&pdev->dev, "failed to register rng device\n");
goto out_clk_disable;
}
dev_info(&pdev->dev, "registered RNG driver\n");
return 0;
out_clk_disable:
clk_disable(clk);
out_free_rng:
platform_set_drvdata(pdev, NULL);
kfree(rng);
out_free_priv:
kfree(priv);
out:
return ret;
}
static int __devexit bcm63xx_rng_remove(struct platform_device *pdev)
{
struct hwrng *rng = platform_get_drvdata(pdev);
struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
hwrng_unregister(rng);
clk_disable(priv->clk);
kfree(priv);
kfree(rng);
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver bcm63xx_rng_driver = {
.probe = bcm63xx_rng_probe,
.remove = __devexit_p(bcm63xx_rng_remove),
.driver = {
.name = "bcm63xx-rng",
.owner = THIS_MODULE,
},
};
module_platform_driver(bcm63xx_rng_driver);
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
MODULE_DESCRIPTION("Broadcom BCM63xx RNG driver");
MODULE_LICENSE("GPL");
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* (C) Copyright 2009-2010 * (C) Copyright 2009-2010
* Nokia Siemens Networks, michael.lawnick.ext@nsn.com * Nokia Siemens Networks, michael.lawnick.ext@nsn.com
* *
* Portions Copyright (C) 2010 Cavium Networks, Inc. * Portions Copyright (C) 2010, 2011 Cavium Networks, Inc.
* *
* This is a driver for the i2c adapter in Cavium Networks' OCTEON processors. * This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.
* *
...@@ -11,17 +11,18 @@ ...@@ -11,17 +11,18 @@
* warranty of any kind, whether express or implied. * warranty of any kind, whether express or implied.
*/ */
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of_i2c.h>
#include <linux/delay.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/io.h>
#include <linux/delay.h> #include <linux/of.h>
#include <linux/platform_device.h>
#include <asm/octeon/octeon.h> #include <asm/octeon/octeon.h>
...@@ -65,7 +66,7 @@ struct octeon_i2c { ...@@ -65,7 +66,7 @@ struct octeon_i2c {
wait_queue_head_t queue; wait_queue_head_t queue;
struct i2c_adapter adap; struct i2c_adapter adap;
int irq; int irq;
int twsi_freq; u32 twsi_freq;
int sys_freq; int sys_freq;
resource_size_t twsi_phys; resource_size_t twsi_phys;
void __iomem *twsi_base; void __iomem *twsi_base;
...@@ -121,10 +122,8 @@ static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg) ...@@ -121,10 +122,8 @@ static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg)
*/ */
static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data) static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
{ {
u64 tmp;
__raw_writeq(data, i2c->twsi_base + TWSI_INT); __raw_writeq(data, i2c->twsi_base + TWSI_INT);
tmp = __raw_readq(i2c->twsi_base + TWSI_INT); __raw_readq(i2c->twsi_base + TWSI_INT);
} }
/** /**
...@@ -515,7 +514,6 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev) ...@@ -515,7 +514,6 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
{ {
int irq, result = 0; int irq, result = 0;
struct octeon_i2c *i2c; struct octeon_i2c *i2c;
struct octeon_i2c_data *i2c_data;
struct resource *res_mem; struct resource *res_mem;
/* All adaptors have an irq. */ /* All adaptors have an irq. */
...@@ -523,86 +521,90 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev) ...@@ -523,86 +521,90 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)
if (irq < 0) if (irq < 0)
return irq; return irq;
i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c) { if (!i2c) {
dev_err(&pdev->dev, "kzalloc failed\n"); dev_err(&pdev->dev, "kzalloc failed\n");
result = -ENOMEM; result = -ENOMEM;
goto out; goto out;
} }
i2c->dev = &pdev->dev; i2c->dev = &pdev->dev;
i2c_data = pdev->dev.platform_data;
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res_mem == NULL) { if (res_mem == NULL) {
dev_err(i2c->dev, "found no memory resource\n"); dev_err(i2c->dev, "found no memory resource\n");
result = -ENXIO; result = -ENXIO;
goto fail_region; goto out;
} }
i2c->twsi_phys = res_mem->start;
i2c->regsize = resource_size(res_mem);
if (i2c_data == NULL) { /*
dev_err(i2c->dev, "no I2C frequency data\n"); * "clock-rate" is a legacy binding, the official binding is
* "clock-frequency". Try the official one first and then
* fall back if it doesn't exist.
*/
if (of_property_read_u32(pdev->dev.of_node,
"clock-frequency", &i2c->twsi_freq) &&
of_property_read_u32(pdev->dev.of_node,
"clock-rate", &i2c->twsi_freq)) {
dev_err(i2c->dev,
"no I2C 'clock-rate' or 'clock-frequency' property\n");
result = -ENXIO; result = -ENXIO;
goto fail_region; goto out;
} }
i2c->twsi_phys = res_mem->start; i2c->sys_freq = octeon_get_io_clock_rate();
i2c->regsize = resource_size(res_mem);
i2c->twsi_freq = i2c_data->i2c_freq;
i2c->sys_freq = i2c_data->sys_freq;
if (!request_mem_region(i2c->twsi_phys, i2c->regsize, res_mem->name)) { if (!devm_request_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize,
res_mem->name)) {
dev_err(i2c->dev, "request_mem_region failed\n"); dev_err(i2c->dev, "request_mem_region failed\n");
goto fail_region; goto out;
} }
i2c->twsi_base = ioremap(i2c->twsi_phys, i2c->regsize); i2c->twsi_base = devm_ioremap(&pdev->dev, i2c->twsi_phys, i2c->regsize);
init_waitqueue_head(&i2c->queue); init_waitqueue_head(&i2c->queue);
i2c->irq = irq; i2c->irq = irq;
result = request_irq(i2c->irq, octeon_i2c_isr, 0, DRV_NAME, i2c); result = devm_request_irq(&pdev->dev, i2c->irq,
octeon_i2c_isr, 0, DRV_NAME, i2c);
if (result < 0) { if (result < 0) {
dev_err(i2c->dev, "failed to attach interrupt\n"); dev_err(i2c->dev, "failed to attach interrupt\n");
goto fail_irq; goto out;
} }
result = octeon_i2c_initlowlevel(i2c); result = octeon_i2c_initlowlevel(i2c);
if (result) { if (result) {
dev_err(i2c->dev, "init low level failed\n"); dev_err(i2c->dev, "init low level failed\n");
goto fail_add; goto out;
} }
result = octeon_i2c_setclock(i2c); result = octeon_i2c_setclock(i2c);
if (result) { if (result) {
dev_err(i2c->dev, "clock init failed\n"); dev_err(i2c->dev, "clock init failed\n");
goto fail_add; goto out;
} }
i2c->adap = octeon_i2c_ops; i2c->adap = octeon_i2c_ops;
i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.parent = &pdev->dev;
i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; i2c->adap.dev.of_node = pdev->dev.of_node;
i2c_set_adapdata(&i2c->adap, i2c); i2c_set_adapdata(&i2c->adap, i2c);
platform_set_drvdata(pdev, i2c); platform_set_drvdata(pdev, i2c);
result = i2c_add_numbered_adapter(&i2c->adap); result = i2c_add_adapter(&i2c->adap);
if (result < 0) { if (result < 0) {
dev_err(i2c->dev, "failed to add adapter\n"); dev_err(i2c->dev, "failed to add adapter\n");
goto fail_add; goto fail_add;
} }
dev_info(i2c->dev, "version %s\n", DRV_VERSION); dev_info(i2c->dev, "version %s\n", DRV_VERSION);
return result; of_i2c_register_devices(&i2c->adap);
return 0;
fail_add: fail_add:
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
free_irq(i2c->irq, i2c);
fail_irq:
iounmap(i2c->twsi_base);
release_mem_region(i2c->twsi_phys, i2c->regsize);
fail_region:
kfree(i2c);
out: out:
return result; return result;
}; };
...@@ -613,19 +615,24 @@ static int __devexit octeon_i2c_remove(struct platform_device *pdev) ...@@ -613,19 +615,24 @@ static int __devexit octeon_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&i2c->adap); i2c_del_adapter(&i2c->adap);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
free_irq(i2c->irq, i2c);
iounmap(i2c->twsi_base);
release_mem_region(i2c->twsi_phys, i2c->regsize);
kfree(i2c);
return 0; return 0;
}; };
static struct of_device_id octeon_i2c_match[] = {
{
.compatible = "cavium,octeon-3860-twsi",
},
{},
};
MODULE_DEVICE_TABLE(of, octeon_i2c_match);
static struct platform_driver octeon_i2c_driver = { static struct platform_driver octeon_i2c_driver = {
.probe = octeon_i2c_probe, .probe = octeon_i2c_probe,
.remove = __devexit_p(octeon_i2c_remove), .remove = __devexit_p(octeon_i2c_remove),
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.of_match_table = octeon_i2c_match,
}, },
}; };
...@@ -635,4 +642,3 @@ MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>"); ...@@ -635,4 +642,3 @@ MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>");
MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors"); MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION); MODULE_VERSION(DRV_VERSION);
MODULE_ALIAS("platform:" DRV_NAME);
...@@ -52,9 +52,10 @@ ...@@ -52,9 +52,10 @@
#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1) #define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1)
#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1) #define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1)
#define JZ_NAND_CTRL_ASSERT_CHIP_MASK 0xaa
#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
#define JZ_NAND_MEM_CMD_OFFSET 0x08000 #define JZ_NAND_MEM_CMD_OFFSET 0x08000
#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
struct jz_nand { struct jz_nand {
struct mtd_info mtd; struct mtd_info mtd;
...@@ -62,8 +63,11 @@ struct jz_nand { ...@@ -62,8 +63,11 @@ struct jz_nand {
void __iomem *base; void __iomem *base;
struct resource *mem; struct resource *mem;
void __iomem *bank_base; unsigned char banks[JZ_NAND_NUM_BANKS];
struct resource *bank_mem; void __iomem *bank_base[JZ_NAND_NUM_BANKS];
struct resource *bank_mem[JZ_NAND_NUM_BANKS];
int selected_bank;
struct jz_nand_platform_data *pdata; struct jz_nand_platform_data *pdata;
bool is_reading; bool is_reading;
...@@ -74,26 +78,50 @@ static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd) ...@@ -74,26 +78,50 @@ static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
return container_of(mtd, struct jz_nand, mtd); return container_of(mtd, struct jz_nand, mtd);
} }
static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
{
struct jz_nand *nand = mtd_to_jz_nand(mtd);
struct nand_chip *chip = mtd->priv;
uint32_t ctrl;
int banknr;
ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
ctrl &= ~JZ_NAND_CTRL_ASSERT_CHIP_MASK;
if (chipnr == -1) {
banknr = -1;
} else {
banknr = nand->banks[chipnr] - 1;
chip->IO_ADDR_R = nand->bank_base[banknr];
chip->IO_ADDR_W = nand->bank_base[banknr];
}
writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
nand->selected_bank = banknr;
}
static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
{ {
struct jz_nand *nand = mtd_to_jz_nand(mtd); struct jz_nand *nand = mtd_to_jz_nand(mtd);
struct nand_chip *chip = mtd->priv; struct nand_chip *chip = mtd->priv;
uint32_t reg; uint32_t reg;
void __iomem *bank_base = nand->bank_base[nand->selected_bank];
BUG_ON(nand->selected_bank < 0);
if (ctrl & NAND_CTRL_CHANGE) { if (ctrl & NAND_CTRL_CHANGE) {
BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE)); BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
if (ctrl & NAND_ALE) if (ctrl & NAND_ALE)
chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_ADDR_OFFSET; bank_base += JZ_NAND_MEM_ADDR_OFFSET;
else if (ctrl & NAND_CLE) else if (ctrl & NAND_CLE)
chip->IO_ADDR_W = nand->bank_base + JZ_NAND_MEM_CMD_OFFSET; bank_base += JZ_NAND_MEM_CMD_OFFSET;
else chip->IO_ADDR_W = bank_base;
chip->IO_ADDR_W = nand->bank_base;
reg = readl(nand->base + JZ_REG_NAND_CTRL); reg = readl(nand->base + JZ_REG_NAND_CTRL);
if (ctrl & NAND_NCE) if (ctrl & NAND_NCE)
reg |= JZ_NAND_CTRL_ASSERT_CHIP(0); reg |= JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank);
else else
reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(0); reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank);
writel(reg, nand->base + JZ_REG_NAND_CTRL); writel(reg, nand->base + JZ_REG_NAND_CTRL);
} }
if (dat != NAND_CMD_NONE) if (dat != NAND_CMD_NONE)
...@@ -252,7 +280,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat, ...@@ -252,7 +280,7 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
} }
static int jz_nand_ioremap_resource(struct platform_device *pdev, static int jz_nand_ioremap_resource(struct platform_device *pdev,
const char *name, struct resource **res, void __iomem **base) const char *name, struct resource **res, void *__iomem *base)
{ {
int ret; int ret;
...@@ -288,6 +316,90 @@ static int jz_nand_ioremap_resource(struct platform_device *pdev, ...@@ -288,6 +316,90 @@ static int jz_nand_ioremap_resource(struct platform_device *pdev,
return ret; return ret;
} }
static inline void jz_nand_iounmap_resource(struct resource *res, void __iomem *base)
{
iounmap(base);
release_mem_region(res->start, resource_size(res));
}
static int __devinit jz_nand_detect_bank(struct platform_device *pdev, struct jz_nand *nand, unsigned char bank, size_t chipnr, uint8_t *nand_maf_id, uint8_t *nand_dev_id) {
int ret;
int gpio;
char gpio_name[9];
char res_name[6];
uint32_t ctrl;
struct mtd_info *mtd = &nand->mtd;
struct nand_chip *chip = &nand->chip;
/* Request GPIO port. */
gpio = JZ_GPIO_MEM_CS0 + bank - 1;
sprintf(gpio_name, "NAND CS%d", bank);
ret = gpio_request(gpio, gpio_name);
if (ret) {
dev_warn(&pdev->dev,
"Failed to request %s gpio %d: %d\n",
gpio_name, gpio, ret);
goto notfound_gpio;
}
/* Request I/O resource. */
sprintf(res_name, "bank%d", bank);
ret = jz_nand_ioremap_resource(pdev, res_name,
&nand->bank_mem[bank - 1],
&nand->bank_base[bank - 1]);
if (ret)
goto notfound_resource;
/* Enable chip in bank. */
jz_gpio_set_function(gpio, JZ_GPIO_FUNC_MEM_CS0);
ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
ctrl |= JZ_NAND_CTRL_ENABLE_CHIP(bank - 1);
writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
if (chipnr == 0) {
/* Detect first chip. */
ret = nand_scan_ident(mtd, 1, NULL);
if (ret)
goto notfound_id;
/* Retrieve the IDs from the first chip. */
chip->select_chip(mtd, 0);
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
*nand_maf_id = chip->read_byte(mtd);
*nand_dev_id = chip->read_byte(mtd);
} else {
/* Detect additional chip. */
chip->select_chip(mtd, chipnr);
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
if (*nand_maf_id != chip->read_byte(mtd)
|| *nand_dev_id != chip->read_byte(mtd)) {
ret = -ENODEV;
goto notfound_id;
}
/* Update size of the MTD. */
chip->numchips++;
mtd->size += chip->chipsize;
}
dev_info(&pdev->dev, "Found chip %i on bank %i\n", chipnr, bank);
return 0;
notfound_id:
dev_info(&pdev->dev, "No chip found on bank %i\n", bank);
ctrl &= ~(JZ_NAND_CTRL_ENABLE_CHIP(bank - 1));
writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
jz_gpio_set_function(gpio, JZ_GPIO_FUNC_NONE);
jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
nand->bank_base[bank - 1]);
notfound_resource:
gpio_free(gpio);
notfound_gpio:
return ret;
}
static int __devinit jz_nand_probe(struct platform_device *pdev) static int __devinit jz_nand_probe(struct platform_device *pdev)
{ {
int ret; int ret;
...@@ -295,6 +407,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) ...@@ -295,6 +407,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
struct nand_chip *chip; struct nand_chip *chip;
struct mtd_info *mtd; struct mtd_info *mtd;
struct jz_nand_platform_data *pdata = pdev->dev.platform_data; struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
size_t chipnr, bank_idx;
uint8_t nand_maf_id = 0, nand_dev_id = 0;
nand = kzalloc(sizeof(*nand), GFP_KERNEL); nand = kzalloc(sizeof(*nand), GFP_KERNEL);
if (!nand) { if (!nand) {
...@@ -305,10 +419,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) ...@@ -305,10 +419,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base); ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base);
if (ret) if (ret)
goto err_free; goto err_free;
ret = jz_nand_ioremap_resource(pdev, "bank", &nand->bank_mem,
&nand->bank_base);
if (ret)
goto err_iounmap_mmio;
if (pdata && gpio_is_valid(pdata->busy_gpio)) { if (pdata && gpio_is_valid(pdata->busy_gpio)) {
ret = gpio_request(pdata->busy_gpio, "NAND busy pin"); ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
...@@ -316,7 +426,7 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) ...@@ -316,7 +426,7 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Failed to request busy gpio %d: %d\n", "Failed to request busy gpio %d: %d\n",
pdata->busy_gpio, ret); pdata->busy_gpio, ret);
goto err_iounmap_mem; goto err_iounmap_mmio;
} }
} }
...@@ -339,22 +449,51 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) ...@@ -339,22 +449,51 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
chip->chip_delay = 50; chip->chip_delay = 50;
chip->cmd_ctrl = jz_nand_cmd_ctrl; chip->cmd_ctrl = jz_nand_cmd_ctrl;
chip->select_chip = jz_nand_select_chip;
if (pdata && gpio_is_valid(pdata->busy_gpio)) if (pdata && gpio_is_valid(pdata->busy_gpio))
chip->dev_ready = jz_nand_dev_ready; chip->dev_ready = jz_nand_dev_ready;
chip->IO_ADDR_R = nand->bank_base;
chip->IO_ADDR_W = nand->bank_base;
nand->pdata = pdata; nand->pdata = pdata;
platform_set_drvdata(pdev, nand); platform_set_drvdata(pdev, nand);
writel(JZ_NAND_CTRL_ENABLE_CHIP(0), nand->base + JZ_REG_NAND_CTRL); /* We are going to autodetect NAND chips in the banks specified in the
* platform data. Although nand_scan_ident() can detect multiple chips,
ret = nand_scan_ident(mtd, 1, NULL); * it requires those chips to be numbered consecuitively, which is not
if (ret) { * always the case for external memory banks. And a fixed chip-to-bank
dev_err(&pdev->dev, "Failed to scan nand\n"); * mapping is not practical either, since for example Dingoo units
goto err_gpio_free; * produced at different times have NAND chips in different banks.
*/
chipnr = 0;
for (bank_idx = 0; bank_idx < JZ_NAND_NUM_BANKS; bank_idx++) {
unsigned char bank;
/* If there is no platform data, look for NAND in bank 1,
* which is the most likely bank since it is the only one
* that can be booted from.
*/
bank = pdata ? pdata->banks[bank_idx] : bank_idx ^ 1;
if (bank == 0)
break;
if (bank > JZ_NAND_NUM_BANKS) {
dev_warn(&pdev->dev,
"Skipping non-existing bank: %d\n", bank);
continue;
}
/* The detection routine will directly or indirectly call
* jz_nand_select_chip(), so nand->banks has to contain the
* bank we're checking.
*/
nand->banks[chipnr] = bank;
if (jz_nand_detect_bank(pdev, nand, bank, chipnr,
&nand_maf_id, &nand_dev_id) == 0)
chipnr++;
else
nand->banks[chipnr] = 0;
}
if (chipnr == 0) {
dev_err(&pdev->dev, "No NAND chips found\n");
goto err_gpio_busy;
} }
if (pdata && pdata->ident_callback) { if (pdata && pdata->ident_callback) {
...@@ -364,8 +503,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) ...@@ -364,8 +503,8 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
ret = nand_scan_tail(mtd); ret = nand_scan_tail(mtd);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Failed to scan nand\n"); dev_err(&pdev->dev, "Failed to scan NAND\n");
goto err_gpio_free; goto err_unclaim_banks;
} }
ret = mtd_device_parse_register(mtd, NULL, NULL, ret = mtd_device_parse_register(mtd, NULL, NULL,
...@@ -382,14 +521,21 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) ...@@ -382,14 +521,21 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
return 0; return 0;
err_nand_release: err_nand_release:
nand_release(&nand->mtd); nand_release(mtd);
err_gpio_free: err_unclaim_banks:
while (chipnr--) {
unsigned char bank = nand->banks[chipnr];
gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
nand->bank_base[bank - 1]);
}
writel(0, nand->base + JZ_REG_NAND_CTRL);
err_gpio_busy:
if (pdata && gpio_is_valid(pdata->busy_gpio))
gpio_free(pdata->busy_gpio);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
gpio_free(pdata->busy_gpio);
err_iounmap_mem:
iounmap(nand->bank_base);
err_iounmap_mmio: err_iounmap_mmio:
iounmap(nand->base); jz_nand_iounmap_resource(nand->mem, nand->base);
err_free: err_free:
kfree(nand); kfree(nand);
return ret; return ret;
...@@ -398,16 +544,26 @@ static int __devinit jz_nand_probe(struct platform_device *pdev) ...@@ -398,16 +544,26 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
static int __devexit jz_nand_remove(struct platform_device *pdev) static int __devexit jz_nand_remove(struct platform_device *pdev)
{ {
struct jz_nand *nand = platform_get_drvdata(pdev); struct jz_nand *nand = platform_get_drvdata(pdev);
struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
size_t i;
nand_release(&nand->mtd); nand_release(&nand->mtd);
/* Deassert and disable all chips */ /* Deassert and disable all chips */
writel(0, nand->base + JZ_REG_NAND_CTRL); writel(0, nand->base + JZ_REG_NAND_CTRL);
iounmap(nand->bank_base); for (i = 0; i < JZ_NAND_NUM_BANKS; ++i) {
release_mem_region(nand->bank_mem->start, resource_size(nand->bank_mem)); unsigned char bank = nand->banks[i];
iounmap(nand->base); if (bank != 0) {
release_mem_region(nand->mem->start, resource_size(nand->mem)); jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
nand->bank_base[bank - 1]);
gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
}
}
if (pdata && gpio_is_valid(pdata->busy_gpio))
gpio_free(pdata->busy_gpio);
jz_nand_iounmap_resource(nand->mem, nand->base);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
kfree(nand); kfree(nand);
......
...@@ -6,19 +6,21 @@ ...@@ -6,19 +6,21 @@
* Copyright (C) 2009 Cavium Networks * Copyright (C) 2009 Cavium Networks
*/ */
#include <linux/capability.h> #include <linux/platform_device.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/init.h> #include <linux/etherdevice.h>
#include <linux/module.h> #include <linux/capability.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/spinlock.h>
#include <linux/if.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/of_mdio.h>
#include <linux/module.h>
#include <linux/of_net.h>
#include <linux/init.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/spinlock.h> #include <linux/io.h>
#include <asm/octeon/octeon.h> #include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-mixx-defs.h> #include <asm/octeon/cvmx-mixx-defs.h>
...@@ -58,8 +60,56 @@ union mgmt_port_ring_entry { ...@@ -58,8 +60,56 @@ union mgmt_port_ring_entry {
} s; } s;
}; };
#define MIX_ORING1 0x0
#define MIX_ORING2 0x8
#define MIX_IRING1 0x10
#define MIX_IRING2 0x18
#define MIX_CTL 0x20
#define MIX_IRHWM 0x28
#define MIX_IRCNT 0x30
#define MIX_ORHWM 0x38
#define MIX_ORCNT 0x40
#define MIX_ISR 0x48
#define MIX_INTENA 0x50
#define MIX_REMCNT 0x58
#define MIX_BIST 0x78
#define AGL_GMX_PRT_CFG 0x10
#define AGL_GMX_RX_FRM_CTL 0x18
#define AGL_GMX_RX_FRM_MAX 0x30
#define AGL_GMX_RX_JABBER 0x38
#define AGL_GMX_RX_STATS_CTL 0x50
#define AGL_GMX_RX_STATS_PKTS_DRP 0xb0
#define AGL_GMX_RX_STATS_OCTS_DRP 0xb8
#define AGL_GMX_RX_STATS_PKTS_BAD 0xc0
#define AGL_GMX_RX_ADR_CTL 0x100
#define AGL_GMX_RX_ADR_CAM_EN 0x108
#define AGL_GMX_RX_ADR_CAM0 0x180
#define AGL_GMX_RX_ADR_CAM1 0x188
#define AGL_GMX_RX_ADR_CAM2 0x190
#define AGL_GMX_RX_ADR_CAM3 0x198
#define AGL_GMX_RX_ADR_CAM4 0x1a0
#define AGL_GMX_RX_ADR_CAM5 0x1a8
#define AGL_GMX_TX_STATS_CTL 0x268
#define AGL_GMX_TX_CTL 0x270
#define AGL_GMX_TX_STAT0 0x280
#define AGL_GMX_TX_STAT1 0x288
#define AGL_GMX_TX_STAT2 0x290
#define AGL_GMX_TX_STAT3 0x298
#define AGL_GMX_TX_STAT4 0x2a0
#define AGL_GMX_TX_STAT5 0x2a8
#define AGL_GMX_TX_STAT6 0x2b0
#define AGL_GMX_TX_STAT7 0x2b8
#define AGL_GMX_TX_STAT8 0x2c0
#define AGL_GMX_TX_STAT9 0x2c8
struct octeon_mgmt { struct octeon_mgmt {
struct net_device *netdev; struct net_device *netdev;
u64 mix;
u64 agl;
int port; int port;
int irq; int irq;
u64 *tx_ring; u64 *tx_ring;
...@@ -85,31 +135,34 @@ struct octeon_mgmt { ...@@ -85,31 +135,34 @@ struct octeon_mgmt {
struct napi_struct napi; struct napi_struct napi;
struct tasklet_struct tx_clean_tasklet; struct tasklet_struct tx_clean_tasklet;
struct phy_device *phydev; struct phy_device *phydev;
struct device_node *phy_np;
resource_size_t mix_phys;
resource_size_t mix_size;
resource_size_t agl_phys;
resource_size_t agl_size;
}; };
static void octeon_mgmt_set_rx_irq(struct octeon_mgmt *p, int enable) static void octeon_mgmt_set_rx_irq(struct octeon_mgmt *p, int enable)
{ {
int port = p->port;
union cvmx_mixx_intena mix_intena; union cvmx_mixx_intena mix_intena;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&p->lock, flags); spin_lock_irqsave(&p->lock, flags);
mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port)); mix_intena.u64 = cvmx_read_csr(p->mix + MIX_INTENA);
mix_intena.s.ithena = enable ? 1 : 0; mix_intena.s.ithena = enable ? 1 : 0;
cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64); cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
spin_unlock_irqrestore(&p->lock, flags); spin_unlock_irqrestore(&p->lock, flags);
} }
static void octeon_mgmt_set_tx_irq(struct octeon_mgmt *p, int enable) static void octeon_mgmt_set_tx_irq(struct octeon_mgmt *p, int enable)
{ {
int port = p->port;
union cvmx_mixx_intena mix_intena; union cvmx_mixx_intena mix_intena;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&p->lock, flags); spin_lock_irqsave(&p->lock, flags);
mix_intena.u64 = cvmx_read_csr(CVMX_MIXX_INTENA(port)); mix_intena.u64 = cvmx_read_csr(p->mix + MIX_INTENA);
mix_intena.s.othena = enable ? 1 : 0; mix_intena.s.othena = enable ? 1 : 0;
cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64); cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
spin_unlock_irqrestore(&p->lock, flags); spin_unlock_irqrestore(&p->lock, flags);
} }
...@@ -146,7 +199,6 @@ static unsigned int ring_size_to_bytes(unsigned int ring_size) ...@@ -146,7 +199,6 @@ static unsigned int ring_size_to_bytes(unsigned int ring_size)
static void octeon_mgmt_rx_fill_ring(struct net_device *netdev) static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
{ {
struct octeon_mgmt *p = netdev_priv(netdev); struct octeon_mgmt *p = netdev_priv(netdev);
int port = p->port;
while (p->rx_current_fill < ring_max_fill(OCTEON_MGMT_RX_RING_SIZE)) { while (p->rx_current_fill < ring_max_fill(OCTEON_MGMT_RX_RING_SIZE)) {
unsigned int size; unsigned int size;
...@@ -177,24 +229,23 @@ static void octeon_mgmt_rx_fill_ring(struct net_device *netdev) ...@@ -177,24 +229,23 @@ static void octeon_mgmt_rx_fill_ring(struct net_device *netdev)
(p->rx_next_fill + 1) % OCTEON_MGMT_RX_RING_SIZE; (p->rx_next_fill + 1) % OCTEON_MGMT_RX_RING_SIZE;
p->rx_current_fill++; p->rx_current_fill++;
/* Ring the bell. */ /* Ring the bell. */
cvmx_write_csr(CVMX_MIXX_IRING2(port), 1); cvmx_write_csr(p->mix + MIX_IRING2, 1);
} }
} }
static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p) static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
{ {
int port = p->port;
union cvmx_mixx_orcnt mix_orcnt; union cvmx_mixx_orcnt mix_orcnt;
union mgmt_port_ring_entry re; union mgmt_port_ring_entry re;
struct sk_buff *skb; struct sk_buff *skb;
int cleaned = 0; int cleaned = 0;
unsigned long flags; unsigned long flags;
mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port)); mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
while (mix_orcnt.s.orcnt) { while (mix_orcnt.s.orcnt) {
spin_lock_irqsave(&p->tx_list.lock, flags); spin_lock_irqsave(&p->tx_list.lock, flags);
mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port)); mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
if (mix_orcnt.s.orcnt == 0) { if (mix_orcnt.s.orcnt == 0) {
spin_unlock_irqrestore(&p->tx_list.lock, flags); spin_unlock_irqrestore(&p->tx_list.lock, flags);
...@@ -214,7 +265,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p) ...@@ -214,7 +265,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
mix_orcnt.s.orcnt = 1; mix_orcnt.s.orcnt = 1;
/* Acknowledge to hardware that we have the buffer. */ /* Acknowledge to hardware that we have the buffer. */
cvmx_write_csr(CVMX_MIXX_ORCNT(port), mix_orcnt.u64); cvmx_write_csr(p->mix + MIX_ORCNT, mix_orcnt.u64);
p->tx_current_fill--; p->tx_current_fill--;
spin_unlock_irqrestore(&p->tx_list.lock, flags); spin_unlock_irqrestore(&p->tx_list.lock, flags);
...@@ -224,7 +275,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p) ...@@ -224,7 +275,7 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p)
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
cleaned++; cleaned++;
mix_orcnt.u64 = cvmx_read_csr(CVMX_MIXX_ORCNT(port)); mix_orcnt.u64 = cvmx_read_csr(p->mix + MIX_ORCNT);
} }
if (cleaned && netif_queue_stopped(p->netdev)) if (cleaned && netif_queue_stopped(p->netdev))
...@@ -241,13 +292,12 @@ static void octeon_mgmt_clean_tx_tasklet(unsigned long arg) ...@@ -241,13 +292,12 @@ static void octeon_mgmt_clean_tx_tasklet(unsigned long arg)
static void octeon_mgmt_update_rx_stats(struct net_device *netdev) static void octeon_mgmt_update_rx_stats(struct net_device *netdev)
{ {
struct octeon_mgmt *p = netdev_priv(netdev); struct octeon_mgmt *p = netdev_priv(netdev);
int port = p->port;
unsigned long flags; unsigned long flags;
u64 drop, bad; u64 drop, bad;
/* These reads also clear the count registers. */ /* These reads also clear the count registers. */
drop = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port)); drop = cvmx_read_csr(p->agl + AGL_GMX_RX_STATS_PKTS_DRP);
bad = cvmx_read_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port)); bad = cvmx_read_csr(p->agl + AGL_GMX_RX_STATS_PKTS_BAD);
if (drop || bad) { if (drop || bad) {
/* Do an atomic update. */ /* Do an atomic update. */
...@@ -261,15 +311,14 @@ static void octeon_mgmt_update_rx_stats(struct net_device *netdev) ...@@ -261,15 +311,14 @@ static void octeon_mgmt_update_rx_stats(struct net_device *netdev)
static void octeon_mgmt_update_tx_stats(struct net_device *netdev) static void octeon_mgmt_update_tx_stats(struct net_device *netdev)
{ {
struct octeon_mgmt *p = netdev_priv(netdev); struct octeon_mgmt *p = netdev_priv(netdev);
int port = p->port;
unsigned long flags; unsigned long flags;
union cvmx_agl_gmx_txx_stat0 s0; union cvmx_agl_gmx_txx_stat0 s0;
union cvmx_agl_gmx_txx_stat1 s1; union cvmx_agl_gmx_txx_stat1 s1;
/* These reads also clear the count registers. */ /* These reads also clear the count registers. */
s0.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT0(port)); s0.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_STAT0);
s1.u64 = cvmx_read_csr(CVMX_AGL_GMX_TXX_STAT1(port)); s1.u64 = cvmx_read_csr(p->agl + AGL_GMX_TX_STAT1);
if (s0.s.xsdef || s0.s.xscol || s1.s.scol || s1.s.mcol) { if (s0.s.xsdef || s0.s.xscol || s1.s.scol || s1.s.mcol) {
/* Do an atomic update. */ /* Do an atomic update. */
...@@ -308,7 +357,6 @@ static u64 octeon_mgmt_dequeue_rx_buffer(struct octeon_mgmt *p, ...@@ -308,7 +357,6 @@ static u64 octeon_mgmt_dequeue_rx_buffer(struct octeon_mgmt *p,
static int octeon_mgmt_receive_one(struct octeon_mgmt *p) static int octeon_mgmt_receive_one(struct octeon_mgmt *p)
{ {
int port = p->port;
struct net_device *netdev = p->netdev; struct net_device *netdev = p->netdev;
union cvmx_mixx_ircnt mix_ircnt; union cvmx_mixx_ircnt mix_ircnt;
union mgmt_port_ring_entry re; union mgmt_port_ring_entry re;
...@@ -381,18 +429,17 @@ static int octeon_mgmt_receive_one(struct octeon_mgmt *p) ...@@ -381,18 +429,17 @@ static int octeon_mgmt_receive_one(struct octeon_mgmt *p)
/* Tell the hardware we processed a packet. */ /* Tell the hardware we processed a packet. */
mix_ircnt.u64 = 0; mix_ircnt.u64 = 0;
mix_ircnt.s.ircnt = 1; mix_ircnt.s.ircnt = 1;
cvmx_write_csr(CVMX_MIXX_IRCNT(port), mix_ircnt.u64); cvmx_write_csr(p->mix + MIX_IRCNT, mix_ircnt.u64);
return rc; return rc;
} }
static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget) static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget)
{ {
int port = p->port;
unsigned int work_done = 0; unsigned int work_done = 0;
union cvmx_mixx_ircnt mix_ircnt; union cvmx_mixx_ircnt mix_ircnt;
int rc; int rc;
mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port)); mix_ircnt.u64 = cvmx_read_csr(p->mix + MIX_IRCNT);
while (work_done < budget && mix_ircnt.s.ircnt) { while (work_done < budget && mix_ircnt.s.ircnt) {
rc = octeon_mgmt_receive_one(p); rc = octeon_mgmt_receive_one(p);
...@@ -400,7 +447,7 @@ static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget) ...@@ -400,7 +447,7 @@ static int octeon_mgmt_receive_packets(struct octeon_mgmt *p, int budget)
work_done++; work_done++;
/* Check for more packets. */ /* Check for more packets. */
mix_ircnt.u64 = cvmx_read_csr(CVMX_MIXX_IRCNT(port)); mix_ircnt.u64 = cvmx_read_csr(p->mix + MIX_IRCNT);
} }
octeon_mgmt_rx_fill_ring(p->netdev); octeon_mgmt_rx_fill_ring(p->netdev);
...@@ -434,16 +481,16 @@ static void octeon_mgmt_reset_hw(struct octeon_mgmt *p) ...@@ -434,16 +481,16 @@ static void octeon_mgmt_reset_hw(struct octeon_mgmt *p)
union cvmx_agl_gmx_bist agl_gmx_bist; union cvmx_agl_gmx_bist agl_gmx_bist;
mix_ctl.u64 = 0; mix_ctl.u64 = 0;
cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64); cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
do { do {
mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(p->port)); mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
} while (mix_ctl.s.busy); } while (mix_ctl.s.busy);
mix_ctl.s.reset = 1; mix_ctl.s.reset = 1;
cvmx_write_csr(CVMX_MIXX_CTL(p->port), mix_ctl.u64); cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
cvmx_read_csr(CVMX_MIXX_CTL(p->port)); cvmx_read_csr(p->mix + MIX_CTL);
cvmx_wait(64); cvmx_wait(64);
mix_bist.u64 = cvmx_read_csr(CVMX_MIXX_BIST(p->port)); mix_bist.u64 = cvmx_read_csr(p->mix + MIX_BIST);
if (mix_bist.u64) if (mix_bist.u64)
dev_warn(p->dev, "MIX failed BIST (0x%016llx)\n", dev_warn(p->dev, "MIX failed BIST (0x%016llx)\n",
(unsigned long long)mix_bist.u64); (unsigned long long)mix_bist.u64);
...@@ -474,7 +521,6 @@ static void octeon_mgmt_cam_state_add(struct octeon_mgmt_cam_state *cs, ...@@ -474,7 +521,6 @@ static void octeon_mgmt_cam_state_add(struct octeon_mgmt_cam_state *cs,
static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
{ {
struct octeon_mgmt *p = netdev_priv(netdev); struct octeon_mgmt *p = netdev_priv(netdev);
int port = p->port;
union cvmx_agl_gmx_rxx_adr_ctl adr_ctl; union cvmx_agl_gmx_rxx_adr_ctl adr_ctl;
union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx; union cvmx_agl_gmx_prtx_cfg agl_gmx_prtx;
unsigned long flags; unsigned long flags;
...@@ -520,29 +566,29 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev) ...@@ -520,29 +566,29 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
spin_lock_irqsave(&p->lock, flags); spin_lock_irqsave(&p->lock, flags);
/* Disable packet I/O. */ /* Disable packet I/O. */
agl_gmx_prtx.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); agl_gmx_prtx.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prev_packet_enable = agl_gmx_prtx.s.en; prev_packet_enable = agl_gmx_prtx.s.en;
agl_gmx_prtx.s.en = 0; agl_gmx_prtx.s.en = 0;
cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64); cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64);
adr_ctl.u64 = 0; adr_ctl.u64 = 0;
adr_ctl.s.cam_mode = cam_mode; adr_ctl.s.cam_mode = cam_mode;
adr_ctl.s.mcst = multicast_mode; adr_ctl.s.mcst = multicast_mode;
adr_ctl.s.bcst = 1; /* Allow broadcast */ adr_ctl.s.bcst = 1; /* Allow broadcast */
cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CTL(port), adr_ctl.u64); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CTL, adr_ctl.u64);
cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM0(port), cam_state.cam[0]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM0, cam_state.cam[0]);
cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM1(port), cam_state.cam[1]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM1, cam_state.cam[1]);
cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM2(port), cam_state.cam[2]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM2, cam_state.cam[2]);
cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM3(port), cam_state.cam[3]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM3, cam_state.cam[3]);
cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM4(port), cam_state.cam[4]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM4, cam_state.cam[4]);
cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM5(port), cam_state.cam[5]); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM5, cam_state.cam[5]);
cvmx_write_csr(CVMX_AGL_GMX_RXX_ADR_CAM_EN(port), cam_state.cam_mask); cvmx_write_csr(p->agl + AGL_GMX_RX_ADR_CAM_EN, cam_state.cam_mask);
/* Restore packet I/O. */ /* Restore packet I/O. */
agl_gmx_prtx.s.en = prev_packet_enable; agl_gmx_prtx.s.en = prev_packet_enable;
cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), agl_gmx_prtx.u64); cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, agl_gmx_prtx.u64);
spin_unlock_irqrestore(&p->lock, flags); spin_unlock_irqrestore(&p->lock, flags);
} }
...@@ -564,7 +610,6 @@ static int octeon_mgmt_set_mac_address(struct net_device *netdev, void *addr) ...@@ -564,7 +610,6 @@ static int octeon_mgmt_set_mac_address(struct net_device *netdev, void *addr)
static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu) static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
{ {
struct octeon_mgmt *p = netdev_priv(netdev); struct octeon_mgmt *p = netdev_priv(netdev);
int port = p->port;
int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM; int size_without_fcs = new_mtu + OCTEON_MGMT_RX_HEADROOM;
/* /*
...@@ -580,8 +625,8 @@ static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -580,8 +625,8 @@ static int octeon_mgmt_change_mtu(struct net_device *netdev, int new_mtu)
netdev->mtu = new_mtu; netdev->mtu = new_mtu;
cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_MAX(port), size_without_fcs); cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_MAX, size_without_fcs);
cvmx_write_csr(CVMX_AGL_GMX_RXX_JABBER(port), cvmx_write_csr(p->agl + AGL_GMX_RX_JABBER,
(size_without_fcs + 7) & 0xfff8); (size_without_fcs + 7) & 0xfff8);
return 0; return 0;
...@@ -591,14 +636,13 @@ static irqreturn_t octeon_mgmt_interrupt(int cpl, void *dev_id) ...@@ -591,14 +636,13 @@ static irqreturn_t octeon_mgmt_interrupt(int cpl, void *dev_id)
{ {
struct net_device *netdev = dev_id; struct net_device *netdev = dev_id;
struct octeon_mgmt *p = netdev_priv(netdev); struct octeon_mgmt *p = netdev_priv(netdev);
int port = p->port;
union cvmx_mixx_isr mixx_isr; union cvmx_mixx_isr mixx_isr;
mixx_isr.u64 = cvmx_read_csr(CVMX_MIXX_ISR(port)); mixx_isr.u64 = cvmx_read_csr(p->mix + MIX_ISR);
/* Clear any pending interrupts */ /* Clear any pending interrupts */
cvmx_write_csr(CVMX_MIXX_ISR(port), mixx_isr.u64); cvmx_write_csr(p->mix + MIX_ISR, mixx_isr.u64);
cvmx_read_csr(CVMX_MIXX_ISR(port)); cvmx_read_csr(p->mix + MIX_ISR);
if (mixx_isr.s.irthresh) { if (mixx_isr.s.irthresh) {
octeon_mgmt_disable_rx_irq(p); octeon_mgmt_disable_rx_irq(p);
...@@ -629,7 +673,6 @@ static int octeon_mgmt_ioctl(struct net_device *netdev, ...@@ -629,7 +673,6 @@ static int octeon_mgmt_ioctl(struct net_device *netdev,
static void octeon_mgmt_adjust_link(struct net_device *netdev) static void octeon_mgmt_adjust_link(struct net_device *netdev)
{ {
struct octeon_mgmt *p = netdev_priv(netdev); struct octeon_mgmt *p = netdev_priv(netdev);
int port = p->port;
union cvmx_agl_gmx_prtx_cfg prtx_cfg; union cvmx_agl_gmx_prtx_cfg prtx_cfg;
unsigned long flags; unsigned long flags;
int link_changed = 0; int link_changed = 0;
...@@ -640,11 +683,9 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev) ...@@ -640,11 +683,9 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev)
link_changed = 1; link_changed = 1;
if (p->last_duplex != p->phydev->duplex) { if (p->last_duplex != p->phydev->duplex) {
p->last_duplex = p->phydev->duplex; p->last_duplex = p->phydev->duplex;
prtx_cfg.u64 = prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port));
prtx_cfg.s.duplex = p->phydev->duplex; prtx_cfg.s.duplex = p->phydev->duplex;
cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
prtx_cfg.u64);
} }
} else { } else {
if (p->last_link) if (p->last_link)
...@@ -670,18 +711,16 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev) ...@@ -670,18 +711,16 @@ static void octeon_mgmt_adjust_link(struct net_device *netdev)
static int octeon_mgmt_init_phy(struct net_device *netdev) static int octeon_mgmt_init_phy(struct net_device *netdev)
{ {
struct octeon_mgmt *p = netdev_priv(netdev); struct octeon_mgmt *p = netdev_priv(netdev);
char phy_id[MII_BUS_ID_SIZE + 3];
if (octeon_is_simulation()) { if (octeon_is_simulation() || p->phy_np == NULL) {
/* No PHYs in the simulator. */ /* No PHYs in the simulator. */
netif_carrier_on(netdev); netif_carrier_on(netdev);
return 0; return 0;
} }
snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", p->port); p->phydev = of_phy_connect(netdev, p->phy_np,
octeon_mgmt_adjust_link, 0,
p->phydev = phy_connect(netdev, phy_id, octeon_mgmt_adjust_link, 0, PHY_INTERFACE_MODE_MII);
PHY_INTERFACE_MODE_MII);
if (IS_ERR(p->phydev)) { if (IS_ERR(p->phydev)) {
p->phydev = NULL; p->phydev = NULL;
...@@ -737,14 +776,14 @@ static int octeon_mgmt_open(struct net_device *netdev) ...@@ -737,14 +776,14 @@ static int octeon_mgmt_open(struct net_device *netdev)
octeon_mgmt_reset_hw(p); octeon_mgmt_reset_hw(p);
mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port)); mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
/* Bring it out of reset if needed. */ /* Bring it out of reset if needed. */
if (mix_ctl.s.reset) { if (mix_ctl.s.reset) {
mix_ctl.s.reset = 0; mix_ctl.s.reset = 0;
cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
do { do {
mix_ctl.u64 = cvmx_read_csr(CVMX_MIXX_CTL(port)); mix_ctl.u64 = cvmx_read_csr(p->mix + MIX_CTL);
} while (mix_ctl.s.reset); } while (mix_ctl.s.reset);
} }
...@@ -755,17 +794,17 @@ static int octeon_mgmt_open(struct net_device *netdev) ...@@ -755,17 +794,17 @@ static int octeon_mgmt_open(struct net_device *netdev)
oring1.u64 = 0; oring1.u64 = 0;
oring1.s.obase = p->tx_ring_handle >> 3; oring1.s.obase = p->tx_ring_handle >> 3;
oring1.s.osize = OCTEON_MGMT_TX_RING_SIZE; oring1.s.osize = OCTEON_MGMT_TX_RING_SIZE;
cvmx_write_csr(CVMX_MIXX_ORING1(port), oring1.u64); cvmx_write_csr(p->mix + MIX_ORING1, oring1.u64);
iring1.u64 = 0; iring1.u64 = 0;
iring1.s.ibase = p->rx_ring_handle >> 3; iring1.s.ibase = p->rx_ring_handle >> 3;
iring1.s.isize = OCTEON_MGMT_RX_RING_SIZE; iring1.s.isize = OCTEON_MGMT_RX_RING_SIZE;
cvmx_write_csr(CVMX_MIXX_IRING1(port), iring1.u64); cvmx_write_csr(p->mix + MIX_IRING1, iring1.u64);
/* Disable packet I/O. */ /* Disable packet I/O. */
prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.en = 0; prtx_cfg.s.en = 0;
cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64); cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
memcpy(sa.sa_data, netdev->dev_addr, ETH_ALEN); memcpy(sa.sa_data, netdev->dev_addr, ETH_ALEN);
octeon_mgmt_set_mac_address(netdev, &sa); octeon_mgmt_set_mac_address(netdev, &sa);
...@@ -782,7 +821,7 @@ static int octeon_mgmt_open(struct net_device *netdev) ...@@ -782,7 +821,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
mix_ctl.s.nbtarb = 0; /* Arbitration mode */ mix_ctl.s.nbtarb = 0; /* Arbitration mode */
/* MII CB-request FIFO programmable high watermark */ /* MII CB-request FIFO programmable high watermark */
mix_ctl.s.mrq_hwm = 1; mix_ctl.s.mrq_hwm = 1;
cvmx_write_csr(CVMX_MIXX_CTL(port), mix_ctl.u64); cvmx_write_csr(p->mix + MIX_CTL, mix_ctl.u64);
if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)
|| OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) { || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) {
...@@ -809,16 +848,16 @@ static int octeon_mgmt_open(struct net_device *netdev) ...@@ -809,16 +848,16 @@ static int octeon_mgmt_open(struct net_device *netdev)
/* Clear statistics. */ /* Clear statistics. */
/* Clear on read. */ /* Clear on read. */
cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_CTL(port), 1); cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_CTL, 1);
cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_DRP(port), 0); cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_PKTS_DRP, 0);
cvmx_write_csr(CVMX_AGL_GMX_RXX_STATS_PKTS_BAD(port), 0); cvmx_write_csr(p->agl + AGL_GMX_RX_STATS_PKTS_BAD, 0);
cvmx_write_csr(CVMX_AGL_GMX_TXX_STATS_CTL(port), 1); cvmx_write_csr(p->agl + AGL_GMX_TX_STATS_CTL, 1);
cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT0(port), 0); cvmx_write_csr(p->agl + AGL_GMX_TX_STAT0, 0);
cvmx_write_csr(CVMX_AGL_GMX_TXX_STAT1(port), 0); cvmx_write_csr(p->agl + AGL_GMX_TX_STAT1, 0);
/* Clear any pending interrupts */ /* Clear any pending interrupts */
cvmx_write_csr(CVMX_MIXX_ISR(port), cvmx_read_csr(CVMX_MIXX_ISR(port))); cvmx_write_csr(p->mix + MIX_ISR, cvmx_read_csr(p->mix + MIX_ISR));
if (request_irq(p->irq, octeon_mgmt_interrupt, 0, netdev->name, if (request_irq(p->irq, octeon_mgmt_interrupt, 0, netdev->name,
netdev)) { netdev)) {
...@@ -829,18 +868,18 @@ static int octeon_mgmt_open(struct net_device *netdev) ...@@ -829,18 +868,18 @@ static int octeon_mgmt_open(struct net_device *netdev)
/* Interrupt every single RX packet */ /* Interrupt every single RX packet */
mix_irhwm.u64 = 0; mix_irhwm.u64 = 0;
mix_irhwm.s.irhwm = 0; mix_irhwm.s.irhwm = 0;
cvmx_write_csr(CVMX_MIXX_IRHWM(port), mix_irhwm.u64); cvmx_write_csr(p->mix + MIX_IRHWM, mix_irhwm.u64);
/* Interrupt when we have 1 or more packets to clean. */ /* Interrupt when we have 1 or more packets to clean. */
mix_orhwm.u64 = 0; mix_orhwm.u64 = 0;
mix_orhwm.s.orhwm = 1; mix_orhwm.s.orhwm = 1;
cvmx_write_csr(CVMX_MIXX_ORHWM(port), mix_orhwm.u64); cvmx_write_csr(p->mix + MIX_ORHWM, mix_orhwm.u64);
/* Enable receive and transmit interrupts */ /* Enable receive and transmit interrupts */
mix_intena.u64 = 0; mix_intena.u64 = 0;
mix_intena.s.ithena = 1; mix_intena.s.ithena = 1;
mix_intena.s.othena = 1; mix_intena.s.othena = 1;
cvmx_write_csr(CVMX_MIXX_INTENA(port), mix_intena.u64); cvmx_write_csr(p->mix + MIX_INTENA, mix_intena.u64);
/* Enable packet I/O. */ /* Enable packet I/O. */
...@@ -871,7 +910,7 @@ static int octeon_mgmt_open(struct net_device *netdev) ...@@ -871,7 +910,7 @@ static int octeon_mgmt_open(struct net_device *netdev)
* frame. GMX checks that the PREAMBLE is sent correctly. * frame. GMX checks that the PREAMBLE is sent correctly.
*/ */
rxx_frm_ctl.s.pre_chk = 1; rxx_frm_ctl.s.pre_chk = 1;
cvmx_write_csr(CVMX_AGL_GMX_RXX_FRM_CTL(port), rxx_frm_ctl.u64); cvmx_write_csr(p->agl + AGL_GMX_RX_FRM_CTL, rxx_frm_ctl.u64);
/* Enable the AGL block */ /* Enable the AGL block */
agl_gmx_inf_mode.u64 = 0; agl_gmx_inf_mode.u64 = 0;
...@@ -879,13 +918,13 @@ static int octeon_mgmt_open(struct net_device *netdev) ...@@ -879,13 +918,13 @@ static int octeon_mgmt_open(struct net_device *netdev)
cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64); cvmx_write_csr(CVMX_AGL_GMX_INF_MODE, agl_gmx_inf_mode.u64);
/* Configure the port duplex and enables */ /* Configure the port duplex and enables */
prtx_cfg.u64 = cvmx_read_csr(CVMX_AGL_GMX_PRTX_CFG(port)); prtx_cfg.u64 = cvmx_read_csr(p->agl + AGL_GMX_PRT_CFG);
prtx_cfg.s.tx_en = 1; prtx_cfg.s.tx_en = 1;
prtx_cfg.s.rx_en = 1; prtx_cfg.s.rx_en = 1;
prtx_cfg.s.en = 1; prtx_cfg.s.en = 1;
p->last_duplex = 1; p->last_duplex = 1;
prtx_cfg.s.duplex = p->last_duplex; prtx_cfg.s.duplex = p->last_duplex;
cvmx_write_csr(CVMX_AGL_GMX_PRTX_CFG(port), prtx_cfg.u64); cvmx_write_csr(p->agl + AGL_GMX_PRT_CFG, prtx_cfg.u64);
p->last_link = 0; p->last_link = 0;
netif_carrier_off(netdev); netif_carrier_off(netdev);
...@@ -949,7 +988,6 @@ static int octeon_mgmt_stop(struct net_device *netdev) ...@@ -949,7 +988,6 @@ static int octeon_mgmt_stop(struct net_device *netdev)
static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev) static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
{ {
struct octeon_mgmt *p = netdev_priv(netdev); struct octeon_mgmt *p = netdev_priv(netdev);
int port = p->port;
union mgmt_port_ring_entry re; union mgmt_port_ring_entry re;
unsigned long flags; unsigned long flags;
int rv = NETDEV_TX_BUSY; int rv = NETDEV_TX_BUSY;
...@@ -993,7 +1031,7 @@ static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev) ...@@ -993,7 +1031,7 @@ static int octeon_mgmt_xmit(struct sk_buff *skb, struct net_device *netdev)
netdev->stats.tx_bytes += skb->len; netdev->stats.tx_bytes += skb->len;
/* Ring the bell. */ /* Ring the bell. */
cvmx_write_csr(CVMX_MIXX_ORING2(port), 1); cvmx_write_csr(p->mix + MIX_ORING2, 1);
rv = NETDEV_TX_OK; rv = NETDEV_TX_OK;
out: out:
...@@ -1071,10 +1109,14 @@ static const struct net_device_ops octeon_mgmt_ops = { ...@@ -1071,10 +1109,14 @@ static const struct net_device_ops octeon_mgmt_ops = {
static int __devinit octeon_mgmt_probe(struct platform_device *pdev) static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
{ {
struct resource *res_irq;
struct net_device *netdev; struct net_device *netdev;
struct octeon_mgmt *p; struct octeon_mgmt *p;
int i; const __be32 *data;
const u8 *mac;
struct resource *res_mix;
struct resource *res_agl;
int len;
int result;
netdev = alloc_etherdev(sizeof(struct octeon_mgmt)); netdev = alloc_etherdev(sizeof(struct octeon_mgmt));
if (netdev == NULL) if (netdev == NULL)
...@@ -1088,14 +1130,63 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev) ...@@ -1088,14 +1130,63 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
p->netdev = netdev; p->netdev = netdev;
p->dev = &pdev->dev; p->dev = &pdev->dev;
p->port = pdev->id; data = of_get_property(pdev->dev.of_node, "cell-index", &len);
if (data && len == sizeof(*data)) {
p->port = be32_to_cpup(data);
} else {
dev_err(&pdev->dev, "no 'cell-index' property\n");
result = -ENXIO;
goto err;
}
snprintf(netdev->name, IFNAMSIZ, "mgmt%d", p->port); snprintf(netdev->name, IFNAMSIZ, "mgmt%d", p->port);
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); result = platform_get_irq(pdev, 0);
if (!res_irq) if (result < 0)
goto err;
p->irq = result;
res_mix = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res_mix == NULL) {
dev_err(&pdev->dev, "no 'reg' resource\n");
result = -ENXIO;
goto err;
}
res_agl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
if (res_agl == NULL) {
dev_err(&pdev->dev, "no 'reg' resource\n");
result = -ENXIO;
goto err;
}
p->mix_phys = res_mix->start;
p->mix_size = resource_size(res_mix);
p->agl_phys = res_agl->start;
p->agl_size = resource_size(res_agl);
if (!devm_request_mem_region(&pdev->dev, p->mix_phys, p->mix_size,
res_mix->name)) {
dev_err(&pdev->dev, "request_mem_region (%s) failed\n",
res_mix->name);
result = -ENXIO;
goto err;
}
if (!devm_request_mem_region(&pdev->dev, p->agl_phys, p->agl_size,
res_agl->name)) {
result = -ENXIO;
dev_err(&pdev->dev, "request_mem_region (%s) failed\n",
res_agl->name);
goto err; goto err;
}
p->mix = (u64)devm_ioremap(&pdev->dev, p->mix_phys, p->mix_size);
p->agl = (u64)devm_ioremap(&pdev->dev, p->agl_phys, p->agl_size);
p->irq = res_irq->start;
spin_lock_init(&p->lock); spin_lock_init(&p->lock);
skb_queue_head_init(&p->tx_list); skb_queue_head_init(&p->tx_list);
...@@ -1108,24 +1199,26 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev) ...@@ -1108,24 +1199,26 @@ static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
netdev->netdev_ops = &octeon_mgmt_ops; netdev->netdev_ops = &octeon_mgmt_ops;
netdev->ethtool_ops = &octeon_mgmt_ethtool_ops; netdev->ethtool_ops = &octeon_mgmt_ethtool_ops;
/* The mgmt ports get the first N MACs. */ mac = of_get_mac_address(pdev->dev.of_node);
for (i = 0; i < 6; i++)
netdev->dev_addr[i] = octeon_bootinfo->mac_addr_base[i]; if (mac)
netdev->dev_addr[5] += p->port; memcpy(netdev->dev_addr, mac, 6);
if (p->port >= octeon_bootinfo->mac_addr_count) p->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
dev_err(&pdev->dev,
"Error %s: Using MAC outside of the assigned range: %pM\n",
netdev->name, netdev->dev_addr);
if (register_netdev(netdev)) pdev->dev.coherent_dma_mask = DMA_BIT_MASK(64);
pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
result = register_netdev(netdev);
if (result)
goto err; goto err;
dev_info(&pdev->dev, "Version " DRV_VERSION "\n"); dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
return 0; return 0;
err: err:
free_netdev(netdev); free_netdev(netdev);
return -ENOENT; return result;
} }
static int __devexit octeon_mgmt_remove(struct platform_device *pdev) static int __devexit octeon_mgmt_remove(struct platform_device *pdev)
...@@ -1137,10 +1230,19 @@ static int __devexit octeon_mgmt_remove(struct platform_device *pdev) ...@@ -1137,10 +1230,19 @@ static int __devexit octeon_mgmt_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct of_device_id octeon_mgmt_match[] = {
{
.compatible = "cavium,octeon-5750-mix",
},
{},
};
MODULE_DEVICE_TABLE(of, octeon_mgmt_match);
static struct platform_driver octeon_mgmt_driver = { static struct platform_driver octeon_mgmt_driver = {
.driver = { .driver = {
.name = "octeon_mgmt", .name = "octeon_mgmt",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = octeon_mgmt_match,
}, },
.probe = octeon_mgmt_probe, .probe = octeon_mgmt_probe,
.remove = __devexit_p(octeon_mgmt_remove), .remove = __devexit_p(octeon_mgmt_remove),
......
...@@ -3,14 +3,17 @@ ...@@ -3,14 +3,17 @@
* License. See the file "COPYING" in the main directory of this archive * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
* *
* Copyright (C) 2009 Cavium Networks * Copyright (C) 2009,2011 Cavium, Inc.
*/ */
#include <linux/gfp.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of_mdio.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/gfp.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/io.h>
#include <asm/octeon/octeon.h> #include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-smix-defs.h> #include <asm/octeon/cvmx-smix-defs.h>
...@@ -18,9 +21,17 @@ ...@@ -18,9 +21,17 @@
#define DRV_VERSION "1.0" #define DRV_VERSION "1.0"
#define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver" #define DRV_DESCRIPTION "Cavium Networks Octeon SMI/MDIO driver"
#define SMI_CMD 0x0
#define SMI_WR_DAT 0x8
#define SMI_RD_DAT 0x10
#define SMI_CLK 0x18
#define SMI_EN 0x20
struct octeon_mdiobus { struct octeon_mdiobus {
struct mii_bus *mii_bus; struct mii_bus *mii_bus;
int unit; u64 register_base;
resource_size_t mdio_phys;
resource_size_t regsize;
int phy_irq[PHY_MAX_ADDR]; int phy_irq[PHY_MAX_ADDR];
}; };
...@@ -35,15 +46,15 @@ static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum) ...@@ -35,15 +46,15 @@ static int octeon_mdiobus_read(struct mii_bus *bus, int phy_id, int regnum)
smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */ smi_cmd.s.phy_op = 1; /* MDIO_CLAUSE_22_READ */
smi_cmd.s.phy_adr = phy_id; smi_cmd.s.phy_adr = phy_id;
smi_cmd.s.reg_adr = regnum; smi_cmd.s.reg_adr = regnum;
cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64); cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64);
do { do {
/* /*
* Wait 1000 clocks so we don't saturate the RSL bus * Wait 1000 clocks so we don't saturate the RSL bus
* doing reads. * doing reads.
*/ */
cvmx_wait(1000); __delay(1000);
smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(p->unit)); smi_rd.u64 = cvmx_read_csr(p->register_base + SMI_RD_DAT);
} while (smi_rd.s.pending && --timeout); } while (smi_rd.s.pending && --timeout);
if (smi_rd.s.val) if (smi_rd.s.val)
...@@ -62,21 +73,21 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id, ...@@ -62,21 +73,21 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
smi_wr.u64 = 0; smi_wr.u64 = 0;
smi_wr.s.dat = val; smi_wr.s.dat = val;
cvmx_write_csr(CVMX_SMIX_WR_DAT(p->unit), smi_wr.u64); cvmx_write_csr(p->register_base + SMI_WR_DAT, smi_wr.u64);
smi_cmd.u64 = 0; smi_cmd.u64 = 0;
smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */ smi_cmd.s.phy_op = 0; /* MDIO_CLAUSE_22_WRITE */
smi_cmd.s.phy_adr = phy_id; smi_cmd.s.phy_adr = phy_id;
smi_cmd.s.reg_adr = regnum; smi_cmd.s.reg_adr = regnum;
cvmx_write_csr(CVMX_SMIX_CMD(p->unit), smi_cmd.u64); cvmx_write_csr(p->register_base + SMI_CMD, smi_cmd.u64);
do { do {
/* /*
* Wait 1000 clocks so we don't saturate the RSL bus * Wait 1000 clocks so we don't saturate the RSL bus
* doing reads. * doing reads.
*/ */
cvmx_wait(1000); __delay(1000);
smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(p->unit)); smi_wr.u64 = cvmx_read_csr(p->register_base + SMI_WR_DAT);
} while (smi_wr.s.pending && --timeout); } while (smi_wr.s.pending && --timeout);
if (timeout <= 0) if (timeout <= 0)
...@@ -88,38 +99,44 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id, ...@@ -88,38 +99,44 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
static int __devinit octeon_mdiobus_probe(struct platform_device *pdev) static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
{ {
struct octeon_mdiobus *bus; struct octeon_mdiobus *bus;
struct resource *res_mem;
union cvmx_smix_en smi_en; union cvmx_smix_en smi_en;
int i;
int err = -ENOENT; int err = -ENOENT;
bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL); bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
if (!bus) if (!bus)
return -ENOMEM; return -ENOMEM;
/* The platform_device id is our unit number. */ res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bus->unit = pdev->id;
if (res_mem == NULL) {
dev_err(&pdev->dev, "found no memory resource\n");
err = -ENXIO;
goto fail;
}
bus->mdio_phys = res_mem->start;
bus->regsize = resource_size(res_mem);
if (!devm_request_mem_region(&pdev->dev, bus->mdio_phys, bus->regsize,
res_mem->name)) {
dev_err(&pdev->dev, "request_mem_region failed\n");
goto fail;
}
bus->register_base =
(u64)devm_ioremap(&pdev->dev, bus->mdio_phys, bus->regsize);
bus->mii_bus = mdiobus_alloc(); bus->mii_bus = mdiobus_alloc();
if (!bus->mii_bus) if (!bus->mii_bus)
goto err; goto fail;
smi_en.u64 = 0; smi_en.u64 = 0;
smi_en.s.en = 1; smi_en.s.en = 1;
cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
/*
* Standard Octeon evaluation boards don't support phy
* interrupts, we need to poll.
*/
for (i = 0; i < PHY_MAX_ADDR; i++)
bus->phy_irq[i] = PHY_POLL;
bus->mii_bus->priv = bus; bus->mii_bus->priv = bus;
bus->mii_bus->irq = bus->phy_irq; bus->mii_bus->irq = bus->phy_irq;
bus->mii_bus->name = "mdio-octeon"; bus->mii_bus->name = "mdio-octeon";
snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%llx", bus->register_base);
bus->mii_bus->name, bus->unit);
bus->mii_bus->parent = &pdev->dev; bus->mii_bus->parent = &pdev->dev;
bus->mii_bus->read = octeon_mdiobus_read; bus->mii_bus->read = octeon_mdiobus_read;
...@@ -127,20 +144,18 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev) ...@@ -127,20 +144,18 @@ static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, bus); dev_set_drvdata(&pdev->dev, bus);
err = mdiobus_register(bus->mii_bus); err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
if (err) if (err)
goto err_register; goto fail_register;
dev_info(&pdev->dev, "Version " DRV_VERSION "\n"); dev_info(&pdev->dev, "Version " DRV_VERSION "\n");
return 0; return 0;
err_register: fail_register:
mdiobus_free(bus->mii_bus); mdiobus_free(bus->mii_bus);
fail:
err:
devm_kfree(&pdev->dev, bus);
smi_en.u64 = 0; smi_en.u64 = 0;
cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
return err; return err;
} }
...@@ -154,14 +169,23 @@ static int __devexit octeon_mdiobus_remove(struct platform_device *pdev) ...@@ -154,14 +169,23 @@ static int __devexit octeon_mdiobus_remove(struct platform_device *pdev)
mdiobus_unregister(bus->mii_bus); mdiobus_unregister(bus->mii_bus);
mdiobus_free(bus->mii_bus); mdiobus_free(bus->mii_bus);
smi_en.u64 = 0; smi_en.u64 = 0;
cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64); cvmx_write_csr(bus->register_base + SMI_EN, smi_en.u64);
return 0; return 0;
} }
static struct of_device_id octeon_mdiobus_match[] = {
{
.compatible = "cavium,octeon-3860-mdio",
},
{},
};
MODULE_DEVICE_TABLE(of, octeon_mdiobus_match);
static struct platform_driver octeon_mdiobus_driver = { static struct platform_driver octeon_mdiobus_driver = {
.driver = { .driver = {
.name = "mdio-octeon", .name = "mdio-octeon",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = octeon_mdiobus_match,
}, },
.probe = octeon_mdiobus_probe, .probe = octeon_mdiobus_probe,
.remove = __devexit_p(octeon_mdiobus_remove), .remove = __devexit_p(octeon_mdiobus_remove),
......
...@@ -144,6 +144,15 @@ config SPI_EP93XX ...@@ -144,6 +144,15 @@ config SPI_EP93XX
This enables using the Cirrus EP93xx SPI controller in master This enables using the Cirrus EP93xx SPI controller in master
mode. mode.
config SPI_FALCON
tristate "Falcon SPI controller support"
depends on SOC_FALCON
help
The external bus unit (EBU) found on the FALC-ON SoC has SPI
emulation that is designed for serial flash access. This driver
has only been tested with m25p80 type chips. The hardware has no
support for other types of SPI peripherals.
config SPI_GPIO config SPI_GPIO
tristate "GPIO-based bitbanging SPI Master" tristate "GPIO-based bitbanging SPI Master"
depends on GENERIC_GPIO depends on GENERIC_GPIO
......
...@@ -26,6 +26,7 @@ obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o ...@@ -26,6 +26,7 @@ obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o
obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
obj-$(CONFIG_SPI_FALCON) += spi-falcon.o
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
......
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*
* Copyright (C) 2012 Thomas Langer <thomas.langer@lantiq.com>
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <lantiq_soc.h>
#define DRV_NAME "sflash-falcon"
#define FALCON_SPI_XFER_BEGIN (1 << 0)
#define FALCON_SPI_XFER_END (1 << 1)
/* Bus Read Configuration Register0 */
#define BUSRCON0 0x00000010
/* Bus Write Configuration Register0 */
#define BUSWCON0 0x00000018
/* Serial Flash Configuration Register */
#define SFCON 0x00000080
/* Serial Flash Time Register */
#define SFTIME 0x00000084
/* Serial Flash Status Register */
#define SFSTAT 0x00000088
/* Serial Flash Command Register */
#define SFCMD 0x0000008C
/* Serial Flash Address Register */
#define SFADDR 0x00000090
/* Serial Flash Data Register */
#define SFDATA 0x00000094
/* Serial Flash I/O Control Register */
#define SFIO 0x00000098
/* EBU Clock Control Register */
#define EBUCC 0x000000C4
/* Dummy Phase Length */
#define SFCMD_DUMLEN_OFFSET 16
#define SFCMD_DUMLEN_MASK 0x000F0000
/* Chip Select */
#define SFCMD_CS_OFFSET 24
#define SFCMD_CS_MASK 0x07000000
/* field offset */
#define SFCMD_ALEN_OFFSET 20
#define SFCMD_ALEN_MASK 0x00700000
/* SCK Rise-edge Position */
#define SFTIME_SCKR_POS_OFFSET 8
#define SFTIME_SCKR_POS_MASK 0x00000F00
/* SCK Period */
#define SFTIME_SCK_PER_OFFSET 0
#define SFTIME_SCK_PER_MASK 0x0000000F
/* SCK Fall-edge Position */
#define SFTIME_SCKF_POS_OFFSET 12
#define SFTIME_SCKF_POS_MASK 0x0000F000
/* Device Size */
#define SFCON_DEV_SIZE_A23_0 0x03000000
#define SFCON_DEV_SIZE_MASK 0x0F000000
/* Read Data Position */
#define SFTIME_RD_POS_MASK 0x000F0000
/* Data Output */
#define SFIO_UNUSED_WD_MASK 0x0000000F
/* Command Opcode mask */
#define SFCMD_OPC_MASK 0x000000FF
/* dlen bytes of data to write */
#define SFCMD_DIR_WRITE 0x00000100
/* Data Length offset */
#define SFCMD_DLEN_OFFSET 9
/* Command Error */
#define SFSTAT_CMD_ERR 0x20000000
/* Access Command Pending */
#define SFSTAT_CMD_PEND 0x00400000
/* Frequency set to 100MHz. */
#define EBUCC_EBUDIV_SELF100 0x00000001
/* Serial Flash */
#define BUSRCON0_AGEN_SERIAL_FLASH 0xF0000000
/* 8-bit multiplexed */
#define BUSRCON0_PORTW_8_BIT_MUX 0x00000000
/* Serial Flash */
#define BUSWCON0_AGEN_SERIAL_FLASH 0xF0000000
/* Chip Select after opcode */
#define SFCMD_KEEP_CS_KEEP_SELECTED 0x00008000
#define CLOCK_100M 100000000
#define CLOCK_50M 50000000
struct falcon_sflash {
u32 sfcmd; /* for caching of opcode, direction, ... */
struct spi_master *master;
};
int falcon_sflash_xfer(struct spi_device *spi, struct spi_transfer *t,
unsigned long flags)
{
struct device *dev = &spi->dev;
struct falcon_sflash *priv = spi_master_get_devdata(spi->master);
const u8 *txp = t->tx_buf;
u8 *rxp = t->rx_buf;
unsigned int bytelen = ((8 * t->len + 7) / 8);
unsigned int len, alen, dumlen;
u32 val;
enum {
state_init,
state_command_prepare,
state_write,
state_read,
state_disable_cs,
state_end
} state = state_init;
do {
switch (state) {
case state_init: /* detect phase of upper layer sequence */
{
/* initial write ? */
if (flags & FALCON_SPI_XFER_BEGIN) {
if (!txp) {
dev_err(dev,
"BEGIN without tx data!\n");
return -ENODATA;
}
/*
* Prepare the parts of the sfcmd register,
* which should not change during a sequence!
* Only exception are the length fields,
* especially alen and dumlen.
*/
priv->sfcmd = ((spi->chip_select
<< SFCMD_CS_OFFSET)
& SFCMD_CS_MASK);
priv->sfcmd |= SFCMD_KEEP_CS_KEEP_SELECTED;
priv->sfcmd |= *txp;
txp++;
bytelen--;
if (bytelen) {
/*
* more data:
* maybe address and/or dummy
*/
state = state_command_prepare;
break;
} else {
dev_dbg(dev, "write cmd %02X\n",
priv->sfcmd & SFCMD_OPC_MASK);
}
}
/* continued write ? */
if (txp && bytelen) {
state = state_write;
break;
}
/* read data? */
if (rxp && bytelen) {
state = state_read;
break;
}
/* end of sequence? */
if (flags & FALCON_SPI_XFER_END)
state = state_disable_cs;
else
state = state_end;
break;
}
/* collect tx data for address and dummy phase */
case state_command_prepare:
{
/* txp is valid, already checked */
val = 0;
alen = 0;
dumlen = 0;
while (bytelen > 0) {
if (alen < 3) {
val = (val << 8) | (*txp++);
alen++;
} else if ((dumlen < 15) && (*txp == 0)) {
/*
* assume dummy bytes are set to 0
* from upper layer
*/
dumlen++;
txp++;
} else {
break;
}
bytelen--;
}
priv->sfcmd &= ~(SFCMD_ALEN_MASK | SFCMD_DUMLEN_MASK);
priv->sfcmd |= (alen << SFCMD_ALEN_OFFSET) |
(dumlen << SFCMD_DUMLEN_OFFSET);
if (alen > 0)
ltq_ebu_w32(val, SFADDR);
dev_dbg(dev, "wr %02X, alen=%d (addr=%06X) dlen=%d\n",
priv->sfcmd & SFCMD_OPC_MASK,
alen, val, dumlen);
if (bytelen > 0) {
/* continue with write */
state = state_write;
} else if (flags & FALCON_SPI_XFER_END) {
/* end of sequence? */
state = state_disable_cs;
} else {
/*
* go to end and expect another
* call (read or write)
*/
state = state_end;
}
break;
}
case state_write:
{
/* txp still valid */
priv->sfcmd |= SFCMD_DIR_WRITE;
len = 0;
val = 0;
do {
if (bytelen--)
val |= (*txp++) << (8 * len++);
if ((flags & FALCON_SPI_XFER_END)
&& (bytelen == 0)) {
priv->sfcmd &=
~SFCMD_KEEP_CS_KEEP_SELECTED;
}
if ((len == 4) || (bytelen == 0)) {
ltq_ebu_w32(val, SFDATA);
ltq_ebu_w32(priv->sfcmd
| (len<<SFCMD_DLEN_OFFSET),
SFCMD);
len = 0;
val = 0;
priv->sfcmd &= ~(SFCMD_ALEN_MASK
| SFCMD_DUMLEN_MASK);
}
} while (bytelen);
state = state_end;
break;
}
case state_read:
{
/* read data */
priv->sfcmd &= ~SFCMD_DIR_WRITE;
do {
if ((flags & FALCON_SPI_XFER_END)
&& (bytelen <= 4)) {
priv->sfcmd &=
~SFCMD_KEEP_CS_KEEP_SELECTED;
}
len = (bytelen > 4) ? 4 : bytelen;
bytelen -= len;
ltq_ebu_w32(priv->sfcmd
| (len << SFCMD_DLEN_OFFSET), SFCMD);
priv->sfcmd &= ~(SFCMD_ALEN_MASK
| SFCMD_DUMLEN_MASK);
do {
val = ltq_ebu_r32(SFSTAT);
if (val & SFSTAT_CMD_ERR) {
/* reset error status */
dev_err(dev, "SFSTAT: CMD_ERR");
dev_err(dev, " (%x)\n", val);
ltq_ebu_w32(SFSTAT_CMD_ERR,
SFSTAT);
return -EBADE;
}
} while (val & SFSTAT_CMD_PEND);
val = ltq_ebu_r32(SFDATA);
do {
*rxp = (val & 0xFF);
rxp++;
val >>= 8;
len--;
} while (len);
} while (bytelen);
state = state_end;
break;
}
case state_disable_cs:
{
priv->sfcmd &= ~SFCMD_KEEP_CS_KEEP_SELECTED;
ltq_ebu_w32(priv->sfcmd | (0 << SFCMD_DLEN_OFFSET),
SFCMD);
val = ltq_ebu_r32(SFSTAT);
if (val & SFSTAT_CMD_ERR) {
/* reset error status */
dev_err(dev, "SFSTAT: CMD_ERR (%x)\n", val);
ltq_ebu_w32(SFSTAT_CMD_ERR, SFSTAT);
return -EBADE;
}
state = state_end;
break;
}
case state_end:
break;
}
} while (state != state_end);
return 0;
}
static int falcon_sflash_setup(struct spi_device *spi)
{
unsigned int i;
unsigned long flags;
if (spi->chip_select > 0)
return -ENODEV;
spin_lock_irqsave(&ebu_lock, flags);
if (spi->max_speed_hz >= CLOCK_100M) {
/* set EBU clock to 100 MHz */
ltq_sys1_w32_mask(0, EBUCC_EBUDIV_SELF100, EBUCC);
i = 1; /* divider */
} else {
/* set EBU clock to 50 MHz */
ltq_sys1_w32_mask(EBUCC_EBUDIV_SELF100, 0, EBUCC);
/* search for suitable divider */
for (i = 1; i < 7; i++) {
if (CLOCK_50M / i <= spi->max_speed_hz)
break;
}
}
/* setup period of serial clock */
ltq_ebu_w32_mask(SFTIME_SCKF_POS_MASK
| SFTIME_SCKR_POS_MASK
| SFTIME_SCK_PER_MASK,
(i << SFTIME_SCKR_POS_OFFSET)
| (i << (SFTIME_SCK_PER_OFFSET + 1)),
SFTIME);
/*
* set some bits of unused_wd, to not trigger HOLD/WP
* signals on non QUAD flashes
*/
ltq_ebu_w32((SFIO_UNUSED_WD_MASK & (0x8 | 0x4)), SFIO);
ltq_ebu_w32(BUSRCON0_AGEN_SERIAL_FLASH | BUSRCON0_PORTW_8_BIT_MUX,
BUSRCON0);
ltq_ebu_w32(BUSWCON0_AGEN_SERIAL_FLASH, BUSWCON0);
/* set address wrap around to maximum for 24-bit addresses */
ltq_ebu_w32_mask(SFCON_DEV_SIZE_MASK, SFCON_DEV_SIZE_A23_0, SFCON);
spin_unlock_irqrestore(&ebu_lock, flags);
return 0;
}
static int falcon_sflash_prepare_xfer(struct spi_master *master)
{
return 0;
}
static int falcon_sflash_unprepare_xfer(struct spi_master *master)
{
return 0;
}
static int falcon_sflash_xfer_one(struct spi_master *master,
struct spi_message *m)
{
struct falcon_sflash *priv = spi_master_get_devdata(master);
struct spi_transfer *t;
unsigned long spi_flags;
unsigned long flags;
int ret = 0;
priv->sfcmd = 0;
m->actual_length = 0;
spi_flags = FALCON_SPI_XFER_BEGIN;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (list_is_last(&t->transfer_list, &m->transfers))
spi_flags |= FALCON_SPI_XFER_END;
spin_lock_irqsave(&ebu_lock, flags);
ret = falcon_sflash_xfer(m->spi, t, spi_flags);
spin_unlock_irqrestore(&ebu_lock, flags);
if (ret)
break;
m->actual_length += t->len;
WARN_ON(t->delay_usecs || t->cs_change);
spi_flags = 0;
}
m->status = ret;
m->complete(m->context);
return 0;
}
static int __devinit falcon_sflash_probe(struct platform_device *pdev)
{
struct falcon_sflash *priv;
struct spi_master *master;
int ret;
if (ltq_boot_select() != BS_SPI) {
dev_err(&pdev->dev, "invalid bootstrap options\n");
return -ENODEV;
}
master = spi_alloc_master(&pdev->dev, sizeof(*priv));
if (!master)
return -ENOMEM;
priv = spi_master_get_devdata(master);
priv->master = master;
master->mode_bits = SPI_MODE_3;
master->num_chipselect = 1;
master->bus_num = -1;
master->setup = falcon_sflash_setup;
master->prepare_transfer_hardware = falcon_sflash_prepare_xfer;
master->transfer_one_message = falcon_sflash_xfer_one;
master->unprepare_transfer_hardware = falcon_sflash_unprepare_xfer;
master->dev.of_node = pdev->dev.of_node;
platform_set_drvdata(pdev, priv);
ret = spi_register_master(master);
if (ret)
spi_master_put(master);
return ret;
}
static int __devexit falcon_sflash_remove(struct platform_device *pdev)
{
struct falcon_sflash *priv = platform_get_drvdata(pdev);
spi_unregister_master(priv->master);
return 0;
}
static const struct of_device_id falcon_sflash_match[] = {
{ .compatible = "lantiq,sflash-falcon" },
{},
};
MODULE_DEVICE_TABLE(of, falcon_sflash_match);
static struct platform_driver falcon_sflash_driver = {
.probe = falcon_sflash_probe,
.remove = __devexit_p(falcon_sflash_remove),
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = falcon_sflash_match,
}
};
module_platform_driver(falcon_sflash_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Lantiq Falcon SPI/SFLASH controller driver");
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/of_mdio.h>
#include <net/dst.h> #include <net/dst.h>
...@@ -161,22 +162,23 @@ static void cvm_oct_adjust_link(struct net_device *dev) ...@@ -161,22 +162,23 @@ static void cvm_oct_adjust_link(struct net_device *dev)
int cvm_oct_phy_setup_device(struct net_device *dev) int cvm_oct_phy_setup_device(struct net_device *dev)
{ {
struct octeon_ethernet *priv = netdev_priv(dev); struct octeon_ethernet *priv = netdev_priv(dev);
struct device_node *phy_node;
int phy_addr = cvmx_helper_board_get_mii_address(priv->port); if (!priv->of_node)
if (phy_addr != -1) { return 0;
char phy_id[MII_BUS_ID_SIZE + 3];
snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", phy_addr); phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0);
if (!phy_node)
return 0;
priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0, priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0,
PHY_INTERFACE_MODE_GMII); PHY_INTERFACE_MODE_GMII);
if (priv->phydev == NULL)
return -ENODEV;
priv->last_link = 0;
phy_start_aneg(priv->phydev);
if (IS_ERR(priv->phydev)) {
priv->phydev = NULL;
return -1;
}
priv->last_link = 0;
phy_start_aneg(priv->phydev);
}
return 0; return 0;
} }
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
* This file may also be available under a different license from Cavium. * This file may also be available under a different license from Cavium.
* Contact Cavium Networks for more information * Contact Cavium Networks for more information
**********************************************************************/ **********************************************************************/
#include <linux/platform_device.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -32,6 +33,7 @@ ...@@ -32,6 +33,7 @@
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/of_net.h>
#include <net/dst.h> #include <net/dst.h>
...@@ -113,15 +115,6 @@ int rx_napi_weight = 32; ...@@ -113,15 +115,6 @@ int rx_napi_weight = 32;
module_param(rx_napi_weight, int, 0444); module_param(rx_napi_weight, int, 0444);
MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter."); MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter.");
/*
* The offset from mac_addr_base that should be used for the next port
* that is configured. By convention, if any mgmt ports exist on the
* chip, they get the first mac addresses, The ports controlled by
* this driver are numbered sequencially following any mgmt addresses
* that may exist.
*/
static unsigned int cvm_oct_mac_addr_offset;
/** /**
* cvm_oct_poll_queue - Workqueue for polling operations. * cvm_oct_poll_queue - Workqueue for polling operations.
*/ */
...@@ -176,7 +169,7 @@ static void cvm_oct_periodic_worker(struct work_struct *work) ...@@ -176,7 +169,7 @@ static void cvm_oct_periodic_worker(struct work_struct *work)
queue_delayed_work(cvm_oct_poll_queue, &priv->port_periodic_work, HZ); queue_delayed_work(cvm_oct_poll_queue, &priv->port_periodic_work, HZ);
} }
static __init void cvm_oct_configure_common_hw(void) static __devinit void cvm_oct_configure_common_hw(void)
{ {
/* Setup the FPA */ /* Setup the FPA */
cvmx_fpa_enable(); cvmx_fpa_enable();
...@@ -396,23 +389,21 @@ static void cvm_oct_common_set_multicast_list(struct net_device *dev) ...@@ -396,23 +389,21 @@ static void cvm_oct_common_set_multicast_list(struct net_device *dev)
* Returns Zero on success * Returns Zero on success
*/ */
static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) static int cvm_oct_set_mac_filter(struct net_device *dev)
{ {
struct octeon_ethernet *priv = netdev_priv(dev); struct octeon_ethernet *priv = netdev_priv(dev);
union cvmx_gmxx_prtx_cfg gmx_cfg; union cvmx_gmxx_prtx_cfg gmx_cfg;
int interface = INTERFACE(priv->port); int interface = INTERFACE(priv->port);
int index = INDEX(priv->port); int index = INDEX(priv->port);
memcpy(dev->dev_addr, addr + 2, 6);
if ((interface < 2) if ((interface < 2)
&& (cvmx_helper_interface_get_mode(interface) != && (cvmx_helper_interface_get_mode(interface) !=
CVMX_HELPER_INTERFACE_MODE_SPI)) { CVMX_HELPER_INTERFACE_MODE_SPI)) {
int i; int i;
uint8_t *ptr = addr; uint8_t *ptr = dev->dev_addr;
uint64_t mac = 0; uint64_t mac = 0;
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
mac = (mac << 8) | (uint64_t) (ptr[i + 2]); mac = (mac << 8) | (uint64_t)ptr[i];
gmx_cfg.u64 = gmx_cfg.u64 =
cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
...@@ -421,17 +412,17 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) ...@@ -421,17 +412,17 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac); cvmx_write_csr(CVMX_GMXX_SMACX(index, interface), mac);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface),
ptr[2]); ptr[0]);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface),
ptr[3]); ptr[1]);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface),
ptr[4]); ptr[2]);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface),
ptr[5]); ptr[3]);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface),
ptr[6]); ptr[4]);
cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface),
ptr[7]); ptr[5]);
cvm_oct_common_set_multicast_list(dev); cvm_oct_common_set_multicast_list(dev);
cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface),
gmx_cfg.u64); gmx_cfg.u64);
...@@ -439,6 +430,15 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) ...@@ -439,6 +430,15 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
return 0; return 0;
} }
static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
{
int r = eth_mac_addr(dev, addr);
if (r)
return r;
return cvm_oct_set_mac_filter(dev);
}
/** /**
* cvm_oct_common_init - per network device initialization * cvm_oct_common_init - per network device initialization
* @dev: Device to initialize * @dev: Device to initialize
...@@ -448,26 +448,17 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr) ...@@ -448,26 +448,17 @@ static int cvm_oct_common_set_mac_address(struct net_device *dev, void *addr)
int cvm_oct_common_init(struct net_device *dev) int cvm_oct_common_init(struct net_device *dev)
{ {
struct octeon_ethernet *priv = netdev_priv(dev); struct octeon_ethernet *priv = netdev_priv(dev);
struct sockaddr sa; const u8 *mac = NULL;
u64 mac = ((u64)(octeon_bootinfo->mac_addr_base[0] & 0xff) << 40) |
((u64)(octeon_bootinfo->mac_addr_base[1] & 0xff) << 32) | if (priv->of_node)
((u64)(octeon_bootinfo->mac_addr_base[2] & 0xff) << 24) | mac = of_get_mac_address(priv->of_node);
((u64)(octeon_bootinfo->mac_addr_base[3] & 0xff) << 16) |
((u64)(octeon_bootinfo->mac_addr_base[4] & 0xff) << 8) | if (mac && is_valid_ether_addr(mac)) {
(u64)(octeon_bootinfo->mac_addr_base[5] & 0xff); memcpy(dev->dev_addr, mac, ETH_ALEN);
dev->addr_assign_type &= ~NET_ADDR_RANDOM;
mac += cvm_oct_mac_addr_offset; } else {
sa.sa_data[0] = (mac >> 40) & 0xff; eth_hw_addr_random(dev);
sa.sa_data[1] = (mac >> 32) & 0xff; }
sa.sa_data[2] = (mac >> 24) & 0xff;
sa.sa_data[3] = (mac >> 16) & 0xff;
sa.sa_data[4] = (mac >> 8) & 0xff;
sa.sa_data[5] = mac & 0xff;
if (cvm_oct_mac_addr_offset >= octeon_bootinfo->mac_addr_count)
printk(KERN_DEBUG "%s: Using MAC outside of the assigned range:"
" %pM\n", dev->name, sa.sa_data);
cvm_oct_mac_addr_offset++;
/* /*
* Force the interface to use the POW send if always_use_pow * Force the interface to use the POW send if always_use_pow
...@@ -488,7 +479,7 @@ int cvm_oct_common_init(struct net_device *dev) ...@@ -488,7 +479,7 @@ int cvm_oct_common_init(struct net_device *dev)
SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops); SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops);
cvm_oct_phy_setup_device(dev); cvm_oct_phy_setup_device(dev);
dev->netdev_ops->ndo_set_mac_address(dev, &sa); cvm_oct_set_mac_filter(dev);
dev->netdev_ops->ndo_change_mtu(dev, dev->mtu); dev->netdev_ops->ndo_change_mtu(dev, dev->mtu);
/* /*
...@@ -595,22 +586,55 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = { ...@@ -595,22 +586,55 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = {
extern void octeon_mdiobus_force_mod_depencency(void); extern void octeon_mdiobus_force_mod_depencency(void);
static int __init cvm_oct_init_module(void) static struct device_node * __devinit cvm_oct_of_get_child(const struct device_node *parent,
int reg_val)
{
struct device_node *node = NULL;
int size;
const __be32 *addr;
for (;;) {
node = of_get_next_child(parent, node);
if (!node)
break;
addr = of_get_property(node, "reg", &size);
if (addr && (be32_to_cpu(*addr) == reg_val))
break;
}
return node;
}
static struct device_node * __devinit cvm_oct_node_for_port(struct device_node *pip,
int interface, int port)
{
struct device_node *ni, *np;
ni = cvm_oct_of_get_child(pip, interface);
if (!ni)
return NULL;
np = cvm_oct_of_get_child(ni, port);
of_node_put(ni);
return np;
}
static int __devinit cvm_oct_probe(struct platform_device *pdev)
{ {
int num_interfaces; int num_interfaces;
int interface; int interface;
int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE;
int qos; int qos;
struct device_node *pip;
octeon_mdiobus_force_mod_depencency(); octeon_mdiobus_force_mod_depencency();
pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION); pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION);
if (OCTEON_IS_MODEL(OCTEON_CN52XX)) pip = pdev->dev.of_node;
cvm_oct_mac_addr_offset = 2; /* First two are the mgmt ports. */ if (!pip) {
else if (OCTEON_IS_MODEL(OCTEON_CN56XX)) pr_err("Error: No 'pip' in /aliases\n");
cvm_oct_mac_addr_offset = 1; /* First one is the mgmt port. */ return -EINVAL;
else }
cvm_oct_mac_addr_offset = 0;
cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet"); cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet");
if (cvm_oct_poll_queue == NULL) { if (cvm_oct_poll_queue == NULL) {
...@@ -689,10 +713,11 @@ static int __init cvm_oct_init_module(void) ...@@ -689,10 +713,11 @@ static int __init cvm_oct_init_module(void)
cvmx_helper_interface_get_mode(interface); cvmx_helper_interface_get_mode(interface);
int num_ports = cvmx_helper_ports_on_interface(interface); int num_ports = cvmx_helper_ports_on_interface(interface);
int port; int port;
int port_index;
for (port = cvmx_helper_get_ipd_port(interface, 0); for (port_index = 0, port = cvmx_helper_get_ipd_port(interface, 0);
port < cvmx_helper_get_ipd_port(interface, num_ports); port < cvmx_helper_get_ipd_port(interface, num_ports);
port++) { port_index++, port++) {
struct octeon_ethernet *priv; struct octeon_ethernet *priv;
struct net_device *dev = struct net_device *dev =
alloc_etherdev(sizeof(struct octeon_ethernet)); alloc_etherdev(sizeof(struct octeon_ethernet));
...@@ -703,6 +728,7 @@ static int __init cvm_oct_init_module(void) ...@@ -703,6 +728,7 @@ static int __init cvm_oct_init_module(void)
/* Initialize the device private structure. */ /* Initialize the device private structure. */
priv = netdev_priv(dev); priv = netdev_priv(dev);
priv->of_node = cvm_oct_node_for_port(pip, interface, port_index);
INIT_DELAYED_WORK(&priv->port_periodic_work, INIT_DELAYED_WORK(&priv->port_periodic_work,
cvm_oct_periodic_worker); cvm_oct_periodic_worker);
...@@ -787,7 +813,7 @@ static int __init cvm_oct_init_module(void) ...@@ -787,7 +813,7 @@ static int __init cvm_oct_init_module(void)
return 0; return 0;
} }
static void __exit cvm_oct_cleanup_module(void) static int __devexit cvm_oct_remove(struct platform_device *pdev)
{ {
int port; int port;
...@@ -835,10 +861,29 @@ static void __exit cvm_oct_cleanup_module(void) ...@@ -835,10 +861,29 @@ static void __exit cvm_oct_cleanup_module(void)
if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL)
cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL,
CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128); CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128);
return 0;
} }
static struct of_device_id cvm_oct_match[] = {
{
.compatible = "cavium,octeon-3860-pip",
},
{},
};
MODULE_DEVICE_TABLE(of, cvm_oct_match);
static struct platform_driver cvm_oct_driver = {
.probe = cvm_oct_probe,
.remove = __devexit_p(cvm_oct_remove),
.driver = {
.owner = THIS_MODULE,
.name = KBUILD_MODNAME,
.of_match_table = cvm_oct_match,
},
};
module_platform_driver(cvm_oct_driver);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>"); MODULE_AUTHOR("Cavium Networks <support@caviumnetworks.com>");
MODULE_DESCRIPTION("Cavium Networks Octeon ethernet driver."); MODULE_DESCRIPTION("Cavium Networks Octeon ethernet driver.");
module_init(cvm_oct_init_module);
module_exit(cvm_oct_cleanup_module);
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#ifndef OCTEON_ETHERNET_H #ifndef OCTEON_ETHERNET_H
#define OCTEON_ETHERNET_H #define OCTEON_ETHERNET_H
#include <linux/of.h>
/** /**
* This is the definition of the Ethernet driver's private * This is the definition of the Ethernet driver's private
* driver state stored in netdev_priv(dev). * driver state stored in netdev_priv(dev).
...@@ -59,6 +61,7 @@ struct octeon_ethernet { ...@@ -59,6 +61,7 @@ struct octeon_ethernet {
void (*poll) (struct net_device *dev); void (*poll) (struct net_device *dev);
struct delayed_work port_periodic_work; struct delayed_work port_periodic_work;
struct work_struct port_work; /* may be unused. */ struct work_struct port_work; /* may be unused. */
struct device_node *of_node;
}; };
int cvm_oct_free_work(void *work_queue_entry); int cvm_oct_free_work(void *work_queue_entry);
......
#ifndef _INCLUDE_LIBFDT_H_
#define _INCLUDE_LIBFDT_H_
#include <linux/libfdt_env.h>
#include "../../scripts/dtc/libfdt/fdt.h"
#include "../../scripts/dtc/libfdt/libfdt.h"
#endif /* _INCLUDE_LIBFDT_H_ */
#ifndef _LIBFDT_ENV_H
#define _LIBFDT_ENV_H
#include <linux/string.h>
#include <asm/byteorder.h>
#define fdt32_to_cpu(x) be32_to_cpu(x)
#define cpu_to_fdt32(x) cpu_to_be32(x)
#define fdt64_to_cpu(x) be64_to_cpu(x)
#define cpu_to_fdt64(x) cpu_to_be64(x)
#endif /* _LIBFDT_ENV_H */
...@@ -395,4 +395,10 @@ config SIGNATURE ...@@ -395,4 +395,10 @@ config SIGNATURE
Digital signature verification. Currently only RSA is supported. Digital signature verification. Currently only RSA is supported.
Implementation is done using GnuPG MPI library Implementation is done using GnuPG MPI library
#
# libfdt files, only selected if needed.
#
config LIBFDT
bool
endmenu endmenu
...@@ -130,6 +130,11 @@ obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o ...@@ -130,6 +130,11 @@ obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o
obj-$(CONFIG_STMP_DEVICE) += stmp_device.o obj-$(CONFIG_STMP_DEVICE) += stmp_device.o
libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o
$(foreach file, $(libfdt_files), \
$(eval CFLAGS_$(file) = -I$(src)/../scripts/dtc/libfdt))
lib-$(CONFIG_LIBFDT) += $(libfdt_files)
hostprogs-y := gen_crc32table hostprogs-y := gen_crc32table
clean-files := crc32table.h clean-files := crc32table.h
......
#include <linux/libfdt_env.h>
#include "../scripts/dtc/libfdt/fdt.c"
#include <linux/libfdt_env.h>
#include "../scripts/dtc/libfdt/fdt_ro.c"
#include <linux/libfdt_env.h>
#include "../scripts/dtc/libfdt/fdt_rw.c"
#include <linux/libfdt_env.h>
#include "../scripts/dtc/libfdt/fdt_strerror.c"
#include <linux/libfdt_env.h>
#include "../scripts/dtc/libfdt/fdt_sw.c"
#include <linux/libfdt_env.h>
#include "../scripts/dtc/libfdt/fdt_wip.c"
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册