/* Initialize NAND flash access */
int bcma_nflash_init(struct bcma_drv_cc *cc)
{
	struct bcma_bus *bus = cc->core->bus;

	if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 &&
	    cc->core->id.rev != 0x38) {
		bcma_err(bus, "NAND flash on unsupported board!\n");
		return -ENOTSUPP;
	}

	if (!(cc->capabilities & BCMA_CC_CAP_NFLASH)) {
		bcma_err(bus, "NAND flash not present according to ChipCommon\n");
		return -ENODEV;
	}

	cc->nflash.present = true;
	if (cc->core->id.rev == 38 &&
	    (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT))
		cc->nflash.boot = true;

	/* Prepare platform device, but don't register it yet. It's too early,
	 * malloc (required by device_private_init) is not available yet. */
	bcma_nflash_dev.dev.platform_data = &cc->nflash;

	return 0;
}
Exemple #2
0
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
{
	u32 leddc_on = 10;
	u32 leddc_off = 90;

	if (cc->setup_done)
		return;

	bcma_core_chipcommon_early_init(cc);

	if (cc->core->id.rev >= 20) {
		bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
		bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0);
	}

	if (cc->capabilities & BCMA_CC_CAP_PMU)
		bcma_pmu_init(cc);
	if (cc->capabilities & BCMA_CC_CAP_PCTL)
		bcma_err(cc->core->bus, "Power control not implemented!\n");

	if (cc->core->id.rev >= 16) {
		if (cc->core->bus->sprom.leddc_on_time &&
		    cc->core->bus->sprom.leddc_off_time) {
			leddc_on = cc->core->bus->sprom.leddc_on_time;
			leddc_off = cc->core->bus->sprom.leddc_off_time;
		}
		bcma_cc_write32(cc, BCMA_CC_GPIOTIMER,
			((leddc_on << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) |
			 (leddc_off << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT)));
	}
	cc->ticks_per_ms = bcma_chipco_watchdog_ticks_per_ms(cc);

	cc->setup_done = true;
}
Exemple #3
0
static void bcma_core_chipcommon_flash_detect(struct bcma_drv_cc *cc)
{
	struct bcma_bus *bus = cc->core->bus;

	switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
	case BCMA_CC_FLASHT_STSER:
	case BCMA_CC_FLASHT_ATSER:
		bcma_debug(bus, "Found serial flash\n");
		bcma_sflash_init(cc);
		break;
	case BCMA_CC_FLASHT_PARA:
		bcma_debug(bus, "Found parallel flash\n");
		bcma_pflash_init(cc);
		break;
	default:
		bcma_err(bus, "Flash type not supported\n");
	}

	if (cc->core->id.rev == 38 ||
	    bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
		if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
			bcma_debug(bus, "Found NAND flash\n");
			bcma_nflash_init(cc);
		}
	}
}
static void bcma_sflash_cmd(struct bcma_drv_cc *cc, u32 opcode)
{
	int i;
	bcma_cc_write32(cc, BCMA_CC_FLASHCTL,
			BCMA_CC_FLASHCTL_START | opcode);
	for (i = 0; i < 1000; i++) {
		if (!(bcma_cc_read32(cc, BCMA_CC_FLASHCTL) &
		      BCMA_CC_FLASHCTL_BUSY))
			return;
		cpu_relax();
	}
	bcma_err(cc->core->bus, "SFLASH control command failed (timeout)!\n");
}
Exemple #5
0
/* If the root port is capable of returning Config Request
 * Retry Status (CRS) Completion Status to software then
 * enable the feature.
 */
