/* Temporary list of yet-to-be-attached buses */ static LIST_HEAD(attach_queue); /* List if running buses */ static LIST_HEAD(buses); /* Software ID counter */ staticunsignedint next_busnumber; /* buses_mutes locks the two buslists and the next_busnumber. * Don't lock this directly, but use ssb_buses_[un]lock() below.
*/ static DEFINE_MUTEX(buses_mutex);
/* There are differences in the codeflow, if the bus is * initialized from early boot, as various needed services * are not available early. This is a mechanism to delay * these initializations to after early boot has finished. * It's also used to avoid mutex locking, as that's not * available and needed early.
*/ staticbool ssb_is_early_boot = 1;
if (dev->driver) {
ssb_drv = drv_to_ssb_drv(dev->driver); if (ssb_drv && ssb_drv->suspend)
err = ssb_drv->suspend(ssb_dev, state); if (err) goto out;
}
out: return err;
}
int ssb_bus_resume(struct ssb_bus *bus)
{ int err;
/* Reset HW state information in memory, so that HW is * completely reinitialized.
*/
bus->mapped_device = NULL; #ifdef CONFIG_SSB_DRIVER_PCICORE
bus->pcicore.setup_done = 0; #endif
err = ssb_bus_powerup(bus, 0); if (err) return err;
err = ssb_pcmcia_hardware_setup(bus); if (err) {
ssb_bus_may_powerdown(bus); return err;
}
ssb_chipco_resume(&bus->chipco);
ssb_bus_may_powerdown(bus);
#ifdef CONFIG_SSB_SPROM /** ssb_devices_freeze - Freeze all devices on the bus. * * After freezing no device driver will be handling a device * on this bus anymore. ssb_devices_thaw() must be called after * a successful freeze to reactivate the devices. * * @bus: The bus. * @ctx: Context structure. Pass this to ssb_devices_thaw().
*/ int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx)
{ struct ssb_device *sdev; struct ssb_driver *sdrv; unsignedint i;
/** ssb_devices_thaw - Unfreeze all devices on the bus. * * This will re-attach the device drivers and re-init the devices. * * @ctx: The context structure from ssb_devices_freeze()
*/ int ssb_devices_thaw(struct ssb_freeze_context *ctx)
{ struct ssb_bus *bus = ctx->bus; struct ssb_device *sdev; struct ssb_driver *sdrv; unsignedint i; int err, result = 0;
for (i = 0; i < bus->nr_devices; i++) { if (!ctx->device_frozen[i]) continue;
sdev = &bus->devices[i];
if (WARN_ON(!sdev->dev || !sdev->dev->driver)) continue;
sdrv = drv_to_ssb_drv(sdev->dev->driver); if (WARN_ON(!sdrv || !sdrv->probe)) continue;
err = sdrv->probe(sdev, &sdev->id); if (err) {
dev_err(sdev->dev, "Failed to thaw device %s\n",
dev_name(sdev->dev));
result = err;
}
ssb_device_put(sdev);
}
staticint ssb_devices_register(struct ssb_bus *bus)
{ struct ssb_device *sdev; struct device *dev; struct __ssb_dev_wrapper *devwrap; int i, err = 0; int dev_idx = 0;
for (i = 0; i < bus->nr_devices; i++) {
sdev = &(bus->devices[i]);
/* We don't register SSB-system devices to the kernel, * as the drivers for them are built into SSB.
*/ switch (sdev->id.coreid) { case SSB_DEV_CHIPCOMMON: case SSB_DEV_PCI: case SSB_DEV_PCIE: case SSB_DEV_PCMCIA: case SSB_DEV_MIPS: case SSB_DEV_MIPS_3302: case SSB_DEV_EXTIF: continue;
}
devwrap = kzalloc(sizeof(*devwrap), GFP_KERNEL); if (!devwrap) {
err = -ENOMEM; goto error;
}
dev = &devwrap->dev;
devwrap->sdev = sdev;
sdev->dev = dev;
err = device_register(dev); if (err) {
pr_err("Could not register %s\n", dev_name(dev)); /* Set dev to NULL to not unregister * dev on error unwinding.
*/
sdev->dev = NULL;
put_device(dev); goto error;
}
dev_idx++;
}
#ifdef CONFIG_SSB_DRIVER_MIPS if (bus->mipscore.pflash.present) {
err = platform_device_register(&ssb_pflash_dev); if (err)
pr_err("Error registering parallel flash\n");
} #endif
#ifdef CONFIG_SSB_SFLASH if (bus->mipscore.sflash.present) {
err = platform_device_register(&ssb_sflash_dev); if (err)
pr_err("Error registering serial flash\n");
} #endif
/* Needs ssb_buses_lock() */ staticint ssb_attach_queued_buses(void)
{ struct ssb_bus *bus, *n; int err = 0; int drop_them_all = 0;
list_for_each_entry_safe(bus, n, &attach_queue, list) { if (drop_them_all) {
list_del(&bus->list); continue;
} /* Can't init the PCIcore in ssb_bus_register(), as that * is too early in boot for embedded systems * (no udelay() available). So do it here in attach stage.
*/
err = ssb_bus_powerup(bus, 0); if (err) goto error;
ssb_pcicore_init(&bus->pcicore); if (bus->bustype == SSB_BUSTYPE_SSB)
ssb_watchdog_register(bus);
err = ssb_gpio_init(bus); if (err == -ENOTSUPP)
pr_debug("GPIO driver not activated\n"); elseif (err)
pr_debug("Error registering GPIO driver: %i\n", err);
/* Queue it for attach. * See the comment at the ssb_is_early_boot definition.
*/
list_add_tail(&bus->list, &attach_queue); if (!ssb_is_early_boot) { /* This is not early boot, so we must attach the bus now */
err = ssb_attach_queued_buses(); if (err) goto err_dequeue;
}
next_busnumber++;
ssb_buses_unlock();
err = ssb_bus_register(bus, ssb_pci_get_invariants, 0); if (!err) {
dev_info(&host_pci->dev, "Sonics Silicon Backplane found on PCI device %s\n",
dev_name(&host_pci->dev));
} else {
dev_err(&host_pci->dev, "Failed to register PCI version of SSB with error %d\n",
err);
}
return err;
} #endif/* CONFIG_SSB_PCIHOST */
#ifdef CONFIG_SSB_PCMCIAHOST int ssb_bus_pcmciabus_register(struct ssb_bus *bus, struct pcmcia_device *pcmcia_dev, unsignedlong baseaddr)
{ int err;
for (i = 0; i < bus->nr_devices; i++) {
ent = &(bus->devices[i]); if (ent->id.vendor != dev->id.vendor) continue; if (ent->id.coreid != dev->id.coreid) continue;
static u32 clkfactor_f6_resolve(u32 v)
{ /* map the magic values */ switch (v) { case SSB_CHIPCO_CLK_F6_2: return 2; case SSB_CHIPCO_CLK_F6_3: return 3; case SSB_CHIPCO_CLK_F6_4: return 4; case SSB_CHIPCO_CLK_F6_5: return 5; case SSB_CHIPCO_CLK_F6_6: return 6; case SSB_CHIPCO_CLK_F6_7: return 7;
} return 1;
}
/* Calculate the speed the backplane would run at a given set of clockcontrol values */
u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m)
{
u32 n1, n2, clock, m1, m2, m3, mc;
/* The REJECT bit seems to be different for Backplane rev 2.3 */ switch (rev) { case SSB_IDLOW_SSBREV_22: case SSB_IDLOW_SSBREV_24: case SSB_IDLOW_SSBREV_26: return SSB_TMSLOW_REJECT; case SSB_IDLOW_SSBREV_23: return SSB_TMSLOW_REJECT_23; case SSB_IDLOW_SSBREV_25: /* TODO - find the proper REJECT bit */ case SSB_IDLOW_SSBREV_27: /* same here */ return SSB_TMSLOW_REJECT; /* this is a guess */ case SSB_IDLOW_SSBREV: break; default:
WARN(1, KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
} return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23);
}
int ssb_device_is_enabled(struct ssb_device *dev)
{
u32 val;
u32 reject;
reject = ssb_tmslow_reject_bitmask(dev);
val = ssb_read32(dev, SSB_TMSLOW);
val &= SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET | reject;
staticvoid ssb_flush_tmslow(struct ssb_device *dev)
{ /* Make _really_ sure the device has finished the TMSLOW * register write transaction, as we risk running into * a machine check exception otherwise. * Do this by reading the register back to commit the * PCI write and delay an additional usec for the device * to react to the change.
*/
ssb_read32(dev, SSB_TMSLOW);
udelay(1);
}
/* Wait for bitmask in a register to get set or cleared. * timeout is in units of ten-microseconds
*/ staticint ssb_wait_bits(struct ssb_device *dev, u16 reg, u32 bitmask, int timeout, int set)
{ int i;
u32 val;
for (i = 0; i < timeout; i++) {
val = ssb_read32(dev, reg); if (set) { if ((val & bitmask) == bitmask) return 0;
} else { if (!(val & bitmask)) return 0;
}
udelay(10);
}
dev_err(dev->dev, "Timeout waiting for bitmask %08X on register %04X to %s\n",
bitmask, reg, set ? "set" : "clear");
/* Some chipsets need routing known for PCIe and 64-bit DMA */ staticbool ssb_dma_translation_special_bit(struct ssb_device *dev)
{
u16 chip_id = dev->bus->chip_id;
int ssb_bus_may_powerdown(struct ssb_bus *bus)
{ struct ssb_chipcommon *cc; int err = 0;
/* On buses where more than one core may be working * at a time, we must not powerdown stuff if there are * still cores that may want to run.
*/ if (bus->bustype == SSB_BUSTYPE_SSB) goto out;
cc = &bus->chipco;
if (!cc->dev) goto out; if (cc->dev->id.revision < 5) goto out;
staticvoid ssb_broadcast_value(struct ssb_device *dev,
u32 address, u32 data)
{ #ifdef CONFIG_SSB_DRIVER_PCICORE /* This is used for both, PCI and ChipCommon core, so be careful. */
BUILD_BUG_ON(SSB_PCICORE_BCAST_ADDR != SSB_CHIPCO_BCAST_ADDR);
BUILD_BUG_ON(SSB_PCICORE_BCAST_DATA != SSB_CHIPCO_BCAST_DATA); #endif
#ifdef CONFIG_SSB_DRIVER_PCICORE
dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev; #else
dev = bus->chipco.dev; #endif if (WARN_ON(!dev)) return; /* This forces an update of the cached registers. */
ssb_broadcast_value(dev, 0xFD8, 0);
}
EXPORT_SYMBOL(ssb_commit_settings);
u32 ssb_admatch_base(u32 adm)
{
u32 base = 0;
switch (adm & SSB_ADM_TYPE) { case SSB_ADM_TYPE0:
base = (adm & SSB_ADM_BASE0); break; case SSB_ADM_TYPE1:
WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
base = (adm & SSB_ADM_BASE1); break; case SSB_ADM_TYPE2:
WARN_ON(adm & SSB_ADM_NEG); /* unsupported */
base = (adm & SSB_ADM_BASE2); break; default:
WARN_ON(1);
}
/* See the comment at the ssb_is_early_boot definition */
ssb_is_early_boot = 0;
err = bus_register(&ssb_bustype); if (err) return err;
/* Maybe we already registered some buses at early boot. * Check for this and attach them
*/
ssb_buses_lock();
err = ssb_attach_queued_buses();
ssb_buses_unlock(); if (err) {
bus_unregister(&ssb_bustype); goto out;
}
err = b43_pci_ssb_bridge_init(); if (err) {
pr_err("Broadcom 43xx PCI-SSB-bridge initialization failed\n"); /* don't fail SSB init because of this */
}
err = ssb_host_pcmcia_init(); if (err) {
pr_err("PCMCIA host initialization failed\n"); /* don't fail SSB init because of this */
}
err = ssb_gige_init(); if (err) {
pr_err("SSB Broadcom Gigabit Ethernet driver initialization failed\n"); /* don't fail SSB init because of this */
err = 0;
}
out: return err;
} /* ssb must be initialized after PCI but before the ssb drivers. * That means we must use some initcall between subsys_initcall * and device_initcall.
*/
fs_initcall(ssb_modinit);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.