예제 #1
0
파일: clk.c 프로젝트: EMFPGA/linux_media
/*
 * IPsec clock
 */
static void ipsec_set(struct clk *clk, int enable)
{
	if (BCMCPU_IS_6362())
		bcm_hwclock_set(CKCTL_6362_IPSEC_EN, enable);
	else if (BCMCPU_IS_6368())
		bcm_hwclock_set(CKCTL_6368_IPSEC_EN, enable);
}
예제 #2
0
파일: clk.c 프로젝트: EMFPGA/linux_media
struct clk *clk_get(struct device *dev, const char *id)
{
	if (!strcmp(id, "enet0"))
		return &clk_enet0;
	if (!strcmp(id, "enet1"))
		return &clk_enet1;
	if (!strcmp(id, "enetsw"))
		return &clk_enetsw;
	if (!strcmp(id, "ephy"))
		return &clk_ephy;
	if (!strcmp(id, "usbh"))
		return &clk_usbh;
	if (!strcmp(id, "usbd"))
		return &clk_usbd;
	if (!strcmp(id, "spi"))
		return &clk_spi;
	if (!strcmp(id, "hsspi"))
		return &clk_hsspi;
	if (!strcmp(id, "xtm"))
		return &clk_xtm;
	if (!strcmp(id, "periph"))
		return &clk_periph;
	if ((BCMCPU_IS_3368() || BCMCPU_IS_6358()) && !strcmp(id, "pcm"))
		return &clk_pcm;
	if ((BCMCPU_IS_6362() || BCMCPU_IS_6368()) && !strcmp(id, "ipsec"))
		return &clk_ipsec;
	if ((BCMCPU_IS_6328() || BCMCPU_IS_6362()) && !strcmp(id, "pcie"))
		return &clk_pcie;
	return ERR_PTR(-ENOENT);
}
예제 #3
0
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);
}
예제 #4
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_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();
}
예제 #5
0
파일: clk.c 프로젝트: AllenDou/linux
/*
 * USB device clock
 */
static void usbd_set(struct clk *clk, int enable)
{
	if (BCMCPU_IS_6328())
		bcm_hwclock_set(CKCTL_6328_USBD_EN, enable);
	else if (BCMCPU_IS_6368())
		bcm_hwclock_set(CKCTL_6368_USBD_EN, enable);
}
예제 #6
0
파일: dev-spi.c 프로젝트: XRobinHe/linux
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);
}
예제 #7
0
파일: dev-spi.c 프로젝트: XRobinHe/linux
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;
}
예제 #8
0
파일: dev-enet.c 프로젝트: 03199618/linux
int __init
bcm63xx_enetsw_register(const struct bcm63xx_enetsw_platform_data *pd)
{
	int ret;

	if (!BCMCPU_IS_6328() && !BCMCPU_IS_6362() && !BCMCPU_IS_6368())
		return -ENODEV;

	ret = register_shared();
	if (ret)
		return ret;

	enetsw_res[0].start = bcm63xx_regset_address(RSET_ENETSW);
	enetsw_res[0].end = enetsw_res[0].start;
	enetsw_res[0].end += RSET_ENETSW_SIZE - 1;
	enetsw_res[1].start = bcm63xx_get_irq_number(IRQ_ENETSW_RXDMA0);
	enetsw_res[2].start = bcm63xx_get_irq_number(IRQ_ENETSW_TXDMA0);
	if (!enetsw_res[2].start)
		enetsw_res[2].start = -1;

	memcpy(bcm63xx_enetsw_device.dev.platform_data, pd, sizeof(*pd));

	if (BCMCPU_IS_6328())
		enetsw_pd.num_ports = ENETSW_PORTS_6328;
	else if (BCMCPU_IS_6362() || BCMCPU_IS_6368())
		enetsw_pd.num_ports = ENETSW_PORTS_6368;

	enetsw_pd.dma_has_sram = true;
	enetsw_pd.dma_chan_width = ENETDMA_CHAN_WIDTH;
	enetsw_pd.dma_chan_en_mask = ENETDMAC_CHANCFG_EN_MASK;
	enetsw_pd.dma_chan_int_mask = ENETDMAC_IR_PKTDONE_MASK;

	ret = platform_device_register(&bcm63xx_enetsw_device);
	if (ret)
		return ret;

	return 0;
}
예제 #9
0
파일: clk.c 프로젝트: EMFPGA/linux_media
/*
 * XTM clock
 */
