X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc%2Fplatforms%2Fkatana.c;h=720f8b3e2fbc508b9aa42cc321c32a9b9397d504;hb=refs%2Fremotes%2Fvserver;hp=bad8f27fa614d058949922c0023f8513dae78930;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c index bad8f27fa..720f8b3e2 100644 --- a/arch/ppc/platforms/katana.c +++ b/arch/ppc/platforms/katana.c @@ -1,9 +1,8 @@ /* - * arch/ppc/platforms/katana.c + * Board setup routines for the Artesyn Katana cPCI boards. * - * Board setup routines for the Artesyn Katana 750 based boards. - * - * Tim Montgomery + * Author: Tim Montgomery + * Maintained by: Mark A. Greer * * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il * Based on code done by - Mark A. Greer @@ -17,7 +16,6 @@ * Supports the Artesyn 750i, 752i, and 3750. The 752i is virtually identical * to the 750i except that it has an mv64460 bridge. */ -#include #include #include #include @@ -26,23 +24,34 @@ #include #include #include -#include +#include #include +#include #ifdef CONFIG_BOOTIMG #include #endif +#include +#include #include #include #include #include #include +#include #include #include +#include + +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; -static struct mv64x60_handle bh; -static katana_id_t katana_id; -static u32 cpld_base; -static u32 sram_base; +unsigned char __res[sizeof(bd_t)]; /* PCI Interrupt routing */ static int __init @@ -61,8 +70,12 @@ katana_irq_lookup_750i(unsigned char idsel, unsigned char pin) 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 = 6, irqs_per_slot = 4; + const long min_idsel = 4, max_idsel = 8, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; } @@ -105,7 +118,7 @@ katana_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) void __init katana_get_board_id(void) { - switch (in_8((volatile char *)(cpld_base + KATANA_CPLD_PRODUCT_ID))) { + switch (in_8(cpld_base + KATANA_CPLD_PRODUCT_ID)) { case KATANA_PRODUCT_ID_3750: katana_id = KATANA_ID_3750; break; @@ -138,7 +151,7 @@ katana_get_proc_num(void) save_exclude = mv64x60_pci_exclude_bridge; mv64x60_pci_exclude_bridge = 0; - early_read_config_word(bh.hose_a, 0, + early_read_config_word(bh.hose_b, 0, PCI_DEVFN(0,0), PCI_DEVICE_ID, &val); mv64x60_pci_exclude_bridge = save_exclude; @@ -170,56 +183,144 @@ katana_get_proc_num(void) static inline int katana_is_monarch(void) { - return in_8((volatile char *)(cpld_base + KATANA_CPLD_BD_CFG_3)) & + return in_8(cpld_base + KATANA_CPLD_BD_CFG_3) & KATANA_CPLD_BD_CFG_3_MONARCH; } static void __init -katana_enable_ipmi(void) +katana_setup_bridge(void) { - u8 reset_out; + struct pci_controller hose; + struct mv64x60_setup_info si; + void __iomem *vaddr; + int i; + u32 v; + u16 val, type; + u8 save_exclude; - /* Enable access to IPMI ctlr by clearing IPMI PORTSEL bit in CPLD */ - reset_out = in_8((volatile char *)(cpld_base + KATANA_CPLD_RESET_OUT)); - reset_out &= ~KATANA_CPLD_RESET_OUT_PORTSEL; - out_8((volatile void *)(cpld_base + KATANA_CPLD_RESET_OUT), reset_out); - return; -} + /* + * Some versions of the Katana firmware mistakenly change the vendor + * & device id fields in the bridge's pci device (visible via pci + * config accesses). This breaks mv64x60_init() because those values + * are used to identify the type of bridge that's there. Artesyn + * claims that the subsystem vendor/device id's will have the correct + * Marvell values so this code puts back the correct values from there. + */ + memset(&hose, 0, sizeof(hose)); + vaddr = ioremap(CONFIG_MV64X60_NEW_BASE, MV64x60_INTERNAL_SPACE_SIZE); + setup_indirect_pci_nomap(&hose, vaddr + MV64x60_PCI0_CONFIG_ADDR, + vaddr + MV64x60_PCI0_CONFIG_DATA); + save_exclude = mv64x60_pci_exclude_bridge; + mv64x60_pci_exclude_bridge = 0; + + early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID, &val); + + if (val != PCI_VENDOR_ID_MARVELL) { + early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), + PCI_SUBSYSTEM_VENDOR_ID, &val); + early_write_config_word(&hose, 0, PCI_DEVFN(0, 0), + PCI_VENDOR_ID, val); + early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), + PCI_SUBSYSTEM_ID, &val); + early_write_config_word(&hose, 0, PCI_DEVFN(0, 0), + PCI_DEVICE_ID, val); + } -static unsigned long -katana_bus_freq(void) -{ - u8 bd_cfg_0; + /* + * While we're in here, set the hotswap register correctly. + * Turn off blue LED; mask ENUM#, clear insertion & extraction bits. + */ + early_read_config_dword(&hose, 0, PCI_DEVFN(0, 0), + MV64360_PCICFG_CPCI_HOTSWAP, &v); + v &= ~(1<<19); + v |= ((1<<17) | (1<<22) | (1<<23)); + early_write_config_dword(&hose, 0, PCI_DEVFN(0, 0), + MV64360_PCICFG_CPCI_HOTSWAP, v); - bd_cfg_0 = in_8((volatile char *)(cpld_base + KATANA_CPLD_BD_CFG_0)); + /* While we're at it, grab the bridge type for later */ + early_read_config_word(&hose, 0, PCI_DEVFN(0, 0), PCI_DEVICE_ID, &type); - switch (bd_cfg_0 & KATANA_CPLD_BD_CFG_0_SYSCLK_MASK) { - case KATANA_CPLD_BD_CFG_0_SYSCLK_200: - return 200000000; - break; + mv64x60_pci_exclude_bridge = save_exclude; + iounmap(vaddr); - case KATANA_CPLD_BD_CFG_0_SYSCLK_166: - return 166666666; - break; + memset(&si, 0, sizeof(si)); - case KATANA_CPLD_BD_CFG_0_SYSCLK_133: - return 133333333; - break; + si.phys_reg_base = CONFIG_MV64X60_NEW_BASE; - case KATANA_CPLD_BD_CFG_0_SYSCLK_100: - return 100000000; - break; + si.pci_1.enable_bus = 1; + si.pci_1.pci_io.cpu_base = KATANA_PCI1_IO_START_PROC_ADDR; + si.pci_1.pci_io.pci_base_hi = 0; + si.pci_1.pci_io.pci_base_lo = KATANA_PCI1_IO_START_PCI_ADDR; + si.pci_1.pci_io.size = KATANA_PCI1_IO_SIZE; + si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; + si.pci_1.pci_mem[0].cpu_base = KATANA_PCI1_MEM_START_PROC_ADDR; + si.pci_1.pci_mem[0].pci_base_hi = KATANA_PCI1_MEM_START_PCI_HI_ADDR; + si.pci_1.pci_mem[0].pci_base_lo = KATANA_PCI1_MEM_START_PCI_LO_ADDR; + si.pci_1.pci_mem[0].size = KATANA_PCI1_MEM_SIZE; + si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; + si.pci_1.pci_cmd_bits = 0; + si.pci_1.latency_timer = 0x80; - default: - return 133333333; - break; + 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_1.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_1.acc_cntl_options[i] = + MV64360_PCI_ACC_CNTL_SNOOP_WB | + MV64360_PCI_ACC_CNTL_SWAP_NONE | + MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | + ((type == PCI_DEVICE_ID_MARVELL_MV64360) ? + MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES : + MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES); +#endif } + + /* Lookup PCI host bridges */ + if (mv64x60_init(&bh, &si)) + printk(KERN_WARNING "Bridge initialization failed.\n"); + + pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */ + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = katana_map_irq; + ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; + + mv64x60_set_bus(&bh, 1, 0); + bh.hose_b->first_busno = 0; + bh.hose_b->last_busno = 0xff; + + /* + * Need to access hotswap reg which is in the pci config area of the + * bridge's hose 0. Note that pcibios_alloc_controller() can't be used + * to alloc hose_a b/c that would make hose 0 known to the generic + * pci code which we don't want. + */ + bh.hose_a = &katana_hose_a; + setup_indirect_pci_nomap(bh.hose_a, + bh.v_base + MV64x60_PCI0_CONFIG_ADDR, + bh.v_base + MV64x60_PCI0_CONFIG_DATA); } /* Bridge & platform setup routines */ void __init katana_intr_setup(void) { + if (bh.type == MV64x60_TYPE_MV64460) /* As per instns from Marvell */ + mv64x60_clr_bits(&bh, MV64x60_CPU_MASTER_CNTL, 1 << 15); + /* MPP 8, 9, and 10 */ mv64x60_clr_bits(&bh, MV64x60_MPP_CNTL_1, 0xfff); @@ -242,9 +343,16 @@ katana_intr_setup(void) /* Config GPP intr ctlr to respond to level trigger */ mv64x60_set_bits(&bh, MV64x60_COMM_ARBITER_CNTL, (1<<10)); - /* Erranum FEr PCI-#8 */ - mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1<<5) | (1<<9)); - mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1<<5) | (1<<9)); + if (bh.type == MV64x60_TYPE_MV64360) { + /* Erratum FEr PCI-#9 */ + mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, + (1<<4) | (1<<5) | (1<<6) | (1<<7)); + mv64x60_set_bits(&bh, MV64x60_PCI1_CMD, (1<<8) | (1<<9)); + } else { + mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1<<6) | (1<<7)); + mv64x60_set_bits(&bh, MV64x60_PCI1_CMD, + (1<<4) | (1<<5) | (1<<8) | (1<<9)); + } /* * Dismiss and then enable interrupt on GPP interrupt cause @@ -263,13 +371,12 @@ katana_intr_setup(void) * BIT25 summarizes GPP interrupts 8-15 */ mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1<<25)); - return; } void __init katana_setup_peripherals(void) { - u32 base, size_0, size_1; + u32 base; /* Set up windows for boot CS, soldered & socketed flash, and CPLD */ mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, @@ -277,19 +384,22 @@ katana_setup_peripherals(void) bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); /* Assume firmware set up window sizes correctly for dev 0 & 1 */ - mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, &base, &size_0); + mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, &base, + &katana_flash_size_0); - if (size_0 > 0) { + if (katana_flash_size_0 > 0) { mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, - KATANA_SOLDERED_FLASH_BASE, size_0, 0); + KATANA_SOLDERED_FLASH_BASE, katana_flash_size_0, 0); bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); } - mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, &base, &size_1); + mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, &base, + &katana_flash_size_1); - if (size_1 > 0) { + if (katana_flash_size_1 > 0) { mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, - (KATANA_SOLDERED_FLASH_BASE + size_0), size_1, 0); + (KATANA_SOLDERED_FLASH_BASE + katana_flash_size_0), + katana_flash_size_1, 0); bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); } @@ -300,12 +410,12 @@ katana_setup_peripherals(void) mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN, KATANA_CPLD_BASE, KATANA_CPLD_SIZE, 0); bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN); - cpld_base = (u32)ioremap(KATANA_CPLD_BASE, KATANA_CPLD_SIZE); + cpld_base = ioremap(KATANA_CPLD_BASE, KATANA_CPLD_SIZE); mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0); bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); - sram_base = (u32)ioremap(KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE); + sram_base = ioremap(KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE); /* Set up Enet->SRAM window */ mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, @@ -339,79 +449,22 @@ katana_setup_peripherals(void) * internal data path in SRAM since it's first time accessing it * while after reset it's not configured. */ - memset((void *)sram_base, 0, MV64360_SRAM_SIZE); + memset(sram_base, 0, MV64360_SRAM_SIZE); /* Only processor zero [on 3750] is an PCI interrupt controller */ if (katana_get_proc_num() == 0) katana_intr_setup(); - - return; } static void __init -katana_setup_bridge(void) +katana_enable_ipmi(void) { - struct mv64x60_setup_info si; - int i; - - memset(&si, 0, sizeof(si)); - - si.phys_reg_base = KATANA_BRIDGE_REG_BASE; - - si.pci_1.enable_bus = 1; - si.pci_1.pci_io.cpu_base = KATANA_PCI1_IO_START_PROC_ADDR; - si.pci_1.pci_io.pci_base_hi = 0; - si.pci_1.pci_io.pci_base_lo = KATANA_PCI1_IO_START_PCI_ADDR; - si.pci_1.pci_io.size = KATANA_PCI1_IO_SIZE; - si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; - si.pci_1.pci_mem[0].cpu_base = KATANA_PCI1_MEM_START_PROC_ADDR; - si.pci_1.pci_mem[0].pci_base_hi = KATANA_PCI1_MEM_START_PCI_HI_ADDR; - si.pci_1.pci_mem[0].pci_base_lo = KATANA_PCI1_MEM_START_PCI_LO_ADDR; - si.pci_1.pci_mem[0].size = KATANA_PCI1_MEM_SIZE; - si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; - si.pci_1.pci_cmd_bits = 0; - si.pci_1.latency_timer = 0x80; - - 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_1.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_NONE; /* errata */ - si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; /* errata */ - si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; /* errata */ - - si.pci_1.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 - } - - /* Lookup PCI host bridges */ - if (mv64x60_init(&bh, &si)) - printk(KERN_WARNING "Bridge initialization failed.\n"); - - pci_dram_offset = 0; /* sys mem at same addr on PCI & cpu bus */ - ppc_md.pci_swizzle = common_swizzle; - ppc_md.pci_map_irq = katana_map_irq; - ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; - - mv64x60_set_bus(&bh, 1, 0); - bh.hose_b->first_busno = 0; - bh.hose_b->last_busno = 0xff; + u8 reset_out; - return; + /* Enable access to IPMI ctlr by clearing IPMI PORTSEL bit in CPLD */ + reset_out = in_8(cpld_base + KATANA_CPLD_RESET_OUT); + reset_out &= ~KATANA_CPLD_RESET_OUT_PORTSEL; + out_8(cpld_base + KATANA_CPLD_RESET_OUT, reset_out); } static void __init @@ -440,12 +493,11 @@ katana_setup_arch(void) * DD2.0 has bug that requires the L2 to be in WRT mode * avoid dirty data in cache */ - if (PVR_REV(mfspr(PVR)) == 0x0200) { + if (PVR_REV(mfspr(SPRN_PVR)) == 0x0200) { printk(KERN_INFO "DD2.0 detected. Setting L2 cache" "to Writethrough mode\n"); _set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2WT); - } - else + } else _set_L2CR(L2CR_L2E | L2CR_L2PE); if (ppc_md.progress) @@ -455,10 +507,37 @@ katana_setup_arch(void) katana_setup_peripherals(); katana_enable_ipmi(); + katana_bus_frequency = katana_bus_freq(cpld_base); + printk(KERN_INFO "Artesyn Communication Products, LLC - Katana(TM)\n"); if (ppc_md.progress) ppc_md.progress("katana_setup_arch: exit", 0); - return; +} + +void +katana_fixup_resources(struct pci_dev *dev) +{ + u16 v16; + + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES>>2); + + pci_read_config_word(dev, PCI_COMMAND, &v16); + v16 |= PCI_COMMAND_INVALIDATE | PCI_COMMAND_FAST_BACK; + pci_write_config_word(dev, PCI_COMMAND, v16); +} + +static const unsigned int cpu_750xx[32] = { /* 750FX & 750GX */ + 0, 0, 2, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,/* 0-15*/ + 16, 17, 18, 19, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 0 /*16-31*/ +}; + +static int +katana_get_cpu_freq(void) +{ + unsigned long pll_cfg; + + pll_cfg = (mfspr(SPRN_HID1) & 0xf8000000) >> 27; + return katana_bus_frequency * cpu_750xx[pll_cfg]/2; } /* Platform device data fixup routines. */ @@ -466,16 +545,22 @@ katana_setup_arch(void) static void __init katana_fixup_mpsc_pdata(struct platform_device *pdev) { - struct mpsc_pdata *pdata; + struct mpsc_pdata *pdata = (struct mpsc_pdata *)pdev->dev.platform_data; + bd_t *bdp = (bd_t *)__res; - pdata = (struct mpsc_pdata *)pdev->dev.platform_data; + if (bdp->bi_baudrate) + pdata->default_baud = bdp->bi_baudrate; + else + pdata->default_baud = KATANA_DEFAULT_BAUD; pdata->max_idle = 40; - pdata->default_baud = KATANA_DEFAULT_BAUD; pdata->brg_clk_src = KATANA_MPSC_CLK_SRC; - pdata->brg_clk_freq = KATANA_MPSC_CLK_FREQ; - - return; + /* + * TCLK (not SysCLk) is routed to BRG, then to the MPSC. On most parts, + * TCLK == SysCLK but on 64460, they are separate pins. + * SysCLK can go up to 200 MHz but TCLK can only go up to 133 MHz. + */ + pdata->brg_clk_freq = min(katana_bus_frequency, MV64x60_TCLK_FREQ_MAX); } #endif @@ -483,36 +568,34 @@ katana_fixup_mpsc_pdata(struct platform_device *pdev) static void __init katana_fixup_eth_pdata(struct platform_device *pdev) { - struct mv64xxx_eth_platform_data *eth_pd; + struct mv643xx_eth_platform_data *eth_pd; static u16 phy_addr[] = { KATANA_ETH0_PHY_ADDR, KATANA_ETH1_PHY_ADDR, KATANA_ETH2_PHY_ADDR, }; - int rx_size = KATANA_ETH_RX_QUEUE_SIZE * MV64340_ETH_DESC_SIZE; - int tx_size = KATANA_ETH_TX_QUEUE_SIZE * MV64340_ETH_DESC_SIZE; eth_pd = pdev->dev.platform_data; eth_pd->force_phy_addr = 1; eth_pd->phy_addr = phy_addr[pdev->id]; eth_pd->tx_queue_size = KATANA_ETH_TX_QUEUE_SIZE; eth_pd->rx_queue_size = KATANA_ETH_RX_QUEUE_SIZE; - eth_pd->tx_sram_addr = mv643xx_sram_alloc(tx_size); +} +#endif - if (eth_pd->tx_sram_addr) - eth_pd->tx_sram_size = tx_size; - else - printk(KERN_ERR "mv643xx_sram_alloc failed\n"); +#if defined(CONFIG_SYSFS) +static void __init +katana_fixup_mv64xxx_pdata(struct platform_device *pdev) +{ + struct mv64xxx_pdata *pdata = (struct mv64xxx_pdata *) + pdev->dev.platform_data; - eth_pd->rx_sram_addr = mv643xx_sram_alloc(rx_size); - if (eth_pd->rx_sram_addr) - eth_pd->rx_sram_size = rx_size; - else - printk(KERN_ERR "mv643xx_sram_alloc failed\n"); + /* Katana supports the mv64xxx hotswap register */ + pdata->hs_reg_valid = 1; } #endif -static int __init +static int katana_platform_notify(struct device *dev) { static struct { @@ -520,13 +603,16 @@ katana_platform_notify(struct device *dev) void ((*rtn)(struct platform_device *pdev)); } dev_map[] = { #if defined(CONFIG_SERIAL_MPSC) - { MPSC_CTLR_NAME "0", katana_fixup_mpsc_pdata }, - { MPSC_CTLR_NAME "1", katana_fixup_mpsc_pdata }, + { MPSC_CTLR_NAME ".0", katana_fixup_mpsc_pdata }, + { MPSC_CTLR_NAME ".1", katana_fixup_mpsc_pdata }, #endif #if defined(CONFIG_MV643XX_ETH) - { MV64XXX_ETH_NAME "0", katana_fixup_eth_pdata }, - { MV64XXX_ETH_NAME "1", katana_fixup_eth_pdata }, - { MV64XXX_ETH_NAME "2", katana_fixup_eth_pdata }, + { MV643XX_ETH_NAME ".0", katana_fixup_eth_pdata }, + { MV643XX_ETH_NAME ".1", katana_fixup_eth_pdata }, + { MV643XX_ETH_NAME ".2", katana_fixup_eth_pdata }, +#endif +#if defined(CONFIG_SYSFS) + { MV64XXX_DEV_NAME ".0", katana_fixup_mv64xxx_pdata }, #endif }; struct platform_device *pdev; @@ -535,8 +621,7 @@ katana_platform_notify(struct device *dev) if (dev && dev->bus_id) for (i=0; ibus_id, dev_map[i].bus_id, - BUS_ID_SIZE)) { - + BUS_ID_SIZE)) { pdev = container_of(dev, struct platform_device, dev); dev_map[i].rtn(pdev); @@ -545,14 +630,79 @@ katana_platform_notify(struct device *dev) return 0; } +#ifdef CONFIG_MTD_PHYSMAP + +#ifndef MB +#define MB (1 << 20) +#endif + +/* + * MTD Layout depends on amount of soldered FLASH in system. Sizes in MB. + * + * FLASH Amount: 128 64 32 16 + * ------------- --- -- -- -- + * Monitor: 1 1 1 1 + * Primary Kernel: 1.5 1.5 1.5 1.5 + * Primary fs: 30 30 + * Secondary Kernel: 1.5 1.5 N/A N/A + * Secondary fs: N/A N/A + * User: + */ +static int __init +katana_setup_mtd(void) +{ + u32 size; + int ptbl_entries; + static struct mtd_partition *ptbl; + + size = katana_flash_size_0 + katana_flash_size_1; + if (!size) + return -ENOMEM; + + ptbl_entries = (size >= (64*MB)) ? 6 : 4; + + if ((ptbl = kcalloc(ptbl_entries, sizeof(struct mtd_partition), + GFP_KERNEL)) == NULL) { + printk(KERN_WARNING "Can't alloc MTD partition table\n"); + return -ENOMEM; + } + + ptbl[0].name = "Monitor"; + ptbl[0].size = KATANA_MTD_MONITOR_SIZE; + ptbl[1].name = "Primary Kernel"; + ptbl[1].offset = MTDPART_OFS_NXTBLK; + ptbl[1].size = 0x00180000; /* 1.5 MB */ + ptbl[2].name = "Primary Filesystem"; + ptbl[2].offset = MTDPART_OFS_APPEND; + ptbl[2].size = MTDPART_SIZ_FULL; /* Correct for 16 & 32 MB */ + ptbl[ptbl_entries-1].name = "User FLASH"; + ptbl[ptbl_entries-1].offset = KATANA_MTD_MONITOR_SIZE; + ptbl[ptbl_entries-1].size = MTDPART_SIZ_FULL; + + if (size >= (64*MB)) { + ptbl[2].size = 30*MB; + ptbl[3].name = "Secondary Kernel"; + ptbl[3].offset = MTDPART_OFS_NXTBLK; + ptbl[3].size = 0x00180000; /* 1.5 MB */ + ptbl[4].name = "Secondary Filesystem"; + ptbl[4].offset = MTDPART_OFS_APPEND; + ptbl[4].size = MTDPART_SIZ_FULL; + } + + physmap_map.size = size; + physmap_set_partitions(ptbl, ptbl_entries); + return 0; +} +arch_initcall(katana_setup_mtd); +#endif + static void katana_restart(char *cmd) { - volatile ulong i = 10000000; + ulong i = 10000000; /* issue hard reset to the reset command register */ - out_8((volatile char *)(cpld_base + KATANA_CPLD_RST_CMD), - KATANA_CPLD_RST_CMD_HR); + out_8(cpld_base + KATANA_CPLD_RST_CMD, KATANA_CPLD_RST_CMD_HR); while (i-- > 0) ; panic("restart failed\n"); @@ -561,6 +711,29 @@ katana_restart(char *cmd) static void katana_halt(void) { + u8 v; + + /* Turn on blue LED to indicate its okay to remove */ + if (katana_id == KATANA_ID_750I) { + u32 v; + u8 save_exclude; + + /* Set LOO bit in cPCI HotSwap reg of hose 0 to turn on LED. */ + save_exclude = mv64x60_pci_exclude_bridge; + mv64x60_pci_exclude_bridge = 0; + early_read_config_dword(bh.hose_a, 0, PCI_DEVFN(0, 0), + MV64360_PCICFG_CPCI_HOTSWAP, &v); + v &= 0xff; + v |= (1 << 19); + early_write_config_dword(bh.hose_a, 0, PCI_DEVFN(0, 0), + MV64360_PCICFG_CPCI_HOTSWAP, v); + mv64x60_pci_exclude_bridge = save_exclude; + } else if (katana_id == KATANA_ID_752I) { + v = in_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF); + v |= HSL_PLD_HOT_SWAP_LED_BIT; + out_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF, v); + } + while (1) ; /* NOTREACHED */ } @@ -575,36 +748,65 @@ katana_power_off(void) static int katana_show_cpuinfo(struct seq_file *m) { + char *s; + + seq_printf(m, "cpu freq\t: %dMHz\n", + (katana_get_cpu_freq() + 500000) / 1000000); + seq_printf(m, "bus freq\t: %ldMHz\n", + ((long)katana_bus_frequency + 500000) / 1000000); seq_printf(m, "vendor\t\t: Artesyn Communication Products, LLC\n"); seq_printf(m, "board\t\t: "); - switch (katana_id) { case KATANA_ID_3750: - seq_printf(m, "Katana 3750\n"); + seq_printf(m, "Katana 3750"); break; case KATANA_ID_750I: - seq_printf(m, "Katana 750i\n"); + seq_printf(m, "Katana 750i"); break; case KATANA_ID_752I: - seq_printf(m, "Katana 752i\n"); + seq_printf(m, "Katana 752i"); break; default: - seq_printf(m, "Unknown\n"); + seq_printf(m, "Unknown"); break; } + seq_printf(m, " (product id: 0x%x)\n", + in_8(cpld_base + KATANA_CPLD_PRODUCT_ID)); - seq_printf(m, "product ID\t: 0x%x\n", - in_8((volatile char *)(cpld_base + KATANA_CPLD_PRODUCT_ID))); + seq_printf(m, "pci mode\t: %sMonarch\n", + katana_is_monarch()? "" : "Non-"); seq_printf(m, "hardware rev\t: 0x%x\n", - in_8((volatile char *)(cpld_base+KATANA_CPLD_HARDWARE_VER))); - seq_printf(m, "PLD rev\t\t: 0x%x\n", - in_8((volatile char *)(cpld_base + KATANA_CPLD_PLD_VER))); - seq_printf(m, "PLB freq\t: %ldMhz\n", katana_bus_freq() / 1000000); - seq_printf(m, "PCI\t\t: %sMonarch\n", katana_is_monarch()? "" : "Non-"); + in_8(cpld_base+KATANA_CPLD_HARDWARE_VER)); + seq_printf(m, "pld rev\t\t: 0x%x\n", + in_8(cpld_base + KATANA_CPLD_PLD_VER)); + + 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; } @@ -612,36 +814,53 @@ katana_show_cpuinfo(struct seq_file *m) static void __init katana_calibrate_decr(void) { - ulong freq; + u32 freq; - freq = katana_bus_freq() / 4; + freq = katana_bus_frequency / 4; printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", - freq / 1000000, freq % 1000000); + (long)freq / 1000000, (long)freq % 1000000); tb_ticks_per_jiffy = freq / HZ; tb_to_us = mulhwu_scale_factor(freq, 1000000); - - return; } +/* + * The katana supports both uImage and zImage. If uImage, get the mem size + * from the bd info. If zImage, the bootwrapper adds a BI_MEMSIZE entry in + * the bi_rec data which is sucked out and put into boot_mem_size by + * parse_bootinfo(). MMU_init() will then use the boot_mem_size for the mem + * size and not call this routine. The only way this will fail is when a uImage + * is used but the fw doesn't pass in a valid bi_memsize. This should never + * happen, though. + */ unsigned long __init katana_find_end_of_memory(void) { - return mv64x60_get_mem_size(KATANA_BRIDGE_REG_BASE, - MV64x60_TYPE_MV64360); + bd_t *bdp = (bd_t *)__res; + return bdp->bi_memsize; } -static inline void -katana_set_bat(void) +#if defined(CONFIG_I2C_MV64XXX) && defined(CONFIG_SENSORS_M41T00) +extern ulong m41t00_get_rtc_time(void); +extern int m41t00_set_rtc_time(ulong); + +static int __init +katana_rtc_hookup(void) { - mb(); - mtspr(DBAT2U, 0xf0001ffe); - mtspr(DBAT2L, 0xf000002a); - mb(); + struct timespec tv; + + ppc_md.get_rtc_time = m41t00_get_rtc_time; + ppc_md.set_rtc_time = m41t00_set_rtc_time; + + tv.tv_nsec = 0; + tv.tv_sec = (ppc_md.get_rtc_time)(); + do_settimeofday(&tv); - return; + return 0; } +late_initcall(katana_rtc_hookup); +#endif #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) static void __init @@ -657,9 +876,35 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, { parse_bootinfo(find_bootinfo()); + /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer) + * are non-zero, then we should use the board info from the bd_t + * structure and the cmdline pointed to by r6 instead of the + * information from birecs, if any. Otherwise, use the information + * from birecs as discovered by the preceeding call to + * parse_bootinfo(). This rule should work with both PPCBoot, which + * uses a bd_t board info structure, and the kernel boot wrapper, + * which uses birecs. + */ + if (r3 && r6) { + /* copy board info structure */ + memcpy((void *)__res, (void *)(r3+KERNELBASE), sizeof(bd_t)); + /* copy command line */ + *(char *)(r7+KERNELBASE) = 0; + strcpy(cmd_line, (char *)(r6+KERNELBASE)); + } + +#ifdef CONFIG_BLK_DEV_INITRD + /* take care of initrd if we have one */ + if (r4) { + initrd_start = r4 + KERNELBASE; + initrd_end = r5 + KERNELBASE; + } +#endif /* CONFIG_BLK_DEV_INITRD */ + isa_mem_base = 0; ppc_md.setup_arch = katana_setup_arch; + ppc_md.pcibios_fixup_resources = katana_fixup_resources; ppc_md.show_cpuinfo = katana_show_cpuinfo; ppc_md.init_IRQ = mv64360_init_irq; ppc_md.get_irq = mv64360_get_irq; @@ -672,13 +917,10 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) ppc_md.setup_io_mappings = katana_map_io; ppc_md.progress = mv64x60_mpsc_progress; - mv64x60_progress_init(KATANA_BRIDGE_REG_BASE); + mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE); #endif #if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH) platform_notify = katana_platform_notify; #endif - - katana_set_bat(); /* Need for katana_find_end_of_memory and progress */ - return; }