static void bcma_core_pci_enable_crs(struct bcma_drv_pci *pc)
{
    struct bcma_bus *bus = pc->core->bus;
    u8 cap_ptr, root_ctrl, root_cap, dev;
    u16 val16;
    int i;

    cap_ptr = bcma_find_pci_capability(pc, 0, 0, PCI_CAP_ID_EXP, NULL,
                                       NULL);
    root_cap = cap_ptr + PCI_EXP_RTCAP;
    bcma_extpci_read_config(pc, 0, 0, root_cap, &val16, sizeof(u16));
    if (val16 & BCMA_CORE_PCI_RC_CRS_VISIBILITY) {
        /* Enable CRS software visibility */
        root_ctrl = cap_ptr + PCI_EXP_RTCTL;
        val16 = PCI_EXP_RTCTL_CRSSVE;
        bcma_extpci_read_config(pc, 0, 0, root_ctrl, &val16,
                                sizeof(u16));

        /* Initiate a configuration request to read the vendor id
         * field of the device function's config space header after
         * 100 ms wait time from the end of Reset. If the device is
         * not done with its internal initialization, it must at
         * least return a completion TLP, with a completion status
         * of "Configuration Request Retry Status (CRS)". The root
         * complex must complete the request to the host by returning
         * a read-data value of 0001h for the Vendor ID field and
         * all 1s for any additional bytes included in the request.
         * Poll using the config reads for max wait time of 1 sec or
         * until we receive the successful completion status. Repeat
         * the procedure for all the devices.
         */
        for (dev = 1; dev < BCMA_PCI_SLOT_MAX; dev++) {
            for (i = 0; i < 100000; i++) {
                bcma_extpci_read_config(pc, dev, 0,
                                        PCI_VENDOR_ID, &val16,
                                        sizeof(val16));
                if (val16 != 0x1)
                    break;
                udelay(10);
            }
            if (val16 == 0x1)
                bcma_err(bus, "PCI: Broken device in slot %d\n",
                         dev);
        }
    }
}
Exemple #6
0
static void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
{
#if IS_BUILTIN(CONFIG_BCM47XX)
	unsigned int irq;
	u32 baud_base;
	u32 i;
	unsigned int ccrev = cc->core->id.rev;
	struct bcma_serial_port *ports = cc->serial_ports;

	if (ccrev >= 11 && ccrev != 15) {
		baud_base = bcma_chipco_get_alp_clock(cc);
		if (ccrev >= 21) {
			/* Turn off UART clock before switching clocksource. */
			bcma_cc_write32(cc, BCMA_CC_CORECTL,
				       bcma_cc_read32(cc, BCMA_CC_CORECTL)
				       & ~BCMA_CC_CORECTL_UARTCLKEN);
		}
		/* Set the override bit so we don't divide it */
		bcma_cc_write32(cc, BCMA_CC_CORECTL,
			       bcma_cc_read32(cc, BCMA_CC_CORECTL)
			       | BCMA_CC_CORECTL_UARTCLK0);
		if (ccrev >= 21) {
			/* Re-enable the UART clock. */
			bcma_cc_write32(cc, BCMA_CC_CORECTL,
				       bcma_cc_read32(cc, BCMA_CC_CORECTL)
				       | BCMA_CC_CORECTL_UARTCLKEN);
		}
	} else {
		bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n",
			 ccrev);
		return;
	}

	irq = bcma_core_irq(cc->core, 0);

	/* Determine the registers of the UARTs */
	cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
	for (i = 0; i < cc->nr_serial_ports; i++) {
		ports[i].regs = cc->core->io_addr + BCMA_CC_UART0_DATA +
				(i * 256);
		ports[i].irq = irq;
		ports[i].baud_base = baud_base;
		ports[i].reg_shift = 0;
	}
#endif /* CONFIG_BCM47XX */
}
static bool bcma_wait_reg(struct bcma_bus *bus, void __iomem *addr, u32 mask,
			  u32 value, int timeout)
{
	unsigned long deadline = jiffies + timeout;
	u32 val;

	do {
		val = readl(addr);
		if ((val & mask) == value)
			return true;
		cpu_relax();
		udelay(10);
	} while (!time_after_eq(jiffies, deadline));

	bcma_err(bus, "Timeout waiting for register %p\n", addr);

	return false;
}
Exemple #8
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;
}
static int __devinit bcma_host_pci_probe(struct pci_dev *dev,
					 const struct pci_device_id *id)
{
	struct bcma_bus *bus;
	int err = -ENOMEM;
	const char *name;
	u32 val;

	/* Alloc */
	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
	if (!bus)
		goto out;

	/* Basic PCI configuration */
	err = pci_enable_device(dev);
	if (err)
		goto err_kfree_bus;

	name = dev_name(&dev->dev);
	if (dev->driver && dev->driver->name)
		name = dev->driver->name;
	err = pci_request_regions(dev, name);
	if (err)
		goto err_pci_disable;
	pci_set_master(dev);

	/* Disable the RETRY_TIMEOUT register (0x41) to keep
	 * PCI Tx retries from interfering with C3 CPU state */
	pci_read_config_dword(dev, 0x40, &val);
	if ((val & 0x0000ff00) != 0)
		pci_write_config_dword(dev, 0x40, val & 0xffff00ff);

	/* SSB needed additional powering up, do we have any AMBA PCI cards? */
	if (!pci_is_pcie(dev))
		bcma_err(bus, "PCI card detected, report problems.\n");

	/* Map MMIO */
	err = -ENOMEM;
	bus->mmio = pci_iomap(dev, 0, ~0UL);
	if (!bus->mmio)
		goto err_pci_release_regions;

	/* Host specific */
	bus->host_pci = dev;
	bus->hosttype = BCMA_HOSTTYPE_PCI;
	bus->ops = &bcma_host_pci_ops;

	bus->boardinfo.vendor = bus->host_pci->subsystem_vendor;
	bus->boardinfo.type = bus->host_pci->subsystem_device;

	/* Register */
	err = bcma_bus_register(bus);
	if (err)
		goto err_pci_unmap_mmio;

	pci_set_drvdata(dev, bus);

out:
	return err;

err_pci_unmap_mmio:
	pci_iounmap(dev, bus->mmio);
err_pci_release_regions:
	pci_release_regions(dev);
err_pci_disable:
	pci_disable_device(dev);
err_kfree_bus:
	kfree(bus);
	return err;
}