User Tools

Site Tools


This is an old revision of the document!


Explain devm_ioremap_resource(), with examples. Add some links.

Let's talk about resources

struct resource

From include/linux/ioport.h, a device can have a number of resources of different types:

 * Resources are tree-like, allowing
 * nesting etc..
struct resource {
	resource_size_t start;
	resource_size_t end;
	const char *name;
	unsigned long flags;
	unsigned long desc;
	struct resource *parent, *sibling, *child;

A small sample of resource types from that same file (IORESOURCE_MEM is the one representing physical memory that many drivers are interested in):

#define IORESOURCE_BITS		0x000000ff	/* Bus-specific bits */

#define IORESOURCE_TYPE_BITS	0x00001f00	/* Resource type */
#define IORESOURCE_IO		0x00000100	/* PCI/ISA I/O ports */
#define IORESOURCE_MEM		0x00000200
#define IORESOURCE_REG		0x00000300	/* Register offsets */
#define IORESOURCE_IRQ		0x00000400
#define IORESOURCE_DMA		0x00000800
#define IORESOURCE_BUS		0x00001000
... snip ...

struct platform_device

From include/linux/platform_device.h:

struct platform_device {
	const char	*name;
	int		id;
	bool		id_auto;
	struct device	dev;            <--- wrapper around generic device
	u32		num_resources;
	struct resource	*resource;

	const struct platform_device_id	*id_entry;
	char *driver_override; /* Driver name to force a match */

	/* MFD cell pointer */
	struct mfd_cell *mfd_cell;

	/* arch specific additions */
	struct pdev_archdata	archdata;

From the same file:

#define to_platform_device(x) container_of((x), struct platform_device, dev)


From drivers/base/platform.c, given a platform device and a resource type, return that resource type or NULL:

 * platform_get_resource - get a resource for a device
 * @dev: platform device
 * @type: resource type
 * @num: resource index
struct resource *platform_get_resource(struct platform_device *dev,
				       unsigned int type, unsigned int num)
	int i;

	for (i = 0; i < dev->num_resources; i++) {
		struct resource *r = &dev->resource[i];

		if (type == resource_type(r) && num-- == 0)
			return r;
	return NULL;



Specifically map the memory resource of a (platform) device:

void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res);


 * devm_ioremap_resource() - check, request region, and ioremap resource
 * @dev: generic device to handle the resource for
 * @res: resource to be handled
 * Checks that a resource is a valid memory region, requests the memory
 * region and ioremaps it. All operations are managed and will be undone
 * on driver detach.
 * Returns a pointer to the remapped memory or an ERR_PTR() encoded error code
 * on failure. Usage example:
 *	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 *	base = devm_ioremap_resource(&pdev->dev, res);
 *	if (IS_ERR(base))
 *		return PTR_ERR(base);
void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res)
	resource_size_t size;
	const char *name;
	void __iomem *dest_ptr;


	if (!res || resource_type(res) != IORESOURCE_MEM) {
		dev_err(dev, "invalid resource\n");

	size = resource_size(res);
	name = res->name ?: dev_name(dev);

	if (!devm_request_mem_region(dev, res->start, size, name)) {
		dev_err(dev, "can't request region for resource %pR\n", res);

	dest_ptr = devm_ioremap(dev, res->start, size);
	if (!dest_ptr) {
		dev_err(dev, "ioremap failed for resource %pR\n", res);
		devm_release_mem_region(dev, res->start, size);
		dest_ptr = IOMEM_ERR_PTR(-ENOMEM);

	return dest_ptr;


Broadcom Cygnus


eth0: ethernet@18042000 {
        compatible = "brcm,amac";
        reg = <0x18042000 0x1000>,
              <0x18110000 0x1000>;
        reg-names = "amac_base", "idm_base";
        interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
        status = "disabled";


static const struct of_device_id bgmac_of_enet_match[] = {
        {.compatible = "brcm,amac",},
        {.compatible = "brcm,nsp-amac",},
        {.compatible = "brcm,ns2-amac",},

MODULE_DEVICE_TABLE(of, bgmac_of_enet_match);

static struct platform_driver bgmac_enet_driver = {
        .driver = {
                .name  = "bgmac-enet",
                .of_match_table = bgmac_of_enet_match,
                .pm = BGMAC_PM_OPS
        .probe = bgmac_probe,
        .remove = bgmac_remove,



regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "amac_base");
if (!regs) {
        dev_err(&pdev->dev, "Unable to obtain base resource\n");
        return -EINVAL;

bgmac->plat.base = devm_ioremap_resource(&pdev->dev, regs);
if (IS_ERR(bgmac->plat.base))
        return PTR_ERR(bgmac->plat.base);

regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "idm_base");
if (regs) {
        bgmac->plat.idm_base = devm_ioremap_resource(&pdev->dev, regs);
        if (IS_ERR(bgmac->plat.idm_base))
                return PTR_ERR(bgmac->plat.idm_base);
        bgmac->feature_flags &= ~BGMAC_FEAT_IDM_MASK;
devm_ioremap_resource.1532968803.txt.gz · Last modified: 2018/07/30 16:40 by rpjday