Exemplo n.º 1
0
static u8 chipid_to_nrcores(u16 chipid)
{
	switch (chipid) {
	case 0x5365:
		return 7;
	case 0x4306:
		return 6;
	case 0x4310:
		return 8;
	case 0x4307:
	case 0x4301:
		return 5;
	case 0x4401:
	case 0x4402:
		return 3;
	case 0x4710:
	case 0x4610:
	case 0x4704:
		return 9;
	default:
		ssb_printk(KERN_ERR PFX
			   "CHIPID not in nrcores fallback list\n");
	}

	return 1;
}
Exemplo n.º 2
0
static u16 pcidev_to_chipid(struct pci_dev *pci_dev)
{
	u16 chipid_fallback = 0;

	switch (pci_dev->device) {
	case 0x4301:
		chipid_fallback = 0x4301;
		break;
	case 0x4305 ... 0x4307:
		chipid_fallback = 0x4307;
		break;
	case 0x4403:
		chipid_fallback = 0x4402;
		break;
	case 0x4610 ... 0x4615:
		chipid_fallback = 0x4610;
		break;
	case 0x4710 ... 0x4715:
		chipid_fallback = 0x4710;
		break;
	case 0x4320 ... 0x4325:
		chipid_fallback = 0x4309;
		break;
	case PCI_DEVICE_ID_BCM4401:
	case PCI_DEVICE_ID_BCM4401B0:
	case PCI_DEVICE_ID_BCM4401B1:
		chipid_fallback = 0x4401;
		break;
	default:
		ssb_printk(KERN_ERR PFX
			   "PCI-ID not in fallback list\n");
	}

	return chipid_fallback;
}
Exemplo n.º 3
0
/* Lowlevel coreswitching */
int ssb_pci_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
{
	int err;
	int attempts = 0;
	u32 cur_core;

	while (1) {
		err = pci_write_config_dword(bus->host_pci, SSB_BAR0_WIN,
					     (coreidx * SSB_CORE_SIZE)
					     + SSB_ENUM_BASE);
		if (err)
			goto error;
		err = pci_read_config_dword(bus->host_pci, SSB_BAR0_WIN,
					    &cur_core);
		if (err)
			goto error;
		cur_core = (cur_core - SSB_ENUM_BASE)
			   / SSB_CORE_SIZE;
		if (cur_core == coreidx)
			break;

		if (attempts++ > SSB_BAR0_MAX_RETRIES)
			goto error;
		udelay(10);
	}
	return 0;
error:
	ssb_printk(KERN_ERR PFX "Failed to switch to core %u\n", coreidx);
	return -ENODEV;
}
Exemplo n.º 4
0
ssize_t ssb_attr_sprom_store(struct ssb_bus *bus,
			     const char *buf, size_t count,
			     int (*sprom_check_crc)(const u16 *sprom, size_t size),
			     int (*sprom_write)(struct ssb_bus *bus, const u16 *sprom))
{
	u16 *sprom;
	int res = 0, err = -ENOMEM;
	size_t sprom_size_words = bus->sprom_size;
	struct ssb_freeze_context freeze;

	sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL);
	if (!sprom)
		goto out;
	err = hex2sprom(sprom, buf, count, sprom_size_words);
	if (err) {
		err = -EINVAL;
		goto out_kfree;
	}
	err = sprom_check_crc(sprom, sprom_size_words);
	if (err) {
		err = -EINVAL;
		goto out_kfree;
	}

	err = -ERESTARTSYS;
	if (mutex_lock_interruptible(&bus->sprom_mutex))
		goto out_kfree;
	err = ssb_devices_freeze(bus, &freeze);
	if (err) {
		ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n");
		goto out_unlock;
	}
	res = sprom_write(bus, sprom);
	err = ssb_devices_thaw(&freeze);
	if (err)
		ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n");
out_unlock:
	mutex_unlock(&bus->sprom_mutex);
out_kfree:
	kfree(sprom);