static void xtm_set(struct clk *clk, int enable)
{
	if (!BCMCPU_IS_6368())
		return;

	bcm_hwclock_set(CKCTL_6368_SAR_EN |
			CKCTL_6368_SWPKT_SAR_EN, enable);

	if (enable) {
		/* reset sar core afer clock change */
		bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 1);
		mdelay(1);
		bcm63xx_core_set_reset(BCM63XX_RESET_SAR, 0);
		mdelay(1);
	}
}
예제 #10
0
static void enetsw_set(struct clk *clk, int enable)
{
	if (!BCMCPU_IS_6368())
		return;
	bcm_hwclock_set(CKCTL_6368_ROBOSW_CLK_EN |
			CKCTL_6368_SWPKT_USB_EN |
			CKCTL_6368_SWPKT_SAR_EN, enable);
	if (enable) {
		u32 val;

		
		val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
		val &= ~SOFTRESET_6368_ENETSW_MASK;
		bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
		msleep(10);
		val |= SOFTRESET_6368_ENETSW_MASK;
		bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
		msleep(10);
	}
}
예제 #11
0
static void xtm_set(struct clk *clk, int enable)
{
	if (!BCMCPU_IS_6368())
		return;

	bcm_hwclock_set(CKCTL_6368_SAR_CLK_EN |
			CKCTL_6368_SWPKT_SAR_EN, enable);

	if (enable) {
		u32 val;

		
		val = bcm_perf_readl(PERF_SOFTRESET_6368_REG);
		val &= ~SOFTRESET_6368_SAR_MASK;
		bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
		mdelay(1);
		val |= SOFTRESET_6368_SAR_MASK;
		bcm_perf_writel(val, PERF_SOFTRESET_6368_REG);
		mdelay(1);
	}
}
예제 #12
0
파일: clk.c 프로젝트: EMFPGA/linux_media
/*
 * Ethernet switch clock
 */
static void enetsw_set(struct clk *clk, int enable)
{
	if (BCMCPU_IS_6328())
		bcm_hwclock_set(CKCTL_6328_ROBOSW_EN, enable);
	else if (BCMCPU_IS_6362())
		bcm_hwclock_set(CKCTL_6362_ROBOSW_EN, enable);
	else if (BCMCPU_IS_6368())
		bcm_hwclock_set(CKCTL_6368_ROBOSW_EN |
				CKCTL_6368_SWPKT_USB_EN |
				CKCTL_6368_SWPKT_SAR_EN,
				enable);
	else
		return;

	if (enable) {
		/* reset switch core afer clock change */
		bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 1);
		msleep(10);
		bcm63xx_core_set_reset(BCM63XX_RESET_ENETSW, 0);
		msleep(10);
	}
}
예제 #13
0
파일: mpi.c 프로젝트: pgid69/bcm63xx-phone
static void bcm_mpi_enable_extra_CSs(u16 cs)
{
   /*
    Code adapted from http://pastebin.com/g0bQGPRj
   */

   if (BCMCPU_IS_6358()) {
      if (cs >= 2) {
         /* BCM6358 */
         u32 val;
         /* Enable Overlay for SPI SS Pins */
         val = bcm_gpio_readl(GPIO_MODE_REG);
         val |= GPIO_MODE_6358_EXTRA_SPI_SS;
         bcm_gpio_writel(val, GPIO_MODE_REG);
         /* Enable SPI Slave Select as Output Pins */
         /* GPIO 32 is SS2, GPIO 33 is SS3 */
         val = bcm_gpio_readl(GPIO_CTL_HI_REG);
         val |= 0x0003;
         bcm_gpio_writel(val, GPIO_CTL_HI_REG);
      }
   }

   if (BCMCPU_IS_6368()) {
      if (cs >= 2) {
         /* BCM6368 */
         u32 val;
         /* Enable Extra SPI CS */
         val = bcm_gpio_readl(GPIO_MODE_REG);
         val |= (GPIO_MODE_6368_SPI_SSN2 << (cs - 2));
         bcm_gpio_writel(val, GPIO_MODE_REG);
         /* Enable SPI Slave Select as Output Pins */
         /* GPIO 28 is SS2, GPIO 29 is SS3, GPIO 30 is SS4, GPIO 31 is SS5*/
         val = bcm_gpio_readl(GPIO_CTL_LO_REG);
         val |= (GPIO_MODE_6368_SPI_SSN2 << (cs - 2));
         bcm_gpio_writel(val, GPIO_CTL_LO_REG);
      }
   }
}
예제 #14
0
파일: dev-enet.c 프로젝트: 03199618/linux
static int __init register_shared(void)
{
	int ret, chan_count;

	if (shared_device_registered)
		return 0;

	bcm63xx_enetdmac_regs_init();

	shared_res[0].start = bcm63xx_regset_address(RSET_ENETDMA);
	shared_res[0].end = shared_res[0].start;
	if (BCMCPU_IS_6345())
		shared_res[0].end += (RSET_6345_ENETDMA_SIZE) - 1;
	else
		shared_res[0].end += (RSET_ENETDMA_SIZE)  - 1;

	if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368())
		chan_count = 32;
	else if (BCMCPU_IS_6345())
		chan_count = 8;
	else
		chan_count = 16;

	shared_res[1].start = bcm63xx_regset_address(RSET_ENETDMAC);
	shared_res[1].end = shared_res[1].start;
	shared_res[1].end += RSET_ENETDMAC_SIZE(chan_count)  - 1;

	shared_res[2].start = bcm63xx_regset_address(RSET_ENETDMAS);
	shared_res[2].end = shared_res[2].start;
	shared_res[2].end += RSET_ENETDMAS_SIZE(chan_count)  - 1;

	ret = platform_device_register(&bcm63xx_enet_shared_device);
	if (ret)
		return ret;
	shared_device_registered = 1;

	return 0;
}
예제 #15
0
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;
}
예제 #16
0
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;
}
예제 #17
0
파일: prom.c 프로젝트: 168519/linux
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
		 */
	}
}
예제 #18
0
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;
}