void __init prom_init(void) { u32 reg, mask; bcm63xx_cpu_init(); /* stop any running watchdog */ bcm_wdt_writel(WDT_STOP_1, WDT_CTL_REG); bcm_wdt_writel(WDT_STOP_2, WDT_CTL_REG); /* disable all hardware blocks clock for now */ if (BCMCPU_IS_6338()) mask = CKCTL_6338_ALL_SAFE_EN; else if (BCMCPU_IS_6345()) mask = CKCTL_6345_ALL_SAFE_EN; else if (BCMCPU_IS_6348()) mask = CKCTL_6348_ALL_SAFE_EN; else if (BCMCPU_IS_6358()) mask = CKCTL_6358_ALL_SAFE_EN; else if (BCMCPU_IS_6368()) mask = CKCTL_6368_ALL_SAFE_EN; else mask = 0; reg = bcm_perf_readl(PERF_CKCTL_REG); reg &= ~mask; bcm_perf_writel(reg, PERF_CKCTL_REG); /* register gpiochip */ bcm63xx_gpio_init(); /* do low level board init */ board_prom_init(); }
static void usbh_set(struct clk *clk, int enable) { if (BCMCPU_IS_6348()) bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); else if (BCMCPU_IS_6368()) bcm_hwclock_set(CKCTL_6368_USBH_CLK_EN, enable); }
int __init bcm63xx_spi_register(void) { if (BCMCPU_IS_6328() || BCMCPU_IS_6345()) return -ENODEV; spi_resources[0].start = bcm63xx_regset_address(RSET_SPI); spi_resources[0].end = spi_resources[0].start; spi_resources[1].start = bcm63xx_get_irq_number(IRQ_SPI); if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1; spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE; spi_pdata.msg_type_shift = SPI_6338_MSG_TYPE_SHIFT; spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH; } if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) { spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1; spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE; spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT; spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH; } bcm63xx_spi_regs_init(); return platform_device_register(&bcm63xx_spi_device); }
static __init void bcm63xx_spi_regs_init(void) { if (BCMCPU_IS_6338()) bcm63xx_regs_spi = bcm6338_regs_spi; if (BCMCPU_IS_6348()) bcm63xx_regs_spi = bcm6348_regs_spi; if (BCMCPU_IS_6358()) bcm63xx_regs_spi = bcm6358_regs_spi; if (BCMCPU_IS_6368()) bcm63xx_regs_spi = bcm6368_regs_spi; }
/* * early init callback */ void __init board_prom_init(void) { u32 val; /* read base address of boot chip select (0) */ val = bcm_mpi_readl(MPI_CSBASE_REG(0)); val &= MPI_CSBASE_BASE_MASK; /* assume board is a Livebox */ memcpy(&board, bcm963xx_boards[0], sizeof(board)); /* setup pin multiplexing depending on board enabled device, * this has to be done this early since PCI init is done * inside arch_initcall */ val = 0; if (board.has_pci) { bcm63xx_pci_enabled = 1; if (BCMCPU_IS_6348()) val |= GPIO_MODE_6348_G2_PCI; } if (board.has_pccard) { if (BCMCPU_IS_6348()) val |= GPIO_MODE_6348_G1_MII_PCCARD; } if (board.has_enet0 && !board.enet0.use_internal_phy) { if (BCMCPU_IS_6348()) val |= GPIO_MODE_6348_G3_EXT_MII | GPIO_MODE_6348_G0_EXT_MII; } if (board.has_enet1 && !board.enet1.use_internal_phy) { if (BCMCPU_IS_6348()) val |= GPIO_MODE_6348_G3_EXT_MII | GPIO_MODE_6348_G0_EXT_MII; } bcm_gpio_writel(val, GPIO_MODE_REG); }
/* * attempt to detect the amount of memory installed */ static unsigned int detect_memory_size(void) { unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0; u32 val; if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { val = bcm_sdram_readl(SDRAM_CFG_REG); rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT; cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT; is_32bits = (val & SDRAM_CFG_32B_MASK) ? 1 : 0; banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1; }
static void spi_set(struct clk *clk, int enable) { u32 mask; if (BCMCPU_IS_6338()) mask = CKCTL_6338_SPI_EN; else if (BCMCPU_IS_6348()) mask = CKCTL_6348_SPI_EN; else mask = CKCTL_6358_SPI_EN; bcm_hwclock_set(mask, enable); }
static void bcm63xx_external_irq_clear(struct irq_data *d) { unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; u32 reg, regaddr; regaddr = get_ext_irq_perf_reg(irq); reg = bcm_perf_readl(regaddr); if (BCMCPU_IS_6348()) reg |= EXTIRQ_CFG_CLEAR_6348(irq % 4); else reg |= EXTIRQ_CFG_CLEAR(irq % 4); bcm_perf_writel(reg, regaddr); }
/* * Ethernet MAC "misc" clock: dma clocks and main clock on 6348 */ static void enet_misc_set(struct clk *clk, int enable) { u32 mask; if (BCMCPU_IS_6338()) mask = CKCTL_6338_ENET_EN; else if (BCMCPU_IS_6345()) mask = CKCTL_6345_ENET_EN; else if (BCMCPU_IS_6348()) mask = CKCTL_6348_ENET_EN; else /* BCMCPU_IS_6358 */ mask = CKCTL_6358_EMUSB_EN; bcm_hwclock_set(mask, enable); }
/* * external IRQs operations: mask/unmask and clear on PERF external * irq control register. */ static void bcm63xx_external_irq_mask(struct irq_data *d) { unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; u32 reg, regaddr; regaddr = get_ext_irq_perf_reg(irq); reg = bcm_perf_readl(regaddr); if (BCMCPU_IS_6348()) reg &= ~EXTIRQ_CFG_MASK_6348(irq % 4); else reg &= ~EXTIRQ_CFG_MASK(irq % 4); bcm_perf_writel(reg, regaddr); if (is_ext_irq_cascaded) internal_irq_mask(irq + ext_irq_start); }
static void bcm63xx_external_irq_clear(struct irq_data *d) { unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; u32 reg, regaddr; unsigned long flags; regaddr = get_ext_irq_perf_reg(irq); spin_lock_irqsave(&epic_lock, flags); reg = bcm_perf_readl(regaddr); if (BCMCPU_IS_6348()) reg |= EXTIRQ_CFG_CLEAR_6348(irq % 4); else reg |= EXTIRQ_CFG_CLEAR(irq % 4); bcm_perf_writel(reg, regaddr); spin_unlock_irqrestore(&epic_lock, flags); }
/* * attempt to detect the amount of memory installed */ static unsigned int detect_memory_size(void) { unsigned int cols = 0, rows = 0, is_32bits = 0, banks = 0; u32 val; if (BCMCPU_IS_6328() || BCMCPU_IS_6362()) return bcm_ddr_readl(DDR_CSEND_REG) << 24; if (BCMCPU_IS_6345()) { val = bcm_sdram_readl(SDRAM_MBASE_REG); return val * 8 * 1024 * 1024; } if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) { val = bcm_sdram_readl(SDRAM_CFG_REG); rows = (val & SDRAM_CFG_ROW_MASK) >> SDRAM_CFG_ROW_SHIFT; cols = (val & SDRAM_CFG_COL_MASK) >> SDRAM_CFG_COL_SHIFT; is_32bits = (val & SDRAM_CFG_32B_MASK) ? 1 : 0; banks = (val & SDRAM_CFG_BANK_MASK) ? 2 : 1; }
int __init bcm63xx_pcmcia_register(void) { int ret, i; if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358()) return 0; /* use correct pcmcia ready gpio depending on processor */ switch (bcm63xx_get_cpu_id()) { case BCM6348_CPU_ID: pd.ready_gpio = 22; break; case BCM6358_CPU_ID: pd.ready_gpio = 22; break; default: return -ENODEV; } pcmcia_resources[0].start = bcm63xx_regset_address(RSET_PCMCIA); pcmcia_resources[0].end = pcmcia_resources[0].start; pcmcia_resources[0].end += RSET_PCMCIA_SIZE - 1; pcmcia_resources[4].start = bcm63xx_get_irq_number(IRQ_PCMCIA); /* configure pcmcia chip selects */ for (i = 0; i < 3; i++) { ret = config_pcmcia_cs(pcmcia_cs[i][0], pcmcia_cs[i][1], pcmcia_cs[i][2]); if (ret) goto out_err; } return platform_device_register(&bcm63xx_pcmcia_device); out_err: printk(KERN_ERR "unable to set pcmcia chip select"); return ret; }
/* * external IRQs operations: mask/unmask and clear on PERF external * irq control register. */ static void bcm63xx_external_irq_mask(struct irq_data *d) { unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; u32 reg, regaddr; unsigned long flags; regaddr = get_ext_irq_perf_reg(irq); spin_lock_irqsave(&epic_lock, flags); reg = bcm_perf_readl(regaddr); if (BCMCPU_IS_6348()) reg &= ~EXTIRQ_CFG_MASK_6348(irq % 4); else reg &= ~EXTIRQ_CFG_MASK(irq % 4); bcm_perf_writel(reg, regaddr); spin_unlock_irqrestore(&epic_lock, flags); if (is_ext_irq_cascaded) internal_irq_mask(irq_get_irq_data(irq + ext_irq_start)); }
static int __devinit ohci_hcd_bcm63xx_drv_probe(struct platform_device *pdev) { struct resource *res_mem; struct usb_hcd *hcd; struct ohci_hcd *ohci; struct clk *clk; u32 reg; int ret, irq; res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); if (!res_mem || irq < 0) return -ENODEV; /* enable USB host clock */ clk = clk_get(&pdev->dev, "usbh"); if (IS_ERR(clk)) return -ENODEV; clk_enable(clk); usb_host_clock = clk; msleep(100); if (BCMCPU_IS_6348()) bcm_rset_writel(RSET_OHCI_PRIV, 0, OHCI_PRIV_REG); else if (BCMCPU_IS_6358()) { reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG); reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK; reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK; bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG); /* * The magic value comes for the original vendor BSP * and is needed for USB to work. Datasheet does not * help, so the magic value is used as-is. */ bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020, USBH_PRIV_TEST_6358_REG); } else if (BCMCPU_IS_6368()) { reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG); reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK; reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK; bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG); reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG); reg |= USBH_PRIV_SETUP_IOC_MASK; bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG); } hcd = usb_create_hcd(&ohci_bcm63xx_hc_driver, &pdev->dev, "bcm63xx"); if (!hcd) return -ENOMEM; hcd->rsrc_start = res_mem->start; hcd->rsrc_len = res_mem->end - res_mem->start + 1; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { pr_debug("request_mem_region failed\n"); ret = -EBUSY; goto out; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { pr_debug("ioremap failed\n"); ret = -EIO; goto out1; } ohci = hcd_to_ohci(hcd); ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC | OHCI_QUIRK_FRAME_NO; ohci_hcd_init(ohci); ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); if (ret) goto out2; platform_set_drvdata(pdev, hcd); return 0; out2: iounmap(hcd->regs); out1: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); out: usb_put_hcd(hcd); return ret; }
/* * USB host clock */ static void usbh_set(struct clk *clk, int enable) { if (!BCMCPU_IS_6348()) return; bcm_hwclock_set(CKCTL_6348_USBH_EN, enable); }
static int __init bcm63xx_pci_init(void) { unsigned int mem_size; u32 val; if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358() && !BCMCPU_IS_6368()) return -ENODEV; if (!bcm63xx_pci_enabled) return -ENODEV; pci_iospace_start = ioremap_nocache(BCM_PCI_IO_BASE_PA, 4); if (!pci_iospace_start) return -ENOMEM; val = BCM_PCI_MEM_BASE_PA & MPI_L2P_BASE_MASK; bcm_mpi_writel(val, MPI_L2PMEMBASE1_REG); bcm_mpi_writel(~(BCM_PCI_MEM_SIZE - 1), MPI_L2PMEMRANGE1_REG); bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PMEMREMAP1_REG); val = bcm_pcmcia_readl(PCMCIA_C1_REG); val &= ~PCMCIA_C1_CBIDSEL_MASK; val |= (CARDBUS_PCI_IDSEL << PCMCIA_C1_CBIDSEL_SHIFT); bcm_pcmcia_writel(val, PCMCIA_C1_REG); #ifdef CONFIG_CARDBUS val = BCM_CB_MEM_BASE_PA & MPI_L2P_BASE_MASK; bcm_mpi_writel(val, MPI_L2PMEMBASE2_REG); bcm_mpi_writel(~(BCM_CB_MEM_SIZE - 1), MPI_L2PMEMRANGE2_REG); val |= MPI_L2PREMAP_ENABLED_MASK | MPI_L2PREMAP_IS_CARDBUS_MASK; bcm_mpi_writel(val, MPI_L2PMEMREMAP2_REG); #else bcm_mpi_writel(0, MPI_L2PMEMREMAP2_REG); #endif val = BCM_PCI_IO_BASE_PA & MPI_L2P_BASE_MASK; bcm_mpi_writel(val, MPI_L2PIOBASE_REG); bcm_mpi_writel(~(BCM_PCI_IO_SIZE - 1), MPI_L2PIORANGE_REG); bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PIOREMAP_REG); bcm_mpi_writel(MPI_LOCBUSCTL_EN_PCI_GPIO_MASK, MPI_LOCBUSCTL_REG); bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3); if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) val = MPI_SP0_REMAP_ENABLE_MASK; else val = 0; bcm_mpi_writel(val, MPI_SP0_REMAP_REG); bcm63xx_int_cfg_writel(0x0, PCI_BASE_ADDRESS_4); bcm_mpi_writel(0, MPI_SP1_REMAP_REG); mem_size = bcm63xx_get_memory_size(); if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() & 0xf0) == 0xa0) { if (mem_size > (16 * 1024 * 1024)) printk(KERN_WARNING "bcm63xx: this CPU " "revision cannot handle more than 16MB " "of RAM for PCI bus mastering\n"); } else { bcm_mpi_writel(~(mem_size - 1), MPI_SP0_RANGE_REG); bcm_mpi_writel(0, MPI_SP1_RANGE_REG); } val = bcm63xx_int_cfg_readl(BCMPCI_REG_TIMERS); val &= ~REG_TIMER_RETRY_MASK; bcm63xx_int_cfg_writel(val, BCMPCI_REG_TIMERS); val = bcm63xx_int_cfg_readl(PCI_COMMAND); val |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); bcm63xx_int_cfg_writel(val, PCI_COMMAND); val = bcm_mpi_readl(MPI_PCIMODESEL_REG); val &= ~MPI_PCIMODESEL_BAR1_NOSWAP_MASK; val &= ~MPI_PCIMODESEL_BAR2_NOSWAP_MASK; val &= ~MPI_PCIMODESEL_PREFETCH_MASK; val |= (8 << MPI_PCIMODESEL_PREFETCH_SHIFT); bcm_mpi_writel(val, MPI_PCIMODESEL_REG); val = bcm_mpi_readl(MPI_LOCINT_REG); val |= MPI_LOCINT_MASK(MPI_LOCINT_EXT_PCI_INT); bcm_mpi_writel(val, MPI_LOCINT_REG); register_pci_controller(&bcm63xx_controller); #ifdef CONFIG_CARDBUS register_pci_controller(&bcm63xx_cb_controller); #endif request_mem_region(BCM_PCI_IO_BASE_PA, BCM_PCI_IO_SIZE, "bcm63xx PCI IO space"); return 0; }
void __init prom_init(void) { u32 reg, mask; bcm63xx_cpu_init(); /* stop any running watchdog */ bcm_wdt_writel(WDT_STOP_1, WDT_CTL_REG); bcm_wdt_writel(WDT_STOP_2, WDT_CTL_REG); /* disable all hardware blocks clock for now */ if (BCMCPU_IS_3368()) mask = CKCTL_3368_ALL_SAFE_EN; else if (BCMCPU_IS_6328()) mask = CKCTL_6328_ALL_SAFE_EN; else if (BCMCPU_IS_6338()) mask = CKCTL_6338_ALL_SAFE_EN; else if (BCMCPU_IS_6345()) mask = CKCTL_6345_ALL_SAFE_EN; else if (BCMCPU_IS_6348()) mask = CKCTL_6348_ALL_SAFE_EN; else if (BCMCPU_IS_6358()) mask = CKCTL_6358_ALL_SAFE_EN; else if (BCMCPU_IS_6362()) mask = CKCTL_6362_ALL_SAFE_EN; else if (BCMCPU_IS_6368()) mask = CKCTL_6368_ALL_SAFE_EN; else mask = 0; reg = bcm_perf_readl(PERF_CKCTL_REG); reg &= ~mask; bcm_perf_writel(reg, PERF_CKCTL_REG); /* register gpiochip */ bcm63xx_gpio_init(); /* do low level board init */ board_prom_init(); /* set up SMP */ if (!register_bmips_smp_ops()) { /* * BCM6328 might not have its second CPU enabled, while BCM3368 * and BCM6358 need special handling for their shared TLB, so * disable SMP for now. */ if (BCMCPU_IS_6328()) { reg = bcm_readl(BCM_6328_OTP_BASE + OTP_USER_BITS_6328_REG(3)); if (reg & OTP_6328_REG3_TP1_DISABLED) bmips_smp_enabled = 0; } else if (BCMCPU_IS_3368() || BCMCPU_IS_6358()) { bmips_smp_enabled = 0; } if (!bmips_smp_enabled) return; /* * The bootloader has set up the CPU1 reset vector at * 0xa000_0200. * This conflicts with the special interrupt vector (IV). * The bootloader has also set up CPU1 to respond to the wrong * IPI interrupt. * Here we will start up CPU1 in the background and ask it to * reconfigure itself then go back to sleep. */ memcpy((void *)0xa0000200, &bmips_smp_movevec, 0x20); __sync(); set_c0_cause(C_SW0); cpumask_set_cpu(1, &bmips_booted_mask); /* * FIXME: we really should have some sort of hazard barrier here */ } }
static int bcm63xx_external_irq_set_type(struct irq_data *d, unsigned int flow_type) { unsigned int irq = d->irq - IRQ_EXTERNAL_BASE; u32 reg, regaddr; int levelsense, sense, bothedge; flow_type &= IRQ_TYPE_SENSE_MASK; if (flow_type == IRQ_TYPE_NONE) flow_type = IRQ_TYPE_LEVEL_LOW; levelsense = sense = bothedge = 0; switch (flow_type) { case IRQ_TYPE_EDGE_BOTH: bothedge = 1; break; case IRQ_TYPE_EDGE_RISING: sense = 1; break; case IRQ_TYPE_EDGE_FALLING: break; case IRQ_TYPE_LEVEL_HIGH: levelsense = 1; sense = 1; break; case IRQ_TYPE_LEVEL_LOW: levelsense = 1; break; default: printk(KERN_ERR "bogus flow type combination given !\n"); return -EINVAL; } regaddr = get_ext_irq_perf_reg(irq); reg = bcm_perf_readl(regaddr); irq %= 4; if (BCMCPU_IS_6348()) { if (levelsense) reg |= EXTIRQ_CFG_LEVELSENSE_6348(irq); else reg &= ~EXTIRQ_CFG_LEVELSENSE_6348(irq); if (sense) reg |= EXTIRQ_CFG_SENSE_6348(irq); else reg &= ~EXTIRQ_CFG_SENSE_6348(irq); if (bothedge) reg |= EXTIRQ_CFG_BOTHEDGE_6348(irq); else reg &= ~EXTIRQ_CFG_BOTHEDGE_6348(irq); } if (BCMCPU_IS_6338() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) { if (levelsense) reg |= EXTIRQ_CFG_LEVELSENSE(irq); else reg &= ~EXTIRQ_CFG_LEVELSENSE(irq); if (sense) reg |= EXTIRQ_CFG_SENSE(irq); else reg &= ~EXTIRQ_CFG_SENSE(irq); if (bothedge) reg |= EXTIRQ_CFG_BOTHEDGE(irq); else reg &= ~EXTIRQ_CFG_BOTHEDGE(irq); } bcm_perf_writel(reg, regaddr); irqd_set_trigger_type(d, flow_type); if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) __irq_set_handler_locked(d->irq, handle_level_irq); else __irq_set_handler_locked(d->irq, handle_edge_irq); return IRQ_SET_MASK_OK_NOCOPY; }
static int __init bcm63xx_pci_init(void) { unsigned int mem_size; u32 val; if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358()) return -ENODEV; if (!bcm63xx_pci_enabled) return -ENODEV; /* * configuration access are done through IO space, remap 4 * first bytes to access it from CPU. * * this means that no io access from CPU should happen while * we do a configuration cycle, but there's no way we can add * a spinlock for each io access, so this is currently kind of * broken on SMP. */ pci_iospace_start = ioremap_nocache(BCM_PCI_IO_BASE_PA, 4); if (!pci_iospace_start) return -ENOMEM; /* setup local bus to PCI access (PCI memory) */ val = BCM_PCI_MEM_BASE_PA & MPI_L2P_BASE_MASK; bcm_mpi_writel(val, MPI_L2PMEMBASE1_REG); bcm_mpi_writel(~(BCM_PCI_MEM_SIZE - 1), MPI_L2PMEMRANGE1_REG); bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PMEMREMAP1_REG); /* set Cardbus IDSEL (type 0 cfg access on primary bus for * this IDSEL will be done on Cardbus instead) */ val = bcm_pcmcia_readl(PCMCIA_C1_REG); val &= ~PCMCIA_C1_CBIDSEL_MASK; val |= (CARDBUS_PCI_IDSEL << PCMCIA_C1_CBIDSEL_SHIFT); bcm_pcmcia_writel(val, PCMCIA_C1_REG); #ifdef CONFIG_CARDBUS /* setup local bus to PCI access (Cardbus memory) */ val = BCM_CB_MEM_BASE_PA & MPI_L2P_BASE_MASK; bcm_mpi_writel(val, MPI_L2PMEMBASE2_REG); bcm_mpi_writel(~(BCM_CB_MEM_SIZE - 1), MPI_L2PMEMRANGE2_REG); val |= MPI_L2PREMAP_ENABLED_MASK | MPI_L2PREMAP_IS_CARDBUS_MASK; bcm_mpi_writel(val, MPI_L2PMEMREMAP2_REG); #else /* disable second access windows */ bcm_mpi_writel(0, MPI_L2PMEMREMAP2_REG); #endif /* setup local bus to PCI access (IO memory), we have only 1 * IO window for both PCI and cardbus, but it cannot handle * both at the same time, assume standard PCI for now, if * cardbus card has IO zone, PCI fixup will change window to * cardbus */ val = BCM_PCI_IO_BASE_PA & MPI_L2P_BASE_MASK; bcm_mpi_writel(val, MPI_L2PIOBASE_REG); bcm_mpi_writel(~(BCM_PCI_IO_SIZE - 1), MPI_L2PIORANGE_REG); bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PIOREMAP_REG); /* enable PCI related GPIO pins */ bcm_mpi_writel(MPI_LOCBUSCTL_EN_PCI_GPIO_MASK, MPI_LOCBUSCTL_REG); /* setup PCI to local bus access, used by PCI device to target * local RAM while bus mastering */ bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3); if (BCMCPU_IS_6358()) val = MPI_SP0_REMAP_ENABLE_MASK; else val = 0; bcm_mpi_writel(val, MPI_SP0_REMAP_REG); bcm63xx_int_cfg_writel(0x0, PCI_BASE_ADDRESS_4); bcm_mpi_writel(0, MPI_SP1_REMAP_REG); mem_size = bcm63xx_get_memory_size(); /* 6348 before rev b0 exposes only 16 MB of RAM memory through * PCI, throw a warning if we have more memory */ if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() & 0xf0) == 0xa0) { if (mem_size > (16 * 1024 * 1024)) printk(KERN_WARNING "bcm63xx: this CPU " "revision cannot handle more than 16MB " "of RAM for PCI bus mastering\n"); } else { /* setup sp0 range to local RAM size */ bcm_mpi_writel(~(mem_size - 1), MPI_SP0_RANGE_REG); bcm_mpi_writel(0, MPI_SP1_RANGE_REG); } /* change host bridge retry counter to infinite number of * retry, needed for some broadcom wifi cards with Silicon * Backplane bus where access to srom seems very slow */ val = bcm63xx_int_cfg_readl(BCMPCI_REG_TIMERS); val &= ~REG_TIMER_RETRY_MASK; bcm63xx_int_cfg_writel(val, BCMPCI_REG_TIMERS); /* enable memory decoder and bus mastering */ val = bcm63xx_int_cfg_readl(PCI_COMMAND); val |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); bcm63xx_int_cfg_writel(val, PCI_COMMAND); /* enable read prefetching & disable byte swapping for bus * mastering transfers */ val = bcm_mpi_readl(MPI_PCIMODESEL_REG); val &= ~MPI_PCIMODESEL_BAR1_NOSWAP_MASK; val &= ~MPI_PCIMODESEL_BAR2_NOSWAP_MASK; val &= ~MPI_PCIMODESEL_PREFETCH_MASK; val |= (8 << MPI_PCIMODESEL_PREFETCH_SHIFT); bcm_mpi_writel(val, MPI_PCIMODESEL_REG); /* enable pci interrupt */ val = bcm_mpi_readl(MPI_LOCINT_REG); val |= MPI_LOCINT_MASK(MPI_LOCINT_EXT_PCI_INT); bcm_mpi_writel(val, MPI_LOCINT_REG); register_pci_controller(&bcm63xx_controller); #ifdef CONFIG_CARDBUS register_pci_controller(&bcm63xx_cb_controller); #endif /* mark memory space used for IO mapping as reserved */ request_mem_region(BCM_PCI_IO_BASE_PA, BCM_PCI_IO_SIZE, "bcm63xx PCI IO space"); return 0; }
/* * early init callback, read nvram data from flash and checksum it */ void __init board_prom_init(void) { unsigned int i; u8 *boot_addr, *cfe; char cfe_version[32]; char *board_name; u32 val; /* read base address of boot chip select (0) * 6328 does not have MPI but boots from a fixed address */ if (BCMCPU_IS_6328()) val = 0x18000000; else { val = bcm_mpi_readl(MPI_CSBASE_REG(0)); val &= MPI_CSBASE_BASE_MASK; } boot_addr = (u8 *)KSEG1ADDR(val); /* dump cfe version */ cfe = boot_addr + BCM963XX_CFE_VERSION_OFFSET; if (!memcmp(cfe, "cfe-v", 5)) snprintf(cfe_version, sizeof(cfe_version), "%u.%u.%u-%u.%u", cfe[5], cfe[6], cfe[7], cfe[8], cfe[9]); else strcpy(cfe_version, "unknown"); printk(KERN_INFO PFX "CFE version: %s\n", cfe_version); bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET); board_name = bcm63xx_nvram_get_name(); /* find board by name */ for (i = 0; i < ARRAY_SIZE(bcm963xx_boards); i++) { if (strncmp(board_name, bcm963xx_boards[i]->name, 16)) continue; /* copy, board desc array is marked initdata */ memcpy(&board, bcm963xx_boards[i], sizeof(board)); break; } /* bail out if board is not found, will complain later */ if (!board.name[0]) { char name[17]; memcpy(name, board_name, 16); name[16] = 0; printk(KERN_ERR PFX "unknown bcm963xx board: %s\n", name); return; } /* setup pin multiplexing depending on board enabled device, * this has to be done this early since PCI init is done * inside arch_initcall */ val = 0; #ifdef CONFIG_PCI if (board.has_pci) { bcm63xx_pci_enabled = 1; if (BCMCPU_IS_6348()) val |= GPIO_MODE_6348_G2_PCI; } #endif if (board.has_pccard) { if (BCMCPU_IS_6348()) val |= GPIO_MODE_6348_G1_MII_PCCARD; } if (board.has_enet0 && !board.enet0.use_internal_phy) { if (BCMCPU_IS_6348()) val |= GPIO_MODE_6348_G3_EXT_MII | GPIO_MODE_6348_G0_EXT_MII; } if (board.has_enet1 && !board.enet1.use_internal_phy) { if (BCMCPU_IS_6348()) val |= GPIO_MODE_6348_G3_EXT_MII | GPIO_MODE_6348_G0_EXT_MII; } bcm_gpio_writel(val, GPIO_MODE_REG); }