out:
	if (res)
		return res;
	return err ? err : count;
}
Exemplo n.º 5
0
static int sprom_do_write(struct ssb_bus *bus, const u16 *sprom)
{
	struct pci_dev *pdev = bus->host_pci;
	int i, err;
	u32 spromctl;

	ssb_printk(KERN_NOTICE PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n");
	err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
	if (err)
		goto err_ctlreg;
	spromctl |= SSB_SPROMCTL_WE;
	err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
	if (err)
		goto err_ctlreg;
	ssb_printk(KERN_NOTICE PFX "[ 0%%");
	msleep(500);
	for (i = 0; i < SSB_SPROMSIZE_WORDS; i++) {
		if (i == SSB_SPROMSIZE_WORDS / 4)
			ssb_printk("25%%");
		else if (i == SSB_SPROMSIZE_WORDS / 2)
			ssb_printk("50%%");
		else if (i == (SSB_SPROMSIZE_WORDS / 4) * 3)
			ssb_printk("75%%");
		else if (i % 2)
			ssb_printk(".");
		writew(sprom[i], bus->mmio + SSB_SPROM_BASE + (i * 2));
		mmiowb();
		msleep(20);
	}
	err = pci_read_config_dword(pdev, SSB_SPROMCTL, &spromctl);
	if (err)
		goto err_ctlreg;
	spromctl &= ~SSB_SPROMCTL_WE;
	err = pci_write_config_dword(pdev, SSB_SPROMCTL, spromctl);
	if (err)
		goto err_ctlreg;
	msleep(500);
	ssb_printk("100%% ]\n");
	ssb_printk(KERN_NOTICE PFX "SPROM written.\n");

	return 0;
err_ctlreg:
	ssb_printk(KERN_ERR PFX "Could not access SPROM control register.\n");
	return err;
}
Exemplo n.º 6
0
/* This function is called when doing a pci_enable_device().
 * We must first check if the device is a device on the PCI-core bridge. */
int ssb_pcicore_plat_dev_init(struct pci_dev *d)
{
	if (d->bus->ops != &ssb_pcicore_pciops) {
		/* This is not a device on the PCI-core bridge. */
		return -ENODEV;
	}

	ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
		   pci_name(d));

	/* Fix up interrupt lines */
	d->irq = ssb_mips_irq(extpci_core->dev) + 2;
	pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);

	return 0;
}
Exemplo n.º 7
0
static void __init ssb_fixup_pcibridge(struct pci_dev *dev)
{
	if (dev->bus->number != 0 || PCI_SLOT(dev->devfn) != 0)
		return;

	ssb_printk(KERN_INFO "PCI: fixing up bridge\n");

	/* Enable PCI bridge bus mastering and memory space */
	pci_set_master(dev);
	pcibios_enable_device(dev, ~0);

	/* Enable PCI bridge BAR1 prefetch and burst */
	pci_write_config_dword(dev, SSB_BAR1_CONTROL, 3);

	/* Make sure our latency is high enough to handle the devices behind us */
	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xa8);
}
Exemplo n.º 8
0
int ssb_pcicore_plat_dev_init(struct pci_dev *d)
{
	struct resource *res;
	int pos, size;
	u32 *base;

	if (d->bus->ops != &ssb_pcicore_pciops) {
		
		return -ENODEV;
	}

	ssb_printk(KERN_INFO "PCI: Fixing up device %s\n",
		   pci_name(d));

	
	for (pos = 0; pos < 6; pos++) {
		res = &d->resource[pos];
		if (res->flags & IORESOURCE_IO)
			base = &ssb_pcicore_pcibus_iobase;
		else
			base = &ssb_pcicore_pcibus_membase;
		res->flags |= IORESOURCE_PCI_FIXED;
		if (res->end) {
			size = res->end - res->start + 1;
			if (*base & (size - 1))
				*base = (*base + size) & ~(size - 1);
			res->start = *base;
			res->end = res->start + size - 1;
			*base += size;
			pci_write_config_dword(d, PCI_BASE_ADDRESS_0 + (pos << 2), res->start);
		}
		
		if (d->bus->number == 0 && PCI_SLOT(d->devfn) == 0)
			break;
	}
	
	d->irq = ssb_mips_irq(extpci_core->dev) + 2;
	pci_write_config_byte(d, PCI_INTERRUPT_LINE, d->irq);

	return 0;
}
Exemplo n.º 9
0
int ssb_pci_switch_core(struct ssb_bus *bus,
			struct ssb_device *dev)
{
	int err;
	unsigned long flags;

#if SSB_VERBOSE_PCICORESWITCH_DEBUG
	ssb_printk(KERN_INFO PFX
		   "Switching to %s core, index %d\n",
		   ssb_core_name(dev->id.coreid),
		   dev->core_index);
#endif

	spin_lock_irqsave(&bus->bar_lock, flags);
	err = ssb_pci_switch_coreidx(bus, dev->core_index);
	if (!err)
		bus->mapped_device = dev;
	spin_unlock_irqrestore(&bus->bar_lock, flags);

	return err;
}