bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
{
	struct bcma_bus *bus = pc->core->bus;
	u16 chipid_top;
	u32 tmp;

	chipid_top = (bus->chipinfo.id & 0xFF00);
	if (chipid_top != 0x4700 &&
	    chipid_top != 0x5300)
		return false;

	if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
		bcma_info(bus, "This PCI core is disabled and not working\n");
		return false;
	}

	bcma_core_enable(pc->core, 0);

	return !mips_busprobe32(tmp, pc->core->io_addr);
}
Example #2
0
void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
{
    struct bcma_bus *bus = pc->core->bus;
    struct bcma_drv_pci_host *pc_host;
    u32 tmp;
    u32 pci_membase_1G;
    unsigned long io_map_base;

    bcma_info(bus, "PCIEcore in host mode found\n");

    if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
        bcma_info(bus, "This PCIE core is disabled and not working\n");
        return;
    }

    pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
    if (!pc_host)  {
        bcma_err(bus, "can not allocate memory");
        return;
    }

    pc->host_controller = pc_host;
    pc_host->pci_controller.io_resource = &pc_host->io_resource;
    pc_host->pci_controller.mem_resource = &pc_host->mem_resource;
    pc_host->pci_controller.pci_ops = &pc_host->pci_ops;
    pc_host->pdev = pc;

    pci_membase_1G = BCMA_SOC_PCI_DMA;
    pc_host->host_cfg_addr = BCMA_SOC_PCI_CFG;

    pc_host->pci_ops.read = bcma_core_pci_hostmode_read_config;
    pc_host->pci_ops.write = bcma_core_pci_hostmode_write_config;

    pc_host->mem_resource.name = "BCMA PCIcore external memory",
                          pc_host->mem_resource.start = BCMA_SOC_PCI_DMA;
    pc_host->mem_resource.end = BCMA_SOC_PCI_DMA + BCMA_SOC_PCI_DMA_SZ - 1;
    pc_host->mem_resource.flags = IORESOURCE_MEM | IORESOURCE_PCI_FIXED;

    pc_host->io_resource.name = "BCMA PCIcore external I/O",
                         pc_host->io_resource.start = 0x100;
    pc_host->io_resource.end = 0x7FF;
    pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED;

    /* Reset RC */
    usleep_range(3000, 5000);
    pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE);
    msleep(50);
    pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST |
                    BCMA_CORE_PCI_CTL_RST_OE);

    /* 64 MB I/O access window. On 4716, use
     * sbtopcie0 to access the device registers. We
     * can't use address match 2 (1 GB window) region
     * as mips can't generate 64-bit address on the
     * backplane.
     */
    if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4716 ||
            bus->chipinfo.id == BCMA_CHIP_ID_BCM4748) {
        pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
        pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
                                    BCMA_SOC_PCI_MEM_SZ - 1;
        pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
                        BCMA_CORE_PCI_SBTOPCI_MEM | BCMA_SOC_PCI_MEM);
    } else if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
        tmp = BCMA_CORE_PCI_SBTOPCI_MEM;
        tmp |= BCMA_CORE_PCI_SBTOPCI_PREF;
        tmp |= BCMA_CORE_PCI_SBTOPCI_BURST;
        if (pc->core->core_unit == 0) {
            pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
            pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
                                        BCMA_SOC_PCI_MEM_SZ - 1;
            pc_host->io_resource.start = 0x100;
            pc_host->io_resource.end = 0x47F;
            pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
            pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
                            tmp | BCMA_SOC_PCI_MEM);
        } else if (pc->core->core_unit == 1) {
            pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
            pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
                                        BCMA_SOC_PCI_MEM_SZ - 1;
            pc_host->io_resource.start = 0x480;
            pc_host->io_resource.end = 0x7FF;
            pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
            pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
            pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
                            tmp | BCMA_SOC_PCI1_MEM);
        }
    } else
        pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
                        BCMA_CORE_PCI_SBTOPCI_IO);

    /* 64 MB configuration access window */
    pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI1, BCMA_CORE_PCI_SBTOPCI_CFG0);

    /* 1 GB memory access window */
    pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI2,
                    BCMA_CORE_PCI_SBTOPCI_MEM | pci_membase_1G);


    /* As per PCI Express Base Spec 1.1 we need to wait for
     * at least 100 ms from the end of a reset (cold/warm/hot)
     * before issuing configuration requests to PCI Express
     * devices.
     */
    msleep(100);

    bcma_core_pci_enable_crs(pc);

    if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706 ||
            bus->chipinfo.id == BCMA_CHIP_ID_BCM4716) {
        u16 val16;
        bcma_extpci_read_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL,
                                &val16, sizeof(val16));
        val16 |= (2 << 5);	/* Max payload size of 512 */
        val16 |= (2 << 12);	/* MRRS 512 */
        bcma_extpci_write_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL,
                                 &val16, sizeof(val16));
    }

    /* Enable PCI bridge BAR0 memory & master access */
    tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
    bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp));

    /* Enable PCI interrupts */
    pcicore_write32(pc, BCMA_CORE_PCI_IMASK, BCMA_CORE_PCI_IMASK_INTA);

    /* Ok, ready to run, register it to the system.
     * The following needs change, if we want to port hostmode
     * to non-MIPS platform. */
    io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start,
                  resource_size(&pc_host->mem_resource));
    pc_host->pci_controller.io_map_base = io_map_base;
    set_io_port_base(pc_host->pci_controller.io_map_base);
    /* Give some time to the PCI controller to configure itself with the new
     * values. Not waiting at this point causes crashes of the machine. */
    usleep_range(10000, 15000);
    register_pci_controller(&pc_host->pci_controller);
    return;
}
/* Initialize serial flash access */
int bcma_sflash_init(struct bcma_drv_cc *cc)
{
	struct bcma_bus *bus = cc->core->bus;
	struct bcma_sflash *sflash = &cc->sflash;
	struct bcma_sflash_tbl_e *e;
	u32 id, id2;

	switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
	case BCMA_CC_FLASHT_STSER:
		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_DP);

		bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 0);
		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
		id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);

		bcma_cc_write32(cc, BCMA_CC_FLASHADDR, 1);
		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_ST_RES);
		id2 = bcma_cc_read32(cc, BCMA_CC_FLASHDATA);

		switch (id) {
		case 0xbf:
			for (e = bcma_sflash_sst_tbl; e->name; e++) {
				if (e->id == id2)
					break;
			}
			break;
		case 0x13:
			return -ENOTSUPP;
		default:
			for (e = bcma_sflash_st_tbl; e->name; e++) {
				if (e->id == id)
					break;
			}
			break;
		}
		if (!e->name) {
			bcma_err(bus, "Unsupported ST serial flash (id: 0x%X, id2: 0x%X)\n", id, id2);
			return -ENOTSUPP;
		}

		break;
	case BCMA_CC_FLASHT_ATSER:
		bcma_sflash_cmd(cc, BCMA_CC_FLASHCTL_AT_STATUS);
		id = bcma_cc_read32(cc, BCMA_CC_FLASHDATA) & 0x3c;

		for (e = bcma_sflash_at_tbl; e->name; e++) {
			if (e->id == id)
				break;
		}
		if (!e->name) {
			bcma_err(bus, "Unsupported Atmel serial flash (id: 0x%X)\n", id);
			return -ENOTSUPP;
		}

		break;
	default:
		bcma_err(bus, "Unsupported flash type\n");
		return -ENOTSUPP;
	}

	sflash->window = BCMA_SOC_FLASH2;
	sflash->blocksize = e->blocksize;
	sflash->numblocks = e->numblocks;
	sflash->size = sflash->blocksize * sflash->numblocks;
	sflash->present = true;

	bcma_info(bus, "Found %s serial flash (size: %dKiB, blocksize: 0x%X, blocks: %d)\n",
		  e->name, sflash->size / 1024, sflash->blocksize,
		  sflash->numblocks);

	/* Prepare platform device, but don't register it yet. It's too early,
	 * malloc (required by device_private_init) is not available yet. */
	bcma_sflash_dev.resource[0].end = bcma_sflash_dev.resource[0].start +
					  sflash->size;
	bcma_sflash_dev.dev.platform_data = sflash;

	return 0;
}