Commit 9918cda5 authored by Uwe Kleine-König's avatar Uwe Kleine-König Committed by Russell King

[ARM] 4210/1: base for new machine type "NetSilicon NS9360"

Signed-off-by: default avatarUwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent ae0a846e
......@@ -271,6 +271,14 @@ config ARCH_L7200
If you have any questions or comments about the Linux kernel port
to this board, send e-mail to <sjhill@cotw.com>.
config ARCH_NS9XXX
bool "NetSilicon NS9xxx"
help
Say Y here if you intend to run this kernel on a NetSilicon NS9xxx
System.
<http://www.digi.com/products/microprocessors/index.jsp>
config ARCH_PNX4008
bool "Philips Nexperia PNX4008 Mobile"
help
......@@ -381,6 +389,8 @@ source "arch/arm/mach-at91rm9200/Kconfig"
source "arch/arm/mach-netx/Kconfig"
source "arch/arm/mach-ns9xxx/Kconfig"
# Definitions to make life easier
config ARCH_ACORN
bool
......
......@@ -124,10 +124,12 @@ endif
machine-$(CONFIG_ARCH_H720X) := h720x
machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
machine-$(CONFIG_ARCH_REALVIEW) := realview
machine-$(CONFIG_ARCH_AT91) := at91rm9200
machine-$(CONFIG_ARCH_EP93XX) := ep93xx
machine-$(CONFIG_ARCH_PNX4008) := pnx4008
machine-$(CONFIG_ARCH_NETX) := netx
machine-$(CONFIG_ARCH_AT91) := at91rm9200
machine-$(CONFIG_ARCH_EP93XX) := ep93xx
machine-$(CONFIG_ARCH_PNX4008) := pnx4008
machine-$(CONFIG_ARCH_NETX) := netx
machine-$(CONFIG_ARCH_NS9XXX) := ns9xxx
textofs-$(CONFIG_ARCH_NS9XXX) := 0x00108000
ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line.
......
if ARCH_NS9XXX
menu "NS9xxx Implementations"
config MACH_CC9P9360DEV
bool "Connect Core 9P 9360 on an A9M9750 Devboard"
select PROCESSOR_NS9360
select BOARD_A9M9750DEV
help
Say Y here if you are using the Digi Connect Core 9P 9360
on an A9M9750 Development Board.
config PROCESSOR_NS9360
bool
config BOARD_A9M9750DEV
bool
endmenu
endif
obj-y := irq.o time.o generic.o
obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o
obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o
zreladdr-y := 0x108000
params_phys-y := 0x100
/*
* arch/arm/mach-ns9xxx/board-a9m9750dev.c
*
* Copyright (C) 2006,2007 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/platform_device.h>
#include <linux/serial_8250.h>
#include <linux/irq.h>
#include <asm/mach/map.h>
#include <asm/arch-ns9xxx/board.h>
#include <asm/arch-ns9xxx/regs-sys.h>
#include <asm/arch-ns9xxx/regs-mem.h>
#include <asm/arch-ns9xxx/regs-bbu.h>
#include <asm/arch-ns9xxx/regs-board-a9m9750dev.h>
#include "board-a9m9750dev.h"
static struct map_desc board_a9m9750dev_io_desc[] __initdata = {
{ /* FPGA on CS0 */
.virtual = io_p2v(NS9XXX_CSxSTAT_PHYS(0)),
.pfn = __phys_to_pfn(NS9XXX_CSxSTAT_PHYS(0)),
.length = NS9XXX_CS0STAT_LENGTH,
.type = MT_DEVICE,
},
};
void __init board_a9m9750dev_map_io(void)
{
iotable_init(board_a9m9750dev_io_desc,
ARRAY_SIZE(board_a9m9750dev_io_desc));
}
static void a9m9750dev_fpga_ack_irq(unsigned int irq)
{
/* nothing */
}
static void a9m9750dev_fpga_mask_irq(unsigned int irq)
{
FPGA_IER &= ~(1 << (irq - FPGA_IRQ(0)));
}
static void a9m9750dev_fpga_maskack_irq(unsigned int irq)
{
a9m9750dev_fpga_mask_irq(irq);
a9m9750dev_fpga_ack_irq(irq);
}
static void a9m9750dev_fpga_unmask_irq(unsigned int irq)
{
FPGA_IER |= 1 << (irq - FPGA_IRQ(0));
}
static struct irq_chip a9m9750dev_fpga_chip = {
.ack = a9m9750dev_fpga_ack_irq,
.mask = a9m9750dev_fpga_mask_irq,
.mask_ack = a9m9750dev_fpga_maskack_irq,
.unmask = a9m9750dev_fpga_unmask_irq,
};
static void a9m9750dev_fpga_demux_handler(unsigned int irq,
struct irq_desc *desc)
{
int stat = FPGA_ISR;
while (stat != 0) {
int irqno = fls(stat) - 1;
stat &= ~(1 << irqno);
desc = irq_desc + FPGA_IRQ(irqno);
desc_handle_irq(irqno, desc);
}
}
void __init board_a9m9750dev_init_irq(void)
{
u32 reg;
int i;
/*
* configure gpio for IRQ_EXT2
* use GPIO 11, because GPIO 32 is used for the LCD
*/
/* XXX: proper GPIO handling */
BBU_GC(2) &= ~0x2000;
for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) {
set_irq_chip(i, &a9m9750dev_fpga_chip);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID);
}
/* IRQ_EXT2: level sensitive + active low */
reg = SYS_EIC(2);
REGSET(reg, SYS_EIC, PLTY, AL);
REGSET(reg, SYS_EIC, LVEDG, LEVEL);
SYS_EIC(2) = reg;
set_irq_chained_handler(IRQ_EXT2,
a9m9750dev_fpga_demux_handler);
}
static struct plat_serial8250_port board_a9m9750dev_serial8250_port[] = {
{
.iobase = FPGA_UARTA_BASE,
.membase = (unsigned char*)FPGA_UARTA_BASE,
.mapbase = FPGA_UARTA_BASE,
.irq = IRQ_FPGA_UARTA,
.iotype = UPIO_MEM,
.uartclk = 18432000,
.regshift = 0,
.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
}, {
.iobase = FPGA_UARTB_BASE,
.membase = (unsigned char*)FPGA_UARTB_BASE,
.mapbase = FPGA_UARTB_BASE,
.irq = IRQ_FPGA_UARTB,
.iotype = UPIO_MEM,
.uartclk = 18432000,
.regshift = 0,
.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
}, {
.iobase = FPGA_UARTC_BASE,
.membase = (unsigned char*)FPGA_UARTC_BASE,
.mapbase = FPGA_UARTC_BASE,
.irq = IRQ_FPGA_UARTC,
.iotype = UPIO_MEM,
.uartclk = 18432000,
.regshift = 0,
.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
}, {
.iobase = FPGA_UARTD_BASE,
.membase = (unsigned char*)FPGA_UARTD_BASE,
.mapbase = FPGA_UARTD_BASE,
.irq = IRQ_FPGA_UARTD,
.iotype = UPIO_MEM,
.uartclk = 18432000,
.regshift = 0,
.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ,
}, {
/* end marker */
},
};
static struct platform_device board_a9m9750dev_serial_device = {
.name = "serial8250",
.dev = {
.platform_data = board_a9m9750dev_serial8250_port,
},
};
static struct platform_device *board_a9m9750dev_devices[] __initdata = {
&board_a9m9750dev_serial_device,
};
void __init board_a9m9750dev_init_machine(void)
{
u32 reg;
/* setup static CS0: memory base ... */
REGSETIM(SYS_SMCSSMB(0), SYS_SMCSSMB, CSxB,
NS9XXX_CSxSTAT_PHYS(0) >> 12);
/* ... and mask */
reg = SYS_SMCSSMM(0);
REGSETIM(reg, SYS_SMCSSMM, CSxM, 0xfffff);
REGSET(reg, SYS_SMCSSMM, CSEx, EN);
SYS_SMCSSMM(0) = reg;
/* setup static CS0: memory configuration */
reg = MEM_SMC(0);
REGSET(reg, MEM_SMC, WSMC, OFF);
REGSET(reg, MEM_SMC, BSMC, OFF);
REGSET(reg, MEM_SMC, EW, OFF);
REGSET(reg, MEM_SMC, PB, 1);
REGSET(reg, MEM_SMC, PC, AL);
REGSET(reg, MEM_SMC, PM, DIS);
REGSET(reg, MEM_SMC, MW, 8);
MEM_SMC(0) = reg;
/* setup static CS0: timing */
MEM_SMWED(0) = 0x2;
MEM_SMOED(0) = 0x2;
MEM_SMRD(0) = 0x6;
MEM_SMWD(0) = 0x6;
platform_add_devices(board_a9m9750dev_devices,
ARRAY_SIZE(board_a9m9750dev_devices));
}
/*
* arch/arm/mach-ns9xxx/board-a9m9750dev.h
*
* Copyright (C) 2006 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/init.h>
void __init board_a9m9750dev_map_io(void);
void __init board_a9m9750dev_init_machine(void);
void __init board_a9m9750dev_init_irq(void);
/*
* arch/arm/mach-ns9xxx/generic.c
*
* Copyright (C) 2006 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/memory.h>
#include <asm/page.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <asm/arch-ns9xxx/regs-sys.h>
#include <asm/arch-ns9xxx/regs-mem.h>
#include <asm/arch-ns9xxx/board.h>
static struct map_desc standard_io_desc[] __initdata = {
{ /* BBus */
.virtual = io_p2v(0x90000000),
.pfn = __phys_to_pfn(0x90000000),
.length = 0x00700000,
.type = MT_DEVICE,
}, { /* AHB */
.virtual = io_p2v(0xa0100000),
.pfn = __phys_to_pfn(0xa0100000),
.length = 0x00900000,
.type = MT_DEVICE,
},
};
void __init ns9xxx_map_io(void)
{
iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
}
void __init ns9xxx_init_machine(void)
{
}
/*
* arch/arm/mach-ns9xxx/generic.h
*
* Copyright (C) 2006 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/time.h>
#include <asm/mach/time.h>
#include <linux/init.h>
void __init ns9xxx_init_irq(void);
void __init ns9xxx_map_io(void);
void __init ns9xxx_init_machine(void);
extern struct sys_timer ns9xxx_timer;
/*
* arch/arm/mach-ns9xxx/irq.c
*
* Copyright (C) 2006,2007 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/interrupt.h>
#include <asm/mach/irq.h>
#include <asm/mach-types.h>
#include <asm/arch-ns9xxx/regs-sys.h>
#include <asm/arch-ns9xxx/irqs.h>
#include <asm/arch-ns9xxx/board.h>
#include "generic.h"
static void ns9xxx_ack_irq_timer(unsigned int irq)
{
u32 tc = SYS_TC(irq - IRQ_TIMER0);
REGSET(tc, SYS_TCx, INTC, SET);
SYS_TC(irq - IRQ_TIMER0) = tc;
REGSET(tc, SYS_TCx, INTC, UNSET);
SYS_TC(irq - IRQ_TIMER0) = tc;
}
void (*ns9xxx_ack_irq_functions[NR_IRQS])(unsigned int) = {
[IRQ_TIMER0] = ns9xxx_ack_irq_timer,
[IRQ_TIMER1] = ns9xxx_ack_irq_timer,
[IRQ_TIMER2] = ns9xxx_ack_irq_timer,
[IRQ_TIMER3] = ns9xxx_ack_irq_timer,
};
static void ns9xxx_mask_irq(unsigned int irq)
{
/* XXX: better use cpp symbols */
SYS_IC(irq / 4) &= ~(1 << (7 + 8 * (3 - (irq & 3))));
}
static void ns9xxx_ack_irq(unsigned int irq)
{
if (!ns9xxx_ack_irq_functions[irq]) {
printk(KERN_ERR "no ack function for irq %u\n", irq);
BUG();
}
ns9xxx_ack_irq_functions[irq](irq);
SYS_ISRADDR = 0;
}
static void ns9xxx_maskack_irq(unsigned int irq)
{
ns9xxx_mask_irq(irq);
ns9xxx_ack_irq(irq);
}
static void ns9xxx_unmask_irq(unsigned int irq)
{
/* XXX: better use cpp symbols */
SYS_IC(irq / 4) |= 1 << (7 + 8 * (3 - (irq & 3)));
}
static struct irq_chip ns9xxx_chip = {
.ack = ns9xxx_ack_irq,
.mask = ns9xxx_mask_irq,
.mask_ack = ns9xxx_maskack_irq,
.unmask = ns9xxx_unmask_irq,
};
void __init ns9xxx_init_irq(void)
{
int i;
/* disable all IRQs */
for (i = 0; i < 8; ++i)
SYS_IC(i) = (4 * i) << 24 | (4 * i + 1) << 16 |
(4 * i + 2) << 8 | (4 * i + 3);
/* simple interrupt prio table:
* prio(x) < prio(y) <=> x < y
*/
for (i = 0; i < 32; ++i)
SYS_IVA(i) = i;
for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) {
set_irq_chip(i, &ns9xxx_chip);
set_irq_handler(i, handle_level_irq);
set_irq_flags(i, IRQF_VALID);
}
}
/*
* arch/arm/mach-ns9xxx/mach-cc9p9360dev.c
*
* Copyright (C) 2006 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
#include "board-a9m9750dev.h"
#include "generic.h"
static void __init mach_cc9p9360dev_map_io(void)
{
ns9xxx_map_io();
board_a9m9750dev_map_io();
}
static void __init mach_cc9p9360dev_init_irq(void)
{
ns9xxx_init_irq();
board_a9m9750dev_init_irq();
}
static void __init mach_cc9p9360dev_init_machine(void)
{
ns9xxx_init_machine();
board_a9m9750dev_init_machine();
}
MACHINE_START(CC9P9360DEV, "Connect Core 9P 9360 on an A9M9750 Devboard")
.map_io = mach_cc9p9360dev_map_io,
.init_irq = mach_cc9p9360dev_init_irq,
.init_machine = mach_cc9p9360dev_init_machine,
.timer = &ns9xxx_timer,
.boot_params = 0x100,
MACHINE_END
/*
* arch/arm/mach-ns9xxx/time.c
*
* Copyright (C) 2006 by Digi International Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/jiffies.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/arch-ns9xxx/regs-sys.h>
#include <asm/arch-ns9xxx/clock.h>
#include <asm/arch-ns9xxx/irqs.h>
#include <asm/arch/system.h>
#include "generic.h"
#define TIMERCLOCKSELECT 64
static u32 usecs_per_tick;
static irqreturn_t
ns9xxx_timer_interrupt(int irq, void *dev_id)
{
write_seqlock(&xtime_lock);
timer_tick();
write_sequnlock(&xtime_lock);
return IRQ_HANDLED;
}
static unsigned long ns9xxx_timer_gettimeoffset(void)
{
/* return the microseconds which have passed since the last interrupt
* was _serviced_. That is, if an interrupt is pending or the counter
* reloads, return one periode more. */
u32 counter1 = SYS_TR(0);
int pending = SYS_ISR & (1 << IRQ_TIMER0);
u32 counter2 = SYS_TR(0);
u32 elapsed;
if (pending || counter2 > counter1)
elapsed = 2 * SYS_TRC(0) - counter2;
else
elapsed = SYS_TRC(0) - counter1;
return (elapsed * usecs_per_tick) >> 16;
}
static struct irqaction ns9xxx_timer_irq = {
.name = "NS9xxx Timer Tick",
.flags = IRQF_DISABLED | IRQF_TIMER,
.handler = ns9xxx_timer_interrupt,
};
static void __init ns9xxx_timer_init(void)
{
int tc;
usecs_per_tick =
SH_DIV(1000000 * TIMERCLOCKSELECT, ns9xxx_cpuclock(), 16);
/* disable timer */
if ((tc = SYS_TC(0)) & SYS_TCx_TEN)
SYS_TC(0) = tc & ~SYS_TCx_TEN;
SYS_TRC(0) = SH_DIV(ns9xxx_cpuclock(), (TIMERCLOCKSELECT * HZ), 0);
REGSET(tc, SYS_TCx, TEN, EN);
REGSET(tc, SYS_TCx, TLCS, DIV64); /* This must match TIMERCLOCKSELECT */
REGSET(tc, SYS_TCx, INTS, EN);
REGSET(tc, SYS_TCx, UDS, DOWN);
REGSET(tc, SYS_TCx, TDBG, STOP);
REGSET(tc, SYS_TCx, TSZ, 32);
REGSET(tc, SYS_TCx, REN, EN);
SYS_TC(0) = tc;
setup_irq(IRQ_TIMER0, &ns9xxx_timer_irq);
}
struct sys_timer ns9xxx_timer = {
.init = ns9xxx_timer_init,
.offset = ns9xxx_timer_gettimeoffset,
};
......@@ -171,8 +171,8 @@ config CPU_ARM925T
# ARM926T
config CPU_ARM926T
bool "Support ARM926T processor"
depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261
default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261
depends on ARCH_INTEGRATOR || ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || MACH_REALVIEW_EB || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_NS9XXX
default y if ARCH_VERSATILE_PB || MACH_VERSATILE_AB || ARCH_OMAP730 || ARCH_OMAP16XX || ARCH_PNX4008 || ARCH_NETX || CPU_S3C2412 || ARCH_AT91SAM9260 || ARCH_AT91SAM9261 || ARCH_NS9XXX
select CPU_32v5
select CPU_ABRT_EV5TJ
select CPU_CACHE_VIVT
......
/*
* include/asm-arm/arch-ns9xxx/board.h
*
* Copyright (C) 2006 by Digi International Inc.
* All rights reserved.
*
* 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_BOARD_H
#define __ASM_ARCH_BOARD_H
#include <asm/mach-types.h>
#define board_is_a9m9750dev() (machine_is_cc9p9360dev())
#endif /* ifndef __ASM_ARCH_BOARD_H */