Commit df34403d authored by Vitaly Bordug's avatar Vitaly Bordug Committed by Paul Mackerras

[POWERPC] 8xx: Add mpc885ads support and common mpc8xx files

This adds the core 8xx stuff and specifically mpc885ads board-specific
bits to arch/powerpc. Respective Kconfig has been cleaned up from the stuff
not yet ported over to avoid confusion. Updated and cleaned version.
Signed-off-by: default avatarVitaly Bordug <vbordug@ru.mvista.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent f2a0bd37
/*
* MPC885 ADS Device Tree Source
*
* Copyright 2006 MontaVista Software, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/ {
model = "MPC885ADS";
compatible = "mpc8xx";
#address-cells = <1>;
#size-cells = <1>;
linux,phandle = <100>;
cpus {
#cpus = <1>;
#address-cells = <1>;
#size-cells = <0>;
linux,phandle = <200>;
PowerPC,885@0 {
device_type = "cpu";
reg = <0>;
d-cache-line-size = <20>; // 32 bytes
i-cache-line-size = <20>; // 32 bytes
d-cache-size = <2000>; // L1, 8K
i-cache-size = <2000>; // L1, 8K
timebase-frequency = <0>;
bus-frequency = <0>;
clock-frequency = <0>;
32-bit;
interrupts = <f 2>; // decrementer interrupt
interrupt-parent = <ff000000>;
linux,phandle = <201>;
linux,boot-cpu;
};
};
memory {
device_type = "memory";
linux,phandle = <300>;
reg = <00000000 800000>;
};
soc885@ff000000 {
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "soc";
ranges = <0 ff000000 00100000>;
reg = <ff000000 00000200>;
bus-frequency = <0>;
mdio@e80 {
device_type = "mdio";
compatible = "fs_enet";
reg = <e80 8>;
linux,phandle = <e80>;
#address-cells = <1>;
#size-cells = <0>;
ethernet-phy@0 {
linux,phandle = <e8000>;
reg = <0>;
device_type = "ethernet-phy";
};
ethernet-phy@1 {
linux,phandle = <e8001>;
reg = <1>;
device_type = "ethernet-phy";
};
ethernet-phy@2 {
linux,phandle = <e8002>;
reg = <2>;
device_type = "ethernet-phy";
};
};
fec@e00 {
device_type = "network";
compatible = "fs_enet";
model = "FEC";
device-id = <1>;
reg = <e00 188>;
mac-address = [ 00 00 0C 00 01 FD ];
interrupts = <3 1>;
interrupt-parent = <ff000000>;
phy-handle = <e8000>;
};
fec@1e00 {
device_type = "network";
compatible = "fs_enet";
model = "FEC";
device-id = <2>;
reg = <1e00 188>;
mac-address = [ 00 00 0C 00 02 FD ];
interrupts = <7 1>;
interrupt-parent = <ff000000>;
phy-handle = <e8001>;
};
pic@ff000000 {
linux,phandle = <ff000000>;
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
reg = <0 24>;
built-in;
device_type = "mpc8xx-pic";
compatible = "CPM";
};
cpm@ff000000 {
linux,phandle = <ff000000>;
#address-cells = <1>;
#size-cells = <1>;
#interrupt-cells = <2>;
device_type = "cpm";
model = "CPM";
ranges = <0 0 4000>;
reg = <860 f0>;
command-proc = <9c0>;
brg-frequency = <0>;
interrupts = <0 2>; // cpm error interrupt
interrupt-parent = <930>;
pic@930 {
linux,phandle = <930>;
interrupt-controller;
#address-cells = <0>;
#interrupt-cells = <2>;
interrupts = <5 2 0 2>;
interrupt-parent = <ff000000>;
reg = <930 20>;
built-in;
device_type = "cpm-pic";
compatible = "CPM";
};
smc@a80 {
device_type = "serial";
compatible = "cpm_uart";
model = "SMC";
device-id = <1>;
reg = <a80 10 3e80 40>;
clock-setup = <00ffffff 0>;
rx-clock = <1>;
tx-clock = <1>;
current-speed = <0>;
interrupts = <4 3>;
interrupt-parent = <930>;
};
smc@a90 {
device_type = "serial";
compatible = "cpm_uart";
model = "SMC";
device-id = <2>;
reg = <a90 20 3f80 40>;
clock-setup = <ff00ffff 90000>;
rx-clock = <2>;
tx-clock = <2>;
current-speed = <0>;
interrupts = <3 3>;
interrupt-parent = <930>;
};
scc@a40 {
device_type = "network";
compatible = "fs_enet";
model = "SCC";
device-id = <3>;
reg = <a40 18 3e00 80>;
mac-address = [ 00 00 0C 00 03 FD ];
interrupts = <1c 3>;
interrupt-parent = <930>;
phy-handle = <e8002>;
};
};
};
};
This diff is collapsed.
menu "Platform support"
depends on PPC_8xx
config FADS config FADS
bool bool
config CPM1
bool
choice choice
prompt "8xx Machine Type" prompt "8xx Machine Type"
depends on 8xx depends on 8xx
default RPXLITE default MPC885ADS
config RPXLITE
bool "RPX-Lite"
---help---
Single-board computers based around the PowerPC MPC8xx chips and
intended for embedded applications. The following types are
supported:
RPX-Lite:
Embedded Planet RPX Lite. PC104 form-factor SBC based on the MPC823.
RPX-Classic:
Embedded Planet RPX Classic Low-fat. Credit-card-size SBC based on
the MPC 860
BSE-IP:
Bright Star Engineering ip-Engine.
TQM823L:
TQM850L:
TQM855L:
TQM860L:
MPC8xx based family of mini modules, half credit card size,
up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports,
2 x CAN bus interface, ...
Manufacturer: TQ Components, www.tq-group.de
Date of Release: October (?) 1999
End of Life: not yet :-)
URL:
- module: <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>
- starter kit: <http://www.denx.de/PDF/STK8xxLHWM201.pdf>
- images: <http://www.denx.de/embedded-ppc-en.html>
FPS850L:
FingerPrint Sensor System (based on TQM850L)
Manufacturer: IKENDI AG, <http://www.ikendi.com/>
Date of Release: November 1999
End of life: end 2000 ?
URL: see TQM850L
IVMS8:
MPC860 based board used in the "Integrated Voice Mail System",
Small Version (8 voice channels)
Manufacturer: Speech Design, <http://www.speech-design.de/>
Date of Release: December 2000 (?)
End of life: -
URL: <http://www.speech-design.de/>
IVML24:
MPC860 based board used in the "Integrated Voice Mail System",
Large Version (24 voice channels)
Manufacturer: Speech Design, <http://www.speech-design.de/>
Date of Release: March 2001 (?)
End of life: -
URL: <http://www.speech-design.de/>
HERMES:
Hermes-Pro ISDN/LAN router with integrated 8 x hub
Manufacturer: Multidata Gesellschaft fur Datentechnik und Informatik
<http://www.multidata.de/>
Date of Release: 2000 (?)
End of life: -
URL: <http://www.multidata.de/english/products/hpro.htm>
IP860:
VMEBus IP (Industry Pack) carrier board with MPC860
Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
Date of Release: ?
End of life: -
URL: <http://www.microsys.de/html/ip860.html>
PCU_E:
PCU = Peripheral Controller Unit, Extended
Manufacturer: Siemens AG, ICN (Information and Communication Networks)
<http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html>
Date of Release: April 2001
End of life: August 2001
URL: n. a.
config RPXCLASSIC
bool "RPX-Classic"
help
The RPX-Classic is a single-board computer based on the Motorola
MPC860. It features 16MB of DRAM and a variable amount of flash,
I2C EEPROM, thermal monitoring, a PCMCIA slot, a DIP switch and two
LEDs. Variants with Ethernet ports exist. Say Y here to support it
directly.
config BSEIP
bool "BSE-IP"
help
Say Y here to support the Bright Star Engineering ipEngine SBC.
This is a credit-card-sized device featuring a MPC823 processor,
26MB DRAM, 4MB flash, Ethernet, a 16K-gate FPGA, USB, an LCD/video
controller, and two RS232 ports.
config MPC8XXFADS config MPC8XXFADS
bool "FADS" bool "FADS"
...@@ -107,110 +18,58 @@ config MPC8XXFADS ...@@ -107,110 +18,58 @@ config MPC8XXFADS
config MPC86XADS config MPC86XADS
bool "MPC86XADS" bool "MPC86XADS"
select CPM1
help help
MPC86x Application Development System by Freescale Semiconductor. MPC86x Application Development System by Freescale Semiconductor.
The MPC86xADS is meant to serve as a platform for s/w and h/w The MPC86xADS is meant to serve as a platform for s/w and h/w
development around the MPC86X processor families. development around the MPC86X processor families.
select FADS
config MPC885ADS config MPC885ADS
bool "MPC885ADS" bool "MPC885ADS"
select CPM1
help help
Freescale Semiconductor MPC885 Application Development System (ADS). Freescale Semiconductor MPC885 Application Development System (ADS).
Also known as DUET. Also known as DUET.
The MPC885ADS is meant to serve as a platform for s/w and h/w The MPC885ADS is meant to serve as a platform for s/w and h/w
development around the MPC885 processor family. development around the MPC885 processor family.
config TQM823L endchoice
bool "TQM823L"
help
Say Y here to support the TQM823L, one of an MPC8xx-based family of
mini SBCs (half credit-card size) from TQ Components first released
in late 1999. Technical references are at
<http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
<http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
<http://www.denx.de/embedded-ppc-en.html>.
config TQM850L
bool "TQM850L"
help
Say Y here to support the TQM850L, one of an MPC8xx-based family of
mini SBCs (half credit-card size) from TQ Components first released
in late 1999. Technical references are at
<http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
<http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
<http://www.denx.de/embedded-ppc-en.html>.
config TQM855L menu "Freescale Ethernet driver platform-specific options"
bool "TQM855L" depends on (FS_ENET && MPC885ADS)
help
Say Y here to support the TQM855L, one of an MPC8xx-based family of
mini SBCs (half credit-card size) from TQ Components first released
in late 1999. Technical references are at
<http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
<http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
<http://www.denx.de/embedded-ppc-en.html>.
config TQM860L config MPC8xx_SECOND_ETH
bool "TQM860L" bool "Second Ethernet channel"
depends on MPC885ADS
default y
help help
Say Y here to support the TQM860L, one of an MPC8xx-based family of This enables support for second Ethernet on MPC885ADS and MPC86xADS boards.
mini SBCs (half credit-card size) from TQ Components first released The latter will use SCC1, for 885ADS you can select it below.
in late 1999. Technical references are at
<http://www.denx.de/PDF/TQM8xxLHWM201.pdf>, and
<http://www.denx.de/PDF/STK8xxLHWM201.pdf>, and an image at
<http://www.denx.de/embedded-ppc-en.html>.
config FPS850L choice
bool "FPS850L" prompt "Second Ethernet channel"
depends on MPC8xx_SECOND_ETH
default MPC8xx_SECOND_ETH_FEC2
config IVMS8 config MPC8xx_SECOND_ETH_FEC2
bool "IVMS8" bool "FEC2"
depends on MPC885ADS
help help
Say Y here to support the Integrated Voice-Mail Small 8-channel SBC Enable FEC2 to serve as 2-nd Ethernet channel. Note that SMC2
from Speech Design, released March 2001. The manufacturer's website (often 2-nd UART) will not work if this is enabled.
is at <http://www.speech-design.de/>.
config IVML24 config MPC8xx_SECOND_ETH_SCC3
bool "IVML24" bool "SCC3"
depends on MPC885ADS
help help
Say Y here to support the Integrated Voice-Mail Large 24-channel SBC Enable SCC3 to serve as 2-nd Ethernet channel. Note that SMC1
from Speech Design, released March 2001. The manufacturer's website (often 1-nd UART) will not work if this is enabled.
is at <http://www.speech-design.de/>.
config HERMES_PRO
bool "HERMES"
config IP860
bool "IP860"
config LWMON
bool "LWMON"
config PCU_E
bool "PCU_E"
config CCM
bool "CCM"
config LANTEC endchoice
bool "LANTEC"
config MBX endmenu
bool "MBX"
help
MBX is a line of Motorola single-board computer based around the
MPC821 and MPC860 processors, and intended for embedded-controller
applications. Say Y here to support these boards directly.
config WINCEPT
bool "WinCept"
help
The Wincept 100/110 is a Motorola single-board computer based on the
MPC821 PowerPC, introduced in 1998 and designed to be used in
thin-client machines. Say Y to support it directly.
endchoice endmenu
# #
# MPC8xx Communication options # MPC8xx Communication options
...@@ -219,79 +78,6 @@ endchoice ...@@ -219,79 +78,6 @@ endchoice
menu "MPC8xx CPM Options" menu "MPC8xx CPM Options"
depends on 8xx depends on 8xx
config SCC_ENET
bool "CPM SCC Ethernet"
depends on NET_ETHERNET
help
Enable Ethernet support via the Motorola MPC8xx serial
communications controller.
choice
prompt "SCC used for Ethernet"
depends on SCC_ENET
default SCC1_ENET
config SCC1_ENET
bool "SCC1"
help
Use MPC8xx serial communications controller 1 to drive Ethernet
(default).
config SCC2_ENET
bool "SCC2"
help
Use MPC8xx serial communications controller 2 to drive Ethernet.
config SCC3_ENET
bool "SCC3"
help
Use MPC8xx serial communications controller 3 to drive Ethernet.
endchoice
config FEC_ENET
bool "860T FEC Ethernet"
depends on NET_ETHERNET
help
Enable Ethernet support via the Fast Ethernet Controller (FCC) on
the Motorola MPC8260.
config USE_MDIO
bool "Use MDIO for PHY configuration"
depends on FEC_ENET
help
On some boards the hardware configuration of the ethernet PHY can be
used without any software interaction over the MDIO interface, so
all MII code can be omitted. Say N here if unsure or if you don't
need link status reports.
config FEC_AM79C874
bool "Support AMD79C874 PHY"
depends on USE_MDIO
config FEC_LXT970
bool "Support LXT970 PHY"
depends on USE_MDIO
config FEC_LXT971
bool "Support LXT971 PHY"
depends on USE_MDIO
config FEC_QS6612
bool "Support QS6612 PHY"
depends on USE_MDIO
config ENET_BIG_BUFFERS
bool "Use Big CPM Ethernet Buffers"
depends on SCC_ENET || FEC_ENET
help
Allocate large buffers for MPC8xx Ethernet. Increases throughput
and decreases the likelihood of dropped packets, but costs memory.
config HTDMSOUND
bool "Embedded Planet HIOX Audio"
depends on SOUND=y
# This doesn't really belong here, but it is convenient to ask # This doesn't really belong here, but it is convenient to ask
# 8xx specific questions. # 8xx specific questions.
comment "Generic MPC8xx Options" comment "Generic MPC8xx Options"
......
#
# Makefile for the PowerPC 8xx linux kernel.
#
obj-$(CONFIG_PPC_8xx) += m8xx_setup.o
obj-$(CONFIG_MPC885ADS) += mpc885ads_setup.o
/*
* Copyright (C) 1995 Linus Torvalds
* Adapted from 'alpha' version by Gary Thomas
* Modified by Cort Dougan (cort@cs.nmt.edu)
* Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net)
* Further modified for generic 8xx by Dan.
*/
/*
* bootup setup stuff..
*/
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/a.out.h>
#include <linux/tty.h>
#include <linux/major.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/initrd.h>
#include <linux/ioport.h>
#include <linux/bootmem.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
#include <linux/time.h>
#include <linux/rtc.h>
#include <asm/mmu.h>
#include <asm/reg.h>
#include <asm/residual.h>
#include <asm/io.h>
#include <asm/pgtable.h>
#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#include <asm/machdep.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <asm/prom.h>
#include <asm/fs_pd.h>
#include <mm/mmu_decl.h>
#include "sysdev/mpc8xx_pic.h"
void m8xx_calibrate_decr(void);
extern void m8xx_wdt_handler_install(bd_t *bp);
extern int cpm_pic_init(void);
extern int cpm_get_irq(void);
/* A place holder for time base interrupts, if they are ever enabled. */
irqreturn_t timebase_interrupt(int irq, void * dev)
{
printk ("timebase_interrupt()\n");
return IRQ_HANDLED;
}
static struct irqaction tbint_irqaction = {
.handler = timebase_interrupt,
.mask = CPU_MASK_NONE,
.name = "tbint",
};
/* per-board overridable init_internal_rtc() function. */
void __init __attribute__ ((weak))
init_internal_rtc(void)
{
sit8xx_t *sys_tmr = (sit8xx_t *) immr_map(im_sit);
/* Disable the RTC one second and alarm interrupts. */
clrbits16(&sys_tmr->sit_rtcsc, (RTCSC_SIE | RTCSC_ALE));
/* Enable the RTC */
setbits16(&sys_tmr->sit_rtcsc, (RTCSC_RTF | RTCSC_RTE));
immr_unmap(sys_tmr);
}
static int __init get_freq(char *name, unsigned long *val)
{
struct device_node *cpu;
unsigned int *fp;
int found = 0;
/* The cpu node should have timebase and clock frequency properties */
cpu = of_find_node_by_type(NULL, "cpu");
if (cpu) {
fp = (unsigned int *)get_property(cpu, name, NULL);
if (fp) {
found = 1;
*val = *fp++;
}
of_node_put(cpu);
}
return found;
}
/* The decrementer counts at the system (internal) clock frequency divided by
* sixteen, or external oscillator divided by four. We force the processor
* to use system clock divided by sixteen.
*/
void __init mpc8xx_calibrate_decr(void)
{
struct device_node *cpu;
cark8xx_t *clk_r1;
car8xx_t *clk_r2;
sitk8xx_t *sys_tmr1;
sit8xx_t *sys_tmr2;
int irq, virq;
clk_r1 = (cark8xx_t *) immr_map(im_clkrstk);
/* Unlock the SCCR. */
out_be32(&clk_r1->cark_sccrk, ~KAPWR_KEY);
out_be32(&clk_r1->cark_sccrk, KAPWR_KEY);
immr_unmap(clk_r1);
/* Force all 8xx processors to use divide by 16 processor clock. */
clk_r2 = (car8xx_t *) immr_map(im_clkrst);
setbits32(&clk_r2->car_sccr, 0x02000000);
immr_unmap(clk_r2);
/* Processor frequency is MHz.
*/
ppc_tb_freq = 50000000;
if (!get_freq("bus-frequency", &ppc_tb_freq)) {
printk(KERN_ERR "WARNING: Estimating decrementer frequency "
"(not found)\n");
}
ppc_tb_freq /= 16;
ppc_proc_freq = 50000000;
if (!get_freq("clock-frequency", &ppc_proc_freq))
printk(KERN_ERR "WARNING: Estimating processor frequency"
"(not found)\n");
printk("Decrementer Frequency = 0x%lx\n", ppc_tb_freq);
/* Perform some more timer/timebase initialization. This used
* to be done elsewhere, but other changes caused it to get
* called more than once....that is a bad thing.
*
* First, unlock all of the registers we are going to modify.
* To protect them from corruption during power down, registers
* that are maintained by keep alive power are "locked". To
* modify these registers we have to write the key value to
* the key location associated with the register.
* Some boards power up with these unlocked, while others
* are locked. Writing anything (including the unlock code?)
* to the unlocked registers will lock them again. So, here
* we guarantee the registers are locked, then we unlock them
* for our use.
*/
sys_tmr1 = (sitk8xx_t *) immr_map(im_sitk);
out_be32(&sys_tmr1->sitk_tbscrk, ~KAPWR_KEY);
out_be32(&sys_tmr1->sitk_rtcsck, ~KAPWR_KEY);
out_be32(&sys_tmr1->sitk_tbk, ~KAPWR_KEY);
out_be32(&sys_tmr1->sitk_tbscrk, KAPWR_KEY);
out_be32(&sys_tmr1->sitk_rtcsck, KAPWR_KEY);
out_be32(&sys_tmr1->sitk_tbk, KAPWR_KEY);
immr_unmap(sys_tmr1);
init_internal_rtc();
/* Enabling the decrementer also enables the timebase interrupts
* (or from the other point of view, to get decrementer interrupts
* we have to enable the timebase). The decrementer interrupt
* is wired into the vector table, nothing to do here for that.
*/
cpu = of_find_node_by_type(NULL, "cpu");
virq= irq_of_parse_and_map(cpu, 0);
irq = irq_map[virq].hwirq;
sys_tmr2 = (sit8xx_t *) immr_map(im_sit);
out_be16(&sys_tmr2->sit_tbscr, ((1 << (7 - (irq/2))) << 8) |
(TBSCR_TBF | TBSCR_TBE));
immr_unmap(sys_tmr2);
if (setup_irq(virq, &tbint_irqaction))
panic("Could not allocate timer IRQ!");
#ifdef CONFIG_8xx_WDT
/* Install watchdog timer handler early because it might be
* already enabled by the bootloader
*/
m8xx_wdt_handler_install(binfo);
#endif
}
/* The RTC on the MPC8xx is an internal register.
* We want to protect this during power down, so we need to unlock,
* modify, and re-lock.
*/
int mpc8xx_set_rtc_time(struct rtc_time *tm)
{
sitk8xx_t *sys_tmr1;
sit8xx_t *sys_tmr2;
int time;
sys_tmr1 = (sitk8xx_t *) immr_map(im_sitk);
sys_tmr2 = (sit8xx_t *) immr_map(im_sit);
time = mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
out_be32(&sys_tmr1->sitk_rtck, KAPWR_KEY);
out_be32(&sys_tmr2->sit_rtc, time);
out_be32(&sys_tmr1->sitk_rtck, ~KAPWR_KEY);
immr_unmap(sys_tmr2);
immr_unmap(sys_tmr1);
return 0;
}
void mpc8xx_get_rtc_time(struct rtc_time *tm)
{
unsigned long data;
sit8xx_t *sys_tmr = (sit8xx_t *) immr_map(im_sit);
/* Get time from the RTC. */
data = in_be32(&sys_tmr->sit_rtc);
to_tm(data, tm);
tm->tm_year -= 1900;
tm->tm_mon -= 1;
immr_unmap(sys_tmr);
return;
}
void mpc8xx_restart(char *cmd)
{
__volatile__ unsigned char dummy;
car8xx_t * clk_r = (car8xx_t *) immr_map(im_clkrst);
local_irq_disable();
setbits32(&clk_r->car_plprcr, 0x00000080);
/* Clear the ME bit in MSR to cause checkstop on machine check
*/
mtmsr(mfmsr() & ~0x1000);
dummy = in_8(&clk_r->res[0]);
printk("Restart failed\n");
while(1);
}
void mpc8xx_show_cpuinfo(struct seq_file *m)
{
struct device_node *root;
uint memsize = total_memory;
const char *model = "";
seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
root = of_find_node_by_path("/");
if (root)
model = get_property(root, "model", NULL);
seq_printf(m, "Machine\t\t: %s\n", model);
of_node_put(root);
seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
}
static void cpm_cascade(unsigned int irq, struct irq_desc *desc)
{
int cascade_irq;
if ((cascade_irq = cpm_get_irq()) >= 0) {
struct irq_desc *cdesc = irq_desc + cascade_irq;
generic_handle_irq(cascade_irq);
cdesc->chip->eoi(cascade_irq);
}
desc->chip->eoi(irq);
}
/* Initialize the internal interrupt controller. The number of
* interrupts supported can vary with the processor type, and the
* 82xx family can have up to 64.
* External interrupts can be either edge or level triggered, and
* need to be initialized by the appropriate driver.
*/
void __init m8xx_pic_init(void)
{
int irq;
if (mpc8xx_pic_init()) {
printk(KERN_ERR "Failed interrupt 8xx controller initialization\n");
return;
}
irq = cpm_pic_init();
if (irq != NO_IRQ)
set_irq_chained_handler(irq, cpm_cascade);
}
/*
* A collection of structures, addresses, and values associated with
* the Freescale MPC885ADS board.
* Copied from the FADS stuff.
*
* Author: MontaVista Software, Inc.
* source@mvista.com
*
* 2005 (c) MontaVista Software, Inc. 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.
*/
#ifdef __KERNEL__
#ifndef __ASM_MPC885ADS_H__
#define __ASM_MPC885ADS_H__
#include <asm/ppcboot.h>
#include <sysdev/fsl_soc.h>
/* U-Boot maps BCSR to 0xff080000 */
#define BCSR_ADDR ((uint)0xff080000)
#define BCSR_SIZE ((uint)32)
#define BCSR0 ((uint)(BCSR_ADDR + 0x00))
#define BCSR1 ((uint)(BCSR_ADDR + 0x04))
#define BCSR2 ((uint)(BCSR_ADDR + 0x08))
#define BCSR3 ((uint)(BCSR_ADDR + 0x0c))
#define BCSR4 ((uint)(BCSR_ADDR + 0x10))
#define CFG_PHYDEV_ADDR ((uint)0xff0a0000)
#define BCSR5 ((uint)(CFG_PHYDEV_ADDR + 0x300))
#define IMAP_ADDR (get_immrbase())
#define IMAP_SIZE ((uint)(64 * 1024))
#define MPC8xx_CPM_OFFSET (0x9c0)
#define CPM_MAP_ADDR (get_immrbase() + MPC8xx_CPM_OFFSET)
#define CPM_IRQ_OFFSET 16 // for compability with cpm_uart driver
#define PCMCIA_MEM_ADDR (uint)0xff020000)
#define PCMCIA_MEM_SIZE ((uint)(64 * 1024))
/* Bits of interest in the BCSRs.
*/
#define BCSR1_ETHEN ((uint)0x20000000)
#define BCSR1_IRDAEN ((uint)0x10000000)
#define BCSR1_RS232EN_1 ((uint)0x01000000)
#define BCSR1_PCCEN ((uint)0x00800000)
#define BCSR1_PCCVCC0 ((uint)0x00400000)
#define BCSR1_PCCVPP0 ((uint)0x00200000)
#define BCSR1_PCCVPP1 ((uint)0x00100000)
#define BCSR1_PCCVPP_MASK (BCSR1_PCCVPP0 | BCSR1_PCCVPP1)
#define BCSR1_RS232EN_2 ((uint)0x00040000)
#define BCSR1_PCCVCC1 ((uint)0x00010000)
#define BCSR1_PCCVCC_MASK (BCSR1_PCCVCC0 | BCSR1_PCCVCC1)
#define BCSR4_ETH10_RST ((uint)0x80000000) /* 10Base-T PHY reset*/
#define BCSR4_USB_LO_SPD ((uint)0x04000000)
#define BCSR4_USB_VCC ((uint)0x02000000)
#define BCSR4_USB_FULL_SPD ((uint)0x00040000)
#define BCSR4_USB_EN ((uint)0x00020000)
#define BCSR5_MII2_EN 0x40
#define BCSR5_MII2_RST 0x20
#define BCSR5_T1_RST 0x10
#define BCSR5_ATM155_RST 0x08
#define BCSR5_ATM25_RST 0x04
#define BCSR5_MII1_EN 0x02
#define BCSR5_MII1_RST 0x01
/* Interrupt level assignments */
#define PHY_INTERRUPT SIU_IRQ7 /* PHY link change interrupt */
#define SIU_INT_FEC1 SIU_LEVEL1 /* FEC1 interrupt */
#define SIU_INT_FEC2 SIU_LEVEL3 /* FEC2 interrupt */
#define FEC_INTERRUPT SIU_INT_FEC1 /* FEC interrupt */
/* We don't use the 8259 */
#define NR_8259_INTS 0
/* CPM Ethernet through SCC3 */
#define PA_ENET_RXD ((ushort)0x0040)
#define PA_ENET_TXD ((ushort)0x0080)
#define PE_ENET_TCLK ((uint)0x00004000)
#define PE_ENET_RCLK ((uint)0x00008000)
#define PE_ENET_TENA ((uint)0x00000010)
#define PC_ENET_CLSN ((ushort)0x0400)
#define PC_ENET_RENA ((ushort)0x0800)
/* Control bits in the SICR to route TCLK (CLK5) and RCLK (CLK6) to
* SCC3. Also, make sure GR3 (bit 8) and SC3 (bit 9) are zero */
#define SICR_ENET_MASK ((uint)0x00ff0000)
#define SICR_ENET_CLKRT ((uint)0x002c0000)
#endif /* __ASM_MPC885ADS_H__ */
#endif /* __KERNEL__ */
/*arch/ppc/platforms/mpc885ads-setup.c
*
* Platform setup for the Freescale mpc885ads board
*
* Vitaly Bordug <vbordug@ru.mvista.com>
*
* Copyright 2005 MontaVista Software Inc.
*
* 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/init.h>
#include <linux/module.h>
#include <linux/param.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/root_dev.h>
#include <linux/fs_enet_pd.h>
#include <linux/fs_uart_pd.h>
#include <linux/mii.h>
#include <asm/delay.h>
#include <asm/io.h>
#include <asm/machdep.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/time.h>
#include <asm/ppcboot.h>
#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
#include <asm/commproc.h>
#include <asm/fs_pd.h>
#include <asm/prom.h>
extern void cpm_reset(void);
extern void mpc8xx_show_cpuinfo(struct seq_file*);
extern void mpc8xx_restart(char *cmd);
extern void mpc8xx_calibrate_decr(void);
extern int mpc8xx_set_rtc_time(struct rtc_time *tm);
extern void mpc8xx_get_rtc_time(struct rtc_time *tm);
extern void m8xx_pic_init(void);
extern unsigned int mpc8xx_get_irq(void);
static void init_smc1_uart_ioports(struct fs_uart_platform_info* fpi);
static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi);
static void init_scc3_ioports(struct fs_platform_info* ptr);
void __init mpc885ads_board_setup(void)
{
cpm8xx_t *cp;
unsigned int *bcsr_io;
u8 tmpval8;
#ifdef CONFIG_FS_ENET
iop8xx_t *io_port;
#endif
bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
cp = (cpm8xx_t *)immr_map(im_cpm);
if (bcsr_io == NULL) {
printk(KERN_CRIT "Could not remap BCSR\n");
return;
}
#ifdef CONFIG_SERIAL_CPM_SMC1
clrbits32(bcsr_io, BCSR1_RS232EN_1);
clrbits32(&cp->cp_simode, 0xe0000000 >> 17); /* brg1 */
tmpval8 = in_8(&(cp->cp_smc[0].smc_smcm)) | (SMCM_RX | SMCM_TX);
out_8(&(cp->cp_smc[0].smc_smcm), tmpval8);
clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN); /* brg1 */
#else
setbits32(bcsr_io,BCSR1_RS232EN_1);
out_be16(&cp->cp_smc[0].smc_smcmr, 0);
out_8(&cp->cp_smc[0].smc_smce, 0);
#endif
#ifdef CONFIG_SERIAL_CPM_SMC2
clrbits32(bcsr_io,BCSR1_RS232EN_2);
clrbits32(&cp->cp_simode, 0xe0000000 >> 1);
setbits32(&cp->cp_simode, 0x20000000 >> 1); /* brg2 */
tmpval8 = in_8(&(cp->cp_smc[1].smc_smcm)) | (SMCM_RX | SMCM_TX);
out_8(&(cp->cp_smc[1].smc_smcm), tmpval8);
clrbits16(&cp->cp_smc[1].smc_smcmr, SMCMR_REN | SMCMR_TEN);
init_smc2_uart_ioports(0);
#else
setbits32(bcsr_io,BCSR1_RS232EN_2);
out_be16(&cp->cp_smc[1].smc_smcmr, 0);
out_8(&cp->cp_smc[1].smc_smce, 0);
#endif
immr_unmap(cp);
iounmap(bcsr_io);
#ifdef CONFIG_FS_ENET
/* use MDC for MII (common) */
io_port = (iop8xx_t*)immr_map(im_ioport);
setbits16(&io_port->iop_pdpar, 0x0080);
clrbits16(&io_port->iop_pddir, 0x0080);
bcsr_io = ioremap(BCSR5, sizeof(unsigned long));
clrbits32(bcsr_io,BCSR5_MII1_EN);
clrbits32(bcsr_io,BCSR5_MII1_RST);
#ifndef CONFIG_FC_ENET_HAS_SCC
clrbits32(bcsr_io,BCSR5_MII2_EN);
clrbits32(bcsr_io,BCSR5_MII2_RST);
#endif
iounmap(bcsr_io);
immr_unmap(io_port);
#endif
}
static void init_fec1_ioports(struct fs_platform_info* ptr)
{
cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
/* configure FEC1 pins */
setbits16(&io_port->iop_papar, 0xf830);
setbits16(&io_port->iop_padir, 0x0830);
clrbits16(&io_port->iop_padir, 0xf000);
setbits32(&cp->cp_pbpar, 0x00001001);
clrbits32(&cp->cp_pbdir, 0x00001001);
setbits16(&io_port->iop_pcpar, 0x000c);
clrbits16(&io_port->iop_pcdir, 0x000c);
setbits32(&cp->cp_pepar, 0x00000003);
setbits32(&cp->cp_pedir, 0x00000003);
clrbits32(&cp->cp_peso, 0x00000003);
clrbits32(&cp->cp_cptr, 0x00000100);
immr_unmap(io_port);
immr_unmap(cp);
}
static void init_fec2_ioports(struct fs_platform_info* ptr)
{
cpm8xx_t *cp = (cpm8xx_t *)immr_map(im_cpm);
iop8xx_t *io_port = (iop8xx_t *)immr_map(im_ioport);
/* configure FEC2 pins */
setbits32(&cp->cp_pepar, 0x0003fffc);
setbits32(&cp->cp_pedir, 0x0003fffc);
clrbits32(&cp->cp_peso, 0x000087fc);
setbits32(&cp->cp_peso, 0x00037800);
clrbits32(&cp->cp_cptr, 0x00000080);
immr_unmap(io_port);
immr_unmap(cp);
}
void init_fec_ioports(struct fs_platform_info *fpi)
{
int fec_no = fs_get_fec_index(fpi->fs_no);
switch (fec_no) {
case 0:
init_fec1_ioports(fpi);
break;
case 1:
init_fec2_ioports(fpi);
break;
default:
printk(KERN_ERR "init_fec_ioports: invalid FEC number\n");
return;
}
}
static void init_scc3_ioports(struct fs_platform_info* fpi)
{
unsigned *bcsr_io;
iop8xx_t *io_port;
cpm8xx_t *cp;
bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
io_port = (iop8xx_t *)immr_map(im_ioport);
cp = (cpm8xx_t *)immr_map(im_cpm);
if (bcsr_io == NULL) {
printk(KERN_CRIT "Could not remap BCSR\n");
return;
}
/* Enable the PHY.
*/
clrbits32(bcsr_io+4, BCSR4_ETH10_RST);
udelay(1000);
setbits32(bcsr_io+4, BCSR4_ETH10_RST);
/* Configure port A pins for Txd and Rxd.
*/
setbits16(&io_port->iop_papar, PA_ENET_RXD | PA_ENET_TXD);
clrbits16(&io_port->iop_padir, PA_ENET_RXD | PA_ENET_TXD);
/* Configure port C pins to enable CLSN and RENA.
*/
clrbits16(&io_port->iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
clrbits16(&io_port->iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
setbits16(&io_port->iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
/* Configure port E for TCLK and RCLK.
*/
setbits32(&cp->cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
clrbits32(&cp->cp_pepar, PE_ENET_TENA);
clrbits32(&cp->cp_pedir,
PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
clrbits32(&cp->cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
setbits32(&cp->cp_peso, PE_ENET_TENA);
/* Configure Serial Interface clock routing.
* First, clear all SCC bits to zero, then set the ones we want.
*/
clrbits32(&cp->cp_sicr, SICR_ENET_MASK);
setbits32(&cp->cp_sicr, SICR_ENET_CLKRT);
/* Disable Rx and Tx. SMC1 sshould be stopped if SCC3 eternet are used.
*/
clrbits16(&cp->cp_smc[0].smc_smcmr, SMCMR_REN | SMCMR_TEN);
/* On the MPC885ADS SCC ethernet PHY is initialized in the full duplex mode
* by H/W setting after reset. SCC ethernet controller support only half duplex.
* This discrepancy of modes causes a lot of carrier lost errors.
*/
/* In the original SCC enet driver the following code is placed at
the end of the initialization */
setbits32(&cp->cp_pepar, PE_ENET_TENA);
clrbits32(&cp->cp_pedir, PE_ENET_TENA);
setbits32(&cp->cp_peso, PE_ENET_TENA);
setbits32(bcsr_io+4, BCSR1_ETHEN);
iounmap(bcsr_io);
immr_unmap(io_port);
immr_unmap(cp);
}
void init_scc_ioports(struct fs_platform_info *fpi)
{
int scc_no = fs_get_scc_index(fpi->fs_no);
switch (scc_no) {
case 2:
init_scc3_ioports(fpi);
break;
default:
printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
return;
}
}
static void init_smc1_uart_ioports(struct fs_uart_platform_info* ptr)
{
unsigned *bcsr_io;
cpm8xx_t *cp;
cp = (cpm8xx_t *)immr_map(im_cpm);
setbits32(&cp->cp_pepar, 0x000000c0);
clrbits32(&cp->cp_pedir, 0x000000c0);
clrbits32(&cp->cp_peso, 0x00000040);
setbits32(&cp->cp_peso, 0x00000080);
immr_unmap(cp);
bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
if (bcsr_io == NULL) {
printk(KERN_CRIT "Could not remap BCSR1\n");
return;
}
clrbits32(bcsr_io,BCSR1_RS232EN_1);
iounmap(bcsr_io);
}
static void init_smc2_uart_ioports(struct fs_uart_platform_info* fpi)
{
unsigned *bcsr_io;
cpm8xx_t *cp;
cp = (cpm8xx_t *)immr_map(im_cpm);
setbits32(&cp->cp_pepar, 0x00000c00);
clrbits32(&cp->cp_pedir, 0x00000c00);
clrbits32(&cp->cp_peso, 0x00000400);
setbits32(&cp->cp_peso, 0x00000800);
immr_unmap(cp);
bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
if (bcsr_io == NULL) {
printk(KERN_CRIT "Could not remap BCSR1\n");
return;
}
clrbits32(bcsr_io,BCSR1_RS232EN_2);
iounmap(bcsr_io);
}
void init_smc_ioports(struct fs_uart_platform_info *data)
{
int smc_no = fs_uart_id_fsid2smc(data->fs_no);
switch (smc_no) {
case 0:
init_smc1_uart_ioports(data);
data->brg = data->clk_rx;
break;
case 1:
init_smc2_uart_ioports(data);
data->brg = data->clk_rx;
break;
default:
printk(KERN_ERR "init_scc_ioports: invalid SCC number\n");
return;
}
}
int platform_device_skip(char *model, int id)
{
#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
const char *dev = "FEC";
int n = 2;
#else
const char *dev = "SCC";
int n = 3;
#endif
if (!strcmp(model, dev) && n == id)
return 1;
return 0;
}
static void __init mpc885ads_setup_arch(void)
{
struct device_node *cpu;
cpu = of_find_node_by_type(NULL, "cpu");
if (cpu != 0) {
const unsigned int *fp;
fp = get_property(cpu, "clock-frequency", NULL);
if (fp != 0)
loops_per_jiffy = *fp / HZ;
else
loops_per_jiffy = 50000000 / HZ;
of_node_put(cpu);
}
cpm_reset();
mpc885ads_board_setup();
ROOT_DEV = Root_NFS;
}
static int __init mpc885ads_probe(void)
{
char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
"model", NULL);
if (model == NULL)
return 0;
if (strcmp(model, "MPC885ADS"))
return 0;
return 1;
}
define_machine(mpc885_ads) {
.name = "MPC885 ADS",
.probe = mpc885ads_probe,
.setup_arch = mpc885ads_setup_arch,
.init_IRQ = m8xx_pic_init,
.show_cpuinfo = mpc8xx_show_cpuinfo,
.get_irq = mpc8xx_get_irq,
.restart = mpc8xx_restart,
.calibrate_decr = mpc8xx_calibrate_decr,
.set_rtc_time = mpc8xx_set_rtc_time,
.get_rtc_time = mpc8xx_get_rtc_time,
};
...@@ -8,6 +8,7 @@ endif ...@@ -8,6 +8,7 @@ endif
obj-$(CONFIG_PPC_MPC52xx) += 52xx/ obj-$(CONFIG_PPC_MPC52xx) += 52xx/
obj-$(CONFIG_PPC_CHRP) += chrp/ obj-$(CONFIG_PPC_CHRP) += chrp/
obj-$(CONFIG_4xx) += 4xx/ obj-$(CONFIG_4xx) += 4xx/
obj-$(CONFIG_PPC_8xx) += 8xx/
obj-$(CONFIG_PPC_83xx) += 83xx/ obj-$(CONFIG_PPC_83xx) += 83xx/
obj-$(CONFIG_PPC_85xx) += 85xx/ obj-$(CONFIG_PPC_85xx) += 85xx/
obj-$(CONFIG_PPC_86xx) += 86xx/ obj-$(CONFIG_PPC_86xx) += 86xx/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment