/*
* arch/ppc/platforms/katana.c
*
* Board setup routines for the Artesyn Katana cPCI boards.
*
* Author: Tim Montgomery <timm@artesyncp.com>
* Maintained by: Mark A. Greer <mgreer@mvista.com>
*
* Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
* Based on code done by - Mark A. Greer <mgreer@mvista.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/*
* Supports the Artesyn 750i, 752i, and 3750. The 752i is virtually identical
* to the 750i except that it has an mv64460 bridge.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/kdev_t.h>
#include <linux/console.h>
#include <linux/initrd.h>
#include <linux/root_dev.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/mtd/physmap.h>
#include <linux/mv643xx.h>
#ifdef CONFIG_BOOTIMG
#include <linux/bootimg.h>
#endif
#include <asm/io.h>
#include <asm/unistd.h>
#include <asm/page.h>
#include <asm/time.h>
#include <asm/smp.h>
#include <asm/todc.h>
#include <asm/bootinfo.h>
#include <asm/ppcboot.h>
#include <asm/mv64x60.h>
#include <platforms/katana.h>
#include <asm/machdep.h>
static struct mv64x60_handle bh;
static katana_id_t katana_id;
static void __iomem *cpld_base;
static void __iomem *sram_base;
static u32 katana_flash_size_0;
static u32 katana_flash_size_1;
static u32 katana_bus_frequency;
static struct pci_controller katana_hose_a;
unsigned char __res[sizeof(bd_t)];
/* PCI Interrupt routing */
static int __init
katana_irq_lookup_750i(unsigned char idsel, unsigned char pin)
{
static char pci_irq_table[][4] = {
/*
* PCI IDSEL/INTPIN->INTLINE
* A B C D
*/
/* IDSEL 4 (PMC 1) */
{ KATANA_PCI_INTB_IRQ_750i, KATANA_PCI_INTC_IRQ_750i,
KATANA_PCI_INTD_IRQ_750i, KATANA_PCI_INTA_IRQ_750i },
/* IDSEL 5 (PMC 2) */
{ KATANA_PCI_INTC_IRQ_750i, KATANA_PCI_INTD_IRQ_750i,
KATANA_PCI_INTA_IRQ_750i, KATANA_PCI_INTB_IRQ_750i },
/* IDSEL 6 (T8110) */
{KATANA_PCI_INTD_IRQ_750i, 0, 0, 0 },
/* IDSEL 7 (unused) */
{0, 0, 0, 0 },
/* IDSEL 8 (Intel 82544) (752i only but doesn't harm 750i) */
{KATANA_PCI_INTD_IRQ_750i, 0, 0, 0 },
};
const long min_idsel = 4, max_idsel = 8, irqs_per_slot = 4;
return PCI_IRQ_TABLE_LOOKUP;
}
static int __init
katana_irq_lookup_3750(unsigned char idsel, unsigned char pin)
{
static char pci_irq_table[][4] = {
/*
* PCI IDSEL/INTPIN->INTLINE
* A B C D
*/
{ KATANA_PCI_INTA_IRQ_3750, 0, 0, 0 }, /* IDSEL 3 (BCM5691) */
{ KATANA_PCI_INTB_IRQ_3750, 0, 0, 0 }, /* IDSEL 4 (MV64360 #2)*/
{ KATANA_PCI_INTC_IRQ_3750, 0, 0, 0 }, /* IDSEL 5 (MV64360 #3)*/
};
const long min_idsel = 3, max_idsel = 5, irqs_per_slot = 4;
return PCI_IRQ_TABLE_LOOKUP;
}
static int __init
katana_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
{
switch (katana_id) {
case KATANA_ID_750I:
case KATANA_ID_752I:
return katana_irq_lookup_750i(idsel, pin);
case KATANA_ID_3750:
return katana_irq_lookup_3750(idsel, pin);
default:
printk(KERN_ERR "Bogus board ID\n");
return 0;
}
}
/* Board info retrieval routines */
void __init
katana_get_board_id(void)
{
switch (in_8(cpld_base + KATANA_CPLD_PRODUCT_ID)) {
case KATANA_PRODUCT_ID_3750:
katana_id = KATANA_ID_3750;
break;
case KATANA_PRODUCT_ID_750i:
katana_id = KATANA_ID_750I;
break;
case KATANA_PRODUCT_ID_752i:
katana_id = KATANA_ID_752I;
break;
default:
printk(KERN_ERR "Unsupported board\n");
}
}
int __init
katana_get_proc_num(void)
{
u16 val;
u8 save_exclude;
static int proc = -1;
static u8 first_time = 1;
if (first_time) {
if (katana_id != KATANA_ID_3750)
proc = 0;
else {
save_exclude = mv64x60_pci_exclude_bridge;
mv64x60_pci_exclude_bridge = 0;
early_read_config_word(bh.hose_b, 0,
PCI_DEVFN(0,0), PCI_DEVICE_ID, &val);
mv64x60_pci_exclude_bridge = save_exclude;
switch(val) {
case PCI_DEVICE_ID_KATANA_3750_PROC0:
proc = 0;
break;
case PCI_DEVICE_ID_KATANA_3750_PROC1:
proc = 1;
break;
case PCI_DEVICE_ID_KATANA_3750_PROC2:
proc = 2;
break;
default:
printk(KERN_ERR "Bogus Device ID\n");
}
}
first_time = 0;
}
return proc;
}
static inline int
katana_is_monarch(void)
{
return in_8(cpld_base + KATANA_CPLD_BD_CFG_3) &
KATANA_CPLD_BD_CFG_3_MONARCH;
}
static void __init
katana_setup_bridge(void)
{
struct pci_controller hose;
struct mv64x60_setup_info si;
void __iomem *vaddr;
int i;
u32 v;
u16 val, type;