MV64360 ethernet controller
Dale Farnsworth
dale at farnsworth.org
Thu Feb 1 23:13:52 EST 2007
sb at thebackend.de wrote:
> I recently got a few Force/Motorola PowerPMC-280 PMC modules
> consisting mainly of a MPC7447 G4 an the Marvell MV64360 system
> controller. Since this a hobbyist project only I don't have
> Montavista Linux which seems to already support the board. Instead I
> ported the stock Linux kernel. Works quite well so far. The only
> thing I did not get to work is the integrated ethernet. The
> mv64360_eth driver loads fine and sees both ports. It does not get
> any interrupts for incoming packets (activity led blinks though).
> Only unplugging the cable generates an interrupt.
>
> Since I do not have any documentation on the Marvell chip and the
> company does not answer my request I am quite lost.
>
> The PHY interrupts are routed to one of the GPIO/interrupt pins. I
> did not find any code in the ethernet driver that would be able to
> use it though. Is it needed at all?
>
> Any hint is appreciated!
> Sebastian
Hi Sebastian,
Yes, the driver needs receive and transmit interrupts. However, the
same irq number is used for PHY status change as well as for packet
receive and transmit. I don't see how you could see PHY status change
interrupts and not rx/tx interrupts. mv643xx_eth_int_handler() should
be called for all ethernet-related interrupts*. Are you certain that
you're not seeing rx and tx interrupts?
* You may not see an interrupt on every packet because of the
transmit irq coalescing mechanism and the use of NAPI on receive.
Mark Greer and I are starting on arch/powerpc support for the mv64x60
and ppmc280. We will submit it as when we have something useful.
In the meantime, the arch/ppc code below may serve as a hint.
(Just to be clear, I didn't write this code and don't mean to take
credit for it.)
-Dale
/*
* arch/ppc/platforms/ppmc280.h
*
* Definitions for Motorola PPMC280 board
*
* Based on db64360.h, Written by Rabeeh Khoury - rabeeh at galileo.co.il
* Based on code done by Mark A. Greer <mgreer at mvista.com>
*
* 2001-2002 (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.
*/
/*
* The MV64x60 has 2 PCI buses each with 1 window from the CPU bus to
* PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
* We'll only use one PCI MEM window on each PCI bus.
*
* This is the CPU physical memory map (windows must be at least 1MB and start
* on a boundary that is a multiple of the window size):
*
* 0xf2040000-0xffffffff - Unused
* 0xf2000000-0xf203ffff - Integrated SRAM
* 0xf1010000-0xf1ffffff - Unused
* 0xf1000000-0xf100ffff - MV64360 Registers
* 0xc0800000-0xf0ffffff - Unused
* 0xc0000000-0xc07fffff - Boot flash (BootCS#)
* 0xb2000000-0xb2ffffff - User flash 1 ( CS1)
* 0xb0000000-0xb1ffffff - User flash 0 ( CS0)
* 0xa8000000-0x9fffffff - Unused
* 0xa8000000-0xa7ffffff - PCI 1 I/O (defined in mv64360.h)
* 0xa0000000-0xa7ffffff - PCI 0 I/O (defined in mv64360.h)
* 0x90000000-0x9fffffff - PCI 1 MEM (defined in mv64360.h)
* 0x80000000-0x8fffffff - PCI 0 MEM (defined in mv64360.h)
* 0x20000000-0x7fffffff - Reserved for SDRAM expansion
* 0x00000000-0x1fffffff - On Board SDRAM ( CS0)
*/
#ifndef __PPC_PLATFORMS_PPMC280
#define __PPC_PLATFORMS_PPMC280
/* PCI mappings */
#define PPMC280_PCI0_IO_CPU_BASE 0xa0000000
#define PPMC280_PCI0_IO_PCI_BASE 0x00000000
#define PPMC280_PCI0_IO_SIZE 0x01000000
#define PPMC280_PCI0_MEM_CPU_BASE 0x80000000
#define PPMC280_PCI0_MEM_PCI_BASE 0x80000000
#define PPMC280_PCI0_MEM_SIZE 0x10000000
#define PPMC280_PCI1_IO_CPU_BASE (PPMC280_PCI0_IO_CPU_BASE + \
PPMC280_PCI0_IO_SIZE)
#define PPMC280_PCI1_IO_PCI_BASE (PPMC280_PCI0_IO_PCI_BASE + \
PPMC280_PCI0_IO_SIZE)
#define PPMC280_PCI1_IO_SIZE 0x01000000
#define PPMC280_PCI1_MEM_CPU_BASE (PPMC280_PCI0_MEM_CPU_BASE + \
PPMC280_PCI0_MEM_SIZE)
#define PPMC280_PCI1_MEM_PCI_BASE (PPMC280_PCI0_MEM_PCI_BASE + \
PPMC280_PCI0_MEM_SIZE)
#define PPMC280_PCI1_MEM_SIZE 0x10000000
/* CPU Physical Memory Map setup (other than PCI) */
#define PPMC280_EXT_FLASH_BASE_1 0xb0000000
#define PPMC280_EXT_FLASH_BASE_2 0xb2000000
#define PPMC280_BOOT_FLASH_BASE 0xc0000000 /* BOOT FLASH Base */
#define PPMC280_INTERNAL_SRAM_BASE 0xf2000000
#if defined(CONFIG_MTD_PPMC2800D_FLASH) || defined(CONFIG_MTD_PPMC2800D_FLASH_MODULE)
#define PPMC280_EXT_FLASH_SIZE_ACTUAL 0x04000000
#define PPMC280_BOOT_FLASH_SIZE_ACTUAL 0x01000000 /* =< 16M of Boot FLASH */
#else
#define PPMC280_EXT_FLASH_SIZE_ACTUAL 0x02000000
#define PPMC280_BOOT_FLASH_SIZE_ACTUAL 0x00800000 /* =< 8M of Boot FLASH */
#endif
#define PPMC280_INTERNAL_SRAM_SIZE 0x00040000
#define PPMC280_EXT_FLASH_SIZE max(MV64360_WINDOW_SIZE_MIN, \
PPMC280_EXT_FLASH_SIZE_ACTUAL)
#define PPMC280_BOOT_FLASH_SIZE max(MV64360_WINDOW_SIZE_MIN, \
PPMC280_BOOT_FLASH_SIZE_ACTUAL)
#define PPMC280_EXT_SRAM_SIZE max(MV64360_WINDOW_SIZE_MIN, \
PPMC280_EXT_SRAM_SIZE_ACTUAL)
/* Board-specific IRQ info */
#define PPMC280_PCI_0_IRQ_A 64+27
#define PPMC280_PCI_0_IRQ_B 64+29
#define PPMC280_PCI_0_IRQ_C 64+16
#define PPMC280_PCI_0_IRQ_D 64+17
/* Serial port setup */
#define PPMC280_DEFAULT_BAUD 9600
#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
#define PPMC280_MPSC_CLK_SRC 8 /* TCLK */
#define PPMC280_MPSC_CLK_FREQ 133000000
#endif
#endif /* __PPC_PLATFORMS_PPMC280 */
/*
* arch/ppc/platforms/ppmc280.c
*
* Board setup routines for the Motorola PPMC280 Development Board.
*
* Author: <source at mvista.com>
* Based on ppmc280.c Written by Rabeeh Khoury - rabeeh at galileo.co.il
* Based on code done by - Mark A. Greer <mgreer at mvista.com>
*
* 2001-2003 (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.
*/
#include <linux/config.h>
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/irq.h>
#include <linux/fs.h>
#include <linux/seq_file.h>
#include <linux/console.h>
#include <linux/initrd.h>
#include <linux/root_dev.h>
#include <linux/mv643xx.h>
#include <asm/bootinfo.h>
#include <asm/machdep.h>
#include <asm/mv64x60.h>
#include <asm/time.h>
#include <platforms/ppmc280.h>
#define BOARD_VENDOR "Motorola"
#define BOARD_MACHINE "PPMC280"
static struct mv64x60_handle bh;
static const unsigned int cpu_7447[32] = {
23, 34, 15, 30, 14, 36, 1, 40, 4, 42, 13, 26, 17, 48, 19, 18,
6, 21, 11, 22, 8, 20, 10, 24, 16, 28, 12, 32, 27, 56, 0, 25
};
static int ppmc280_get_bus_speed(void)
{
return 133333333;
}
static int ppmc280_get_cpu_speed(void)
{
unsigned long hid1;
hid1 = (mfspr(SPRN_HID1) & 0x0001f000) >> 12;
return ppmc280_get_bus_speed() * cpu_7447[hid1] / 2;
}
unsigned long __init ppmc280_find_end_of_memory(void)
{
return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
MV64x60_TYPE_MV64360);
}
/*
* Motorola PPMC280 Board PCI interrupt routing.
*/
static int __init
ppmc280_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
static char pci_irq_table[][4] = {
/*
* PCI IDSEL/INTPIN->INTLINE
* A B C D
*/
/* IDSEL 10 - PCI bus 0 */
{ PPMC280_PCI_0_IRQ_C, PPMC280_PCI_0_IRQ_D,
PPMC280_PCI_0_IRQ_A, PPMC280_PCI_0_IRQ_B },
/* IDSEL 11 - PCI bus 0 */
{ PPMC280_PCI_0_IRQ_A, PPMC280_PCI_0_IRQ_B,
PPMC280_PCI_0_IRQ_C, PPMC280_PCI_0_IRQ_D },
/* IDSEL 12 - PCI bus 0 */
{ PPMC280_PCI_0_IRQ_A, PPMC280_PCI_0_IRQ_B,
PPMC280_PCI_0_IRQ_C, PPMC280_PCI_0_IRQ_D },
/* IDSEL 13 - PCI bus 0 */
{ PPMC280_PCI_0_IRQ_B, PPMC280_PCI_0_IRQ_C,
PPMC280_PCI_0_IRQ_D, PPMC280_PCI_0_IRQ_A },
};
const long min_idsel = 10, max_idsel = 13, irqs_per_slot = 4;
return PCI_IRQ_TABLE_LOOKUP;
}
static void __init
ppmc280_setup_peripherals(void)
{
u32 temp;
mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
PPMC280_BOOT_FLASH_BASE, PPMC280_BOOT_FLASH_SIZE, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
PPMC280_INTERNAL_SRAM_BASE, PPMC280_INTERNAL_SRAM_SIZE, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
PPMC280_EXT_FLASH_BASE_1, PPMC280_EXT_FLASH_SIZE, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
PPMC280_EXT_FLASH_BASE_2, PPMC280_EXT_FLASH_SIZE, 0);
bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
mv64x60_clr_bits(&bh, MV64x60_CPU_CONFIG,
((1 << 12) | (1 << 28) | (1 << 29)));
mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1 << 27));
if (ppmc280_get_bus_speed() > 100000000)
mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1 << 23));
mv64x60_set_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1 << 9)); /* 1 cpu */
/* Program WatchDog o/p MPP19:WDE# i.e. 0x4, MPP24:WDNMI# i.e. 0x4 */
temp = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
temp &= 0xFFFF0FFF;
temp |= 0x00004000;
mv64x60_write(&bh, MV64x60_MPP_CNTL_2, temp);
temp = mv64x60_read(&bh, MV64x60_MPP_CNTL_3);
temp &= 0xFFFFFFF0;
temp |= 0x00000004;
mv64x60_write(&bh, MV64x60_MPP_CNTL_3, temp);
/* Make sure WatchDog is disabled */
temp = mv64x60_read(&bh, MV64x60_WDT_WDC);
if (temp & 0x80000000) { /* Is the WD enabled ? */
temp &= ~0x3000000;
temp |= 0x1000000;
mv64x60_write(&bh, MV64x60_WDT_WDC, temp);
temp &= ~0x3000000;
temp |= 0x2000000;
mv64x60_write(&bh, MV64x60_WDT_WDC, temp);
}
/*
* Turn off timer/counters. Not turning off watchdog timer because
* can't read its reg on the 64260A so don't know if we'll be enabling
* or disabling.
*/
mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL,
((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24)));
mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, 0xfb50);
mv64x60_set_bits(&bh, MV64x60_GPP_IO_CNTL, 0xfb50);
#if defined(CONFIG_NOT_COHERENT_CACHE)
mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x00160000);
#else
mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2);
#endif
return;
}
static void __init
ppmc280_setup_bridge(void)
{
struct mv64x60_setup_info si;
int i;
memset(&si, 0, sizeof(si));
si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
si.pci_0.enable_bus = 1;
si.pci_0.pci_io.cpu_base = PPMC280_PCI0_IO_CPU_BASE;
si.pci_0.pci_io.pci_base_hi = 0;
si.pci_0.pci_io.pci_base_lo = PPMC280_PCI0_IO_PCI_BASE;
si.pci_0.pci_io.size = PPMC280_PCI0_IO_SIZE;
si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
si.pci_0.pci_mem[0].cpu_base = PPMC280_PCI0_MEM_CPU_BASE;
si.pci_0.pci_mem[0].pci_base_hi = 0;
si.pci_0.pci_mem[0].pci_base_lo = PPMC280_PCI0_MEM_PCI_BASE;
si.pci_0.pci_mem[0].size = PPMC280_PCI0_MEM_SIZE;
si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
si.pci_0.pci_cmd_bits = 0;
si.pci_0.latency_timer = 0x8;
for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
#if defined(CONFIG_NOT_COHERENT_CACHE)
si.cpu_prot_options[i] = 0;
si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
si.pci_0.acc_cntl_options[i] =
MV64360_PCI_ACC_CNTL_SNOOP_NONE |
MV64360_PCI_ACC_CNTL_SWAP_NONE |
MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
#else
si.cpu_prot_options[i] = 0;
si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB;
si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB;
si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB;
si.pci_0.acc_cntl_options[i] =
MV64360_PCI_ACC_CNTL_SNOOP_WB |
MV64360_PCI_ACC_CNTL_SWAP_NONE |
MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
#endif
}
if (ppc_md.progress)
ppc_md.progress("ppmc280_setup_bridge: mv64x60_init", 0);
/* Lookup PCI host bridges */
if (mv64x60_init(&bh, &si))
printk(KERN_ERR "Bridge initialization failed.\n");
pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */
ppc_md.pci_swizzle = common_swizzle;
ppc_md.pci_map_irq = ppmc280_map_irq;
ppc_md.pci_exclude_device = mv64x60_pci_exclude_device;
mv64x60_set_bus(&bh, 0, 0);
bh.hose_a->first_busno = 0;
bh.hose_a->last_busno = 0xff;
bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
if (ppc_md.progress)
ppc_md.progress("ppmc280_setup_bridge: return", 0);
return;
}
static void __init
ppmc280_setup_arch(void)
{
if (ppc_md.progress)
ppc_md.progress("ppmc280_setup_arch: enter", 0);
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
ROOT_DEV = Root_RAM0;
else
#endif
#ifdef CONFIG_ROOT_NFS
ROOT_DEV = Root_NFS;
#else
ROOT_DEV = Root_SDA2;
#endif
if (ppc_md.progress)
ppc_md.progress("ppmc280_setup_arch: Enabling L2 cache", 0);
/* Enable L2 cache but not L3 cache (if 744x/745x) */
_set_L2CR(_get_L2CR() | L2CR_L2E);
if (ppc_md.progress)
ppc_md.progress("ppmc280_setup_arch: Initializing bridge", 0);
ppmc280_setup_bridge(); /* set up PCI bridge(s) */
ppmc280_setup_peripherals(); /* set up chip selects/GPP/MPP etc */
if (ppc_md.progress)
ppc_md.progress("ppmc280_setup_arch: bridge init complete", 0);
printk(KERN_INFO "%s %s port (C) 2001 MontaVista Software, Inc."
"(source at mvista.com)\n", BOARD_VENDOR, BOARD_MACHINE);
if (ppc_md.progress)
ppc_md.progress("ppmc280_setup_arch: exit", 0);
return;
}
/* Platform device data fixup routines. */
#if defined(CONFIG_SERIAL_MPSC)
static void __init
ppmc280_fixup_mpsc_pdata(struct platform_device *pdev)
{
struct mpsc_pdata *pdata;
pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
pdata->max_idle = 40;
pdata->default_baud = PPMC280_DEFAULT_BAUD;
pdata->brg_clk_src = PPMC280_MPSC_CLK_SRC;
pdata->brg_clk_freq = PPMC280_MPSC_CLK_FREQ;
return;
}
static int
ppmc280_platform_notify(struct device *dev)
{
static struct {
char *bus_id;
void ((*rtn) (struct platform_device * pdev));
} dev_map[] = {
{ MPSC_CTLR_NAME ".0", ppmc280_fixup_mpsc_pdata },
{ MPSC_CTLR_NAME ".1", ppmc280_fixup_mpsc_pdata },
};
struct platform_device *pdev;
int i;
if (dev && dev->bus_id)
for (i = 0; i < ARRAY_SIZE(dev_map); i++)
if (!strncmp(dev->bus_id, dev_map[i].bus_id,
BUS_ID_SIZE)) {
pdev = container_of(dev, struct platform_device,
dev);
dev_map[i].rtn(pdev);
}
return 0;
}
#endif
static void
ppmc280_reset_board(void *addr)
{
u32 temp;
local_irq_disable();
temp = mv64x60_read(&bh, MV64x60_MPP_CNTL_0);
temp &= 0xFFFF0FFF;
mv64x60_write(&bh, MV64x60_MPP_CNTL_0, temp);
mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, 0x0004);
mv64x60_set_bits(&bh, MV64x60_GPP_IO_CNTL, 0x0004);
temp = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
temp &= 0xFFFF0FFF;
mv64x60_write(&bh, MV64x60_MPP_CNTL_2, temp);
mv64x60_set_bits(&bh, MV64x60_GPP_LEVEL_CNTL, 0x80000);
mv64x60_set_bits(&bh, MV64x60_GPP_IO_CNTL, 0x80000);
mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, 0x80004);
return;
}
static void
ppmc280_restart(char *cmd)
{
volatile ulong i = 10000000;
ppmc280_reset_board((void *)0xfff00100);
while (i-- > 0);
panic("restart failed\n");
}
static void
ppmc280_halt(void)
{
local_irq_disable();
while (1);
/* NOTREACHED */
}
static void
ppmc280_power_off(void)
{
ppmc280_halt();
/* NOTREACHED */
}
static int
ppmc280_show_cpuinfo(struct seq_file *m)
{
char *s;
seq_printf(m, "cpu freq\t: %dMHz\n",
(ppmc280_get_cpu_speed() + 500000) / 1000000);
seq_printf(m, "bus freq\t: %dMHz\n",
(ppmc280_get_bus_speed() + 500000) / 1000000);
seq_printf(m, "vendor\t\t: " BOARD_VENDOR "\n");
seq_printf(m, "machine\t\t: " BOARD_MACHINE "\n");
switch (bh.type) {
case MV64x60_TYPE_GT64260A:
s = "gt64260a";
break;
case MV64x60_TYPE_GT64260B:
s = "gt64260b";
break;
case MV64x60_TYPE_MV64360:
s = "mv64360";
break;
case MV64x60_TYPE_MV64460:
s = "mv64460";
break;
default:
s = "Unknown";
}
seq_printf(m, "bridge type\t: %s\n", s);
seq_printf(m, "bridge rev\t: 0x%x\n", bh.rev);
#if defined(CONFIG_NOT_COHERENT_CACHE)
seq_printf(m, "coherency\t: %s\n", "off");
#else
seq_printf(m, "coherency\t: %s\n", "on");
#endif
return 0;
}
static void __init
ppmc280_calibrate_decr(void)
{
ulong freq;
freq = ppmc280_get_bus_speed() / 4;
printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
freq / 1000000, freq % 1000000);
tb_ticks_per_jiffy = freq / HZ;
tb_to_us = mulhwu_scale_factor(freq, 1000000);
return;
}
#if defined(CONFIG_I2C_MV64XXX) && defined(CONFIG_SENSORS_MAX6900)
extern ulong max6900_get_rtc_time(void);
extern int max6900_set_rtc_time(ulong);
static int __init
ppmc280_rtc_hookup(void)
{
struct timespec tv;
if (ppc_md.progress)
ppc_md.progress("ppmc280_rtc_hookup: ", 0);
ppc_md.get_rtc_time = max6900_get_rtc_time;
ppc_md.set_rtc_time = max6900_set_rtc_time;
tv.tv_nsec = 0;
if (ppc_md.progress)
ppc_md.progress("ppmc280_rtc_hookup: call ppc_md.get_rtc_time",
0);
tv.tv_sec = (ppc_md.get_rtc_time)();
do_settimeofday(&tv);
return 0;
}
late_initcall(ppmc280_rtc_hookup);
#endif
/*
* Set BAT 3 to map 0xf1000000 to end of physical memory space.
*/
static __inline__ void
ppmc280_set_bat(void)
{
mb();
mtspr(SPRN_DBAT1U, 0xf0001ffe);
mtspr(SPRN_DBAT1L, 0xf000002a);
mb();
return;
}
#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
static void __init
ppmc280_map_io(void)
{
io_block_mapping(0xf1000000, 0xf1000000, 0x00100000, _PAGE_IO);
io_block_mapping(0xff800000, 0xff800000, 0x00800000, _PAGE_IO);
}
#endif
void __init
platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
{
#ifdef CONFIG_BLK_DEV_INITRD
extern int initrd_below_start_ok;
initrd_start = initrd_end = 0;
initrd_below_start_ok = 0;
#endif /* CONFIG_BLK_DEV_INITRD */
parse_bootinfo(find_bootinfo());
isa_mem_base = 0;
isa_io_base = PPMC280_PCI0_IO_CPU_BASE;
pci_dram_offset = PPMC280_PCI0_MEM_CPU_BASE;
loops_per_jiffy = ppmc280_get_cpu_speed() / HZ;
ppc_md.setup_arch = ppmc280_setup_arch;
ppc_md.show_cpuinfo = ppmc280_show_cpuinfo;
ppc_md.init_IRQ = mv64360_init_irq;
ppc_md.get_irq = mv64360_get_irq;
ppc_md.restart = ppmc280_restart;
ppc_md.power_off = ppmc280_power_off;
ppc_md.halt = ppmc280_halt;
ppc_md.find_end_of_memory = ppmc280_find_end_of_memory;
ppc_md.init = NULL;
ppc_md.calibrate_decr = ppmc280_calibrate_decr;
bh.p_base = CONFIG_MV64X60_NEW_BASE;
ppmc280_set_bat();
#ifdef CONFIG_SERIAL_TEXT_DEBUG
ppc_md.setup_io_mappings = ppmc280_map_io;
ppc_md.progress = mv64x60_mpsc_progress;
mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
#endif /* CONFIG_SERIAL_TEXT_DEBUG */
#ifdef CONFIG_KGDB
ppc_md.setup_io_mappings = ppmc280_map_io;
#endif /* CONFIG_KGDB */
#if defined(CONFIG_SERIAL_MPSC)
platform_notify = ppmc280_platform_notify;
#endif
return;
}
More information about the Linuxppc-embedded
mailing list