/* * Get hardware mutex to block firmware from accessing the pld. * It is possible for the firmware may hold the mutex for an extended length of * time. This function will block until access has been granted.
*/ staticvoid kempld_get_hardware_mutex(struct kempld_device_data *pld)
{ /* The mutex bit will read 1 until access has been granted */ while (ioread8(pld->io_index) & KEMPLD_MUTEX_KEY)
usleep_range(1000, 3000);
}
staticvoid kempld_release_hardware_mutex(struct kempld_device_data *pld)
{ /* The harware mutex is released when 1 is written to the mutex bit. */
iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
}
kempld_pdev = platform_device_register_full(&pdevinfo); if (IS_ERR(kempld_pdev)) return PTR_ERR(kempld_pdev);
return 0;
}
/** * kempld_read8 - read 8 bit register * @pld: kempld_device_data structure describing the PLD * @index: register index on the chip * * kempld_get_mutex must be called prior to calling this function.
*/
u8 kempld_read8(struct kempld_device_data *pld, u8 index)
{
iowrite8(index, pld->io_index); return ioread8(pld->io_data);
}
EXPORT_SYMBOL_GPL(kempld_read8);
/** * kempld_write8 - write 8 bit register * @pld: kempld_device_data structure describing the PLD * @index: register index on the chip * @data: new register value * * kempld_get_mutex must be called prior to calling this function.
*/ void kempld_write8(struct kempld_device_data *pld, u8 index, u8 data)
{
iowrite8(index, pld->io_index);
iowrite8(data, pld->io_data);
}
EXPORT_SYMBOL_GPL(kempld_write8);
/** * kempld_read16 - read 16 bit register * @pld: kempld_device_data structure describing the PLD * @index: register index on the chip * * kempld_get_mutex must be called prior to calling this function.
*/
u16 kempld_read16(struct kempld_device_data *pld, u8 index)
{ return kempld_read8(pld, index) | kempld_read8(pld, index + 1) << 8;
}
EXPORT_SYMBOL_GPL(kempld_read16);
/** * kempld_write16 - write 16 bit register * @pld: kempld_device_data structure describing the PLD * @index: register index on the chip * @data: new register value * * kempld_get_mutex must be called prior to calling this function.
*/ void kempld_write16(struct kempld_device_data *pld, u8 index, u16 data)
{
kempld_write8(pld, index, (u8)data);
kempld_write8(pld, index + 1, (u8)(data >> 8));
}
EXPORT_SYMBOL_GPL(kempld_write16);
/** * kempld_read32 - read 32 bit register * @pld: kempld_device_data structure describing the PLD * @index: register index on the chip * * kempld_get_mutex must be called prior to calling this function.
*/
u32 kempld_read32(struct kempld_device_data *pld, u8 index)
{ return kempld_read16(pld, index) | kempld_read16(pld, index + 2) << 16;
}
EXPORT_SYMBOL_GPL(kempld_read32);
/** * kempld_write32 - write 32 bit register * @pld: kempld_device_data structure describing the PLD * @index: register index on the chip * @data: new register value * * kempld_get_mutex must be called prior to calling this function.
*/ void kempld_write32(struct kempld_device_data *pld, u8 index, u32 data)
{
kempld_write16(pld, index, (u16)data);
kempld_write16(pld, index + 2, (u16)(data >> 16));
}
EXPORT_SYMBOL_GPL(kempld_write32);
/** * kempld_get_info - update device specific information * @pld: kempld_device_data structure describing the PLD * * This function calls the configured board specific kempld_get_info_XXXX * function which is responsible for gathering information about the specific * hardware. The information is then stored within the pld structure.
*/ staticint kempld_get_info(struct kempld_device_data *pld)
{ int ret; conststruct kempld_platform_data *pdata = dev_get_platdata(pld->dev); char major, minor;
ret = pdata->get_info(pld); if (ret) return ret;
/* The Kontron PLD firmware version string has the following format: * Pwxy.zzzz * P: Fixed * w: PLD number - 1 hex digit * x: Major version - 1 alphanumerical digit (0-9A-V) * y: Minor version - 1 alphanumerical digit (0-9A-V)
* zzzz: Build number - 4 zero padded hex digits */
if (pld->info.major < 10)
major = pld->info.major + '0'; else
major = (pld->info.major - 10) + 'A'; if (pld->info.minor < 10)
minor = pld->info.minor + '0'; else
minor = (pld->info.minor - 10) + 'A';
/* * kempld_register_cells - register cell drivers * * This function registers cell drivers for the detected hardware by calling * the configured kempld_register_cells_XXXX function which is responsible * to detect and register the needed cell drivers.
*/ staticint kempld_register_cells(struct kempld_device_data *pld)
{ conststruct kempld_platform_data *pdata = dev_get_platdata(pld->dev);
staticint kempld_detect_device(struct kempld_device_data *pld)
{
u8 index_reg; int ret;
mutex_lock(&pld->lock);
/* Check for empty IO space */
index_reg = ioread8(pld->io_index); if (index_reg == 0xff && ioread8(pld->io_data) == 0xff) {
mutex_unlock(&pld->lock); return -ENODEV;
}
/* Release hardware mutex if acquired */ if (!(index_reg & KEMPLD_MUTEX_KEY)) {
iowrite8(KEMPLD_MUTEX_KEY, pld->io_index); /* PXT and COMe-cPC2 boards may require a second release */
iowrite8(KEMPLD_MUTEX_KEY, pld->io_index);
}
if (IS_ERR_OR_NULL(kempld_pdev)) { /* * No kempld_pdev device has been registered in kempld_init, * so we seem to be probing an ACPI platform device.
*/
pdata = device_get_match_data(dev); if (!pdata) return -ENODEV;
ret = platform_device_add_data(pdev, pdata, sizeof(*pdata)); if (ret) return ret;
} elseif (kempld_pdev == pdev) {
pdata = dev_get_platdata(dev);
} else { /* * The platform device we are probing is not the one we * registered in kempld_init using the DMI table, so this one * comes from ACPI. * As we can only probe one - abort here and use the DMI * based one instead.
*/
dev_notice(dev, "platform device exists - not using ACPI\n"); return -ENODEV;
}
pld = devm_kzalloc(dev, sizeof(*pld), GFP_KERNEL); if (!pld) return -ENOMEM;
ioport = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!ioport) return -EINVAL;
pld->io_base = devm_ioport_map(dev, ioport->start,
resource_size(ioport)); if (!pld->io_base) return -ENOMEM;
/* * This custom DMI iteration allows the driver to be initialized in three ways: * - When a forced_device_id string matches any ident in the kempld_dmi_table, * regardless of whether the DMI device is present in the system dmi table. * - When a matching entry is present in the DMI system tabe. * - Through alternative mechanisms like ACPI.
*/ if (force_device_id[0]) { for (id = kempld_dmi_table; id->matches[0].slot != DMI_NONE; id++) if (strstr(id->ident, force_device_id)) if (!kempld_create_platform_device(&kempld_platform_data_generic)) break; if (id->matches[0].slot == DMI_NONE) return -ENODEV;
} else { for (id = dmi_first_match(kempld_dmi_table); id; id = dmi_first_match(id+1)) if (kempld_create_platform_device(&kempld_platform_data_generic)) break;
} return platform_driver_register(&kempld_driver);
}
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.