parent = ACPI_COMPANION(pdev->dev.parent); if (!parent) return;
/* * MFD child device gets its ACPI handle either from the ACPI device * directly under the parent that matches the either _HID or _CID, or * _ADR or it will use the parent handle if is no ID is given. * * Note that use of _ADR is a grey area in the ACPI specification, * though at least Intel Galileo Gen 2 is using it to distinguish * the children devices.
*/ if (match) { if (match->pnpid) { struct acpi_device_id ids[2] = {}; struct match_ids_walk_data wd = {
.adev = NULL,
.ids = ids,
};
/* Skip if OF node has previously been allocated to a device */
list_for_each_entry(of_entry, &mfd_of_node_list, list) if (of_entry->np == np) return -EAGAIN;
if (!cell->use_of_reg) /* No of_reg defined - allocate first free compatible match */ goto allocate_of_node;
/* We only care about each node's first defined address */ if (of_property_read_reg(np, 0, &of_node_addr, NULL)) /* OF node does not contatin a 'reg' property to match to */ return -EAGAIN;
if (cell->of_reg != of_node_addr) /* No match */ return -EAGAIN;
allocate_of_node:
of_entry = kzalloc(sizeof(*of_entry), GFP_KERNEL); if (!of_entry) return -ENOMEM;
if (!cell->ignore_resource_conflicts) { if (has_acpi_companion(&pdev->dev)) {
ret = acpi_check_resource_conflict(&res[r]); if (ret) goto fail_res_conflict;
}
}
}
ret = platform_device_add_resources(pdev, res, cell->num_resources); if (ret) goto fail_res_conflict;
ret = platform_device_add(pdev); if (ret) goto fail_res_conflict;
if (cell->pm_runtime_no_callbacks)
pm_runtime_no_callbacks(&pdev->dev);
/** * mfd_add_devices - register child devices * * @parent: Pointer to parent device. * @id: Can be PLATFORM_DEVID_AUTO to let the Platform API take care * of device numbering, or will be added to a device's cell_id. * @cells: Array of (struct mfd_cell)s describing child devices. * @n_devs: Number of child devices to register. * @mem_base: Parent register range resource for child devices. * @irq_base: Base of the range of virtual interrupt numbers allocated for * this MFD device. Unused if @domain is specified. * @domain: Interrupt domain to create mappings for hardware interrupts.
*/ int mfd_add_devices(struct device *parent, int id, conststruct mfd_cell *cells, int n_devs, struct resource *mem_base, int irq_base, struct irq_domain *domain)
{ int i; int ret;
for (i = 0; i < n_devs; i++) {
ret = mfd_add_device(parent, id, cells + i, mem_base,
irq_base, domain); if (ret) goto fail;
}
/** * devm_mfd_add_devices - Resource managed version of mfd_add_devices() * * Returns 0 on success or an appropriate negative error number on failure. * All child-devices of the MFD will automatically be removed when it gets * unbinded. * * @dev: Pointer to parent device. * @id: Can be PLATFORM_DEVID_AUTO to let the Platform API take care * of device numbering, or will be added to a device's cell_id. * @cells: Array of (struct mfd_cell)s describing child devices. * @n_devs: Number of child devices to register. * @mem_base: Parent register range resource for child devices. * @irq_base: Base of the range of virtual interrupt numbers allocated for * this MFD device. Unused if @domain is specified. * @domain: Interrupt domain to create mappings for hardware interrupts.
*/ int devm_mfd_add_devices(struct device *dev, int id, conststruct mfd_cell *cells, int n_devs, struct resource *mem_base, int irq_base, struct irq_domain *domain)
{ struct device **ptr; int ret;
ptr = devres_alloc(devm_mfd_dev_release, sizeof(*ptr), GFP_KERNEL); if (!ptr) return -ENOMEM;
ret = mfd_add_devices(dev, id, cells, n_devs, mem_base,
irq_base, domain); if (ret < 0) {
devres_free(ptr); return ret;
}
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.