Merge branch 'orion' into devel
* orion: (26 commits) [ARM] Orion: implement power-off method for QNAP TS-109/209 [ARM] Orion: add support for QNAP TS-109/TS-209 [ARM] Orion: I2C support [I2C] i2c-mv64xxx: Don't set i2c_adapter.retries [I2C] Split mv643xx I2C platform support [ARM] Orion: enable CONFIG_RTC_DRV_M41T80 for D-Link DNS-323 [ARM] Orion defconfig [ARM] Orion: add support for Orion/MV88F5181 based D-Link DNS-323 [ARM] Orion: MV88F5181 support bits [ARM] Orion: Buffalo/Revogear Kurobox Pro support [ARM] OrionNAS RD board support [ARM] Orion: support for Marvell Orion-2 (88F5281) Development Board [ARM] Orion: common platform setup for Gigabit Ethernet port [ARM] Orion: platform device registration for UART, USB and NAND [ARM] Orion: system timer support [ARM] Orion edge GPIO IRQ support [ARM] Orion: IRQ support [ARM] Orion: provide GPIO method for enabling hardware assisted blinking [ARM] Orion: GPIO support [ARM] Orion: programable address map support ... Conflicts: arch/arm/Kconfig arch/arm/Makefile Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
commit
c00d4ffdba
|
@ -334,6 +334,16 @@ config ARCH_MXC
|
|||
help
|
||||
Support for Freescale MXC/iMX-based family of processors
|
||||
|
||||
config ARCH_ORION
|
||||
bool "Marvell Orion"
|
||||
depends on MMU
|
||||
select PCI
|
||||
select GENERIC_GPIO
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
help
|
||||
Support for Marvell Orion System on Chip family.
|
||||
|
||||
config ARCH_PNX4008
|
||||
bool "Philips Nexperia PNX4008 Mobile"
|
||||
help
|
||||
|
@ -454,6 +464,8 @@ source "arch/arm/mach-omap1/Kconfig"
|
|||
|
||||
source "arch/arm/mach-omap2/Kconfig"
|
||||
|
||||
source "arch/arm/mach-orion/Kconfig"
|
||||
|
||||
source "arch/arm/plat-s3c24xx/Kconfig"
|
||||
source "arch/arm/plat-s3c/Kconfig"
|
||||
|
||||
|
@ -732,7 +744,7 @@ config LEDS
|
|||
ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
|
||||
ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \
|
||||
ARCH_AT91 || MACH_TRIZEPS4 || ARCH_DAVINCI || \
|
||||
ARCH_KS8695
|
||||
ARCH_KS8695 || MACH_RD88F5182
|
||||
help
|
||||
If you say Y here, the LEDs on your machine will be used
|
||||
to provide useful information about your current system status.
|
||||
|
@ -967,7 +979,7 @@ config FPE_FASTFPE
|
|||
|
||||
config VFP
|
||||
bool "VFP-format floating point maths"
|
||||
depends on CPU_V6 || CPU_ARM926T || CPU_V7
|
||||
depends on CPU_V6 || CPU_ARM926T || CPU_V7 || CPU_FEROCEON
|
||||
help
|
||||
Say Y to include VFP support code in the kernel. This is needed
|
||||
if your hardware includes a VFP unit.
|
||||
|
|
|
@ -139,6 +139,7 @@ endif
|
|||
machine-$(CONFIG_ARCH_KS8695) := ks8695
|
||||
incdir-$(CONFIG_ARCH_MXC) := mxc
|
||||
machine-$(CONFIG_ARCH_MX3) := mx3
|
||||
machine-$(CONFIG_ARCH_ORION) := orion
|
||||
machine-$(CONFIG_ARCH_MSM7X00A) := msm
|
||||
|
||||
ifeq ($(CONFIG_ARCH_EBSA110),y)
|
||||
|
|
|
@ -623,6 +623,12 @@ proc_types:
|
|||
b __armv4_mmu_cache_off
|
||||
b __armv4_mmu_cache_flush
|
||||
|
||||
.word 0x56055310 @ Feroceon
|
||||
.word 0xfffffff0
|
||||
b __armv4_mmu_cache_on
|
||||
b __armv4_mmu_cache_off
|
||||
b __armv5tej_mmu_cache_flush
|
||||
|
||||
@ These match on the architecture ID
|
||||
|
||||
.word 0x00020000 @ ARMv4T
|
||||
|
@ -641,7 +647,7 @@ proc_types:
|
|||
.word 0x000f0000
|
||||
b __armv4_mmu_cache_on
|
||||
b __armv4_mmu_cache_off
|
||||
b __armv4_mmu_cache_flush
|
||||
b __armv5tej_mmu_cache_flush
|
||||
|
||||
.word 0x0007b000 @ ARMv6
|
||||
.word 0x000ff000
|
||||
|
@ -821,6 +827,13 @@ iflush:
|
|||
mcr p15, 0, r10, c7, c10, 4 @ drain WB
|
||||
mov pc, lr
|
||||
|
||||
__armv5tej_mmu_cache_flush:
|
||||
1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate D cache
|
||||
bne 1b
|
||||
mcr p15, 0, r0, c7, c5, 0 @ flush I cache
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain WB
|
||||
mov pc, lr
|
||||
|
||||
__armv4_mmu_cache_flush:
|
||||
mov r2, #64*1024 @ default: 32K dcache size (*2)
|
||||
mov r11, #32 @ default: 32 byte line size
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,41 @@
|
|||
if ARCH_ORION
|
||||
|
||||
menu "Orion Implementations"
|
||||
|
||||
config MACH_DB88F5281
|
||||
bool "Marvell Orion-2 Development Board"
|
||||
select I2C_BOARDINFO
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support the
|
||||
Marvell Orion-2 (88F5281) Development Board
|
||||
|
||||
config MACH_RD88F5182
|
||||
bool "Marvell Orion-NAS Reference Design"
|
||||
select I2C_BOARDINFO
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support the
|
||||
Marvell Orion-NAS (88F5182) RD2
|
||||
|
||||
config MACH_KUROBOX_PRO
|
||||
bool "KuroBox Pro"
|
||||
select I2C_BOARDINFO
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support the
|
||||
KuroBox Pro platform.
|
||||
|
||||
config MACH_DNS323
|
||||
bool "D-Link DNS-323"
|
||||
select I2C_BOARDINFO
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support the
|
||||
D-Link DNS-323 platform.
|
||||
|
||||
config MACH_TS209
|
||||
bool "QNAP TS-109/TS-209"
|
||||
help
|
||||
Say 'Y' here if you want your kernel to support the
|
||||
QNAP TS-109/TS-209 platform.
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
|
@ -0,0 +1,6 @@
|
|||
obj-y += common.o addr-map.o pci.o gpio.o irq.o time.o
|
||||
obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o
|
||||
obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o
|
||||
obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o
|
||||
obj-$(CONFIG_MACH_DNS323) += dns323-setup.o
|
||||
obj-$(CONFIG_MACH_TS209) += ts209-setup.o
|
|
@ -0,0 +1,3 @@
|
|||
zreladdr-y := 0x00008000
|
||||
params_phys-y := 0x00000100
|
||||
initrd_phys-y := 0x00800000
|
|
@ -0,0 +1,484 @@
|
|||
/*
|
||||
* arch/arm/mach-orion/addr-map.c
|
||||
*
|
||||
* Address map functions for Marvell Orion System On Chip
|
||||
*
|
||||
* Maintainer: Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/hardware.h>
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* The Orion has fully programable address map. There's a separate address
|
||||
* map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB,
|
||||
* Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
|
||||
* address decode windows that allow it to access any of the Orion resources.
|
||||
*
|
||||
* CPU address decoding --
|
||||
* Linux assumes that it is the boot loader that already setup the access to
|
||||
* DDR and internal registers.
|
||||
* Setup access to PCI and PCI-E IO/MEM space is issued by core.c.
|
||||
* Setup access to various devices located on the device bus interface (e.g.
|
||||
* flashes, RTC, etc) should be issued by machine-setup.c according to
|
||||
* specific board population (by using orion_setup_cpu_win()).
|
||||
*
|
||||
* Non-CPU Masters address decoding --
|
||||
* Unlike the CPU, we setup the access from Orion's master interfaces to DDR
|
||||
* banks only (the typical use case).
|
||||
* Setup access for each master to DDR is issued by common.c.
|
||||
*
|
||||
* Note: although orion_setbits() and orion_clrbits() are not atomic
|
||||
* no locking is necessary here since code in this file is only called
|
||||
* at boot time when there is no concurrency issues.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generic Address Decode Windows bit settings
|
||||
*/
|
||||
#define TARGET_DDR 0
|
||||
#define TARGET_PCI 3
|
||||
#define TARGET_PCIE 4
|
||||
#define TARGET_DEV_BUS 1
|
||||
#define ATTR_DDR_CS(n) (((n) ==0) ? 0xe : \
|
||||
((n) == 1) ? 0xd : \
|
||||
((n) == 2) ? 0xb : \
|
||||
((n) == 3) ? 0x7 : 0xf)
|
||||
#define ATTR_PCIE_MEM 0x59
|
||||
#define ATTR_PCIE_IO 0x51
|
||||
#define ATTR_PCI_MEM 0x59
|
||||
#define ATTR_PCI_IO 0x51
|
||||
#define ATTR_DEV_CS0 0x1e
|
||||
#define ATTR_DEV_CS1 0x1d
|
||||
#define ATTR_DEV_CS2 0x1b
|
||||
#define ATTR_DEV_BOOT 0xf
|
||||
#define WIN_EN 1
|
||||
|
||||
/*
|
||||
* Helpers to get DDR banks info
|
||||
*/
|
||||
#define DDR_BASE_CS(n) ORION_DDR_REG(0x1500 + ((n) * 8))
|
||||
#define DDR_SIZE_CS(n) ORION_DDR_REG(0x1504 + ((n) * 8))
|
||||
#define DDR_MAX_CS 4
|
||||
#define DDR_REG_TO_SIZE(reg) (((reg) | 0xffffff) + 1)
|
||||
#define DDR_REG_TO_BASE(reg) ((reg) & 0xff000000)
|
||||
#define DDR_BANK_EN 1
|
||||
|
||||
/*
|
||||
* CPU Address Decode Windows registers
|
||||
*/
|
||||
#define CPU_WIN_CTRL(n) ORION_BRIDGE_REG(0x000 | ((n) << 4))
|
||||
#define CPU_WIN_BASE(n) ORION_BRIDGE_REG(0x004 | ((n) << 4))
|
||||
#define CPU_WIN_REMAP_LO(n) ORION_BRIDGE_REG(0x008 | ((n) << 4))
|
||||
#define CPU_WIN_REMAP_HI(n) ORION_BRIDGE_REG(0x00c | ((n) << 4))
|
||||
#define CPU_MAX_WIN 8
|
||||
|
||||
/*
|
||||
* Use this CPU address decode windows allocation
|
||||
*/
|
||||
#define CPU_WIN_PCIE_IO 0
|
||||
#define CPU_WIN_PCI_IO 1
|
||||
#define CPU_WIN_PCIE_MEM 2
|
||||
#define CPU_WIN_PCI_MEM 3
|
||||
#define CPU_WIN_DEV_BOOT 4
|
||||
#define CPU_WIN_DEV_CS0 5
|
||||
#define CPU_WIN_DEV_CS1 6
|
||||
#define CPU_WIN_DEV_CS2 7
|
||||
|
||||
/*
|
||||
* PCIE Address Decode Windows registers
|
||||
*/
|
||||
#define PCIE_BAR_CTRL(n) ORION_PCIE_REG(0x1804 + ((n - 1) * 4))
|
||||
#define PCIE_BAR_LO(n) ORION_PCIE_REG(0x0010 + ((n) * 8))
|
||||
#define PCIE_BAR_HI(n) ORION_PCIE_REG(0x0014 + ((n) * 8))
|
||||
#define PCIE_WIN_CTRL(n) ORION_PCIE_REG(0x1820 + ((n) << 4))
|
||||
#define PCIE_WIN_BASE(n) ORION_PCIE_REG(0x1824 + ((n) << 4))
|
||||
#define PCIE_WIN_REMAP(n) ORION_PCIE_REG(0x182c + ((n) << 4))
|
||||
#define PCIE_DEFWIN_CTRL ORION_PCIE_REG(0x18b0)
|
||||
#define PCIE_EXPROM_WIN_CTRL ORION_PCIE_REG(0x18c0)
|
||||
#define PCIE_EXPROM_WIN_REMP ORION_PCIE_REG(0x18c4)
|
||||
#define PCIE_MAX_BARS 3
|
||||
#define PCIE_MAX_WINS 5
|
||||
|
||||
/*
|
||||
* Use PCIE BAR '1' for all DDR banks
|
||||
*/
|
||||
#define PCIE_DRAM_BAR 1
|
||||
|
||||
/*
|
||||
* PCI Address Decode Windows registers
|
||||
*/
|
||||
#define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION_PCI_REG(0xc08) : \
|
||||
((n) == 1) ? ORION_PCI_REG(0xd08) : \
|
||||
((n) == 2) ? ORION_PCI_REG(0xc0c) : \
|
||||
((n) == 3) ? ORION_PCI_REG(0xd0c) : 0)
|
||||
#define PCI_BAR_REMAP_DDR_CS(n) (((n) ==0) ? ORION_PCI_REG(0xc48) : \
|
||||
((n) == 1) ? ORION_PCI_REG(0xd48) : \
|
||||
((n) == 2) ? ORION_PCI_REG(0xc4c) : \
|
||||
((n) == 3) ? ORION_PCI_REG(0xd4c) : 0)
|
||||
#define PCI_BAR_ENABLE ORION_PCI_REG(0xc3c)
|
||||
#define PCI_CTRL_BASE_LO(n) ORION_PCI_REG(0x1e00 | ((n) << 4))
|
||||
#define PCI_CTRL_BASE_HI(n) ORION_PCI_REG(0x1e04 | ((n) << 4))
|
||||
#define PCI_CTRL_SIZE(n) ORION_PCI_REG(0x1e08 | ((n) << 4))
|
||||
#define PCI_ADDR_DECODE_CTRL ORION_PCI_REG(0xd3c)
|
||||
|
||||
/*
|
||||
* PCI configuration heleprs for BAR settings
|
||||
*/
|
||||
#define PCI_CONF_FUNC_BAR_CS(n) ((n) >> 1)
|
||||
#define PCI_CONF_REG_BAR_LO_CS(n) (((n) & 1) ? 0x18 : 0x10)
|
||||
#define PCI_CONF_REG_BAR_HI_CS(n) (((n) & 1) ? 0x1c : 0x14)
|
||||
|
||||
/*
|
||||
* Gigabit Ethernet Address Decode Windows registers
|
||||
*/
|
||||
#define ETH_WIN_BASE(win) ORION_ETH_REG(0x200 + ((win) * 8))
|
||||
#define ETH_WIN_SIZE(win) ORION_ETH_REG(0x204 + ((win) * 8))
|
||||
#define ETH_WIN_REMAP(win) ORION_ETH_REG(0x280 + ((win) * 4))
|
||||
#define ETH_WIN_EN ORION_ETH_REG(0x290)
|
||||
#define ETH_WIN_PROT ORION_ETH_REG(0x294)
|
||||
#define ETH_MAX_WIN 6
|
||||
#define ETH_MAX_REMAP_WIN 4
|
||||
|
||||
/*
|
||||
* USB Address Decode Windows registers
|
||||
*/
|
||||
#define USB_WIN_CTRL(i, w) ((i == 0) ? ORION_USB0_REG(0x320 + ((w) << 4)) \
|
||||
: ORION_USB1_REG(0x320 + ((w) << 4)))
|
||||
#define USB_WIN_BASE(i, w) ((i == 0) ? ORION_USB0_REG(0x324 + ((w) << 4)) \
|
||||
: ORION_USB1_REG(0x324 + ((w) << 4)))
|
||||
#define USB_MAX_WIN 4
|
||||
|
||||
/*
|
||||
* SATA Address Decode Windows registers
|
||||
*/
|
||||
#define SATA_WIN_CTRL(win) ORION_SATA_REG(0x30 + ((win) * 0x10))
|
||||
#define SATA_WIN_BASE(win) ORION_SATA_REG(0x34 + ((win) * 0x10))
|
||||
#define SATA_MAX_WIN 4
|
||||
|
||||
static int __init orion_cpu_win_can_remap(u32 win)
|
||||
{
|
||||
u32 dev, rev;
|
||||
|
||||
orion_pcie_id(&dev, &rev);
|
||||
if ((dev == MV88F5281_DEV_ID && win < 4)
|
||||
|| (dev == MV88F5182_DEV_ID && win < 2)
|
||||
|| (dev == MV88F5181_DEV_ID && win < 2))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __init orion_setup_cpu_win(enum orion_target target, u32 base, u32 size, int remap)
|
||||
{
|
||||
u32 win, attr, ctrl;
|
||||
|
||||
switch (target) {
|
||||
case ORION_PCIE_IO:
|
||||
target = TARGET_PCIE;
|
||||
attr = ATTR_PCIE_IO;
|
||||
win = CPU_WIN_PCIE_IO;
|
||||
break;
|
||||
case ORION_PCI_IO:
|
||||
target = TARGET_PCI;
|
||||
attr = ATTR_PCI_IO;
|
||||
win = CPU_WIN_PCI_IO;
|
||||
break;
|
||||
case ORION_PCIE_MEM:
|
||||
target = TARGET_PCIE;
|
||||
attr = ATTR_PCIE_MEM;
|
||||
win = CPU_WIN_PCIE_MEM;
|
||||
break;
|
||||
case ORION_PCI_MEM:
|
||||
target = TARGET_PCI;
|
||||
attr = ATTR_PCI_MEM;
|
||||
win = CPU_WIN_PCI_MEM;
|
||||
break;
|
||||
case ORION_DEV_BOOT:
|
||||
target = TARGET_DEV_BUS;
|
||||
attr = ATTR_DEV_BOOT;
|
||||
win = CPU_WIN_DEV_BOOT;
|
||||
break;
|
||||
case ORION_DEV0:
|
||||
target = TARGET_DEV_BUS;
|
||||
attr = ATTR_DEV_CS0;
|
||||
win = CPU_WIN_DEV_CS0;
|
||||
break;
|
||||
case ORION_DEV1:
|
||||
target = TARGET_DEV_BUS;
|
||||
attr = ATTR_DEV_CS1;
|
||||
win = CPU_WIN_DEV_CS1;
|
||||
break;
|
||||
case ORION_DEV2:
|
||||
target = TARGET_DEV_BUS;
|
||||
attr = ATTR_DEV_CS2;
|
||||
win = CPU_WIN_DEV_CS2;
|
||||
break;
|
||||
case ORION_DDR:
|
||||
case ORION_REGS:
|
||||
/*
|
||||
* Must be mapped by bootloader.
|
||||
*/
|
||||
default:
|
||||
target = attr = win = -1;
|
||||
BUG();
|
||||
}
|
||||
|
||||
base &= 0xffff0000;
|
||||
ctrl = (((size - 1) & 0xffff0000) | (attr << 8) |
|
||||
(target << 4) | WIN_EN);
|
||||
|
||||
orion_write(CPU_WIN_BASE(win), base);
|
||||
orion_write(CPU_WIN_CTRL(win), ctrl);
|
||||
|
||||
if (orion_cpu_win_can_remap(win)) {
|
||||
if (remap >= 0) {
|
||||
orion_write(CPU_WIN_REMAP_LO(win), remap & 0xffff0000);
|
||||
orion_write(CPU_WIN_REMAP_HI(win), 0);
|
||||
} else {
|
||||
orion_write(CPU_WIN_REMAP_LO(win), base);
|
||||
orion_write(CPU_WIN_REMAP_HI(win), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __init orion_setup_cpu_wins(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* First, disable and clear windows
|
||||
*/
|
||||
for (i = 0; i < CPU_MAX_WIN; i++) {
|
||||
orion_write(CPU_WIN_BASE(i), 0);
|
||||
orion_write(CPU_WIN_CTRL(i), 0);
|
||||
if (orion_cpu_win_can_remap(i)) {
|
||||
orion_write(CPU_WIN_REMAP_LO(i), 0);
|
||||
orion_write(CPU_WIN_REMAP_HI(i), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup windows for PCI+PCIE IO+MAM space
|
||||
*/
|
||||
orion_setup_cpu_win(ORION_PCIE_IO, ORION_PCIE_IO_BASE,
|
||||
ORION_PCIE_IO_SIZE, ORION_PCIE_IO_REMAP);
|
||||
orion_setup_cpu_win(ORION_PCI_IO, ORION_PCI_IO_BASE,
|
||||
ORION_PCI_IO_SIZE, ORION_PCI_IO_REMAP);
|
||||
orion_setup_cpu_win(ORION_PCIE_MEM, ORION_PCIE_MEM_BASE,
|
||||
ORION_PCIE_MEM_SIZE, -1);
|
||||
orion_setup_cpu_win(ORION_PCI_MEM, ORION_PCI_MEM_BASE,
|
||||
ORION_PCI_MEM_SIZE, -1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup PCIE BARs and Address Decode Wins:
|
||||
* BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
|
||||
* WIN[0-3] -> DRAM bank[0-3]
|
||||
*/
|
||||
void __init orion_setup_pcie_wins(void)
|
||||
{
|
||||
u32 base, size, i;
|
||||
|
||||
/*
|
||||
* First, disable and clear BARs and windows
|
||||
*/
|
||||
for (i = 1; i < PCIE_MAX_BARS; i++) {
|
||||
orion_write(PCIE_BAR_CTRL(i), 0);
|
||||
orion_write(PCIE_BAR_LO(i), 0);
|
||||
orion_write(PCIE_BAR_HI(i), 0);
|
||||
}
|
||||
|
||||
for (i = 0; i < PCIE_MAX_WINS; i++) {
|
||||
orion_write(PCIE_WIN_CTRL(i), 0);
|
||||
orion_write(PCIE_WIN_BASE(i), 0);
|
||||
orion_write(PCIE_WIN_REMAP(i), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup windows for DDR banks. Count total DDR size on the fly.
|
||||
*/
|
||||
base = DDR_REG_TO_BASE(orion_read(DDR_BASE_CS(0)));
|
||||
size = 0;
|
||||
for (i = 0; i < DDR_MAX_CS; i++) {
|
||||
u32 bank_base, bank_size;
|
||||
bank_size = orion_read(DDR_SIZE_CS(i));
|
||||
bank_base = orion_read(DDR_BASE_CS(i));
|
||||
if (bank_size & DDR_BANK_EN) {
|
||||
bank_size = DDR_REG_TO_SIZE(bank_size);
|
||||
bank_base = DDR_REG_TO_BASE(bank_base);
|
||||
orion_write(PCIE_WIN_BASE(i), bank_base & 0xffff0000);
|
||||
orion_write(PCIE_WIN_REMAP(i), 0);
|
||||
orion_write(PCIE_WIN_CTRL(i),
|
||||
((bank_size-1) & 0xffff0000) |
|
||||
(ATTR_DDR_CS(i) << 8) |
|
||||
(TARGET_DDR << 4) |
|
||||
(PCIE_DRAM_BAR << 1) | WIN_EN);
|
||||
size += bank_size;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup BAR[1] to all DRAM banks
|
||||
*/
|
||||
orion_write(PCIE_BAR_LO(PCIE_DRAM_BAR), base & 0xffff0000);
|
||||
orion_write(PCIE_BAR_HI(PCIE_DRAM_BAR), 0);
|
||||
orion_write(PCIE_BAR_CTRL(PCIE_DRAM_BAR),
|
||||
((size - 1) & 0xffff0000) | WIN_EN);
|
||||
}
|
||||
|
||||
void __init orion_setup_pci_wins(void)
|
||||
{
|
||||
u32 base, size, i;
|
||||
|
||||
/*
|
||||
* First, disable windows
|
||||
*/
|
||||
orion_write(PCI_BAR_ENABLE, 0xffffffff);
|
||||
|
||||
/*
|
||||
* Setup windows for DDR banks.
|
||||
*/
|
||||
for (i = 0; i < DDR_MAX_CS; i++) {
|
||||
base = orion_read(DDR_BASE_CS(i));
|
||||
size = orion_read(DDR_SIZE_CS(i));
|
||||
if (size & DDR_BANK_EN) {
|
||||
u32 bus, dev, func, reg, val;
|
||||
size = DDR_REG_TO_SIZE(size);
|
||||
base = DDR_REG_TO_BASE(base);
|
||||
bus = orion_pci_local_bus_nr();
|
||||
dev = orion_pci_local_dev_nr();
|
||||
func = PCI_CONF_FUNC_BAR_CS(i);
|
||||
reg = PCI_CONF_REG_BAR_LO_CS(i);
|
||||
orion_pci_hw_rd_conf(bus, dev, func, reg, 4, &val);
|
||||
orion_pci_hw_wr_conf(bus, dev, func, reg, 4,
|
||||
(base & 0xfffff000) | (val & 0xfff));
|
||||
reg = PCI_CONF_REG_BAR_HI_CS(i);
|
||||
orion_pci_hw_wr_conf(bus, dev, func, reg, 4, 0);
|
||||
orion_write(PCI_BAR_SIZE_DDR_CS(i),
|
||||
(size - 1) & 0xfffff000);
|
||||
orion_write(PCI_BAR_REMAP_DDR_CS(i),
|
||||
base & 0xfffff000);
|
||||
orion_clrbits(PCI_BAR_ENABLE, (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable automatic update of address remaping when writing to BARs
|
||||
*/
|
||||
orion_setbits(PCI_ADDR_DECODE_CTRL, 1);
|
||||
}
|
||||
|
||||
void __init orion_setup_usb_wins(void)
|
||||
{
|
||||
int i;
|
||||
u32 usb_if, dev, rev;
|
||||
u32 max_usb_if = 1;
|
||||
|
||||
orion_pcie_id(&dev, &rev);
|
||||
if (dev == MV88F5182_DEV_ID)
|
||||
max_usb_if = 2;
|
||||
|
||||
for (usb_if = 0; usb_if < max_usb_if; usb_if++) {
|
||||
/*
|
||||
* First, disable and clear windows
|
||||
*/
|
||||
for (i = 0; i < USB_MAX_WIN; i++) {
|
||||
orion_write(USB_WIN_BASE(usb_if, i), 0);
|
||||
orion_write(USB_WIN_CTRL(usb_if, i), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup windows for DDR banks.
|
||||
*/
|
||||
for (i = 0; i < DDR_MAX_CS; i++) {
|
||||
u32 base, size;
|
||||
size = orion_read(DDR_SIZE_CS(i));
|
||||
base = orion_read(DDR_BASE_CS(i));
|
||||
if (size & DDR_BANK_EN) {
|
||||
base = DDR_REG_TO_BASE(base);
|
||||
size = DDR_REG_TO_SIZE(size);
|
||||
orion_write(USB_WIN_CTRL(usb_if, i),
|
||||
((size-1) & 0xffff0000) |
|
||||
(ATTR_DDR_CS(i) << 8) |
|
||||
(TARGET_DDR << 4) | WIN_EN);
|
||||
orion_write(USB_WIN_BASE(usb_if, i),
|
||||
base & 0xffff0000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __init orion_setup_eth_wins(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* First, disable and clear windows
|
||||
*/
|
||||
for (i = 0; i < ETH_MAX_WIN; i++) {
|
||||
orion_write(ETH_WIN_BASE(i), 0);
|
||||
orion_write(ETH_WIN_SIZE(i), 0);
|
||||
orion_setbits(ETH_WIN_EN, 1 << i);
|
||||
orion_clrbits(ETH_WIN_PROT, 0x3 << (i * 2));
|
||||
if (i < ETH_MAX_REMAP_WIN)
|
||||
orion_write(ETH_WIN_REMAP(i), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup windows for DDR banks.
|
||||
*/
|
||||
for (i = 0; i < DDR_MAX_CS; i++) {
|
||||
u32 base, size;
|
||||
size = orion_read(DDR_SIZE_CS(i));
|
||||
base = orion_read(DDR_BASE_CS(i));
|
||||
if (size & DDR_BANK_EN) {
|
||||
base = DDR_REG_TO_BASE(base);
|
||||
size = DDR_REG_TO_SIZE(size);
|
||||
orion_write(ETH_WIN_SIZE(i), (size-1) & 0xffff0000);
|
||||
orion_write(ETH_WIN_BASE(i), (base & 0xffff0000) |
|
||||
(ATTR_DDR_CS(i) << 8) |
|
||||
TARGET_DDR);
|
||||
orion_clrbits(ETH_WIN_EN, 1 << i);
|
||||
orion_setbits(ETH_WIN_PROT, 0x3 << (i * 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __init orion_setup_sata_wins(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* First, disable and clear windows
|
||||
*/
|
||||
for (i = 0; i < SATA_MAX_WIN; i++) {
|
||||
orion_write(SATA_WIN_BASE(i), 0);
|
||||
orion_write(SATA_WIN_CTRL(i), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup windows for DDR banks.
|
||||
*/
|
||||
for (i = 0; i < DDR_MAX_CS; i++) {
|
||||
u32 base, size;
|
||||
size = orion_read(DDR_SIZE_CS(i));
|
||||
base = orion_read(DDR_BASE_CS(i));
|
||||
if (size & DDR_BANK_EN) {
|
||||
base = DDR_REG_TO_BASE(base);
|
||||
size = DDR_REG_TO_SIZE(size);
|
||||
orion_write(SATA_WIN_CTRL(i),
|
||||
((size-1) & 0xffff0000) |
|
||||
(ATTR_DDR_CS(i) << 8) |
|
||||
(TARGET_DDR << 4) | WIN_EN);
|
||||
orion_write(SATA_WIN_BASE(i),
|
||||
base & 0xffff0000);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
* arch/arm/mach-orion/common.c
|
||||
*
|
||||
* Core functions for Marvell Orion System On Chip
|
||||
*
|
||||
* Maintainer: Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/mv643xx_i2c.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/timex.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/arch/orion.h>
|
||||
#include "common.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* I/O Address Mapping
|
||||
****************************************************************************/
|
||||
static struct map_desc orion_io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = ORION_REGS_BASE,
|
||||
.pfn = __phys_to_pfn(ORION_REGS_BASE),
|
||||
.length = ORION_REGS_SIZE,
|
||||
.type = MT_DEVICE
|
||||
},
|
||||
{
|
||||
.virtual = ORION_PCIE_IO_BASE,
|
||||
.pfn = __phys_to_pfn(ORION_PCIE_IO_BASE),
|
||||
.length = ORION_PCIE_IO_SIZE,
|
||||
.type = MT_DEVICE
|
||||
},
|
||||
{
|
||||
.virtual = ORION_PCI_IO_BASE,
|
||||
.pfn = __phys_to_pfn(ORION_PCI_IO_BASE),
|
||||
.length = ORION_PCI_IO_SIZE,
|
||||
.type = MT_DEVICE
|
||||
},
|
||||
{
|
||||
.virtual = ORION_PCIE_WA_BASE,
|
||||
.pfn = __phys_to_pfn(ORION_PCIE_WA_BASE),
|
||||
.length = ORION_PCIE_WA_SIZE,
|
||||
.type = MT_DEVICE
|
||||
},
|
||||
};
|
||||
|
||||
void __init orion_map_io(void)
|
||||
{
|
||||
iotable_init(orion_io_desc, ARRAY_SIZE(orion_io_desc));
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* UART
|
||||
****************************************************************************/
|
||||
|
||||
static struct resource orion_uart_resources[] = {
|
||||
{
|
||||
.start = UART0_BASE,
|
||||
.end = UART0_BASE + 0xff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = IRQ_ORION_UART0,
|
||||
.end = IRQ_ORION_UART0,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
{
|
||||
.start = UART1_BASE,
|
||||
.end = UART1_BASE + 0xff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = IRQ_ORION_UART1,
|
||||
.end = IRQ_ORION_UART1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct plat_serial8250_port orion_uart_data[] = {
|
||||
{
|
||||
.mapbase = UART0_BASE,
|
||||
.membase = (char *)UART0_BASE,
|
||||
.irq = IRQ_ORION_UART0,
|
||||
.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = ORION_TCLK,
|
||||
},
|
||||
{
|
||||
.mapbase = UART1_BASE,
|
||||
.membase = (char *)UART1_BASE,
|
||||
.irq = IRQ_ORION_UART1,
|
||||
.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
|
||||
.iotype = UPIO_MEM,
|
||||
.regshift = 2,
|
||||
.uartclk = ORION_TCLK,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_device orion_uart = {
|
||||
.name = "serial8250",
|
||||
.id = PLAT8250_DEV_PLATFORM,
|
||||
.dev = {
|
||||
.platform_data = orion_uart_data,
|
||||
},
|
||||
.resource = orion_uart_resources,
|
||||
.num_resources = ARRAY_SIZE(orion_uart_resources),
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
* USB Controller - 2 interfaces
|
||||
******************************************************************************/
|
||||
|
||||
static struct resource orion_ehci0_resources[] = {
|
||||
{
|
||||
.start = ORION_USB0_REG_BASE,
|
||||
.end = ORION_USB0_REG_BASE + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = IRQ_ORION_USB0_CTRL,
|
||||
.end = IRQ_ORION_USB0_CTRL,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource orion_ehci1_resources[] = {
|
||||
{
|
||||
.start = ORION_USB1_REG_BASE,
|
||||
.end = ORION_USB1_REG_BASE + SZ_4K,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.start = IRQ_ORION_USB1_CTRL,
|
||||
.end = IRQ_ORION_USB1_CTRL,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 ehci_dmamask = 0xffffffffUL;
|
||||
|
||||
static struct platform_device orion_ehci0 = {
|
||||
.name = "orion-ehci",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &ehci_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.resource = orion_ehci0_resources,
|
||||
.num_resources = ARRAY_SIZE(orion_ehci0_resources),
|
||||
};
|
||||
|
||||
static struct platform_device orion_ehci1 = {
|
||||
.name = "orion-ehci",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.dma_mask = &ehci_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.resource = orion_ehci1_resources,
|
||||
.num_resources = ARRAY_SIZE(orion_ehci1_resources),
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Gigabit Ethernet port
|
||||
* (The Orion and Discovery (MV643xx) families use the same Ethernet driver)
|
||||
****************************************************************************/
|
||||
|
||||
static struct resource orion_eth_shared_resources[] = {
|
||||
{
|
||||
.start = ORION_ETH_REG_BASE,
|
||||
.end = ORION_ETH_REG_BASE + 0xffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device orion_eth_shared = {
|
||||
.name = MV643XX_ETH_SHARED_NAME,
|
||||
.id = 0,
|
||||
.num_resources = 1,
|
||||
.resource = orion_eth_shared_resources,
|
||||
};
|
||||
|
||||
static struct resource orion_eth_resources[] = {
|
||||
{
|
||||
.name = "eth irq",
|
||||
.start = IRQ_ORION_ETH_SUM,
|
||||
.end = IRQ_ORION_ETH_SUM,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device orion_eth = {
|
||||
.name = MV643XX_ETH_NAME,
|
||||
.id = 0,
|
||||
.num_resources = 1,
|
||||
.resource = orion_eth_resources,
|
||||
};
|
||||
|
||||
void __init orion_eth_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
{
|
||||
orion_eth.dev.platform_data = eth_data;
|
||||
platform_device_register(&orion_eth_shared);
|
||||
platform_device_register(&orion_eth);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* I2C controller
|
||||
* (The Orion and Discovery (MV643xx) families share the same I2C controller)
|
||||
****************************************************************************/
|
||||
|
||||
static struct mv64xxx_i2c_pdata orion_i2c_pdata = {
|
||||
.freq_m = 8, /* assumes 166 MHz TCLK */
|
||||
.freq_n = 3,
|
||||
.timeout = 1000, /* Default timeout of 1 second */
|
||||
};
|
||||
|
||||
static struct resource orion_i2c_resources[] = {
|
||||
{
|
||||
.name = "i2c base",
|
||||
.start = I2C_BASE,
|
||||
.end = I2C_BASE + 0x20 -1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
{
|
||||
.name = "i2c irq",
|
||||
.start = IRQ_ORION_I2C,
|
||||
.end = IRQ_ORION_I2C,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device orion_i2c = {
|
||||
.name = MV64XXX_I2C_CTLR_NAME,
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(orion_i2c_resources),
|
||||
.resource = orion_i2c_resources,
|
||||
.dev = {
|
||||
.platform_data = &orion_i2c_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* General
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Identify device ID and rev from PCIE configuration header space '0'.
|
||||
*/
|
||||
static void orion_id(u32 *dev, u32 *rev, char **dev_name)
|
||||
{
|
||||
orion_pcie_id(dev, rev);
|
||||
|
||||
if (*dev == MV88F5281_DEV_ID) {
|
||||
if (*rev == MV88F5281_REV_D2) {
|
||||
*dev_name = "MV88F5281-D2";
|
||||
} else if (*rev == MV88F5281_REV_D1) {
|
||||
*dev_name = "MV88F5281-D1";
|
||||
} else {
|
||||
*dev_name = "MV88F5281-Rev-Unsupported";
|
||||
}
|
||||
} else if (*dev == MV88F5182_DEV_ID) {
|
||||
if (*rev == MV88F5182_REV_A2) {
|
||||
*dev_name = "MV88F5182-A2";
|
||||
} else {
|
||||
*dev_name = "MV88F5182-Rev-Unsupported";
|
||||
}
|
||||
} else if (*dev == MV88F5181_DEV_ID) {
|
||||
if (*rev == MV88F5181_REV_B1) {
|
||||
*dev_name = "MV88F5181-Rev-B1";
|
||||
} else {
|
||||
*dev_name = "MV88F5181-Rev-Unsupported";
|
||||
}
|
||||
} else {
|
||||
*dev_name = "Device-Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void __init orion_init(void)
|
||||
{
|
||||
char *dev_name;
|
||||
u32 dev, rev;
|
||||
|
||||
orion_id(&dev, &rev, &dev_name);
|
||||
printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, ORION_TCLK);
|
||||
|
||||
/*
|
||||
* Setup Orion address map
|
||||
*/
|
||||
orion_setup_cpu_wins();
|
||||
orion_setup_usb_wins();
|
||||
orion_setup_eth_wins();
|
||||
orion_setup_pci_wins();
|
||||
orion_setup_pcie_wins();
|
||||
if (dev == MV88F5182_DEV_ID)
|
||||
orion_setup_sata_wins();
|
||||
|
||||
/*
|
||||
* REgister devices
|
||||
*/
|
||||
platform_device_register(&orion_uart);
|
||||
platform_device_register(&orion_ehci0);
|
||||
if (dev == MV88F5182_DEV_ID)
|
||||
platform_device_register(&orion_ehci1);
|
||||
platform_device_register(&orion_i2c);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
#ifndef __ARCH_ORION_COMMON_H__
|
||||
#define __ARCH_ORION_COMMON_H__
|
||||
|
||||
/*
|
||||
* Basic Orion init functions used early by machine-setup.
|
||||
*/
|
||||
|
||||
void __init orion_map_io(void);
|
||||
void __init orion_init_irq(void);
|
||||
void __init orion_init(void);
|
||||
|
||||
/*
|
||||
* Enumerations and functions for Orion windows mapping. Used by Orion core
|
||||
* functions to map its interfaces and by the machine-setup to map its on-
|
||||
* board devices. Details in /mach-orion/addr-map.c
|
||||
*/
|
||||
|
||||
enum orion_target {
|
||||
ORION_DEV_BOOT = 0,
|
||||
ORION_DEV0,
|
||||
ORION_DEV1,
|
||||
ORION_DEV2,
|
||||
ORION_PCIE_MEM,
|
||||
ORION_PCIE_IO,
|
||||
ORION_PCI_MEM,
|
||||
ORION_PCI_IO,
|
||||
ORION_DDR,
|
||||
ORION_REGS,
|
||||
ORION_MAX_TARGETS
|
||||
};
|
||||
|
||||
void orion_setup_cpu_win(enum orion_target target, u32 base, u32 size, int remap);
|
||||
void orion_setup_cpu_wins(void);
|
||||
void orion_setup_eth_wins(void);
|
||||
void orion_setup_usb_wins(void);
|
||||
void orion_setup_pci_wins(void);
|
||||
void orion_setup_pcie_wins(void);
|
||||
void orion_setup_sata_wins(void);
|
||||
|
||||
/*
|
||||
* Shared code used internally by other Orion core functions.
|
||||
* (/mach-orion/pci.c)
|
||||
*/
|
||||
|
||||
struct pci_sys_data;
|
||||
struct pci_bus;
|
||||
|
||||
void orion_pcie_id(u32 *dev, u32 *rev);
|
||||
u32 orion_pcie_local_bus_nr(void);
|
||||
u32 orion_pci_local_bus_nr(void);
|
||||
u32 orion_pci_local_dev_nr(void);
|
||||
int orion_pci_sys_setup(int nr, struct pci_sys_data *sys);
|
||||
struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
|
||||
int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 *val);
|
||||
int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func, u32 where, u32 size, u32 val);
|
||||
|
||||
/*
|
||||
* Valid GPIO pins according to MPP setup, used by machine-setup.
|
||||
* (/mach-orion/gpio.c).
|
||||
*/
|
||||
|
||||
void __init orion_gpio_set_valid_pins(u32 pins);
|
||||
void gpio_display(void); /* debug */
|
||||
|
||||
/*
|
||||
* Orion system timer (clocksource + clockevnt, /mach-orion/time.c)
|
||||
*/
|
||||
extern struct sys_timer orion_timer;
|
||||
|
||||
/*
|
||||
* Pull in Orion Ethernet platform_data, used by machine-setup
|
||||
*/
|
||||
|
||||
struct mv643xx_eth_platform_data;
|
||||
|
||||
void __init orion_eth_init(struct mv643xx_eth_platform_data *eth_data);
|
||||
|
||||
#endif /* __ARCH_ORION_COMMON_H__ */
|
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
* arch/arm/mach-orion/db88f5281-setup.c
|
||||
*
|
||||
* Marvell Orion-2 Development Board Setup
|
||||
*
|
||||
* Maintainer: Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/pci.h>
|
||||
#include <asm/arch/orion.h>
|
||||
#include <asm/arch/platform.h>
|
||||
#include "common.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* DB-88F5281 on board devices
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* 512K NOR flash Device bus boot chip select
|
||||
*/
|
||||
|
||||
#define DB88F5281_NOR_BOOT_BASE 0xf4000000
|
||||
#define DB88F5281_NOR_BOOT_SIZE SZ_512K
|
||||
|
||||
/*
|
||||
* 7-Segment on Device bus chip select 0
|
||||
*/
|
||||
|
||||
#define DB88F5281_7SEG_BASE 0xfa000000
|
||||
#define DB88F5281_7SEG_SIZE SZ_1K
|
||||
|
||||
/*
|
||||
* 32M NOR flash on Device bus chip select 1
|
||||
*/
|
||||
|
||||
#define DB88F5281_NOR_BASE 0xfc000000
|
||||
#define DB88F5281_NOR_SIZE SZ_32M
|
||||
|
||||
/*
|
||||
* 32M NAND flash on Device bus chip select 2
|
||||
*/
|
||||
|
||||
#define DB88F5281_NAND_BASE 0xfa800000
|
||||
#define DB88F5281_NAND_SIZE SZ_1K
|
||||
|
||||
/*
|
||||
* PCI
|
||||
*/
|
||||
|
||||
#define DB88F5281_PCI_SLOT0_OFFS 7
|
||||
#define DB88F5281_PCI_SLOT0_IRQ_PIN 12
|
||||
#define DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN 13
|
||||
|
||||
/*****************************************************************************
|
||||
* 512M NOR Flash on Device bus Boot CS
|
||||
****************************************************************************/
|
||||
|
||||
static struct physmap_flash_data db88f5281_boot_flash_data = {
|
||||
.width = 1, /* 8 bit bus width */
|
||||
};
|
||||
|
||||
static struct resource db88f5281_boot_flash_resource = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
.start = DB88F5281_NOR_BOOT_BASE,
|
||||
.end = DB88F5281_NOR_BOOT_BASE + DB88F5281_NOR_BOOT_SIZE - 1,
|
||||
};
|
||||
|
||||
static struct platform_device db88f5281_boot_flash = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &db88f5281_boot_flash_data,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = &db88f5281_boot_flash_resource,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* 32M NOR Flash on Device bus CS1
|
||||
****************************************************************************/
|
||||
|
||||
static struct physmap_flash_data db88f5281_nor_flash_data = {
|
||||
.width = 4, /* 32 bit bus width */
|
||||
};
|
||||
|
||||
static struct resource db88f5281_nor_flash_resource = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
.start = DB88F5281_NOR_BASE,
|
||||
.end = DB88F5281_NOR_BASE + DB88F5281_NOR_SIZE - 1,
|
||||
};
|
||||
|
||||
static struct platform_device db88f5281_nor_flash = {
|
||||
.name = "physmap-flash",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.platform_data = &db88f5281_nor_flash_data,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = &db88f5281_nor_flash_resource,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* 32M NAND Flash on Device bus CS2
|
||||
****************************************************************************/
|
||||
|
||||
static struct mtd_partition db88f5281_nand_parts[] = {
|
||||
{
|
||||
.name = "kernel",
|
||||
.offset = 0,
|
||||
.size = SZ_2M,
|
||||
},
|
||||
{
|
||||
.name = "root",
|
||||
.offset = SZ_2M,
|
||||
.size = (SZ_16M - SZ_2M),
|
||||
},
|
||||
{
|
||||
.name = "user",
|
||||
.offset = SZ_16M,
|
||||
.size = SZ_8M,
|
||||
},
|
||||
{
|
||||
.name = "recovery",
|
||||
.offset = (SZ_16M + SZ_8M),
|
||||
.size = SZ_8M,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource db88f5281_nand_resource = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
.start = DB88F5281_NAND_BASE,
|
||||
.end = DB88F5281_NAND_BASE + DB88F5281_NAND_SIZE - 1,
|
||||
};
|
||||
|
||||
static struct orion_nand_data db88f5281_nand_data = {
|
||||
.parts = db88f5281_nand_parts,
|
||||
.nr_parts = ARRAY_SIZE(db88f5281_nand_parts),
|
||||
.cle = 0,
|
||||
.ale = 1,
|
||||
.width = 8,
|
||||
};
|
||||
|
||||
static struct platform_device db88f5281_nand_flash = {
|
||||
.name = "orion_nand",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &db88f5281_nand_data,
|
||||
},
|
||||
.resource = &db88f5281_nand_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* 7-Segment on Device bus CS0
|
||||
* Dummy counter every 2 sec
|
||||
****************************************************************************/
|
||||
|
||||
static void __iomem *db88f5281_7seg;
|
||||
static struct timer_list db88f5281_timer;
|
||||
|
||||
static void db88f5281_7seg_event(unsigned long data)
|
||||
{
|
||||
static int count = 0;
|
||||
writel(0, db88f5281_7seg + (count << 4));
|
||||
count = (count + 1) & 7;
|
||||
mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
|
||||
}
|
||||
|
||||
static int __init db88f5281_7seg_init(void)
|
||||
{
|
||||
if (machine_is_db88f5281()) {
|
||||
db88f5281_7seg = ioremap(DB88F5281_7SEG_BASE,
|
||||
DB88F5281_7SEG_SIZE);
|
||||
if (!db88f5281_7seg) {
|
||||
printk(KERN_ERR "Failed to ioremap db88f5281_7seg\n");
|
||||
return -EIO;
|
||||
}
|
||||
setup_timer(&db88f5281_timer, db88f5281_7seg_event, 0);
|
||||
mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(db88f5281_7seg_init);
|
||||
|
||||
/*****************************************************************************
|
||||
* PCI
|
||||
****************************************************************************/
|
||||
|
||||
void __init db88f5281_pci_preinit(void)
|
||||
{
|
||||
int pin;
|
||||
|
||||
/*
|
||||
* Configure PCI GPIO IRQ pins
|
||||
*/
|
||||
pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
|
||||
if (gpio_request(pin, "PCI Int1") == 0) {
|
||||
if (gpio_direction_input(pin) == 0) {
|
||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
||||
} else {
|
||||
printk(KERN_ERR "db88f5281_pci_preinit faield to "
|
||||
"set_irq_type pin %d\n", pin);
|
||||
gpio_free(pin);
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
|
||||
}
|
||||
|
||||
pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
|
||||
if (gpio_request(pin, "PCI Int2") == 0) {
|
||||
if (gpio_direction_input(pin) == 0) {
|
||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
||||
} else {
|
||||
printk(KERN_ERR "db88f5281_pci_preinit faield "
|
||||
"to set_irq_type pin %d\n", pin);
|
||||
gpio_free(pin);
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init db88f5281_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
/*
|
||||
* PCIE IRQ is connected internally (not GPIO)
|
||||
*/
|
||||
if (dev->bus->number == orion_pcie_local_bus_nr())
|
||||
return IRQ_ORION_PCIE0_INT;
|
||||
|
||||
/*
|
||||
* PCI IRQs are connected via GPIOs
|
||||
*/
|
||||
switch (slot - DB88F5281_PCI_SLOT0_OFFS) {
|
||||
case 0:
|
||||
return gpio_to_irq(DB88F5281_PCI_SLOT0_IRQ_PIN);
|
||||
case 1:
|
||||
case 2:
|
||||
return gpio_to_irq(DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static struct hw_pci db88f5281_pci __initdata = {
|
||||
.nr_controllers = 2,
|
||||
.preinit = db88f5281_pci_preinit,
|
||||
.swizzle = pci_std_swizzle,
|
||||
.setup = orion_pci_sys_setup,
|
||||
.scan = orion_pci_sys_scan_bus,
|
||||
.map_irq = db88f5281_pci_map_irq,
|
||||
};
|
||||
|
||||
static int __init db88f5281_pci_init(void)
|
||||
{
|
||||
if (machine_is_db88f5281())
|
||||
pci_common_init(&db88f5281_pci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(db88f5281_pci_init);
|
||||
|
||||
/*****************************************************************************
|
||||
* Ethernet
|
||||
****************************************************************************/
|
||||
static struct mv643xx_eth_platform_data db88f5281_eth_data = {
|
||||
.phy_addr = 8,
|
||||
.force_phy_addr = 1,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* RTC DS1339 on I2C bus
|
||||
****************************************************************************/
|
||||
static struct i2c_board_info __initdata db88f5281_i2c_rtc = {
|
||||
.driver_name = "rtc-ds1307",
|
||||
.type = "ds1339",
|
||||
.addr = 0x68,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* General Setup
|
||||
****************************************************************************/
|
||||
|
||||
static struct platform_device *db88f5281_devs[] __initdata = {
|
||||
&db88f5281_boot_flash,
|
||||
&db88f5281_nor_flash,
|
||||
&db88f5281_nand_flash,
|
||||
};
|
||||
|
||||
static void __init db88f5281_init(void)
|
||||
{
|
||||
/*
|
||||
* Basic Orion setup. Need to be called early.
|
||||
*/
|
||||
orion_init();
|
||||
|
||||
/*
|
||||
* Setup the CPU address decode windows for our on-board devices
|
||||
*/
|
||||
orion_setup_cpu_win(ORION_DEV_BOOT, DB88F5281_NOR_BOOT_BASE,
|
||||
DB88F5281_NOR_BOOT_SIZE, -1);
|
||||
orion_setup_cpu_win(ORION_DEV0, DB88F5281_7SEG_BASE,
|
||||
DB88F5281_7SEG_SIZE, -1);
|
||||
orion_setup_cpu_win(ORION_DEV1, DB88F5281_NOR_BASE,
|
||||
DB88F5281_NOR_SIZE, -1);
|
||||
orion_setup_cpu_win(ORION_DEV2, DB88F5281_NAND_BASE,
|
||||
DB88F5281_NAND_SIZE, -1);
|
||||
|
||||
/*
|
||||
* Setup Multiplexing Pins:
|
||||
* MPP0: GPIO (USB Over Current) MPP1: GPIO (USB Vbat input)
|
||||
* MPP2: PCI_REQn[2] MPP3: PCI_GNTn[2]
|
||||
* MPP4: PCI_REQn[3] MPP5: PCI_GNTn[3]
|
||||
* MPP6: GPIO (JP0, CON17.2) MPP7: GPIO (JP1, CON17.1)
|
||||
* MPP8: GPIO (JP2, CON11.2) MPP9: GPIO (JP3, CON11.3)
|
||||
* MPP10: GPIO (RTC int) MPP11: GPIO (Baud Rate Generator)
|
||||
* MPP12: GPIO (PCI int 1) MPP13: GPIO (PCI int 2)
|
||||
* MPP14: NAND_REn[2] MPP15: NAND_WEn[2]
|
||||
* MPP16: UART1_RX MPP17: UART1_TX
|
||||
* MPP18: UART1_CTS MPP19: UART1_RTS
|
||||
* MPP-DEV: DEV_D[16:31]
|
||||
*/
|
||||
orion_write(MPP_0_7_CTRL, 0x00222203);
|
||||
orion_write(MPP_8_15_CTRL, 0x44000000);
|
||||
orion_write(MPP_16_19_CTRL, 0);
|
||||
orion_write(MPP_DEV_CTRL, 0);
|
||||
|
||||
orion_gpio_set_valid_pins(0x00003fc3);
|
||||
|
||||
platform_add_devices(db88f5281_devs, ARRAY_SIZE(db88f5281_devs));
|
||||
i2c_register_board_info(0, &db88f5281_i2c_rtc, 1);
|
||||
orion_eth_init(&db88f5281_eth_data);
|
||||
}
|
||||
|
||||
MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
|
||||
/* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */
|
||||
.phys_io = ORION_REGS_BASE,
|
||||
.io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xfffc,
|
||||
.boot_params = 0x00000100,
|
||||
.init_machine = db88f5281_init,
|
||||
.map_io = orion_map_io,
|
||||
.init_irq = orion_init_irq,
|
||||
.timer = &orion_timer,
|
||||
MACHINE_END
|
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* arch/arm/mach-orion/dns323-setup.c
|
||||
*
|
||||
* Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/pci.h>
|
||||
#include <asm/arch/orion.h>
|
||||
#include <asm/arch/platform.h>
|
||||
#include "common.h"
|
||||
|
||||
#define DNS323_GPIO_LED_RIGHT_AMBER 1
|
||||
#define DNS323_GPIO_LED_LEFT_AMBER 2
|
||||
#define DNS323_GPIO_LED_POWER 5
|
||||
#define DNS323_GPIO_OVERTEMP 6
|
||||
#define DNS323_GPIO_RTC 7
|
||||
#define DNS323_GPIO_POWER_OFF 8
|
||||
#define DNS323_GPIO_KEY_POWER 9
|
||||
#define DNS323_GPIO_KEY_RESET 10
|
||||
|
||||
/****************************************************************************
|
||||
* PCI setup
|
||||
*/
|
||||
|
||||
static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
/* PCI-E */
|
||||
if (dev->bus->number == orion_pcie_local_bus_nr())
|
||||
return IRQ_ORION_PCIE0_INT;
|
||||
|
||||
pr_err("%s: requested mapping for unknown bus\n", __func__);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct hw_pci dns323_pci __initdata = {
|
||||
.nr_controllers = 1,
|
||||
.swizzle = pci_std_swizzle,
|
||||
.setup = orion_pci_sys_setup,
|
||||
.scan = orion_pci_sys_scan_bus,
|
||||
.map_irq = dns323_pci_map_irq,
|
||||
};
|
||||
|
||||
static int __init dns323_pci_init(void)
|
||||
{
|
||||
if (machine_is_dns323())
|
||||
pci_common_init(&dns323_pci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(dns323_pci_init);
|
||||
|
||||
/****************************************************************************
|
||||
* Ethernet
|
||||
*/
|
||||
|
||||
static struct mv643xx_eth_platform_data dns323_eth_data = {
|
||||
.phy_addr = 8,
|
||||
.force_phy_addr = 1,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* 8MiB NOR flash (Spansion S29GL064M90TFIR4)
|
||||
*
|
||||
* Layout as used by D-Link:
|
||||
* 0x00000000-0x00010000 : "MTD1"
|
||||
* 0x00010000-0x00020000 : "MTD2"
|
||||
* 0x00020000-0x001a0000 : "Linux Kernel"
|
||||
* 0x001a0000-0x007d0000 : "File System"
|
||||
* 0x007d0000-0x00800000 : "u-boot"
|
||||
*/
|
||||
|
||||
#define DNS323_NOR_BOOT_BASE 0xf4000000
|
||||
#define DNS323_NOR_BOOT_SIZE SZ_8M
|
||||
|
||||
static struct mtd_partition dns323_partitions[] = {
|
||||
{
|
||||
.name = "MTD1",
|
||||
.size = 0x00010000,
|
||||
.offset = 0,
|
||||
}, {
|
||||
.name = "MTD2",
|
||||
.size = 0x00010000,
|
||||
.offset = 0x00010000,
|
||||
}, {
|
||||
.name = "Linux Kernel",
|
||||
.size = 0x00180000,
|
||||
.offset = 0x00020000,
|
||||
}, {
|
||||
.name = "File System",
|
||||
.size = 0x00630000,
|
||||
.offset = 0x001A0000,
|
||||
}, {
|
||||
.name = "u-boot",
|
||||
.size = 0x00030000,
|
||||
.offset = 0x007d0000,
|
||||
}
|
||||
};
|
||||
|
||||
static struct physmap_flash_data dns323_nor_flash_data = {
|
||||
.width = 1,
|
||||
.parts = dns323_partitions,
|
||||
.nr_parts = ARRAY_SIZE(dns323_partitions)
|
||||
};
|
||||
|
||||
static struct resource dns323_nor_flash_resource = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
.start = DNS323_NOR_BOOT_BASE,
|
||||
.end = DNS323_NOR_BOOT_BASE + DNS323_NOR_BOOT_SIZE - 1,
|
||||
};
|
||||
|
||||
static struct platform_device dns323_nor_flash = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = { .platform_data = &dns323_nor_flash_data, },
|
||||
.resource = &dns323_nor_flash_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* GPIO LEDs (simple - doesn't use hardware blinking support)
|
||||
*/
|
||||
|
||||
static struct gpio_led dns323_leds[] = {
|
||||
{
|
||||
.name = "power:blue",
|
||||
.gpio = DNS323_GPIO_LED_POWER,
|
||||
.active_low = 1,
|
||||
}, {
|
||||
.name = "right:amber",
|
||||
.gpio = DNS323_GPIO_LED_RIGHT_AMBER,
|
||||
.active_low = 1,
|
||||
}, {
|
||||
.name = "left:amber",
|
||||
.gpio = DNS323_GPIO_LED_LEFT_AMBER,
|
||||
.active_low = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpio_led_platform_data dns323_led_data = {
|
||||
.num_leds = ARRAY_SIZE(dns323_leds),
|
||||
.leds = dns323_leds,
|
||||
};
|
||||
|
||||
static struct platform_device dns323_gpio_leds = {
|
||||
.name = "leds-gpio",
|
||||
.id = -1,
|
||||
.dev = { .platform_data = &dns323_led_data, },
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* GPIO Attached Keys
|
||||
*/
|
||||
|
||||
static struct gpio_keys_button dns323_buttons[] = {
|
||||
{
|
||||
.code = KEY_RESTART,
|
||||
.gpio = DNS323_GPIO_KEY_RESET,
|
||||
.desc = "Reset Button",
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.code = KEY_POWER,
|
||||
.gpio = DNS323_GPIO_KEY_POWER,
|
||||
.desc = "Power Button",
|
||||
.active_low = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static struct gpio_keys_platform_data dns323_button_data = {
|
||||
.buttons = dns323_buttons,
|
||||
.nbuttons = ARRAY_SIZE(dns323_buttons),
|
||||
};
|
||||
|
||||
static struct platform_device dns323_button_device = {
|
||||
.name = "gpio-keys",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
.dev = { .platform_data = &dns323_button_data, },
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* General Setup
|
||||
*/
|
||||
|
||||
static struct platform_device *dns323_plat_devices[] __initdata = {
|
||||
&dns323_nor_flash,
|
||||
&dns323_gpio_leds,
|
||||
&dns323_button_device,
|
||||
};
|
||||
|
||||
/*
|
||||
* On the DNS-323 the following devices are attached via I2C:
|
||||
*
|
||||
* i2c addr | chip | description
|
||||
* 0x3e | GMT G760Af | fan speed PWM controller
|
||||
* 0x48 | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible)
|
||||
* 0x68 | ST M41T80 | RTC w/ alarm
|
||||
*/
|
||||
static struct i2c_board_info __initdata dns323_i2c_devices[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("g760a", 0x3e),
|
||||
.type = "g760a",
|
||||
},
|
||||
#if 0
|
||||
/* this entry requires the new-style driver model lm75 driver,
|
||||
* for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
|
||||
{
|
||||
I2C_BOARD_INFO("lm75", 0x48),
|
||||
.type = "g751",
|
||||
},
|
||||
#endif
|
||||
{
|
||||
I2C_BOARD_INFO("rtc-m41t80", 0x68),
|
||||
.type = "m41t80",
|
||||
}
|
||||
};
|
||||
|
||||
/* DNS-323 specific power off method */
|
||||
static void dns323_power_off(void)
|
||||
{
|
||||
pr_info("%s: triggering power-off...\n", __func__);
|
||||
gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
|
||||
}
|
||||
|
||||
static void __init dns323_init(void)
|
||||
{
|
||||
/* Setup basic Orion functions. Need to be called early. */
|
||||
orion_init();
|
||||
|
||||
/* setup flash mapping
|
||||
* CS3 holds a 8 MB Spansion S29GL064M90TFIR4
|
||||
*/
|
||||
orion_setup_cpu_win(ORION_DEV_BOOT, DNS323_NOR_BOOT_BASE,
|
||||
DNS323_NOR_BOOT_SIZE, -1);
|
||||
|
||||
/* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIE
|
||||
*
|
||||
* Open a special address decode windows for the PCIE WA.
|
||||
*/
|
||||
orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE);
|
||||
orion_write(ORION_REGS_BASE | 0x20070,
|
||||
(0x7941 | (((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
|
||||
|
||||
/* set MPP to 0 as D-Link's 2.6.12.6 kernel did */
|
||||
orion_write(MPP_0_7_CTRL, 0);
|
||||
orion_write(MPP_8_15_CTRL, 0);
|
||||
orion_write(MPP_16_19_CTRL, 0);
|
||||
orion_write(MPP_DEV_CTRL, 0);
|
||||
|
||||
/* Define used GPIO pins
|
||||
|
||||
GPIO Map:
|
||||
|
||||
| 0 | | PEX_RST_OUT (not controlled by GPIO)
|
||||
| 1 | Out | right amber LED (= sata ch0 LED) (low-active)
|
||||
| 2 | Out | left amber LED (= sata ch1 LED) (low-active)
|
||||
| 3 | Out | //unknown//
|
||||
| 4 | Out | power button LED (low-active, together with pin #5)
|
||||
| 5 | Out | power button LED (low-active, together with pin #4)
|
||||
| 6 | In | GMT G751-2f overtemp. shutdown signal (low-active)
|
||||
| 7 | In | M41T80 nIRQ/OUT/SQW signal
|
||||
| 8 | Out | triggers power off (high-active)
|
||||
| 9 | In | power button switch (low-active)
|
||||
| 10 | In | reset button switch (low-active)
|
||||
| 11 | Out | //unknown//
|
||||
| 12 | Out | //unknown//
|
||||
| 13 | Out | //unknown//
|
||||
| 14 | Out | //unknown//
|
||||
| 15 | Out | //unknown//
|
||||
*/
|
||||
orion_gpio_set_valid_pins(0x07f6);
|
||||
|
||||
/* register dns323 specific power-off method */
|
||||
if ((gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0)
|
||||
|| (gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0))
|
||||
pr_err("DNS323: failed to setup power-off GPIO\n");
|
||||
|
||||
pm_power_off = dns323_power_off;
|
||||
|
||||
/* register flash and other platform devices */
|
||||
platform_add_devices(dns323_plat_devices,
|
||||
ARRAY_SIZE(dns323_plat_devices));
|
||||
|
||||
i2c_register_board_info(0, dns323_i2c_devices,
|
||||
ARRAY_SIZE(dns323_i2c_devices));
|
||||
|
||||
orion_eth_init(&dns323_eth_data);
|
||||
}
|
||||
|
||||
/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
|
||||
MACHINE_START(DNS323, "D-Link DNS-323")
|
||||
/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
|
||||
.phys_io = ORION_REGS_BASE,
|
||||
.io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC,
|
||||
.boot_params = 0x00000100,
|
||||
.init_machine = dns323_init,
|
||||
.map_io = orion_map_io,
|
||||
.init_irq = orion_init_irq,
|
||||
.timer = &orion_timer,
|
||||
MACHINE_END
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* arch/arm/mach-orion/gpio.c
|
||||
*
|
||||
* GPIO functions for Marvell Orion System On Chip
|
||||
*
|
||||
* Maintainer: Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/orion.h>
|
||||
#include "common.h"
|
||||
|
||||
static DEFINE_SPINLOCK(gpio_lock);
|
||||
static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
|
||||
static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */
|
||||
|
||||
void __init orion_gpio_set_valid_pins(u32 pins)
|
||||
{
|
||||
gpio_valid[0] = pins;
|
||||
}
|
||||
|
||||
/*
|
||||
* GENERIC_GPIO primitives
|
||||
*/
|
||||
int gpio_direction_input(unsigned pin)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
|
||||
pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
/*
|
||||
* Some callers might have not used the gpio_request(),
|
||||
* so flag this pin as requested now.
|
||||
*/
|
||||
if (!gpio_label[pin])
|
||||
gpio_label[pin] = "?";
|
||||
|
||||
orion_setbits(GPIO_IO_CONF, 1 << pin);
|
||||
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_direction_input);
|
||||
|
||||
int gpio_direction_output(unsigned pin, int value)
|
||||
{
|
||||
unsigned long flags;
|
||||
int mask;
|
||||
|
||||
if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
|
||||
pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
/*
|
||||
* Some callers might have not used the gpio_request(),
|
||||
* so flag this pin as requested now.
|
||||
*/
|
||||
if (!gpio_label[pin])
|
||||
gpio_label[pin] = "?";
|
||||
|
||||
mask = 1 << pin;
|
||||
orion_clrbits(GPIO_BLINK_EN, mask);
|
||||
if (value)
|
||||
orion_setbits(GPIO_OUT, mask);
|
||||
else
|
||||
orion_clrbits(GPIO_OUT, mask);
|
||||
orion_clrbits(GPIO_IO_CONF, mask);
|
||||
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_direction_output);
|
||||
|
||||
int gpio_get_value(unsigned pin)
|
||||
{
|
||||
int val, mask = 1 << pin;
|
||||
|
||||
if (orion_read(GPIO_IO_CONF) & mask)
|
||||
val = orion_read(GPIO_DATA_IN) ^ orion_read(GPIO_IN_POL);
|
||||
else
|
||||
val = orion_read(GPIO_OUT);
|
||||
|
||||
return val & mask;
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_get_value);
|
||||
|
||||
void gpio_set_value(unsigned pin, int value)
|
||||
{
|
||||
unsigned long flags;
|
||||
int mask = 1 << pin;
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
orion_clrbits(GPIO_BLINK_EN, mask);
|
||||
if (value)
|
||||
orion_setbits(GPIO_OUT, mask);
|
||||
else
|
||||
orion_clrbits(GPIO_OUT, mask);
|
||||
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_set_value);
|
||||
|
||||
void orion_gpio_set_blink(unsigned pin, int blink)
|
||||
{
|
||||
unsigned long flags;
|
||||
int mask = 1 << pin;
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
orion_clrbits(GPIO_OUT, mask);
|
||||
if (blink)
|
||||
orion_setbits(GPIO_BLINK_EN, mask);
|
||||
else
|
||||
orion_clrbits(GPIO_BLINK_EN, mask);
|
||||
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL(orion_gpio_set_blink);
|
||||
|
||||
int gpio_request(unsigned pin, const char *label)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
|
||||
pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
|
||||
if (gpio_label[pin]) {
|
||||
pr_debug("%s: GPIO %d already used as %s\n",
|
||||
__FUNCTION__, pin, gpio_label[pin]);
|
||||
ret = -EBUSY;
|
||||
} else
|
||||
gpio_label[pin] = label ? label : "?";
|
||||
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_request);
|
||||
|
||||
void gpio_free(unsigned pin)
|
||||
{
|
||||
if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
|
||||
pr_debug("%s: invalid GPIO %d\n", __FUNCTION__, pin);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gpio_label[pin])
|
||||
pr_warning("%s: GPIO %d already freed\n", __FUNCTION__, pin);
|
||||
else
|
||||
gpio_label[pin] = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(gpio_free);
|
||||
|
||||
/* Debug helper */
|
||||
void gpio_display(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < GPIO_MAX; i++) {
|
||||
printk(KERN_DEBUG "Pin-%d: ", i);
|
||||
|
||||
if (!test_bit(i, gpio_valid)) {
|
||||
printk("non-GPIO\n");
|
||||
} else if (!gpio_label[i]) {
|
||||
printk("GPIO, free\n");
|
||||
} else {
|
||||
printk("GPIO, used by %s, ", gpio_label[i]);
|
||||
if (orion_read(GPIO_IO_CONF) & (1 << i)) {
|
||||
printk("input, active %s, level %s, edge %s\n",
|
||||
((orion_read(GPIO_IN_POL) >> i) & 1) ? "low" : "high",
|
||||
((orion_read(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked",
|
||||
((orion_read(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked");
|
||||
} else {
|
||||
printk("output, val=%d\n", (orion_read(GPIO_OUT) >> i) & 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n",
|
||||
MPP_0_7_CTRL, orion_read(MPP_0_7_CTRL));
|
||||
printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n",
|
||||
MPP_8_15_CTRL, orion_read(MPP_8_15_CTRL));
|
||||
printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n",
|
||||
MPP_16_19_CTRL, orion_read(MPP_16_19_CTRL));
|
||||
printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n",
|
||||
MPP_DEV_CTRL, orion_read(MPP_DEV_CTRL));
|
||||
printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n",
|
||||
GPIO_OUT, orion_read(GPIO_OUT));
|
||||
printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n",
|
||||
GPIO_IO_CONF, orion_read(GPIO_IO_CONF));
|
||||
printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n",
|
||||
GPIO_BLINK_EN, orion_read(GPIO_BLINK_EN));
|
||||
printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n",
|
||||
GPIO_IN_POL, orion_read(GPIO_IN_POL));
|
||||
printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n",
|
||||
GPIO_DATA_IN, orion_read(GPIO_DATA_IN));
|
||||
printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n",
|
||||
GPIO_LEVEL_MASK, orion_read(GPIO_LEVEL_MASK));
|
||||
printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n",
|
||||
GPIO_EDGE_CAUSE, orion_read(GPIO_EDGE_CAUSE));
|
||||
printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n",
|
||||
GPIO_EDGE_MASK, orion_read(GPIO_EDGE_MASK));
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* arch/arm/mach-orion/irq.c
|
||||
*
|
||||
* Core IRQ functions for Marvell Orion System On Chip
|
||||
*
|
||||
* Maintainer: Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/arch/orion.h>
|
||||
#include "common.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Orion GPIO IRQ
|
||||
*
|
||||
* GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same
|
||||
* value of the line or the opposite value.
|
||||
*
|
||||
* Level IRQ handlers: DATA_IN is used directly as cause register.
|
||||
* Interrupt are masked by LEVEL_MASK registers.
|
||||
* Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE.
|
||||
* Interrupt are masked by EDGE_MASK registers.
|
||||
* Both-edge handlers: Similar to regular Edge handlers, but also swaps
|
||||
* the polarity to catch the next line transaction.
|
||||
* This is a race condition that might not perfectly
|
||||
* work on some use cases.
|
||||
*
|
||||
* Every eight GPIO lines are grouped (OR'ed) before going up to main
|
||||
* cause register.
|
||||
*
|
||||
* EDGE cause mask
|
||||
* data-in /--------| |-----| |----\
|
||||
* -----| |----- ---- to main cause reg
|
||||
* X \----------------| |----/
|
||||
* polarity LEVEL mask
|
||||
*
|
||||
****************************************************************************/
|
||||
static void orion_gpio_irq_ack(u32 irq)
|
||||
{
|
||||
int pin = irq_to_gpio(irq);
|
||||
if (irq_desc[irq].status & IRQ_LEVEL)
|
||||
/*
|
||||
* Mask bit for level interrupt
|
||||
*/
|
||||
orion_clrbits(GPIO_LEVEL_MASK, 1 << pin);
|
||||
else
|
||||
/*
|
||||
* Clear casue bit for egde interrupt
|
||||
*/
|
||||
orion_clrbits(GPIO_EDGE_CAUSE, 1 << pin);
|
||||
}
|
||||
|
||||
static void orion_gpio_irq_mask(u32 irq)
|
||||
{
|
||||
int pin = irq_to_gpio(irq);
|
||||
if (irq_desc[irq].status & IRQ_LEVEL)
|
||||
orion_clrbits(GPIO_LEVEL_MASK, 1 << pin);
|
||||
else
|
||||
orion_clrbits(GPIO_EDGE_MASK, 1 << pin);
|
||||
}
|
||||
|
||||
static void orion_gpio_irq_unmask(u32 irq)
|
||||
{
|
||||
int pin = irq_to_gpio(irq);
|
||||
if (irq_desc[irq].status & IRQ_LEVEL)
|
||||
orion_setbits(GPIO_LEVEL_MASK, 1 << pin);
|
||||
else
|
||||
orion_setbits(GPIO_EDGE_MASK, 1 << pin);
|
||||
}
|
||||
|
||||
static int orion_gpio_set_irq_type(u32 irq, u32 type)
|
||||
{
|
||||
int pin = irq_to_gpio(irq);
|
||||
struct irq_desc *desc;
|
||||
|
||||
if ((orion_read(GPIO_IO_CONF) & (1 << pin)) == 0) {
|
||||
printk(KERN_ERR "orion_gpio_set_irq_type failed "
|
||||
"(irq %d, pin %d).\n", irq, pin);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
desc = irq_desc + irq;
|
||||
|
||||
switch (type) {
|
||||
case IRQT_HIGH:
|
||||
desc->handle_irq = handle_level_irq;
|
||||
desc->status |= IRQ_LEVEL;
|
||||
orion_clrbits(GPIO_IN_POL, (1 << pin));
|
||||
break;
|
||||
case IRQT_LOW:
|
||||
desc->handle_irq = handle_level_irq;
|
||||
desc->status |= IRQ_LEVEL;
|
||||
orion_setbits(GPIO_IN_POL, (1 << pin));
|
||||
break;
|
||||
case IRQT_RISING:
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
desc->status &= ~IRQ_LEVEL;
|
||||
orion_clrbits(GPIO_IN_POL, (1 << pin));
|
||||
break;
|
||||
case IRQT_FALLING:
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
desc->status &= ~IRQ_LEVEL;
|
||||
orion_setbits(GPIO_IN_POL, (1 << pin));
|
||||
break;
|
||||
case IRQT_BOTHEDGE:
|
||||
desc->handle_irq = handle_edge_irq;
|
||||
desc->status &= ~IRQ_LEVEL;
|
||||
/*
|
||||
* set initial polarity based on current input level
|
||||
*/
|
||||
if ((orion_read(GPIO_IN_POL) ^ orion_read(GPIO_DATA_IN))
|
||||
& (1 << pin))
|
||||
orion_setbits(GPIO_IN_POL, (1 << pin)); /* falling */
|
||||
else
|
||||
orion_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */
|
||||
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
desc->status &= ~IRQ_TYPE_SENSE_MASK;
|
||||
desc->status |= type & IRQ_TYPE_SENSE_MASK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip orion_gpio_irq_chip = {
|
||||
.name = "Orion-IRQ-GPIO",
|
||||
.ack = orion_gpio_irq_ack,
|
||||
.mask = orion_gpio_irq_mask,
|
||||
.unmask = orion_gpio_irq_unmask,
|
||||
.set_type = orion_gpio_set_irq_type,
|
||||
};
|
||||
|
||||
static void orion_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
u32 cause, offs, pin;
|
||||
|
||||
BUG_ON(irq < IRQ_ORION_GPIO_0_7 || irq > IRQ_ORION_GPIO_24_31);
|
||||
offs = (irq - IRQ_ORION_GPIO_0_7) * 8;
|
||||
cause = (orion_read(GPIO_DATA_IN) & orion_read(GPIO_LEVEL_MASK)) |
|
||||
(orion_read(GPIO_EDGE_CAUSE) & orion_read(GPIO_EDGE_MASK));
|
||||
|
||||
for (pin = offs; pin < offs + 8; pin++) {
|
||||
if (cause & (1 << pin)) {
|
||||
irq = gpio_to_irq(pin);
|
||||
desc = irq_desc + irq;
|
||||
if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
|
||||
/* Swap polarity (race with GPIO line) */
|
||||
u32 polarity = orion_read(GPIO_IN_POL);
|
||||
polarity ^= 1 << pin;
|
||||
orion_write(GPIO_IN_POL, polarity);
|
||||
}
|
||||
desc_handle_irq(irq, desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __init orion_init_gpio_irq(void)
|
||||
{
|
||||
int i;
|
||||
struct irq_desc *desc;
|
||||
|
||||
/*
|
||||
* Mask and clear GPIO IRQ interrupts
|
||||
*/
|
||||
orion_write(GPIO_LEVEL_MASK, 0x0);
|
||||
orion_write(GPIO_EDGE_MASK, 0x0);
|
||||
orion_write(GPIO_EDGE_CAUSE, 0x0);
|
||||
|
||||
/*
|
||||
* Register chained level handlers for GPIO IRQs by default.
|
||||
* User can use set_type() if he wants to use edge types handlers.
|
||||
*/
|
||||
for (i = IRQ_ORION_GPIO_START; i < NR_IRQS; i++) {
|
||||
set_irq_chip(i, &orion_gpio_irq_chip);
|
||||
set_irq_handler(i, handle_level_irq);
|
||||
desc = irq_desc + i;
|
||||
desc->status |= IRQ_LEVEL;
|
||||
set_irq_flags(i, IRQF_VALID);
|
||||
}
|
||||
set_irq_chained_handler(IRQ_ORION_GPIO_0_7, orion_gpio_irq_handler);
|
||||
set_irq_chained_handler(IRQ_ORION_GPIO_8_15, orion_gpio_irq_handler);
|
||||
set_irq_chained_handler(IRQ_ORION_GPIO_16_23, orion_gpio_irq_handler);
|
||||
set_irq_chained_handler(IRQ_ORION_GPIO_24_31, orion_gpio_irq_handler);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Orion Main IRQ
|
||||
****************************************************************************/
|
||||
static void orion_main_irq_mask(u32 irq)
|
||||
{
|
||||
orion_clrbits(MAIN_IRQ_MASK, 1 << irq);
|
||||
}
|
||||
|
||||
static void orion_main_irq_unmask(u32 irq)
|
||||
{
|
||||
orion_setbits(MAIN_IRQ_MASK, 1 << irq);
|
||||
}
|
||||
|
||||
static struct irq_chip orion_main_irq_chip = {
|
||||
.name = "Orion-IRQ-Main",
|
||||
.ack = orion_main_irq_mask,
|
||||
.mask = orion_main_irq_mask,
|
||||
.unmask = orion_main_irq_unmask,
|
||||
};
|
||||
|
||||
static void __init orion_init_main_irq(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Mask and clear Main IRQ interrupts
|
||||
*/
|
||||
orion_write(MAIN_IRQ_MASK, 0x0);
|
||||
orion_write(MAIN_IRQ_CAUSE, 0x0);
|
||||
|
||||
/*
|
||||
* Register level handler for Main IRQs
|
||||
*/
|
||||
for (i = 0; i < IRQ_ORION_GPIO_START; i++) {
|
||||
set_irq_chip(i, &orion_main_irq_chip);
|
||||
set_irq_handler(i, handle_level_irq);
|
||||
set_irq_flags(i, IRQF_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
void __init orion_init_irq(void)
|
||||
{
|
||||
orion_init_main_irq();
|
||||
orion_init_gpio_irq();
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* arch/arm/mach-orion/kurobox_pro-setup.c
|
||||
*
|
||||
* Maintainer: Ronen Shitrit <rshitrit@marvell.com>
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/pci.h>
|
||||
#include <asm/arch/orion.h>
|
||||
#include <asm/arch/platform.h>
|
||||
#include "common.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* KUROBOX-PRO Info
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* 256K NOR flash Device bus boot chip select
|
||||
*/
|
||||
|
||||
#define KUROBOX_PRO_NOR_BOOT_BASE 0xf4000000
|
||||
#define KUROBOX_PRO_NOR_BOOT_SIZE SZ_256K
|
||||
|
||||
/*
|
||||
* 256M NAND flash on Device bus chip select 1
|
||||
*/
|
||||
|
||||
#define KUROBOX_PRO_NAND_BASE 0xfc000000
|
||||
#define KUROBOX_PRO_NAND_SIZE SZ_2M
|
||||
|
||||
/*****************************************************************************
|
||||
* 256MB NAND Flash on Device bus CS0
|
||||
****************************************************************************/
|
||||
|
||||
static struct mtd_partition kurobox_pro_nand_parts[] = {
|
||||
{
|
||||
.name = "uImage",
|
||||
.offset = 0,
|
||||
.size = SZ_4M,
|
||||
},
|
||||
{
|
||||
.name = "rootfs",
|
||||
.offset = SZ_4M,
|
||||
.size = SZ_64M,
|
||||
},
|
||||
{
|
||||
.name = "extra",
|
||||
.offset = SZ_4M + SZ_64M,
|
||||
.size = SZ_256M - (SZ_4M + SZ_64M),
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource kurobox_pro_nand_resource = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
.start = KUROBOX_PRO_NAND_BASE,
|
||||
.end = KUROBOX_PRO_NAND_BASE + KUROBOX_PRO_NAND_SIZE - 1,
|
||||
};
|
||||
|
||||
static struct orion_nand_data kurobox_pro_nand_data = {
|
||||
.parts = kurobox_pro_nand_parts,
|
||||
.nr_parts = ARRAY_SIZE(kurobox_pro_nand_parts),
|
||||
.cle = 0,
|
||||
.ale = 1,
|
||||
.width = 8,
|
||||
};
|
||||
|
||||
static struct platform_device kurobox_pro_nand_flash = {
|
||||
.name = "orion_nand",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &kurobox_pro_nand_data,
|
||||
},
|
||||
.resource = &kurobox_pro_nand_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* 256KB NOR Flash on BOOT Device
|
||||
****************************************************************************/
|
||||
|
||||
static struct physmap_flash_data kurobox_pro_nor_flash_data = {
|
||||
.width = 1,
|
||||
};
|
||||
|
||||
static struct resource kurobox_pro_nor_flash_resource = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
.start = KUROBOX_PRO_NOR_BOOT_BASE,
|
||||
.end = KUROBOX_PRO_NOR_BOOT_BASE + KUROBOX_PRO_NOR_BOOT_SIZE - 1,
|
||||
};
|
||||
|
||||
static struct platform_device kurobox_pro_nor_flash = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &kurobox_pro_nor_flash_data,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = &kurobox_pro_nor_flash_resource,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* PCI
|
||||
****************************************************************************/
|
||||
|
||||
static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
/*
|
||||
* PCI isn't used on the Kuro
|
||||
*/
|
||||
if (dev->bus->number == orion_pcie_local_bus_nr())
|
||||
return IRQ_ORION_PCIE0_INT;
|
||||
else
|
||||
printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct hw_pci kurobox_pro_pci __initdata = {
|
||||
.nr_controllers = 1,
|
||||
.swizzle = pci_std_swizzle,
|
||||
.setup = orion_pci_sys_setup,
|
||||
.scan = orion_pci_sys_scan_bus,
|
||||
.map_irq = kurobox_pro_pci_map_irq,
|
||||
};
|
||||
|
||||
static int __init kurobox_pro_pci_init(void)
|
||||
{
|
||||
if (machine_is_kurobox_pro())
|
||||
pci_common_init(&kurobox_pro_pci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(kurobox_pro_pci_init);
|
||||
|
||||
/*****************************************************************************
|
||||
* Ethernet
|
||||
****************************************************************************/
|
||||
|
||||
static struct mv643xx_eth_platform_data kurobox_pro_eth_data = {
|
||||
.phy_addr = 8,
|
||||
.force_phy_addr = 1,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* RTC 5C372a on I2C bus
|
||||
****************************************************************************/
|
||||
static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
|
||||
.driver_name = "rtc-rs5c372",
|
||||
.type = "rs5c372a",
|
||||
.addr = 0x32,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* General Setup
|
||||
****************************************************************************/
|
||||
|
||||
static struct platform_device *kurobox_pro_devices[] __initdata = {
|
||||
&kurobox_pro_nor_flash,
|
||||
&kurobox_pro_nand_flash,
|
||||
};
|
||||
|
||||
static void __init kurobox_pro_init(void)
|
||||
{
|
||||
/*
|
||||
* Setup basic Orion functions. Need to be called early.
|
||||
*/
|
||||
orion_init();
|
||||
|
||||
/*
|
||||
* Setup the CPU address decode windows for our devices
|
||||
*/
|
||||
orion_setup_cpu_win(ORION_DEV_BOOT, KUROBOX_PRO_NOR_BOOT_BASE,
|
||||
KUROBOX_PRO_NOR_BOOT_SIZE, -1);
|
||||
orion_setup_cpu_win(ORION_DEV0, KUROBOX_PRO_NAND_BASE,
|
||||
KUROBOX_PRO_NAND_SIZE, -1);
|
||||
/*
|
||||
* Open a special address decode windows for the PCIE WA.
|
||||
*/
|
||||
orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE);
|
||||
orion_write(ORION_REGS_BASE | 0x20070, (0x7941 |
|
||||
(((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
|
||||
|
||||
/*
|
||||
* Setup Multiplexing Pins --
|
||||
* MPP[0-1] Not used
|
||||
* MPP[2] GPIO Micon
|
||||
* MPP[3] GPIO RTC
|
||||
* MPP[4-5] Not used
|
||||
* MPP[6] Nand Flash REn
|
||||
* MPP[7] Nand Flash WEn
|
||||
* MPP[8-11] Not used
|
||||
* MPP[12] SATA 0 presence Indication
|
||||
* MPP[13] SATA 1 presence Indication
|
||||
* MPP[14] SATA 0 active Indication
|
||||
* MPP[15] SATA 1 active indication
|
||||
* MPP[16-19] Not used
|
||||
*/
|
||||
orion_write(MPP_0_7_CTRL, 0x44220003);
|
||||
orion_write(MPP_8_15_CTRL, 0x55550000);
|
||||
orion_write(MPP_16_19_CTRL, 0x0);
|
||||
|
||||
orion_gpio_set_valid_pins(0x0000000c);
|
||||
|
||||
platform_add_devices(kurobox_pro_devices, ARRAY_SIZE(kurobox_pro_devices));
|
||||
i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
|
||||
orion_eth_init(&kurobox_pro_eth_data);
|
||||
}
|
||||
|
||||
MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
|
||||
/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
|
||||
.phys_io = ORION_REGS_BASE,
|
||||
.io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC,
|
||||
.boot_params = 0x00000100,
|
||||
.init_machine = kurobox_pro_init,
|
||||
.map_io = orion_map_io,
|
||||
.init_irq = orion_init_irq,
|
||||
.timer = &orion_timer,
|
||||
MACHINE_END
|
|
@ -0,0 +1,557 @@
|
|||
/*
|
||||
* arch/arm/mach-orion/pci.c
|
||||
*
|
||||
* PCI and PCIE functions for Marvell Orion System On Chip
|
||||
*
|
||||
* Maintainer: Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <asm/mach/pci.h>
|
||||
#include "common.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* Orion has one PCIE controller and one PCI controller.
|
||||
*
|
||||
* Note1: The local PCIE bus number is '0'. The local PCI bus number
|
||||
* follows the scanned PCIE bridged busses, if any.
|
||||
*
|
||||
* Note2: It is possible for PCI/PCIE agents to access many subsystem's
|
||||
* space, by configuring BARs and Address Decode Windows, e.g. flashes on
|
||||
* device bus, Orion registers, etc. However this code only enable the
|
||||
* access to DDR banks.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* PCIE controller
|
||||
****************************************************************************/
|
||||
#define PCIE_CTRL ORION_PCIE_REG(0x1a00)
|
||||
#define PCIE_STAT ORION_PCIE_REG(0x1a04)
|
||||
#define PCIE_DEV_ID ORION_PCIE_REG(0x0000)
|
||||
#define PCIE_CMD_STAT ORION_PCIE_REG(0x0004)
|
||||
#define PCIE_DEV_REV ORION_PCIE_REG(0x0008)
|
||||
#define PCIE_MASK ORION_PCIE_REG(0x1910)
|
||||
#define PCIE_CONF_ADDR ORION_PCIE_REG(0x18f8)
|
||||
#define PCIE_CONF_DATA ORION_PCIE_REG(0x18fc)
|
||||
|
||||
/*
|
||||
* PCIE_STAT bits
|
||||
*/
|
||||
#define PCIE_STAT_LINK_DOWN 1
|
||||
#define PCIE_STAT_BUS_OFFS 8
|
||||
#define PCIE_STAT_BUS_MASK (0xff << PCIE_STAT_BUS_OFFS)
|
||||
#define PCIE_STAT_DEV_OFFS 20
|
||||
#define PCIE_STAT_DEV_MASK (0x1f << PCIE_STAT_DEV_OFFS)
|
||||
|
||||
/*
|
||||
* PCIE_CONF_ADDR bits
|
||||
*/
|
||||
#define PCIE_CONF_REG(r) ((((r) & 0xf00) << 24) | ((r) & 0xfc))
|
||||
#define PCIE_CONF_FUNC(f) (((f) & 0x3) << 8)
|
||||
#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 11)
|
||||
#define PCIE_CONF_BUS(b) (((b) & 0xff) << 16)
|
||||
#define PCIE_CONF_ADDR_EN (1 << 31)
|
||||
|
||||
/*
|
||||
* PCIE config cycles are done by programming the PCIE_CONF_ADDR register
|
||||
* and then reading the PCIE_CONF_DATA register. Need to make sure these
|
||||
* transactions are atomic.
|
||||
*/
|
||||
static DEFINE_SPINLOCK(orion_pcie_lock);
|
||||
|
||||
void orion_pcie_id(u32 *dev, u32 *rev)
|
||||
{
|
||||
*dev = orion_read(PCIE_DEV_ID) >> 16;
|
||||
*rev = orion_read(PCIE_DEV_REV) & 0xff;
|
||||
}
|
||||
|
||||
u32 orion_pcie_local_bus_nr(void)
|
||||
{
|
||||
u32 stat = orion_read(PCIE_STAT);
|
||||
return((stat & PCIE_STAT_BUS_MASK) >> PCIE_STAT_BUS_OFFS);
|
||||
}
|
||||
|
||||
static u32 orion_pcie_local_dev_nr(void)
|
||||
{
|
||||
u32 stat = orion_read(PCIE_STAT);
|
||||
return((stat & PCIE_STAT_DEV_MASK) >> PCIE_STAT_DEV_OFFS);
|
||||
}
|
||||
|
||||
static u32 orion_pcie_no_link(void)
|
||||
{
|
||||
u32 stat = orion_read(PCIE_STAT);
|
||||
return(stat & PCIE_STAT_LINK_DOWN);
|
||||
}
|
||||
|
||||
static void orion_pcie_set_bus_nr(int nr)
|
||||
{
|
||||
orion_clrbits(PCIE_STAT, PCIE_STAT_BUS_MASK);
|
||||
orion_setbits(PCIE_STAT, nr << PCIE_STAT_BUS_OFFS);
|
||||
}
|
||||
|
||||
static void orion_pcie_master_slave_enable(void)
|
||||
{
|
||||
orion_setbits(PCIE_CMD_STAT, PCI_COMMAND_MASTER |
|
||||
PCI_COMMAND_IO |
|
||||
PCI_COMMAND_MEMORY);
|
||||
}
|
||||
|
||||
static void orion_pcie_enable_interrupts(void)
|
||||
{
|
||||
/*
|
||||
* Enable interrupts lines
|
||||
* INTA[24] INTB[25] INTC[26] INTD[27]
|
||||
*/
|
||||
orion_setbits(PCIE_MASK, 0xf<<24);
|
||||
}
|
||||
|
||||
static int orion_pcie_valid_config(u32 bus, u32 dev)
|
||||
{
|
||||
/*
|
||||
* Don't go out when trying to access --
|
||||
* 1. our own device
|
||||
* 2. where there's no device connected (no link)
|
||||
* 3. nonexisting devices on local bus
|
||||
*/
|
||||
|
||||
if ((orion_pcie_local_bus_nr() == bus) &&
|
||||
(orion_pcie_local_dev_nr() == dev))
|
||||
return 0;
|
||||
|
||||
if (orion_pcie_no_link())
|
||||
return 0;
|
||||
|
||||
if (bus == orion_pcie_local_bus_nr())
|
||||
if (((orion_pcie_local_dev_nr() == 0) && (dev != 1)) ||
|
||||
((orion_pcie_local_dev_nr() != 0) && (dev != 0)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int orion_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
|
||||
int size, u32 *val)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned int dev, rev, pcie_addr;
|
||||
|
||||
if (orion_pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
|
||||
*val = 0xffffffff;
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&orion_pcie_lock, flags);
|
||||
|
||||
orion_write(PCIE_CONF_ADDR, PCIE_CONF_BUS(bus->number) |
|
||||
PCIE_CONF_DEV(PCI_SLOT(devfn)) |
|
||||
PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
|
||||
PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN);
|
||||
|
||||
orion_pcie_id(&dev, &rev);
|
||||
if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
|
||||
/* extended register space */
|
||||
pcie_addr = ORION_PCIE_WA_BASE;
|
||||
pcie_addr |= PCIE_CONF_BUS(bus->number) |
|
||||
PCIE_CONF_DEV(PCI_SLOT(devfn)) |
|
||||
PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
|
||||
PCIE_CONF_REG(where);
|
||||
*val = orion_read(pcie_addr);
|
||||
} else
|
||||
*val = orion_read(PCIE_CONF_DATA);
|
||||
|
||||
if (size == 1)
|
||||
*val = (*val >> (8*(where & 0x3))) & 0xff;
|
||||
else if (size == 2)
|
||||
*val = (*val >> (8*(where & 0x3))) & 0xffff;
|
||||
|
||||
spin_unlock_irqrestore(&orion_pcie_lock, flags);
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
static int orion_pcie_wr_conf(struct pci_bus *bus, u32 devfn, int where,
|
||||
int size, u32 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
if (orion_pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0)
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
spin_lock_irqsave(&orion_pcie_lock, flags);
|
||||
|
||||
ret = PCIBIOS_SUCCESSFUL;
|
||||
|
||||
orion_write(PCIE_CONF_ADDR, PCIE_CONF_BUS(bus->number) |
|
||||
PCIE_CONF_DEV(PCI_SLOT(devfn)) |
|
||||
PCIE_CONF_FUNC(PCI_FUNC(devfn)) |
|
||||
PCIE_CONF_REG(where) | PCIE_CONF_ADDR_EN);
|
||||
|
||||
if (size == 4) {
|
||||
__raw_writel(val, PCIE_CONF_DATA);
|
||||
} else if (size == 2) {
|
||||
__raw_writew(val, PCIE_CONF_DATA + (where & 0x3));
|
||||
} else if (size == 1) {
|
||||
__raw_writeb(val, PCIE_CONF_DATA + (where & 0x3));
|
||||
} else {
|
||||
ret = PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&orion_pcie_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct pci_ops orion_pcie_ops = {
|
||||
.read = orion_pcie_rd_conf,
|
||||
.write = orion_pcie_wr_conf,
|
||||
};
|
||||
|
||||
|
||||
static int orion_pcie_setup(struct pci_sys_data *sys)
|
||||
{
|
||||
struct resource *res;
|
||||
|
||||
/*
|
||||
* Master + Slave enable
|
||||
*/
|
||||
orion_pcie_master_slave_enable();
|
||||
|
||||
/*
|
||||
* Enable interrupts lines A-D
|
||||
*/
|
||||
orion_pcie_enable_interrupts();
|
||||
|
||||
/*
|
||||
* Request resource
|
||||
*/
|
||||
res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
|
||||
if (!res)
|
||||
panic("orion_pci_setup unable to alloc resources");
|
||||
|
||||
/*
|
||||
* IORESOURCE_IO
|
||||
*/
|
||||
res[0].name = "PCI-EX I/O Space";
|
||||
res[0].flags = IORESOURCE_IO;
|
||||
res[0].start = ORION_PCIE_IO_REMAP;
|
||||
res[0].end = res[0].start + ORION_PCIE_IO_SIZE - 1;
|
||||
if (request_resource(&ioport_resource, &res[0]))
|
||||
panic("Request PCIE IO resource failed\n");
|
||||
sys->resource[0] = &res[0];
|
||||
|
||||
/*
|
||||
* IORESOURCE_MEM
|
||||
*/
|
||||
res[1].name = "PCI-EX Memory Space";
|
||||
res[1].flags = IORESOURCE_MEM;
|
||||
res[1].start = ORION_PCIE_MEM_BASE;
|
||||
res[1].end = res[1].start + ORION_PCIE_MEM_SIZE - 1;
|
||||
if (request_resource(&iomem_resource, &res[1]))
|
||||
panic("Request PCIE Memory resource failed\n");
|
||||
sys->resource[1] = &res[1];
|
||||
|
||||
sys->resource[2] = NULL;
|
||||
sys->io_offset = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* PCI controller
|
||||
****************************************************************************/
|
||||
#define PCI_MODE ORION_PCI_REG(0xd00)
|
||||
#define PCI_CMD ORION_PCI_REG(0xc00)
|
||||
#define PCI_P2P_CONF ORION_PCI_REG(0x1d14)
|
||||
#define PCI_CONF_ADDR ORION_PCI_REG(0xc78)
|
||||
#define PCI_CONF_DATA ORION_PCI_REG(0xc7c)
|
||||
|
||||
/*
|
||||
* PCI_MODE bits
|
||||
*/
|
||||
#define PCI_MODE_64BIT (1 << 2)
|
||||
#define PCI_MODE_PCIX ((1 << 4) | (1 << 5))
|
||||
|
||||
/*
|
||||
* PCI_CMD bits
|
||||
*/
|
||||
#define PCI_CMD_HOST_REORDER (1 << 29)
|
||||
|
||||
/*
|
||||
* PCI_P2P_CONF bits
|
||||
*/
|
||||
#define PCI_P2P_BUS_OFFS 16
|
||||
#define PCI_P2P_BUS_MASK (0xff << PCI_P2P_BUS_OFFS)
|
||||
#define PCI_P2P_DEV_OFFS 24
|
||||
#define PCI_P2P_DEV_MASK (0x1f << PCI_P2P_DEV_OFFS)
|
||||
|
||||
/*
|
||||
* PCI_CONF_ADDR bits
|
||||
*/
|
||||
#define PCI_CONF_REG(reg) ((reg) & 0xfc)
|
||||
#define PCI_CONF_FUNC(func) (((func) & 0x3) << 8)
|
||||
#define PCI_CONF_DEV(dev) (((dev) & 0x1f) << 11)
|
||||
#define PCI_CONF_BUS(bus) (((bus) & 0xff) << 16)
|
||||
#define PCI_CONF_ADDR_EN (1 << 31)
|
||||
|
||||
/*
|
||||
* Internal configuration space
|
||||
*/
|
||||
#define PCI_CONF_FUNC_STAT_CMD 0
|
||||
#define PCI_CONF_REG_STAT_CMD 4
|
||||
#define PCIX_STAT 0x64
|
||||
#define PCIX_STAT_BUS_OFFS 8
|
||||
#define PCIX_STAT_BUS_MASK (0xff << PCIX_STAT_BUS_OFFS)
|
||||
|
||||
/*
|
||||
* PCI config cycles are done by programming the PCI_CONF_ADDR register
|
||||
* and then reading the PCI_CONF_DATA register. Need to make sure these
|
||||
* transactions are atomic.
|
||||
*/
|
||||
static DEFINE_SPINLOCK(orion_pci_lock);
|
||||
|
||||
u32 orion_pci_local_bus_nr(void)
|
||||
{
|
||||
u32 conf = orion_read(PCI_P2P_CONF);
|
||||
return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
|
||||
}
|
||||
|
||||
u32 orion_pci_local_dev_nr(void)
|
||||
{
|
||||
u32 conf = orion_read(PCI_P2P_CONF);
|
||||
return((conf & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS);
|
||||
}
|
||||
|
||||
int orion_pci_hw_rd_conf(u32 bus, u32 dev, u32 func,
|
||||
u32 where, u32 size, u32 *val)
|
||||
{
|
||||
unsigned long flags;
|
||||
spin_lock_irqsave(&orion_pci_lock, flags);
|
||||
|
||||
orion_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
|
||||
PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
|
||||
PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
|
||||
|
||||
*val = orion_read(PCI_CONF_DATA);
|
||||
|
||||
if (size == 1)
|
||||
*val = (*val >> (8*(where & 0x3))) & 0xff;
|
||||
else if (size == 2)
|
||||
*val = (*val >> (8*(where & 0x3))) & 0xffff;
|
||||
|
||||
spin_unlock_irqrestore(&orion_pci_lock, flags);
|
||||
|
||||
return PCIBIOS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
int orion_pci_hw_wr_conf(u32 bus, u32 dev, u32 func,
|
||||
u32 where, u32 size, u32 val)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = PCIBIOS_SUCCESSFUL;
|
||||
|
||||
spin_lock_irqsave(&orion_pci_lock, flags);
|
||||
|
||||
orion_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
|
||||
PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
|
||||
PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
|
||||
|
||||
if (size == 4) {
|
||||
__raw_writel(val, PCI_CONF_DATA);
|
||||
} else if (size == 2) {
|
||||
__raw_writew(val, PCI_CONF_DATA + (where & 0x3));
|
||||
} else if (size == 1) {
|
||||
__raw_writeb(val, PCI_CONF_DATA + (where & 0x3));
|
||||
} else {
|
||||
ret = PCIBIOS_BAD_REGISTER_NUMBER;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&orion_pci_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int orion_pci_rd_conf(struct pci_bus *bus, u32 devfn,
|
||||
int where, int size, u32 *val)
|
||||
{
|
||||
/*
|
||||
* Don't go out for local device
|
||||
*/
|
||||
if ((orion_pci_local_bus_nr() == bus->number) &&
|
||||
(orion_pci_local_dev_nr() == PCI_SLOT(devfn))) {
|
||||
*val = 0xffffffff;
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
return orion_pci_hw_rd_conf(bus->number, PCI_SLOT(devfn),
|
||||
PCI_FUNC(devfn), where, size, val);
|
||||
}
|
||||
|
||||
static int orion_pci_wr_conf(struct pci_bus *bus, u32 devfn,
|
||||
int where, int size, u32 val)
|
||||
{
|
||||
/*
|
||||
* Don't go out for local device
|
||||
*/
|
||||
if ((orion_pci_local_bus_nr() == bus->number) &&
|
||||
(orion_pci_local_dev_nr() == PCI_SLOT(devfn)))
|
||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||
|
||||
return orion_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn),
|
||||
PCI_FUNC(devfn), where, size, val);
|
||||
}
|
||||
|
||||
struct pci_ops orion_pci_ops = {
|
||||
.read = orion_pci_rd_conf,
|
||||
.write = orion_pci_wr_conf,
|
||||
};
|
||||
|
||||
static void orion_pci_set_bus_nr(int nr)
|
||||
{
|
||||
u32 p2p = orion_read(PCI_P2P_CONF);
|
||||
|
||||
if (orion_read(PCI_MODE) & PCI_MODE_PCIX) {
|
||||
/*
|
||||
* PCI-X mode
|
||||
*/
|
||||
u32 pcix_status, bus, dev;
|
||||
bus = (p2p & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS;
|
||||
dev = (p2p & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS;
|
||||
orion_pci_hw_rd_conf(bus, dev, 0, PCIX_STAT, 4, &pcix_status);
|
||||
pcix_status &= ~PCIX_STAT_BUS_MASK;
|
||||
pcix_status |= (nr << PCIX_STAT_BUS_OFFS);
|
||||
orion_pci_hw_wr_conf(bus, dev, 0, PCIX_STAT, 4, pcix_status);
|
||||
} else {
|
||||
/*
|
||||
* PCI Conventional mode
|
||||
*/
|
||||
p2p &= ~PCI_P2P_BUS_MASK;
|
||||
p2p |= (nr << PCI_P2P_BUS_OFFS);
|
||||
orion_write(PCI_P2P_CONF, p2p);
|
||||
}
|
||||
}
|
||||
|
||||
static void orion_pci_master_slave_enable(void)
|
||||
{
|
||||
u32 bus_nr, dev_nr, func, reg, val;
|
||||
|
||||
bus_nr = orion_pci_local_bus_nr();
|
||||
dev_nr = orion_pci_local_dev_nr();
|
||||
func = PCI_CONF_FUNC_STAT_CMD;
|
||||
reg = PCI_CONF_REG_STAT_CMD;
|
||||
orion_pci_hw_rd_conf(bus_nr, dev_nr, func, reg, 4, &val);
|
||||
val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
|
||||
orion_pci_hw_wr_conf(bus_nr, dev_nr, func, reg, 4, val | 0x7);
|
||||
}
|
||||
|
||||
static int orion_pci_setup(struct pci_sys_data *sys)
|
||||
{
|
||||
struct resource *res;
|
||||
|
||||
/*
|
||||
* Master + Slave enable
|
||||
*/
|
||||
orion_pci_master_slave_enable();
|
||||
|
||||
/*
|
||||
* Force ordering
|
||||
*/
|
||||
orion_setbits(PCI_CMD, PCI_CMD_HOST_REORDER);
|
||||
|
||||
/*
|
||||
* Request resources
|
||||
*/
|
||||
res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
|
||||
if (!res)
|
||||
panic("orion_pci_setup unable to alloc resources");
|
||||
|
||||
/*
|
||||
* IORESOURCE_IO
|
||||
*/
|
||||
res[0].name = "PCI I/O Space";
|
||||
res[0].flags = IORESOURCE_IO;
|
||||
res[0].start = ORION_PCI_IO_REMAP;
|
||||
res[0].end = res[0].start + ORION_PCI_IO_SIZE - 1;
|
||||
if (request_resource(&ioport_resource, &res[0]))
|
||||
panic("Request PCI IO resource failed\n");
|
||||
sys->resource[0] = &res[0];
|
||||
|
||||
/*
|
||||
* IORESOURCE_MEM
|
||||
*/
|
||||
res[1].name = "PCI Memory Space";
|
||||
res[1].flags = IORESOURCE_MEM;
|
||||
res[1].start = ORION_PCI_MEM_BASE;
|
||||
res[1].end = res[1].start + ORION_PCI_MEM_SIZE - 1;
|
||||
if (request_resource(&iomem_resource, &res[1]))
|
||||
panic("Request PCI Memory resource failed\n");
|
||||
sys->resource[1] = &res[1];
|
||||
|
||||
sys->resource[2] = NULL;
|
||||
sys->io_offset = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* General PCIE + PCI
|
||||
****************************************************************************/
|
||||
int orion_pci_sys_setup(int nr, struct pci_sys_data *sys)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (nr == 0) {
|
||||
/*
|
||||
* PCIE setup
|
||||
*/
|
||||
orion_pcie_set_bus_nr(0);
|
||||
ret = orion_pcie_setup(sys);
|
||||
} else if (nr == 1) {
|
||||
/*
|
||||
* PCI setup
|
||||
*/
|
||||
ret = orion_pci_setup(sys);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct pci_bus *orion_pci_sys_scan_bus(int nr, struct pci_sys_data *sys)
|
||||
{
|
||||
struct pci_ops *ops;
|
||||
struct pci_bus *bus;
|
||||
|
||||
|
||||
if (nr == 0) {
|
||||
u32 pci_bus;
|
||||
/*
|
||||
* PCIE scan
|
||||
*/
|
||||
ops = &orion_pcie_ops;
|
||||
bus = pci_scan_bus(sys->busnr, ops, sys);
|
||||
/*
|
||||
* Set local PCI bus number to follow PCIE bridges (if any)
|
||||
*/
|
||||
pci_bus = bus->number + bus->subordinate - bus->secondary + 1;
|
||||
orion_pci_set_bus_nr(pci_bus);
|
||||
} else if (nr == 1) {
|
||||
/*
|
||||
* PCI scan
|
||||
*/
|
||||
ops = &orion_pci_ops;
|
||||
bus = pci_scan_bus(sys->busnr, ops, sys);
|
||||
} else {
|
||||
BUG();
|
||||
bus = NULL;
|
||||
}
|
||||
|
||||
return bus;
|
||||
}
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* arch/arm/mach-orion/rd88f5182-setup.c
|
||||
*
|
||||
* Marvell Orion-NAS Reference Design Setup
|
||||
*
|
||||
* Maintainer: Ronen Shitrit <rshitrit@marvell.com>
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/leds.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/pci.h>
|
||||
#include <asm/arch/orion.h>
|
||||
#include <asm/arch/platform.h>
|
||||
#include "common.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* RD-88F5182 Info
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* 512K NOR flash Device bus boot chip select
|
||||
*/
|
||||
|
||||
#define RD88F5182_NOR_BOOT_BASE 0xf4000000
|
||||
#define RD88F5182_NOR_BOOT_SIZE SZ_512K
|
||||
|
||||
/*
|
||||
* 16M NOR flash on Device bus chip select 1
|
||||
*/
|
||||
|
||||
#define RD88F5182_NOR_BASE 0xfc000000
|
||||
#define RD88F5182_NOR_SIZE SZ_16M
|
||||
|
||||
/*
|
||||
* PCI
|
||||
*/
|
||||
|
||||
#define RD88F5182_PCI_SLOT0_OFFS 7
|
||||
#define RD88F5182_PCI_SLOT0_IRQ_A_PIN 7
|
||||
#define RD88F5182_PCI_SLOT0_IRQ_B_PIN 6
|
||||
|
||||
/*
|
||||
* GPIO Debug LED
|
||||
*/
|
||||
|
||||
#define RD88F5182_GPIO_DBG_LED 0
|
||||
|
||||
/*****************************************************************************
|
||||
* 16M NOR Flash on Device bus CS1
|
||||
****************************************************************************/
|
||||
|
||||
static struct physmap_flash_data rd88f5182_nor_flash_data = {
|
||||
.width = 1,
|
||||
};
|
||||
|
||||
static struct resource rd88f5182_nor_flash_resource = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
.start = RD88F5182_NOR_BASE,
|
||||
.end = RD88F5182_NOR_BASE + RD88F5182_NOR_SIZE - 1,
|
||||
};
|
||||
|
||||
static struct platform_device rd88f5182_nor_flash = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.platform_data = &rd88f5182_nor_flash_data,
|
||||
},
|
||||
.num_resources = 1,
|
||||
.resource = &rd88f5182_nor_flash_resource,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LEDS
|
||||
|
||||
/*****************************************************************************
|
||||
* Use GPIO debug led as CPU active indication
|
||||
****************************************************************************/
|
||||
|
||||
static void rd88f5182_dbgled_event(led_event_t evt)
|
||||
{
|
||||
int val;
|
||||
|
||||
if (evt == led_idle_end)
|
||||
val = 1;
|
||||
else if (evt == led_idle_start)
|
||||
val = 0;
|
||||
else
|
||||
return;
|
||||
|
||||
gpio_set_value(RD88F5182_GPIO_DBG_LED, val);
|
||||
}
|
||||
|
||||
static int __init rd88f5182_dbgled_init(void)
|
||||
{
|
||||
int pin;
|
||||
|
||||
if (machine_is_rd88f5182()) {
|
||||
pin = RD88F5182_GPIO_DBG_LED;
|
||||
|
||||
if (gpio_request(pin, "DBGLED") == 0) {
|
||||
if (gpio_direction_output(pin, 0) != 0) {
|
||||
printk(KERN_ERR "rd88f5182_dbgled_init failed "
|
||||
"to set output pin %d\n", pin);
|
||||
gpio_free(pin);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "rd88f5182_dbgled_init failed "
|
||||
"to request gpio %d\n", pin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
leds_event = rd88f5182_dbgled_event;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(rd88f5182_dbgled_init);
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* PCI
|
||||
****************************************************************************/
|
||||
|
||||
void __init rd88f5182_pci_preinit(void)
|
||||
{
|
||||
int pin;
|
||||
|
||||
/*
|
||||
* Configure PCI GPIO IRQ pins
|
||||
*/
|
||||
pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
|
||||
if (gpio_request(pin, "PCI IntA") == 0) {
|
||||
if (gpio_direction_input(pin) == 0) {
|
||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
||||
} else {
|
||||
printk(KERN_ERR "rd88f5182_pci_preinit faield to "
|
||||
"set_irq_type pin %d\n", pin);
|
||||
gpio_free(pin);
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "rd88f5182_pci_preinit failed to request gpio %d\n", pin);
|
||||
}
|
||||
|
||||
pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
|
||||
if (gpio_request(pin, "PCI IntB") == 0) {
|
||||
if (gpio_direction_input(pin) == 0) {
|
||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
||||
} else {
|
||||
printk(KERN_ERR "rd88f5182_pci_preinit faield to "
|
||||
"set_irq_type pin %d\n", pin);
|
||||
gpio_free(pin);
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "rd88f5182_pci_preinit failed to gpio_request %d\n", pin);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
/*
|
||||
* PCI-E isn't used on the RD2
|
||||
*/
|
||||
if (dev->bus->number == orion_pcie_local_bus_nr())
|
||||
return IRQ_ORION_PCIE0_INT;
|
||||
|
||||
/*
|
||||
* PCI IRQs are connected via GPIOs
|
||||
*/
|
||||
switch (slot - RD88F5182_PCI_SLOT0_OFFS) {
|
||||
case 0:
|
||||
if (pin == 1)
|
||||
return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_A_PIN);
|
||||
else
|
||||
return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_B_PIN);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static struct hw_pci rd88f5182_pci __initdata = {
|
||||
.nr_controllers = 2,
|
||||
.preinit = rd88f5182_pci_preinit,
|
||||
.swizzle = pci_std_swizzle,
|
||||
.setup = orion_pci_sys_setup,
|
||||
.scan = orion_pci_sys_scan_bus,
|
||||
.map_irq = rd88f5182_pci_map_irq,
|
||||
};
|
||||
|
||||
static int __init rd88f5182_pci_init(void)
|
||||
{
|
||||
if (machine_is_rd88f5182())
|
||||
pci_common_init(&rd88f5182_pci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(rd88f5182_pci_init);
|
||||
|
||||
/*****************************************************************************
|
||||
* Ethernet
|
||||
****************************************************************************/
|
||||
|
||||
static struct mv643xx_eth_platform_data rd88f5182_eth_data = {
|
||||
.phy_addr = 8,
|
||||
.force_phy_addr = 1,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* RTC DS1338 on I2C bus
|
||||
****************************************************************************/
|
||||
static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
|
||||
.driver_name = "rtc-ds1307",
|
||||
.type = "ds1338",
|
||||
.addr = 0x68,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* General Setup
|
||||
****************************************************************************/
|
||||
|
||||
static struct platform_device *rd88f5182_devices[] __initdata = {
|
||||
&rd88f5182_nor_flash,
|
||||
};
|
||||
|
||||
static void __init rd88f5182_init(void)
|
||||
{
|
||||
/*
|
||||
* Setup basic Orion functions. Need to be called early.
|
||||
*/
|
||||
orion_init();
|
||||
|
||||
/*
|
||||
* Setup the CPU address decode windows for our devices
|
||||
*/
|
||||
orion_setup_cpu_win(ORION_DEV_BOOT, RD88F5182_NOR_BOOT_BASE,
|
||||
RD88F5182_NOR_BOOT_SIZE, -1);
|
||||
orion_setup_cpu_win(ORION_DEV1, RD88F5182_NOR_BASE,
|
||||
RD88F5182_NOR_SIZE, -1);
|
||||
|
||||
/*
|
||||
* Open a special address decode windows for the PCIE WA.
|
||||
*/
|
||||
orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE);
|
||||
orion_write(ORION_REGS_BASE | 0x20070, (0x7941 |
|
||||
(((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
|
||||
|
||||
/*
|
||||
* Setup Multiplexing Pins --
|
||||
* MPP[0] Debug Led (GPIO - Out)
|
||||
* MPP[1] Debug Led (GPIO - Out)
|
||||
* MPP[2] N/A
|
||||
* MPP[3] RTC_Int (GPIO - In)
|
||||
* MPP[4] GPIO
|
||||
* MPP[5] GPIO
|
||||
* MPP[6] PCI_intA (GPIO - In)
|
||||
* MPP[7] PCI_intB (GPIO - In)
|
||||
* MPP[8-11] N/A
|
||||
* MPP[12] SATA 0 presence Indication
|
||||
* MPP[13] SATA 1 presence Indication
|
||||
* MPP[14] SATA 0 active Indication
|
||||
* MPP[15] SATA 1 active indication
|
||||
* MPP[16-19] Not used
|
||||
* MPP[20] PCI Clock to MV88F5182
|
||||
* MPP[21] PCI Clock to mini PCI CON11
|
||||
* MPP[22] USB 0 over current indication
|
||||
* MPP[23] USB 1 over current indication
|
||||
* MPP[24] USB 1 over current enable
|
||||
* MPP[25] USB 0 over current enable
|
||||
*/
|
||||
|
||||
orion_write(MPP_0_7_CTRL, 0x00000003);
|
||||
orion_write(MPP_8_15_CTRL, 0x55550000);
|
||||
orion_write(MPP_16_19_CTRL, 0x5555);
|
||||
|
||||
orion_gpio_set_valid_pins(0x000000fb);
|
||||
|
||||
platform_add_devices(rd88f5182_devices, ARRAY_SIZE(rd88f5182_devices));
|
||||
i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);
|
||||
orion_eth_init(&rd88f5182_eth_data);
|
||||
}
|
||||
|
||||
MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
|
||||
/* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
|
||||
.phys_io = ORION_REGS_BASE,
|
||||
.io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC,
|
||||
.boot_params = 0x00000100,
|
||||
.init_machine = rd88f5182_init,
|
||||
.map_io = orion_map_io,
|
||||
.init_irq = orion_init_irq,
|
||||
.timer = &orion_timer,
|
||||
MACHINE_END
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* arch/arm/mach-orion/time.c
|
||||
*
|
||||
* Core time functions for Marvell Orion System On Chip
|
||||
*
|
||||
* Maintainer: Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/arch/orion.h>
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Timer0: clock_event_device, Tick.
|
||||
* Timer1: clocksource, Free running.
|
||||
* WatchDog: Not used.
|
||||
*
|
||||
* Timers are counting down.
|
||||
*/
|
||||
#define CLOCKEVENT 0
|
||||
#define CLOCKSOURCE 1
|
||||
|
||||
/*
|
||||
* Timers bits
|
||||
*/
|
||||
#define BRIDGE_INT_TIMER(x) (1 << ((x) + 1))
|
||||
#define TIMER_EN(x) (1 << ((x) * 2))
|
||||
#define TIMER_RELOAD_EN(x) (1 << (((x) * 2) + 1))
|
||||
#define BRIDGE_INT_TIMER_WD (1 << 3)
|
||||
#define TIMER_WD_EN (1 << 4)
|
||||
#define TIMER_WD_RELOAD_EN (1 << 5)
|
||||
|
||||
static cycle_t orion_clksrc_read(void)
|
||||
{
|
||||
return (0xffffffff - orion_read(TIMER_VAL(CLOCKSOURCE)));
|
||||
}
|
||||
|
||||
static struct clocksource orion_clksrc = {
|
||||
.name = "orion_clocksource",
|
||||
.shift = 20,
|
||||
.rating = 300,
|
||||
.read = orion_clksrc_read,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
static int
|
||||
orion_clkevt_next_event(unsigned long delta, struct clock_event_device *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (delta == 0)
|
||||
return -ETIME;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
/*
|
||||
* Clear and enable timer interrupt bit
|
||||
*/
|
||||
orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT));
|
||||
orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT));
|
||||
|
||||
/*
|
||||
* Setup new timer value
|
||||
*/
|
||||
orion_write(TIMER_VAL(CLOCKEVENT), delta);
|
||||
|
||||
/*
|
||||
* Disable auto reload and kickoff the timer
|
||||
*/
|
||||
orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT));
|
||||
orion_setbits(TIMER_CTRL, TIMER_EN(CLOCKEVENT));
|
||||
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
orion_clkevt_mode(enum clock_event_mode mode, struct clock_event_device *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
if (mode == CLOCK_EVT_MODE_PERIODIC) {
|
||||
/*
|
||||
* Setup latch cycles in timer and enable reload interrupt.
|
||||
*/
|
||||
orion_write(TIMER_VAL_RELOAD(CLOCKEVENT), LATCH);
|
||||
orion_write(TIMER_VAL(CLOCKEVENT), LATCH);
|
||||
orion_setbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT));
|
||||
orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) |
|
||||
TIMER_EN(CLOCKEVENT));
|
||||
} else {
|
||||
/*
|
||||
* Disable timer and interrupt
|
||||
*/
|
||||
orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKEVENT));
|
||||
orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT));
|
||||
orion_clrbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKEVENT) |
|
||||
TIMER_EN(CLOCKEVENT));
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static struct clock_event_device orion_clkevt = {
|
||||
.name = "orion_tick",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.shift = 32,
|
||||
.rating = 300,
|
||||
.cpumask = CPU_MASK_CPU0,
|
||||
.set_next_event = orion_clkevt_next_event,
|
||||
.set_mode = orion_clkevt_mode,
|
||||
};
|
||||
|
||||
static irqreturn_t orion_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
/*
|
||||
* Clear cause bit and do event
|
||||
*/
|
||||
orion_write(BRIDGE_CAUSE, ~BRIDGE_INT_TIMER(CLOCKEVENT));
|
||||
orion_clkevt.event_handler(&orion_clkevt);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction orion_timer_irq = {
|
||||
.name = "orion_tick",
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
.handler = orion_timer_interrupt
|
||||
};
|
||||
|
||||
static void orion_timer_init(void)
|
||||
{
|
||||
/*
|
||||
* Setup clocksource free running timer (no interrupt on reload)
|
||||
*/
|
||||
orion_write(TIMER_VAL(CLOCKSOURCE), 0xffffffff);
|
||||
orion_write(TIMER_VAL_RELOAD(CLOCKSOURCE), 0xffffffff);
|
||||
orion_clrbits(BRIDGE_MASK, BRIDGE_INT_TIMER(CLOCKSOURCE));
|
||||
orion_setbits(TIMER_CTRL, TIMER_RELOAD_EN(CLOCKSOURCE) |
|
||||
TIMER_EN(CLOCKSOURCE));
|
||||
|
||||
/*
|
||||
* Register clocksource
|
||||
*/
|
||||
orion_clksrc.mult =
|
||||
clocksource_hz2mult(CLOCK_TICK_RATE, orion_clksrc.shift);
|
||||
|
||||
clocksource_register(&orion_clksrc);
|
||||
|
||||
/*
|
||||
* Connect and enable tick handler
|
||||
*/
|
||||
setup_irq(IRQ_ORION_BRIDGE, &orion_timer_irq);
|
||||
|
||||
/*
|
||||
* Register clockevent
|
||||
*/
|
||||
orion_clkevt.mult =
|
||||
div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, orion_clkevt.shift);
|
||||
orion_clkevt.max_delta_ns =
|
||||
clockevent_delta2ns(0xfffffffe, &orion_clkevt);
|
||||
orion_clkevt.min_delta_ns =
|
||||
clockevent_delta2ns(1, &orion_clkevt);
|
||||
|
||||
clockevents_register_device(&orion_clkevt);
|
||||
}
|
||||
|
||||
struct sys_timer orion_timer = {
|
||||
.init = orion_timer_init,
|
||||
};
|
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
* QNAP TS-109/TS-209 Board Setup
|
||||
*
|
||||
* Maintainer: Byron Bradley <byron.bbradley@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/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/serial_reg.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/pci.h>
|
||||
#include <asm/arch/orion.h>
|
||||
#include <asm/arch/platform.h>
|
||||
#include "common.h"
|
||||
|
||||
#define QNAP_TS209_NOR_BOOT_BASE 0xf4000000
|
||||
#define QNAP_TS209_NOR_BOOT_SIZE SZ_8M
|
||||
|
||||
/****************************************************************************
|
||||
* 8MiB NOR flash. The struct mtd_partition is not in the same order as the
|
||||
* partitions on the device because we want to keep compatability with
|
||||
* existing QNAP firmware.
|
||||
*
|
||||
* Layout as used by QNAP:
|
||||
* [2] 0x00000000-0x00200000 : "Kernel"
|
||||
* [3] 0x00200000-0x00600000 : "RootFS1"
|
||||
* [4] 0x00600000-0x00700000 : "RootFS2"
|
||||
* [6] 0x00700000-0x00760000 : "NAS Config" (read-only)
|
||||
* [5] 0x00760000-0x00780000 : "U-Boot Config"
|
||||
* [1] 0x00780000-0x00800000 : "U-Boot" (read-only)
|
||||
***************************************************************************/
|
||||
static struct mtd_partition qnap_ts209_partitions[] = {
|
||||
{
|
||||
.name = "U-Boot",
|
||||
.size = 0x00080000,
|
||||
.offset = 0x00780000,
|
||||
.mask_flags = MTD_WRITEABLE,
|
||||
}, {
|
||||
.name = "Kernel",
|
||||
.size = 0x00200000,
|
||||
.offset = 0,
|
||||
}, {
|
||||
.name = "RootFS1",
|
||||
.size = 0x00400000,
|
||||
.offset = 0x00200000,
|
||||
}, {
|
||||
.name = "RootFS2",
|
||||
.size = 0x00100000,
|
||||
.offset = 0x00600000,
|
||||
}, {
|
||||
.name = "U-Boot Config",
|
||||
.size = 0x00020000,
|
||||
.offset = 0x00760000,
|
||||
}, {
|
||||
.name = "NAS Config",
|
||||
.size = 0x00060000,
|
||||
.offset = 0x00700000,
|
||||
.mask_flags = MTD_WRITEABLE,
|
||||
}
|
||||
};
|
||||
|
||||
static struct physmap_flash_data qnap_ts209_nor_flash_data = {
|
||||
.width = 1,
|
||||
.parts = qnap_ts209_partitions,
|
||||
.nr_parts = ARRAY_SIZE(qnap_ts209_partitions)
|
||||
};
|
||||
|
||||
static struct resource qnap_ts209_nor_flash_resource = {
|
||||
.flags = IORESOURCE_MEM,
|
||||
.start = QNAP_TS209_NOR_BOOT_BASE,
|
||||
.end = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1,
|
||||
};
|
||||
|
||||
static struct platform_device qnap_ts209_nor_flash = {
|
||||
.name = "physmap-flash",
|
||||
.id = 0,
|
||||
.dev = { .platform_data = &qnap_ts209_nor_flash_data, },
|
||||
.resource = &qnap_ts209_nor_flash_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* PCI
|
||||
****************************************************************************/
|
||||
|
||||
#define QNAP_TS209_PCI_SLOT0_OFFS 7
|
||||
#define QNAP_TS209_PCI_SLOT0_IRQ_PIN 6
|
||||
#define QNAP_TS209_PCI_SLOT1_IRQ_PIN 7
|
||||
|
||||
void __init qnap_ts209_pci_preinit(void)
|
||||
{
|
||||
int pin;
|
||||
|
||||
/*
|
||||
* Configure PCI GPIO IRQ pins
|
||||
*/
|
||||
pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
|
||||
if (gpio_request(pin, "PCI Int1") == 0) {
|
||||
if (gpio_direction_input(pin) == 0) {
|
||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
||||
} else {
|
||||
printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
|
||||
"set_irq_type pin %d\n", pin);
|
||||
gpio_free(pin);
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
|
||||
"%d\n", pin);
|
||||
}
|
||||
|
||||
pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
|
||||
if (gpio_request(pin, "PCI Int2") == 0) {
|
||||
if (gpio_direction_input(pin) == 0) {
|
||||
set_irq_type(gpio_to_irq(pin), IRQT_LOW);
|
||||
} else {
|
||||
printk(KERN_ERR "qnap_ts209_pci_preinit failed "
|
||||
"to set_irq_type pin %d\n", pin);
|
||||
gpio_free(pin);
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
|
||||
"%d\n", pin);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
/*
|
||||
* PCIE IRQ is connected internally (not GPIO)
|
||||
*/
|
||||
if (dev->bus->number == orion_pcie_local_bus_nr())
|
||||
return IRQ_ORION_PCIE0_INT;
|
||||
|
||||
/*
|
||||
* PCI IRQs are connected via GPIOs
|
||||
*/
|
||||
switch (slot - QNAP_TS209_PCI_SLOT0_OFFS) {
|
||||
case 0:
|
||||
return gpio_to_irq(QNAP_TS209_PCI_SLOT0_IRQ_PIN);
|
||||
case 1:
|
||||
return gpio_to_irq(QNAP_TS209_PCI_SLOT1_IRQ_PIN);
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static struct hw_pci qnap_ts209_pci __initdata = {
|
||||
.nr_controllers = 2,
|
||||
.preinit = qnap_ts209_pci_preinit,
|
||||
.swizzle = pci_std_swizzle,
|
||||
.setup = orion_pci_sys_setup,
|
||||
.scan = orion_pci_sys_scan_bus,
|
||||
.map_irq = qnap_ts209_pci_map_irq,
|
||||
};
|
||||
|
||||
static int __init qnap_ts209_pci_init(void)
|
||||
{
|
||||
if (machine_is_ts_x09())
|
||||
pci_common_init(&qnap_ts209_pci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
subsys_initcall(qnap_ts209_pci_init);
|
||||
|
||||
/*****************************************************************************
|
||||
* Ethernet
|
||||
****************************************************************************/
|
||||
|
||||
static struct mv643xx_eth_platform_data qnap_ts209_eth_data = {
|
||||
.phy_addr = 8,
|
||||
.force_phy_addr = 1,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* RTC S35390A on I2C bus
|
||||
****************************************************************************/
|
||||
static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
|
||||
.driver_name = "rtc-s35390a",
|
||||
.addr = 0x30,
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* GPIO Attached Keys
|
||||
* Power button is attached to the PIC microcontroller
|
||||
****************************************************************************/
|
||||
|
||||
#define QNAP_TS209_GPIO_KEY_MEDIA 1
|
||||
#define QNAP_TS209_GPIO_KEY_RESET 2
|
||||
|
||||
static struct gpio_keys_button qnap_ts209_buttons[] = {
|
||||
{
|
||||
.code = KEY_RESTART,
|
||||
.gpio = QNAP_TS209_GPIO_KEY_MEDIA,
|
||||
.desc = "USB Copy Button",
|
||||
.active_low = 1,
|
||||
},
|
||||
{
|
||||
.code = KEY_POWER,
|
||||
.gpio = QNAP_TS209_GPIO_KEY_RESET,
|
||||
.desc = "Reset Button",
|
||||
.active_low = 1,
|
||||
}
|
||||
};
|
||||
|
||||
static struct gpio_keys_platform_data qnap_ts209_button_data = {
|
||||
.buttons = qnap_ts209_buttons,
|
||||
.nbuttons = ARRAY_SIZE(qnap_ts209_buttons),
|
||||
};
|
||||
|
||||
static struct platform_device qnap_ts209_button_device = {
|
||||
.name = "gpio-keys",
|
||||
.id = -1,
|
||||
.num_resources = 0,
|
||||
.dev = { .platform_data = &qnap_ts209_button_data, },
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* General Setup
|
||||
****************************************************************************/
|
||||
|
||||
static struct platform_device *qnap_ts209_devices[] __initdata = {
|
||||
&qnap_ts209_nor_flash,
|
||||
&qnap_ts209_button_device,
|
||||
};
|
||||
|
||||
/*
|
||||
* QNAP TS-[12]09 specific power off method via UART1-attached PIC
|
||||
*/
|
||||
|
||||
#define UART1_REG(x) (UART1_BASE + ((UART_##x) << 2))
|
||||
|
||||
static void qnap_ts209_power_off(void)
|
||||
{
|
||||
/* 19200 baud divisor */
|
||||
const unsigned divisor = ((ORION_TCLK + (8 * 19200)) / (16 * 19200));
|
||||
|
||||
pr_info("%s: triggering power-off...\n", __func__);
|
||||
|
||||
/* hijack uart1 and reset into sane state (19200,8n1) */
|
||||
orion_write(UART1_REG(LCR), 0x83);
|
||||
orion_write(UART1_REG(DLL), divisor & 0xff);
|
||||
orion_write(UART1_REG(DLM), (divisor >> 8) & 0xff);
|
||||
orion_write(UART1_REG(LCR), 0x03);
|
||||
orion_write(UART1_REG(IER), 0x00);
|
||||
orion_write(UART1_REG(FCR), 0x00);
|
||||
orion_write(UART1_REG(MCR), 0x00);
|
||||
|
||||
/* send the power-off command 'A' to PIC */
|
||||
orion_write(UART1_REG(TX), 'A');
|
||||
}
|
||||
|
||||
static void __init qnap_ts209_init(void)
|
||||
{
|
||||
/*
|
||||
* Setup basic Orion functions. Need to be called early.
|
||||
*/
|
||||
orion_init();
|
||||
|
||||
/*
|
||||
* Setup flash mapping
|
||||
*/
|
||||
orion_setup_cpu_win(ORION_DEV_BOOT, QNAP_TS209_NOR_BOOT_BASE,
|
||||
QNAP_TS209_NOR_BOOT_SIZE, -1);
|
||||
|
||||
/*
|
||||
* Open a special address decode windows for the PCIE WA.
|
||||
*/
|
||||
orion_write(ORION_REGS_BASE | 0x20074, ORION_PCIE_WA_BASE);
|
||||
orion_write(ORION_REGS_BASE | 0x20070, (0x7941 |
|
||||
(((ORION_PCIE_WA_SIZE >> 16) - 1)) << 16));
|
||||
|
||||
/*
|
||||
* Setup Multiplexing Pins --
|
||||
* MPP[0] Reserved
|
||||
* MPP[1] USB copy button (0 active)
|
||||
* MPP[2] Load defaults button (0 active)
|
||||
* MPP[3] GPIO RTC
|
||||
* MPP[4-5] Reserved
|
||||
* MPP[6] PCI Int A
|
||||
* MPP[7] PCI Int B
|
||||
* MPP[8-11] Reserved
|
||||
* MPP[12] SATA 0 presence
|
||||
* MPP[13] SATA 1 presence
|
||||
* MPP[14] SATA 0 active
|
||||
* MPP[15] SATA 1 active
|
||||
* MPP[16] UART1 RXD
|
||||
* MPP[17] UART1 TXD
|
||||
* MPP[18] SW_RST (0 active)
|
||||
* MPP[19] Reserved
|
||||
* MPP[20] PCI clock 0
|
||||
* MPP[21] PCI clock 1
|
||||
* MPP[22] USB 0 over current
|
||||
* MPP[23-25] Reserved
|
||||
*/
|
||||
orion_write(MPP_0_7_CTRL, 0x3);
|
||||
orion_write(MPP_8_15_CTRL, 0x55550000);
|
||||
orion_write(MPP_16_19_CTRL, 0x5500);
|
||||
orion_gpio_set_valid_pins(0x3cc0fff);
|
||||
|
||||
/* register ts209 specific power-off method */
|
||||
pm_power_off = qnap_ts209_power_off;
|
||||
|
||||
platform_add_devices(qnap_ts209_devices,
|
||||
ARRAY_SIZE(qnap_ts209_devices));
|
||||
i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);
|
||||
orion_eth_init(&qnap_ts209_eth_data);
|
||||
}
|
||||
|
||||
MACHINE_START(TS209, "QNAP TS-109/TS-209")
|
||||
/* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
|
||||
.phys_io = ORION_REGS_BASE,
|
||||
.io_pg_offst = ((ORION_REGS_BASE) >> 18) & 0xFFFC,
|
||||
.boot_params = 0x00000100,
|
||||
.init_machine = qnap_ts209_init,
|
||||
.map_io = orion_map_io,
|
||||
.init_irq = orion_init_irq,
|
||||
.timer = &orion_timer,
|
||||
MACHINE_END
|
|
@ -342,6 +342,27 @@ config CPU_XSC3
|
|||
select CPU_TLB_V4WBI if MMU
|
||||
select IO_36
|
||||
|
||||
# Feroceon
|
||||
config CPU_FEROCEON
|
||||
bool
|
||||
depends on ARCH_ORION
|
||||
default y
|
||||
select CPU_32v5
|
||||
select CPU_ABRT_EV5T
|
||||
select CPU_CACHE_VIVT
|
||||
select CPU_CP15_MMU
|
||||
select CPU_COPY_V4WB if MMU
|
||||
select CPU_TLB_V4WBI if MMU
|
||||
|
||||
config CPU_FEROCEON_OLD_ID
|
||||
bool "Accept early Feroceon cores with an ARM926 ID"
|
||||
depends on CPU_FEROCEON && !CPU_ARM926T
|
||||
default y
|
||||
help
|
||||
This enables the usage of some old Feroceon cores
|
||||
for which the CPU ID is equal to the ARM926 ID.
|
||||
Relevant for Feroceon-1850 and early Feroceon-2850.
|
||||
|
||||
# ARMv6
|
||||
config CPU_V6
|
||||
bool "Support ARM V6 processor"
|
||||
|
@ -539,7 +560,7 @@ comment "Processor Features"
|
|||
|
||||
config ARM_THUMB
|
||||
bool "Support Thumb user binaries"
|
||||
depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7
|
||||
depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_V6 || CPU_V7 || CPU_FEROCEON
|
||||
default y
|
||||
help
|
||||
Say Y if you want to include kernel support for running user space
|
||||
|
@ -601,7 +622,7 @@ config CPU_DCACHE_SIZE
|
|||
|
||||
config CPU_DCACHE_WRITETHROUGH
|
||||
bool "Force write through D-cache"
|
||||
depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020) && !CPU_DCACHE_DISABLE
|
||||
depends on (CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_FEROCEON) && !CPU_DCACHE_DISABLE
|
||||
default y if CPU_ARM925T
|
||||
help
|
||||
Say Y here to use the data cache in writethrough mode. Unless you
|
||||
|
|
|
@ -68,6 +68,7 @@ obj-$(CONFIG_CPU_SA110) += proc-sa110.o
|
|||
obj-$(CONFIG_CPU_SA1100) += proc-sa1100.o
|
||||
obj-$(CONFIG_CPU_XSCALE) += proc-xscale.o
|
||||
obj-$(CONFIG_CPU_XSC3) += proc-xsc3.o
|
||||
obj-$(CONFIG_CPU_FEROCEON) += proc-feroceon.o
|
||||
obj-$(CONFIG_CPU_V6) += proc-v6.o
|
||||
obj-$(CONFIG_CPU_V7) += proc-v7.o
|
||||
|
||||
|
|
|
@ -0,0 +1,506 @@
|
|||
/*
|
||||
* linux/arch/arm/mm/proc-feroceon.S: MMU functions for Feroceon
|
||||
*
|
||||
* Heavily based on proc-arm926.S
|
||||
* Maintainer: Assaf Hoffman <hoffman@marvell.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 program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/elf.h>
|
||||
#include <asm/pgtable-hwdef.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include "proc-macros.S"
|
||||
|
||||
/*
|
||||
* This is the maximum size of an area which will be invalidated
|
||||
* using the single invalidate entry instructions. Anything larger
|
||||
* than this, and we go for the whole cache.
|
||||
*
|
||||
* This value should be chosen such that we choose the cheapest
|
||||
* alternative.
|
||||
*/
|
||||
#define CACHE_DLIMIT 16384
|
||||
|
||||
/*
|
||||
* the cache line size of the I and D cache
|
||||
*/
|
||||
#define CACHE_DLINESIZE 32
|
||||
|
||||
.text
|
||||
/*
|
||||
* cpu_feroceon_proc_init()
|
||||
*/
|
||||
ENTRY(cpu_feroceon_proc_init)
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* cpu_feroceon_proc_fin()
|
||||
*/
|
||||
ENTRY(cpu_feroceon_proc_fin)
|
||||
stmfd sp!, {lr}
|
||||
mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
|
||||
msr cpsr_c, ip
|
||||
bl feroceon_flush_kern_cache_all
|
||||
mrc p15, 0, r0, c1, c0, 0 @ ctrl register
|
||||
bic r0, r0, #0x1000 @ ...i............
|
||||
bic r0, r0, #0x000e @ ............wca.
|
||||
mcr p15, 0, r0, c1, c0, 0 @ disable caches
|
||||
ldmfd sp!, {pc}
|
||||
|
||||
/*
|
||||
* cpu_feroceon_reset(loc)
|
||||
*
|
||||
* Perform a soft reset of the system. Put the CPU into the
|
||||
* same state as it would be if it had been reset, and branch
|
||||
* to what would be the reset vector.
|
||||
*
|
||||
* loc: location to jump to for soft reset
|
||||
*/
|
||||
.align 5
|
||||
ENTRY(cpu_feroceon_reset)
|
||||
mov ip, #0
|
||||
mcr p15, 0, ip, c7, c7, 0 @ invalidate I,D caches
|
||||
mcr p15, 0, ip, c7, c10, 4 @ drain WB
|
||||
#ifdef CONFIG_MMU
|
||||
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
|
||||
#endif
|
||||
mrc p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
bic ip, ip, #0x000f @ ............wcam
|
||||
bic ip, ip, #0x1100 @ ...i...s........
|
||||
mcr p15, 0, ip, c1, c0, 0 @ ctrl register
|
||||
mov pc, r0
|
||||
|
||||
/*
|
||||
* cpu_feroceon_do_idle()
|
||||
*
|
||||
* Called with IRQs disabled
|
||||
*/
|
||||
.align 10
|
||||
ENTRY(cpu_feroceon_do_idle)
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer
|
||||
mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* flush_user_cache_all()
|
||||
*
|
||||
* Clean and invalidate all cache entries in a particular
|
||||
* address space.
|
||||
*/
|
||||
ENTRY(feroceon_flush_user_cache_all)
|
||||
/* FALLTHROUGH */
|
||||
|
||||
/*
|
||||
* flush_kern_cache_all()
|
||||
*
|
||||
* Clean and invalidate the entire cache.
|
||||
*/
|
||||
ENTRY(feroceon_flush_kern_cache_all)
|
||||
mov r2, #VM_EXEC
|
||||
mov ip, #0
|
||||
__flush_whole_cache:
|
||||
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
|
||||
#else
|
||||
1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
|
||||
bne 1b
|
||||
#endif
|
||||
tst r2, #VM_EXEC
|
||||
mcrne p15, 0, ip, c7, c5, 0 @ invalidate I cache
|
||||
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* flush_user_cache_range(start, end, flags)
|
||||
*
|
||||
* Clean and invalidate a range of cache entries in the
|
||||
* specified address range.
|
||||
*
|
||||
* - start - start address (inclusive)
|
||||
* - end - end address (exclusive)
|
||||
* - flags - vm_flags describing address space
|
||||
*/
|
||||
ENTRY(feroceon_flush_user_cache_range)
|
||||
mov ip, #0
|
||||
sub r3, r1, r0 @ calculate total size
|
||||
cmp r3, #CACHE_DLIMIT
|
||||
bgt __flush_whole_cache
|
||||
1: tst r2, #VM_EXEC
|
||||
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
|
||||
mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
|
||||
add r0, r0, #CACHE_DLINESIZE
|
||||
mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
|
||||
mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
|
||||
add r0, r0, #CACHE_DLINESIZE
|
||||
#else
|
||||
mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
|
||||
mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
|
||||
add r0, r0, #CACHE_DLINESIZE
|
||||
mcr p15, 0, r0, c7, c14, 1 @ clean and invalidate D entry
|
||||
mcrne p15, 0, r0, c7, c5, 1 @ invalidate I entry
|
||||
add r0, r0, #CACHE_DLINESIZE
|
||||
#endif
|
||||
cmp r0, r1
|
||||
blo 1b
|
||||
tst r2, #VM_EXEC
|
||||
mcrne p15, 0, ip, c7, c10, 4 @ drain WB
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* coherent_kern_range(start, end)
|
||||
*
|
||||
* Ensure coherency between the Icache and the Dcache in the
|
||||
* region described by start, end. If you have non-snooping
|
||||
* Harvard caches, you need to implement this function.
|
||||
*
|
||||
* - start - virtual start address
|
||||
* - end - virtual end address
|
||||
*/
|
||||
ENTRY(feroceon_coherent_kern_range)
|
||||
/* FALLTHROUGH */
|
||||
|
||||
/*
|
||||
* coherent_user_range(start, end)
|
||||
*
|
||||
* Ensure coherency between the Icache and the Dcache in the
|
||||
* region described by start, end. If you have non-snooping
|
||||
* Harvard caches, you need to implement this function.
|
||||
*
|
||||
* - start - virtual start address
|
||||
* - end - virtual end address
|
||||
*/
|
||||
ENTRY(feroceon_coherent_user_range)
|
||||
bic r0, r0, #CACHE_DLINESIZE - 1
|
||||
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
|
||||
mcr p15, 0, r0, c7, c5, 1 @ invalidate I entry
|
||||
add r0, r0, #CACHE_DLINESIZE
|
||||
cmp r0, r1
|
||||
blo 1b
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain WB
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* flush_kern_dcache_page(void *page)
|
||||
*
|
||||
* Ensure no D cache aliasing occurs, either with itself or
|
||||
* the I cache
|
||||
*
|
||||
* - addr - page aligned address
|
||||
*/
|
||||
ENTRY(feroceon_flush_kern_dcache_page)
|
||||
add r1, r0, #PAGE_SZ
|
||||
1: mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
|
||||
add r0, r0, #CACHE_DLINESIZE
|
||||
cmp r0, r1
|
||||
blo 1b
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain WB
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* dma_inv_range(start, end)
|
||||
*
|
||||
* Invalidate (discard) the specified virtual address range.
|
||||
* May not write back any entries. If 'start' or 'end'
|
||||
* are not cache line aligned, those lines must be written
|
||||
* back.
|
||||
*
|
||||
* - start - virtual start address
|
||||
* - end - virtual end address
|
||||
*
|
||||
* (same as v4wb)
|
||||
*/
|
||||
ENTRY(feroceon_dma_inv_range)
|
||||
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
tst r0, #CACHE_DLINESIZE - 1
|
||||
mcrne p15, 0, r0, c7, c10, 1 @ clean D entry
|
||||
tst r1, #CACHE_DLINESIZE - 1
|
||||
mcrne p15, 0, r1, c7, c10, 1 @ clean D entry
|
||||
#endif
|
||||
bic r0, r0, #CACHE_DLINESIZE - 1
|
||||
1: mcr p15, 0, r0, c7, c6, 1 @ invalidate D entry
|
||||
add r0, r0, #CACHE_DLINESIZE
|
||||
cmp r0, r1
|
||||
blo 1b
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain WB
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* dma_clean_range(start, end)
|
||||
*
|
||||
* Clean the specified virtual address range.
|
||||
*
|
||||
* - start - virtual start address
|
||||
* - end - virtual end address
|
||||
*
|
||||
* (same as v4wb)
|
||||
*/
|
||||
ENTRY(feroceon_dma_clean_range)
|
||||
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
bic r0, r0, #CACHE_DLINESIZE - 1
|
||||
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
|
||||
add r0, r0, #CACHE_DLINESIZE
|
||||
cmp r0, r1
|
||||
blo 1b
|
||||
#endif
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain WB
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* dma_flush_range(start, end)
|
||||
*
|
||||
* Clean and invalidate the specified virtual address range.
|
||||
*
|
||||
* - start - virtual start address
|
||||
* - end - virtual end address
|
||||
*/
|
||||
ENTRY(feroceon_dma_flush_range)
|
||||
bic r0, r0, #CACHE_DLINESIZE - 1
|
||||
1:
|
||||
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
mcr p15, 0, r0, c7, c14, 1 @ clean+invalidate D entry
|
||||
#else
|
||||
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
|
||||
#endif
|
||||
add r0, r0, #CACHE_DLINESIZE
|
||||
cmp r0, r1
|
||||
blo 1b
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain WB
|
||||
mov pc, lr
|
||||
|
||||
ENTRY(feroceon_cache_fns)
|
||||
.long feroceon_flush_kern_cache_all
|
||||
.long feroceon_flush_user_cache_all
|
||||
.long feroceon_flush_user_cache_range
|
||||
.long feroceon_coherent_kern_range
|
||||
.long feroceon_coherent_user_range
|
||||
.long feroceon_flush_kern_dcache_page
|
||||
.long feroceon_dma_inv_range
|
||||
.long feroceon_dma_clean_range
|
||||
.long feroceon_dma_flush_range
|
||||
|
||||
ENTRY(cpu_feroceon_dcache_clean_area)
|
||||
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
1: mcr p15, 0, r0, c7, c10, 1 @ clean D entry
|
||||
add r0, r0, #CACHE_DLINESIZE
|
||||
subs r1, r1, #CACHE_DLINESIZE
|
||||
bhi 1b
|
||||
#endif
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain WB
|
||||
mov pc, lr
|
||||
|
||||
/* =============================== PageTable ============================== */
|
||||
|
||||
/*
|
||||
* cpu_feroceon_switch_mm(pgd)
|
||||
*
|
||||
* Set the translation base pointer to be as described by pgd.
|
||||
*
|
||||
* pgd: new page tables
|
||||
*/
|
||||
.align 5
|
||||
ENTRY(cpu_feroceon_switch_mm)
|
||||
#ifdef CONFIG_MMU
|
||||
mov ip, #0
|
||||
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
mcr p15, 0, ip, c7, c6, 0 @ invalidate D cache
|
||||
#else
|
||||
@ && 'Clean & Invalidate whole DCache'
|
||||
1: mrc p15, 0, r15, c7, c14, 3 @ test,clean,invalidate
|
||||
bne 1b
|
||||
#endif
|
||||
mcr p15, 0, ip, c7, c5, 0 @ invalidate I cache
|
||||
mcr p15, 0, ip, c7, c10, 4 @ drain WB
|
||||
mcr p15, 0, r0, c2, c0, 0 @ load page table pointer
|
||||
mcr p15, 0, ip, c8, c7, 0 @ invalidate I & D TLBs
|
||||
#endif
|
||||
mov pc, lr
|
||||
|
||||
/*
|
||||
* cpu_feroceon_set_pte_ext(ptep, pte, ext)
|
||||
*
|
||||
* Set a PTE and flush it out
|
||||
*/
|
||||
.align 5
|
||||
ENTRY(cpu_feroceon_set_pte_ext)
|
||||
#ifdef CONFIG_MMU
|
||||
str r1, [r0], #-2048 @ linux version
|
||||
|
||||
eor r1, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
|
||||
|
||||
bic r2, r1, #PTE_SMALL_AP_MASK
|
||||
bic r2, r2, #PTE_TYPE_MASK
|
||||
orr r2, r2, #PTE_TYPE_SMALL
|
||||
|
||||
tst r1, #L_PTE_USER @ User?
|
||||
orrne r2, r2, #PTE_SMALL_AP_URO_SRW
|
||||
|
||||
tst r1, #L_PTE_WRITE | L_PTE_DIRTY @ Write and Dirty?
|
||||
orreq r2, r2, #PTE_SMALL_AP_UNO_SRW
|
||||
|
||||
tst r1, #L_PTE_PRESENT | L_PTE_YOUNG @ Present and Young?
|
||||
movne r2, #0
|
||||
|
||||
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
eor r3, r2, #0x0a @ C & small page?
|
||||
tst r3, #0x0b
|
||||
biceq r2, r2, #4
|
||||
#endif
|
||||
str r2, [r0] @ hardware version
|
||||
mov r0, r0
|
||||
#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
mcr p15, 0, r0, c7, c10, 1 @ clean D entry
|
||||
#endif
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain WB
|
||||
#endif
|
||||
mov pc, lr
|
||||
|
||||
__INIT
|
||||
|
||||
.type __feroceon_setup, #function
|
||||
__feroceon_setup:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c7 @ invalidate I,D caches on v4
|
||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer on v4
|
||||
#ifdef CONFIG_MMU
|
||||
mcr p15, 0, r0, c8, c7 @ invalidate I,D TLBs on v4
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
|
||||
mov r0, #4 @ disable write-back on caches explicitly
|
||||
mcr p15, 7, r0, c15, c0, 0
|
||||
#endif
|
||||
|
||||
adr r5, feroceon_crval
|
||||
ldmia r5, {r5, r6}
|
||||
mrc p15, 0, r0, c1, c0 @ get control register v4
|
||||
bic r0, r0, r5
|
||||
orr r0, r0, r6
|
||||
#ifdef CONFIG_CPU_CACHE_ROUND_ROBIN
|
||||
orr r0, r0, #0x4000 @ .1.. .... .... ....
|
||||
#endif
|
||||
mov pc, lr
|
||||
.size __feroceon_setup, . - __feroceon_setup
|
||||
|
||||
/*
|
||||
* R
|
||||
* .RVI ZFRS BLDP WCAM
|
||||
* .011 0001 ..11 0101
|
||||
*
|
||||
*/
|
||||
.type feroceon_crval, #object
|
||||
feroceon_crval:
|
||||
crval clear=0x00007f3f, mmuset=0x00003135, ucset=0x00001134
|
||||
|
||||
__INITDATA
|
||||
|
||||
/*
|
||||
* Purpose : Function pointers used to access above functions - all calls
|
||||
* come through these
|
||||
*/
|
||||
.type feroceon_processor_functions, #object
|
||||
feroceon_processor_functions:
|
||||
.word v5t_early_abort
|
||||
.word cpu_feroceon_proc_init
|
||||
.word cpu_feroceon_proc_fin
|
||||
.word cpu_feroceon_reset
|
||||
.word cpu_feroceon_do_idle
|
||||
.word cpu_feroceon_dcache_clean_area
|
||||
.word cpu_feroceon_switch_mm
|
||||
.word cpu_feroceon_set_pte_ext
|
||||
.size feroceon_processor_functions, . - feroceon_processor_functions
|
||||
|
||||
.section ".rodata"
|
||||
|
||||
.type cpu_arch_name, #object
|
||||
cpu_arch_name:
|
||||
.asciz "armv5te"
|
||||
.size cpu_arch_name, . - cpu_arch_name
|
||||
|
||||
.type cpu_elf_name, #object
|
||||
cpu_elf_name:
|
||||
.asciz "v5"
|
||||
.size cpu_elf_name, . - cpu_elf_name
|
||||
|
||||
.type cpu_feroceon_name, #object
|
||||
cpu_feroceon_name:
|
||||
.asciz "Feroceon"
|
||||
.size cpu_feroceon_name, . - cpu_feroceon_name
|
||||
|
||||
.align
|
||||
|
||||
.section ".proc.info.init", #alloc, #execinstr
|
||||
|
||||
#ifdef CONFIG_CPU_FEROCEON_OLD_ID
|
||||
.type __feroceon_old_id_proc_info,#object
|
||||
__feroceon_old_id_proc_info:
|
||||
.long 0x41069260
|
||||
.long 0xfffffff0
|
||||
.long PMD_TYPE_SECT | \
|
||||
PMD_SECT_BUFFERABLE | \
|
||||
PMD_SECT_CACHEABLE | \
|
||||
PMD_BIT4 | \
|
||||
PMD_SECT_AP_WRITE | \
|
||||
PMD_SECT_AP_READ
|
||||
.long PMD_TYPE_SECT | \
|
||||
PMD_BIT4 | \
|
||||
PMD_SECT_AP_WRITE | \
|
||||
PMD_SECT_AP_READ
|
||||
b __feroceon_setup
|
||||
.long cpu_arch_name
|
||||
.long cpu_elf_name
|
||||
.long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
|
||||
.long cpu_feroceon_name
|
||||
.long feroceon_processor_functions
|
||||
.long v4wbi_tlb_fns
|
||||
.long v4wb_user_fns
|
||||
.long feroceon_cache_fns
|
||||
.size __feroceon_old_id_proc_info, . - __feroceon_old_id_proc_info
|
||||
#endif
|
||||
|
||||
.type __feroceon_proc_info,#object
|
||||
__feroceon_proc_info:
|
||||
.long 0x56055310
|
||||
.long 0xfffffff0
|
||||
.long PMD_TYPE_SECT | \
|
||||
PMD_SECT_BUFFERABLE | \
|
||||
PMD_SECT_CACHEABLE | \
|
||||
PMD_BIT4 | \
|
||||
PMD_SECT_AP_WRITE | \
|
||||
PMD_SECT_AP_READ
|
||||
.long PMD_TYPE_SECT | \
|
||||
PMD_BIT4 | \
|
||||
PMD_SECT_AP_WRITE | \
|
||||
PMD_SECT_AP_READ
|
||||
b __feroceon_setup
|
||||
.long cpu_arch_name
|
||||
.long cpu_elf_name
|
||||
.long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
|
||||
.long cpu_feroceon_name
|
||||
.long feroceon_processor_functions
|
||||
.long v4wbi_tlb_fns
|
||||
.long v4wb_user_fns
|
||||
.long feroceon_cache_fns
|
||||
.size __feroceon_proc_info, . - __feroceon_proc_info
|
|
@ -361,12 +361,6 @@ static int __init mv64x60_i2c_device_setup(struct device_node *np, int id)
|
|||
else
|
||||
pdata.timeout = 1000; /* 1 second */
|
||||
|
||||
prop = of_get_property(np, "retries", NULL);
|
||||
if (prop)
|
||||
pdata.retries = *prop;
|
||||
else
|
||||
pdata.retries = 1;
|
||||
|
||||
pdev = platform_device_alloc(MV64XXX_I2C_CTLR_NAME, id);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -411,7 +411,6 @@ static struct mv64xxx_i2c_pdata mv64xxx_i2c_pdata = {
|
|||
.freq_m = 8,
|
||||
.freq_n = 3,
|
||||
.timeout = 1000, /* Default timeout of 1 second */
|
||||
.retries = 1,
|
||||
};
|
||||
|
||||
static struct resource mv64xxx_i2c_resources[] = {
|
||||
|
|
|
@ -643,7 +643,7 @@ config I2C_PCA_ISA
|
|||
|
||||
config I2C_MV64XXX
|
||||
tristate "Marvell mv64xxx I2C Controller"
|
||||
depends on MV64X60 && EXPERIMENTAL
|
||||
depends on (MV64X60 || ARCH_ORION) && EXPERIMENTAL
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
built-in I2C interface on the Marvell 64xxx line of host bridges.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Driver for the i2c controller on the Marvell line of host bridges for MIPS
|
||||
* and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0).
|
||||
* Driver for the i2c controller on the Marvell line of host bridges
|
||||
* (e.g, gt642[46]0, mv643[46]0, mv644[46]0, and Orion SoC family).
|
||||
*
|
||||
* Author: Mark A. Greer <mgreer@mvista.com>
|
||||
*
|
||||
|
@ -14,7 +14,7 @@
|
|||
#include <linux/spinlock.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mv643xx.h>
|
||||
#include <linux/mv643xx_i2c.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <asm/io.h>
|
||||
|
@ -86,6 +86,7 @@ struct mv64xxx_i2c_data {
|
|||
u32 cntl_bits;
|
||||
void __iomem *reg_base;
|
||||
u32 reg_base_p;
|
||||
u32 reg_size;
|
||||
u32 addr1;
|
||||
u32 addr2;
|
||||
u32 bytes_left;
|
||||
|
@ -463,17 +464,20 @@ static int __devinit
|
|||
mv64xxx_i2c_map_regs(struct platform_device *pd,
|
||||
struct mv64xxx_i2c_data *drv_data)
|
||||
{
|
||||
struct resource *r;
|
||||
int size;
|
||||
struct resource *r = platform_get_resource(pd, IORESOURCE_MEM, 0);
|
||||
|
||||
if ((r = platform_get_resource(pd, IORESOURCE_MEM, 0)) &&
|
||||
request_mem_region(r->start, MV64XXX_I2C_REG_BLOCK_SIZE,
|
||||
drv_data->adapter.name)) {
|
||||
if (!r)
|
||||
return -ENODEV;
|
||||
|
||||
drv_data->reg_base = ioremap(r->start,
|
||||
MV64XXX_I2C_REG_BLOCK_SIZE);
|
||||
drv_data->reg_base_p = r->start;
|
||||
} else
|
||||
return -ENOMEM;
|
||||
size = r->end - r->start + 1;
|
||||
|
||||
if (!request_mem_region(r->start, size, drv_data->adapter.name))
|
||||
return -EBUSY;
|
||||
|
||||
drv_data->reg_base = ioremap(r->start, size);
|
||||
drv_data->reg_base_p = r->start;
|
||||
drv_data->reg_size = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -483,8 +487,7 @@ mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
|
|||
{
|
||||
if (drv_data->reg_base) {
|
||||
iounmap(drv_data->reg_base);
|
||||
release_mem_region(drv_data->reg_base_p,
|
||||
MV64XXX_I2C_REG_BLOCK_SIZE);
|
||||
release_mem_region(drv_data->reg_base_p, drv_data->reg_size);
|
||||
}
|
||||
|
||||
drv_data->reg_base = NULL;
|
||||
|
@ -529,7 +532,6 @@ mv64xxx_i2c_probe(struct platform_device *pd)
|
|||
drv_data->adapter.owner = THIS_MODULE;
|
||||
drv_data->adapter.class = I2C_CLASS_HWMON;
|
||||
drv_data->adapter.timeout = pdata->timeout;
|
||||
drv_data->adapter.retries = pdata->retries;
|
||||
drv_data->adapter.nr = pd->id;
|
||||
platform_set_drvdata(pd, drv_data);
|
||||
i2c_set_adapdata(&drv_data->adapter, drv_data);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* linux/include/asm-arm/arch-orion/debug-macro.S
|
||||
*
|
||||
* Debugging macro include header
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.macro addruart,rx
|
||||
mov \rx, #0xf1000000
|
||||
orr \rx, \rx, #0x00012000
|
||||
.endm
|
||||
|
||||
#define UART_SHIFT 2
|
||||
#include <asm/hardware/debug-8250.S>
|
|
@ -0,0 +1 @@
|
|||
/* empty */
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/entry-macro.S
|
||||
*
|
||||
* Low-level IRQ helper macros for Orion platforms
|
||||
*
|
||||
* 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 <asm/arch/orion.h>
|
||||
|
||||
.macro disable_fiq
|
||||
.endm
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
ldr \base, =MAIN_IRQ_CAUSE
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
ldr \irqstat, [\base, #0] @ main cause
|
||||
ldr \tmp, [\base, #(MAIN_IRQ_MASK - MAIN_IRQ_CAUSE)] @ main mask
|
||||
mov \irqnr, #0 @ default irqnr
|
||||
@ find cause bits that are unmasked
|
||||
ands \irqstat, \irqstat, \tmp @ clear Z flag if any
|
||||
clzne \irqnr, \irqstat @ calc irqnr
|
||||
rsbne \irqnr, \irqnr, #31
|
||||
.endm
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/gpio.h
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
extern int gpio_request(unsigned pin, const char *label);
|
||||
extern void gpio_free(unsigned pin);
|
||||
extern int gpio_direction_input(unsigned pin);
|
||||
extern int gpio_direction_output(unsigned pin, int value);
|
||||
extern int gpio_get_value(unsigned pin);
|
||||
extern void gpio_set_value(unsigned pin, int value);
|
||||
extern void orion_gpio_set_blink(unsigned pin, int blink);
|
||||
extern void gpio_display(void); /* debug */
|
||||
|
||||
static inline int gpio_to_irq(int pin)
|
||||
{
|
||||
return pin + IRQ_ORION_GPIO_START;
|
||||
}
|
||||
|
||||
static inline int irq_to_gpio(int irq)
|
||||
{
|
||||
return irq - IRQ_ORION_GPIO_START;
|
||||
}
|
||||
|
||||
#include <asm-generic/gpio.h> /* cansleep wrappers */
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/hardware.h
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_HARDWARE_H__
|
||||
#define __ASM_ARCH_HARDWARE_H__
|
||||
|
||||
#include "orion.h"
|
||||
|
||||
#define PCI_MEMORY_VADDR ORION_PCI_SYS_MEM_BASE
|
||||
#define PCI_IO_VADDR ORION_PCI_SYS_IO_BASE
|
||||
|
||||
#define pcibios_assign_all_busses() 1
|
||||
|
||||
#define PCIBIOS_MIN_IO 0x1000
|
||||
#define PCIBIOS_MIN_MEM 0x01000000
|
||||
#define PCIMEM_BASE PCI_MEMORY_VADDR /* mem base for VGA */
|
||||
|
||||
#endif /* _ASM_ARCH_HARDWARE_H */
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/io.h
|
||||
*
|
||||
* Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARM_ARCH_IO_H
|
||||
#define __ASM_ARM_ARCH_IO_H
|
||||
|
||||
#include "orion.h"
|
||||
|
||||
#define IO_SPACE_LIMIT 0xffffffff
|
||||
#define IO_SPACE_REMAP ORION_PCI_SYS_IO_BASE
|
||||
|
||||
static inline void __iomem *__io(unsigned long addr)
|
||||
{
|
||||
return (void __iomem *)addr;
|
||||
}
|
||||
|
||||
#define __io(a) __io(a)
|
||||
#define __mem_pci(a) (a)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/irqs.h
|
||||
*
|
||||
* IRQ definitions for Orion SoC
|
||||
*
|
||||
* Maintainer: Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_IRQS_H__
|
||||
#define __ASM_ARCH_IRQS_H__
|
||||
|
||||
#include "orion.h" /* need GPIO_MAX */
|
||||
|
||||
/*
|
||||
* Orion Main Interrupt Controller
|
||||
*/
|
||||
#define IRQ_ORION_BRIDGE 0
|
||||
#define IRQ_ORION_DOORBELL_H2C 1
|
||||
#define IRQ_ORION_DOORBELL_C2H 2
|
||||
#define IRQ_ORION_UART0 3
|
||||
#define IRQ_ORION_UART1 4
|
||||
#define IRQ_ORION_I2C 5
|
||||
#define IRQ_ORION_GPIO_0_7 6
|
||||
#define IRQ_ORION_GPIO_8_15 7
|
||||
#define IRQ_ORION_GPIO_16_23 8
|
||||
#define IRQ_ORION_GPIO_24_31 9
|
||||
#define IRQ_ORION_PCIE0_ERR 10
|
||||
#define IRQ_ORION_PCIE0_INT 11
|
||||
#define IRQ_ORION_USB1_CTRL 12
|
||||
#define IRQ_ORION_DEV_BUS_ERR 14
|
||||
#define IRQ_ORION_PCI_ERR 15
|
||||
#define IRQ_ORION_USB_BR_ERR 16
|
||||
#define IRQ_ORION_USB0_CTRL 17
|
||||
#define IRQ_ORION_ETH_RX 18
|
||||
#define IRQ_ORION_ETH_TX 19
|
||||
#define IRQ_ORION_ETH_MISC 20
|
||||
#define IRQ_ORION_ETH_SUM 21
|
||||
#define IRQ_ORION_ETH_ERR 22
|
||||
#define IRQ_ORION_IDMA_ERR 23
|
||||
#define IRQ_ORION_IDMA_0 24
|
||||
#define IRQ_ORION_IDMA_1 25
|
||||
#define IRQ_ORION_IDMA_2 26
|
||||
#define IRQ_ORION_IDMA_3 27
|
||||
#define IRQ_ORION_CESA 28
|
||||
#define IRQ_ORION_SATA 29
|
||||
#define IRQ_ORION_XOR0 30
|
||||
#define IRQ_ORION_XOR1 31
|
||||
|
||||
/*
|
||||
* Orion General Purpose Pins
|
||||
*/
|
||||
#define IRQ_ORION_GPIO_START 32
|
||||
#define NR_GPIO_IRQS GPIO_MAX
|
||||
|
||||
#define NR_IRQS (IRQ_ORION_GPIO_START + NR_GPIO_IRQS)
|
||||
|
||||
#endif /* __ASM_ARCH_IRQS_H__ */
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/memory.h
|
||||
*
|
||||
* Marvell Orion memory definitions
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_MMU_H
|
||||
#define __ASM_ARCH_MMU_H
|
||||
|
||||
#define PHYS_OFFSET UL(0x00000000)
|
||||
|
||||
#define __virt_to_bus(x) __virt_to_phys(x)
|
||||
#define __bus_to_virt(x) __phys_to_virt(x)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/orion.h
|
||||
*
|
||||
* Generic definitions of Orion SoC flavors:
|
||||
* Orion-1, Orion-NAS, Orion-VoIP, and Orion-2.
|
||||
*
|
||||
* Maintainer: Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_ORION_H__
|
||||
#define __ASM_ARCH_ORION_H__
|
||||
|
||||
/*******************************************************************************
|
||||
* Orion Address Map
|
||||
* Use the same mapping (1:1 virtual:physical) of internal registers and
|
||||
* PCI system (PCI+PCIE) for all machines.
|
||||
* Each machine defines the rest of its mapping (e.g. device bus flashes)
|
||||
******************************************************************************/
|
||||
#define ORION_REGS_BASE 0xf1000000
|
||||
#define ORION_REGS_SIZE SZ_1M
|
||||
|
||||
#define ORION_PCI_SYS_MEM_BASE 0xe0000000
|
||||
#define ORION_PCIE_MEM_BASE ORION_PCI_SYS_MEM_BASE
|
||||
#define ORION_PCIE_MEM_SIZE SZ_128M
|
||||
#define ORION_PCI_MEM_BASE (ORION_PCIE_MEM_BASE + ORION_PCIE_MEM_SIZE)
|
||||
#define ORION_PCI_MEM_SIZE SZ_128M
|
||||
|
||||
#define ORION_PCI_SYS_IO_BASE 0xf2000000
|
||||
#define ORION_PCIE_IO_BASE ORION_PCI_SYS_IO_BASE
|
||||
#define ORION_PCIE_IO_SIZE SZ_1M
|
||||
#define ORION_PCIE_IO_REMAP (ORION_PCIE_IO_BASE - ORION_PCI_SYS_IO_BASE)
|
||||
#define ORION_PCI_IO_BASE (ORION_PCIE_IO_BASE + ORION_PCIE_IO_SIZE)
|
||||
#define ORION_PCI_IO_SIZE SZ_1M
|
||||
#define ORION_PCI_IO_REMAP (ORION_PCI_IO_BASE - ORION_PCI_SYS_IO_BASE)
|
||||
/* Relevant only for Orion-NAS */
|
||||
#define ORION_PCIE_WA_BASE 0xf0000000
|
||||
#define ORION_PCIE_WA_SIZE SZ_16M
|
||||
|
||||
/*******************************************************************************
|
||||
* Supported Devices & Revisions
|
||||
******************************************************************************/
|
||||
/* Orion-1 (88F5181) */
|
||||
#define MV88F5181_DEV_ID 0x5181
|
||||
#define MV88F5181_REV_B1 3
|
||||
/* Orion-NAS (88F5182) */
|
||||
#define MV88F5182_DEV_ID 0x5182
|
||||
#define MV88F5182_REV_A2 2
|
||||
/* Orion-2 (88F5281) */
|
||||
#define MV88F5281_DEV_ID 0x5281
|
||||
#define MV88F5281_REV_D1 5
|
||||
#define MV88F5281_REV_D2 6
|
||||
|
||||
/*******************************************************************************
|
||||
* Orion Registers Map
|
||||
******************************************************************************/
|
||||
#define ORION_DDR_REG_BASE (ORION_REGS_BASE | 0x00000)
|
||||
#define ORION_DEV_BUS_REG_BASE (ORION_REGS_BASE | 0x10000)
|
||||
#define ORION_BRIDGE_REG_BASE (ORION_REGS_BASE | 0x20000)
|
||||
#define ORION_PCI_REG_BASE (ORION_REGS_BASE | 0x30000)
|
||||
#define ORION_PCIE_REG_BASE (ORION_REGS_BASE | 0x40000)
|
||||
#define ORION_USB0_REG_BASE (ORION_REGS_BASE | 0x50000)
|
||||
#define ORION_ETH_REG_BASE (ORION_REGS_BASE | 0x70000)
|
||||
#define ORION_SATA_REG_BASE (ORION_REGS_BASE | 0x80000)
|
||||
#define ORION_USB1_REG_BASE (ORION_REGS_BASE | 0xa0000)
|
||||
|
||||
#define ORION_DDR_REG(x) (ORION_DDR_REG_BASE | (x))
|
||||
#define ORION_DEV_BUS_REG(x) (ORION_DEV_BUS_REG_BASE | (x))
|
||||
#define ORION_BRIDGE_REG(x) (ORION_BRIDGE_REG_BASE | (x))
|
||||
#define ORION_PCI_REG(x) (ORION_PCI_REG_BASE | (x))
|
||||
#define ORION_PCIE_REG(x) (ORION_PCIE_REG_BASE | (x))
|
||||
#define ORION_USB0_REG(x) (ORION_USB0_REG_BASE | (x))
|
||||
#define ORION_USB1_REG(x) (ORION_USB1_REG_BASE | (x))
|
||||
#define ORION_ETH_REG(x) (ORION_ETH_REG_BASE | (x))
|
||||
#define ORION_SATA_REG(x) (ORION_SATA_REG_BASE | (x))
|
||||
|
||||
/*******************************************************************************
|
||||
* Device Bus Registers
|
||||
******************************************************************************/
|
||||
#define MPP_0_7_CTRL ORION_DEV_BUS_REG(0x000)
|
||||
#define MPP_8_15_CTRL ORION_DEV_BUS_REG(0x004)
|
||||
#define MPP_16_19_CTRL ORION_DEV_BUS_REG(0x050)
|
||||
#define MPP_DEV_CTRL ORION_DEV_BUS_REG(0x008)
|
||||
#define MPP_RESET_SAMPLE ORION_DEV_BUS_REG(0x010)
|
||||
#define GPIO_OUT ORION_DEV_BUS_REG(0x100)
|
||||
#define GPIO_IO_CONF ORION_DEV_BUS_REG(0x104)
|
||||
#define GPIO_BLINK_EN ORION_DEV_BUS_REG(0x108)
|
||||
#define GPIO_IN_POL ORION_DEV_BUS_REG(0x10c)
|
||||
#define GPIO_DATA_IN ORION_DEV_BUS_REG(0x110)
|
||||
#define GPIO_EDGE_CAUSE ORION_DEV_BUS_REG(0x114)
|
||||
#define GPIO_EDGE_MASK ORION_DEV_BUS_REG(0x118)
|
||||
#define GPIO_LEVEL_MASK ORION_DEV_BUS_REG(0x11c)
|
||||
#define DEV_BANK_0_PARAM ORION_DEV_BUS_REG(0x45c)
|
||||
#define DEV_BANK_1_PARAM ORION_DEV_BUS_REG(0x460)
|
||||
#define DEV_BANK_2_PARAM ORION_DEV_BUS_REG(0x464)
|
||||
#define DEV_BANK_BOOT_PARAM ORION_DEV_BUS_REG(0x46c)
|
||||
#define DEV_BUS_CTRL ORION_DEV_BUS_REG(0x4c0)
|
||||
#define DEV_BUS_INT_CAUSE ORION_DEV_BUS_REG(0x4d0)
|
||||
#define DEV_BUS_INT_MASK ORION_DEV_BUS_REG(0x4d4)
|
||||
#define I2C_BASE ORION_DEV_BUS_REG(0x1000)
|
||||
#define UART0_BASE ORION_DEV_BUS_REG(0x2000)
|
||||
#define UART1_BASE ORION_DEV_BUS_REG(0x2100)
|
||||
#define GPIO_MAX 32
|
||||
|
||||
/***************************************************************************
|
||||
* Orion CPU Bridge Registers
|
||||
**************************************************************************/
|
||||
#define CPU_CONF ORION_BRIDGE_REG(0x100)
|
||||
#define CPU_CTRL ORION_BRIDGE_REG(0x104)
|
||||
#define CPU_RESET_MASK ORION_BRIDGE_REG(0x108)
|
||||
#define CPU_SOFT_RESET ORION_BRIDGE_REG(0x10c)
|
||||
#define POWER_MNG_CTRL_REG ORION_BRIDGE_REG(0x11C)
|
||||
#define BRIDGE_CAUSE ORION_BRIDGE_REG(0x110)
|
||||
#define BRIDGE_MASK ORION_BRIDGE_REG(0x114)
|
||||
#define MAIN_IRQ_CAUSE ORION_BRIDGE_REG(0x200)
|
||||
#define MAIN_IRQ_MASK ORION_BRIDGE_REG(0x204)
|
||||
#define TIMER_CTRL ORION_BRIDGE_REG(0x300)
|
||||
#define TIMER_VAL(x) ORION_BRIDGE_REG(0x314 + ((x) * 8))
|
||||
#define TIMER_VAL_RELOAD(x) ORION_BRIDGE_REG(0x310 + ((x) * 8))
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/*******************************************************************************
|
||||
* Helpers to access Orion registers
|
||||
******************************************************************************/
|
||||
#include <asm/types.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define orion_read(r) __raw_readl(r)
|
||||
#define orion_write(r, val) __raw_writel(val, r)
|
||||
|
||||
/*
|
||||
* These are not preempt safe. Locks, if needed, must be taken care by caller.
|
||||
*/
|
||||
#define orion_setbits(r, mask) orion_write((r), orion_read(r) | (mask))
|
||||
#define orion_clrbits(r, mask) orion_write((r), orion_read(r) & ~(mask))
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ASM_ARCH_ORION_H__ */
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* asm-arm/arch-orion/platform.h
|
||||
*
|
||||
* Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_PLATFORM_H__
|
||||
#define __ASM_ARCH_PLATFORM_H__
|
||||
|
||||
/*
|
||||
* Device bus NAND private data
|
||||
*/
|
||||
struct orion_nand_data {
|
||||
struct mtd_partition *parts;
|
||||
u32 nr_parts;
|
||||
u8 ale; /* address line number connected to ALE */
|
||||
u8 cle; /* address line number connected to CLE */
|
||||
u8 width; /* buswidth */
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/system.h
|
||||
*
|
||||
* Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_SYSTEM_H
|
||||
#define __ASM_ARCH_SYSTEM_H
|
||||
|
||||
#include <asm/arch/hardware.h>
|
||||
#include <asm/arch/orion.h>
|
||||
|
||||
static inline void arch_idle(void)
|
||||
{
|
||||
cpu_do_idle();
|
||||
}
|
||||
|
||||
static inline void arch_reset(char mode)
|
||||
{
|
||||
/*
|
||||
* Enable and issue soft reset
|
||||
*/
|
||||
orion_setbits(CPU_RESET_MASK, (1 << 2));
|
||||
orion_setbits(CPU_SOFT_RESET, 1);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/timex.h
|
||||
*
|
||||
* Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define ORION_TCLK 166666667
|
||||
#define CLOCK_TICK_RATE ORION_TCLK
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/uncompress.h
|
||||
*
|
||||
* Tzachi Perelstein <tzachi@marvell.com>
|
||||
*
|
||||
* 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 <asm/arch/orion.h>
|
||||
|
||||
#define MV_UART_LSR ((volatile unsigned char *)(UART0_BASE + 0x14))
|
||||
#define MV_UART_THR ((volatile unsigned char *)(UART0_BASE + 0x0))
|
||||
|
||||
#define LSR_THRE 0x20
|
||||
|
||||
static void putc(const char c)
|
||||
{
|
||||
int j = 0x1000;
|
||||
while (--j && !(*MV_UART_LSR & LSR_THRE))
|
||||
barrier();
|
||||
*MV_UART_THR = c;
|
||||
}
|
||||
|
||||
static void flush(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void orion_early_putstr(const char *ptr)
|
||||
{
|
||||
char c;
|
||||
while ((c = *ptr++) != '\0') {
|
||||
if (c == '\n')
|
||||
putc('\r');
|
||||
putc(c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* nothing to do
|
||||
*/
|
||||
#define arch_decomp_setup()
|
||||
#define arch_decomp_wdog()
|
|
@ -0,0 +1,5 @@
|
|||
/*
|
||||
* include/asm-arm/arch-orion/vmalloc.h
|
||||
*/
|
||||
|
||||
#define VMALLOC_END 0xf0000000
|
|
@ -94,6 +94,14 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_FEROCEON)
|
||||
# ifdef _CACHE
|
||||
# define MULTI_CACHE 1
|
||||
# else
|
||||
# define _CACHE feroceon
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CPU_V6)
|
||||
//# ifdef _CACHE
|
||||
# define MULTI_CACHE 1
|
||||
|
|
|
@ -185,6 +185,14 @@
|
|||
# define CPU_NAME cpu_xsc3
|
||||
# endif
|
||||
# endif
|
||||
# ifdef CONFIG_CPU_FEROCEON
|
||||
# ifdef CPU_NAME
|
||||
# undef MULTI_CPU
|
||||
# define MULTI_CPU
|
||||
# else
|
||||
# define CPU_NAME cpu_feroceon
|
||||
# endif
|
||||
# endif
|
||||
# ifdef CONFIG_CPU_V6
|
||||
# ifdef CPU_NAME
|
||||
# undef MULTI_CPU
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <asm/types.h>
|
||||
#include <linux/mv643xx_eth.h>
|
||||
#include <linux/mv643xx_i2c.h>
|
||||
|
||||
/****************************************/
|
||||
/* Processor Address Space */
|
||||
|
@ -863,7 +864,6 @@
|
|||
/* I2C Registers */
|
||||
/****************************************/
|
||||
|
||||
#define MV64XXX_I2C_CTLR_NAME "mv64xxx_i2c"
|
||||
#define MV64XXX_I2C_OFFSET 0xc000
|
||||
#define MV64XXX_I2C_REG_BLOCK_SIZE 0x0020
|
||||
|
||||
|
@ -968,14 +968,6 @@ struct mpsc_pdata {
|
|||
u32 brg_clk_freq;
|
||||
};
|
||||
|
||||
/* i2c Platform Device, Driver Data */
|
||||
struct mv64xxx_i2c_pdata {
|
||||
u32 freq_m;
|
||||
u32 freq_n;
|
||||
u32 timeout; /* In milliseconds */
|
||||
u32 retries;
|
||||
};
|
||||
|
||||
/* Watchdog Platform Device, Driver Data */
|
||||
#define MV64x60_WDT_NAME "mv64x60_wdt"
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 _MV64XXX_I2C_H_
|
||||
#define _MV64XXX_I2C_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
#define MV64XXX_I2C_CTLR_NAME "mv64xxx_i2c"
|
||||
|
||||
/* i2c Platform Device, Driver Data */
|
||||
struct mv64xxx_i2c_pdata {
|
||||
u32 freq_m;
|
||||
u32 freq_n;
|
||||
u32 timeout; /* In milliseconds */
|
||||
};
|
||||
|
||||
#endif /*_MV64XXX_I2C_H_*/
|
Loading…
Reference in New Issue