/* Probe for registered devices */ static int __devinit aes3_rx_of_probe(struct of_device *ofdev, const struct of_device_id *match) { struct resource r_mem_struct = {}; struct resource r_irq_struct[2] = {}; struct resource *addressRange = &r_mem_struct; struct resource *irq = r_irq_struct; struct resource *meter_irq = &r_irq_struct[0]; struct resource *aes_irq = &r_irq_struct[1]; struct platform_device *pdev = to_platform_device(&ofdev->dev); const char *name = ofdev->node->name; int rc = 0; /* Obtain the resources for this instance */ rc = of_address_to_resource(ofdev->node, 0, addressRange); if(rc) { printk(KERN_ERR "%s : No address found in device tree\n", name); return(rc); } rc = of_irq_to_resource(ofdev->node, 0, meter_irq); if(rc == NO_IRQ) { printk(KERN_ERR "%s : No metering IRQ found in device tree\n", name); return(rc); } rc = of_irq_to_resource(ofdev->node, 1, aes_irq); if(rc == NO_IRQ) { printk(KERN_ERR "%s : No channel IRQ found in device tree\n", name); return(rc); } /* Dispatch to the generic function */ return(aes3_rx_probe(name, pdev, addressRange, irq, NULL, NULL, NULL)); }
static inline int mscan_get_config(unsigned long *addr, unsigned int *irq) { #if defined(CONFIG_PPC_MERGE) || LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27) /* Use Open Firmware device tree */ struct device_node *np = NULL; unsigned int i; int ret; for (i = 0; i < RTCAN_MSCAN_DEVS; i++) { struct resource r[2] = {}; np = of_find_compatible_node(np, NULL, "fsl,mpc5200-mscan"); if (np == NULL) np = of_find_compatible_node(np, NULL, "mpc5200-mscan"); if (np == NULL) break; ret = of_address_to_resource(np, 0, &r[0]); if (ret) return ret; of_irq_to_resource(np, 0, &r[1]); addr[i] = r[0].start; irq[i] = r[1].start; rtcan_mscan_count++; } #else addr[0] = MSCAN_CAN1_ADDR; irq[0] = MSCAN_CAN1_IRQ; addr[1] = MSCAN_CAN2_ADDR; irq[1] = MSCAN_CAN2_IRQ; rtcan_mscan_count = 2; #endif return 0; }
/* Probe for registered devices */ static int __devinit mailbox_of_probe(struct of_device *ofdev, const struct of_device_id *match) { struct resource r_mem_struct = {}; struct resource r_irq_struct = {}; struct resource *addressRange = &r_mem_struct; struct resource *irq = &r_irq_struct; struct platform_device *pdev = to_platform_device(&ofdev->dev); const char *name = dev_name(&ofdev->dev); int rc = 0; /* Obtain the resources for this instance */ rc = of_address_to_resource(ofdev->node, 0, addressRange); if(rc) { dev_warn(&ofdev->dev, "Invalid address\n"); return(rc); } rc = of_irq_to_resource(ofdev->node, 0, irq); if(rc == NO_IRQ) { /* No IRQ was defined; null the resource pointer to indicate polled mode */ irq = NULL; return(rc); } /* Dispatch to the generic function */ return(mailbox_probe(name, pdev, addressRange, irq)); }
static int __devinit xilinx_iic_of_probe(struct platform_device *ofdev, const struct of_device_id *match) { u32 ten_bit_addr, gpo_width; struct resource r_irq_struct; struct resource r_mem_struct; struct resource *r_irq = &r_irq_struct; /* Interrupt resources */ struct resource *r_mem = &r_mem_struct; /* IO mem resources */ int rc = 0; printk(KERN_INFO "Device Tree Probing \'%s\'\n", ofdev->dev.of_node->name); /* Get iospace for the device */ rc = of_address_to_resource(ofdev->dev.of_node, 0, r_mem); if(rc) { dev_warn(&ofdev->dev, "invalid address\n"); return rc; } /* Get IRQ for the device */ rc = of_irq_to_resource(ofdev->dev.of_node, 0, r_irq); if(!rc) { dev_warn(&ofdev->dev, "no IRQ found.\n"); return rc; } ten_bit_addr = get_u32(ofdev, "xlnx,ten-bit-adr"); gpo_width = get_u32(ofdev, "xlnx,gpo-width"); return xilinx_iic_setup(&ofdev->dev, ofdev->dev.of_node, r_mem, r_irq, ten_bit_addr, gpo_width); }
static int __devinit xps2_of_probe(struct of_device *ofdev, const struct of_device_id *match) { struct resource r_irq_struct; struct resource r_mem_struct; struct resource *r_irq = &r_irq_struct; /* Interrupt resources */ struct resource *r_mem = &r_mem_struct; /* IO mem resources */ int rc = 0; const unsigned int *id; printk(KERN_INFO "Device Tree Probing \'%s\'\n", ofdev->node->name); /* Get iospace for the device */ rc = of_address_to_resource(ofdev->node, 0, r_mem); if(rc) { dev_warn(&ofdev->dev, "invalid address\n"); return rc; } /* Get IRQ for the device */ rc = of_irq_to_resource(ofdev->node, 0, r_irq); if(rc == NO_IRQ) { dev_warn(&ofdev->dev, "no IRQ found.\n"); return rc; } id = of_get_property(ofdev->node, "port-number", NULL); return xps2_setup(&ofdev->dev, id ? *id : -1, r_mem, r_irq); }
static inline int mscan_get_config(unsigned long *addr, unsigned int *irq) { /* Use Open Firmware device tree */ struct device_node *np = NULL; unsigned int i; int ret; for (i = 0; i < RTCAN_MSCAN_DEVS; i++) { struct resource r[2] = {}; np = of_find_compatible_node(np, NULL, "fsl,mpc5200-mscan"); if (np == NULL) np = of_find_compatible_node(np, NULL, "mpc5200-mscan"); if (np == NULL) break; ret = of_address_to_resource(np, 0, &r[0]); if (ret) return ret; of_irq_to_resource(np, 0, &r[1]); addr[i] = r[0].start; irq[i] = r[1].start; rtcan_mscan_count++; } return 0; }
static int wsa_map_irq(struct wsa_resource *wsa_res, int irq) { if (wsa_res == NULL) { pr_err("%s: wsa_res is NULL\n", __func__); return -EINVAL; } return of_irq_to_resource(wsa_res->dev->of_node, irq, NULL); }
int of_irq_count(struct device_node *dev) { int nr = 0; while (of_irq_to_resource(dev, nr, NULL)) nr++; return nr; }
/** * of_irq_to_resource_table - Fill in resource table with node's IRQ info * @dev: pointer to device tree node * @res: array of resources to fill in * @nr_irqs: the number of IRQs (and upper bound for num of @res elements) * * Returns the size of the filled in table (up to @nr_irqs). */ int of_irq_to_resource_table(struct device_node *dev, struct resource *res, int nr_irqs) { int i; for (i = 0; i < nr_irqs; i++, res++) if (!of_irq_to_resource(dev, i, res)) break; return i; }
static int __init fsl_i2c_of_init(void) { struct device_node *np; unsigned int i; struct platform_device *i2c_dev; int ret; for (np = NULL, i = 0; (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL; i++) { struct resource r[2]; struct fsl_i2c_platform_data i2c_data; const unsigned char *flags = NULL; memset(&r, 0, sizeof(r)); memset(&i2c_data, 0, sizeof(i2c_data)); ret = of_address_to_resource(np, 0, &r[0]); if (ret) goto err; of_irq_to_resource(np, 0, &r[1]); i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); if (IS_ERR(i2c_dev)) { ret = PTR_ERR(i2c_dev); goto err; } i2c_data.device_flags = 0; flags = of_get_property(np, "dfsrr", NULL); if (flags) i2c_data.device_flags |= FSL_I2C_DEV_SEPARATE_DFSRR; flags = of_get_property(np, "fsl5200-clocking", NULL); if (flags) i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200; ret = platform_device_add_data(i2c_dev, &i2c_data, sizeof(struct fsl_i2c_platform_data)); if (ret) goto unreg; } return 0; unreg: platform_device_unregister(i2c_dev); err: return ret; }
static int __devinit xilinx_spi_of_probe(struct of_device *ofdev, const struct of_device_id *match) { struct spi_master *master; struct xspi_platform_data *pdata; struct resource r_mem; struct resource r_irq; int rc = 0; const u32 *prop; int len; rc = of_address_to_resource(ofdev->node, 0, &r_mem); if (rc) { dev_warn(&ofdev->dev, "invalid address\n"); return rc; } rc = of_irq_to_resource(ofdev->node, 0, &r_irq); if (rc == NO_IRQ) { dev_warn(&ofdev->dev, "no IRQ found\n"); return -ENODEV; } ofdev->dev.platform_data = kzalloc(sizeof(struct xspi_platform_data), GFP_KERNEL); pdata = ofdev->dev.platform_data; if (!pdata) return -ENOMEM; /* number of slave select bits is required */ prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len); if (!prop || len < sizeof(*prop)) { dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n"); return -EINVAL; } pdata->num_chipselect = *prop; pdata->bits_per_word = 8; master = xilinx_spi_init(&ofdev->dev, &r_mem, r_irq.start, -1); if (!master) return -ENODEV; dev_set_drvdata(&ofdev->dev, master); /* Add any subnodes on the SPI bus */ of_register_spi_devices(master, ofdev->node); return 0; }
static void __devinit add_phy(struct mii_bus *bus, struct device_node *np) { const u32 *data; int len, id, irq; data = of_get_property(np, "reg", &len); if (!data || len != 4) return; id = *data; bus->phy_mask &= ~(1 << id); irq = of_irq_to_resource(np, 0, NULL); if (irq != NO_IRQ) bus->irq[id] = irq; }
static int do_pd_setup(struct fs_enet_private *fep) { struct of_device *ofdev = to_of_device(fep->dev); fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL); if (fep->interrupt == NO_IRQ) return -EINVAL; fep->scc.sccp = of_iomap(ofdev->node, 0); if (!fep->scc.sccp) return -EINVAL; fep->scc.ep = of_iomap(ofdev->node, 1); if (!fep->scc.ep) { iounmap(fep->scc.sccp); return -EINVAL; } return 0; }
static int do_pd_setup(struct fs_enet_private *fep) { struct of_device *ofdev = to_of_device(fep->dev); struct fs_platform_info *fpi = fep->fpi; int ret = -EINVAL; fep->interrupt = of_irq_to_resource(ofdev->node, 0, NULL); if (fep->interrupt == NO_IRQ) goto out; fep->fcc.fccp = of_iomap(ofdev->node, 0); if (!fep->fcc.fccp) goto out; fep->fcc.ep = of_iomap(ofdev->node, 1); if (!fep->fcc.ep) goto out_fccp; fep->fcc.fcccp = of_iomap(ofdev->node, 2); if (!fep->fcc.fcccp) goto out_ep; fep->fcc.mem = (void __iomem *)cpm2_immr; fpi->dpram_offset = cpm_dpalloc(128, 8); if (IS_ERR_VALUE(fpi->dpram_offset)) { ret = fpi->dpram_offset; goto out_fcccp; } return 0; out_fcccp: iounmap(fep->fcc.fcccp); out_ep: iounmap(fep->fcc.ep); out_fccp: iounmap(fep->fcc.fccp); out: return ret; }
static int __devinit xps2_of_probe(struct platform_device *ofdev) { struct resource r_irq; struct resource r_mem; struct xps2data *drvdata; struct serio *serio; struct device *dev = &ofdev->dev; resource_size_t remap_size, phys_addr; int error; dev_info(dev, "Device Tree Probing \'%s\'\n", ofdev->dev.of_node->name); error = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem); if (error) { dev_err(dev, "invalid address\n"); return error; } if (!of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq)) { dev_err(dev, "no IRQ found\n"); return -ENODEV; } drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL); if (!drvdata) { dev_err(dev, "Couldn't allocate device private record\n"); return -ENOMEM; } dev_set_drvdata(dev, drvdata); spin_lock_init(&drvdata->lock); drvdata->irq = r_irq.start; phys_addr = r_mem.start; remap_size = resource_size(&r_mem); if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) { dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", (unsigned long long)phys_addr); error = -EBUSY; goto failed1; } drvdata->base_address = ioremap(phys_addr, remap_size); if (drvdata->base_address == NULL) { dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", (unsigned long long)phys_addr); error = -EFAULT; goto failed2; } out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0); out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET); dev_info(dev, "Xilinx PS2 at 0x%08llX mapped to 0x%p, irq=%d\n", (unsigned long long)phys_addr, drvdata->base_address, drvdata->irq); serio = &drvdata->serio; serio->id.type = SERIO_8042; serio->write = sxps2_write; serio->open = sxps2_open; serio->close = sxps2_close; serio->port_data = drvdata; serio->dev.parent = dev; snprintf(serio->name, sizeof(serio->name), "Xilinx XPS PS/2 at %08llX", (unsigned long long)phys_addr); snprintf(serio->phys, sizeof(serio->phys), "xilinxps2/serio at %08llX", (unsigned long long)phys_addr); serio_register_port(serio); return 0; failed2: release_mem_region(phys_addr, remap_size); failed1: kfree(drvdata); dev_set_drvdata(dev, NULL); return error; }
/* * Probe routine for each detected JobR subsystem. It assumes that * property detection was picked up externally. */ int caam_jr_probe(struct platform_device *pdev, struct device_node *np, int ring) { struct device *ctrldev, *jrdev; struct platform_device *jr_pdev; struct caam_drv_private *ctrlpriv; struct caam_drv_private_jr *jrpriv; int error; /* FIXME: perhaps "struct resource *" for OF and non? */ u32 *jroffset, *irqres; #ifndef CONFIG_OF char *rname, rinst; #endif ctrldev = &pdev->dev; ctrlpriv = dev_get_drvdata(ctrldev); jrpriv = kmalloc(sizeof(struct caam_drv_private_jr), GFP_KERNEL); if (jrpriv == NULL) { dev_err(ctrldev, "can't alloc private mem for job ring %d\n", ring); return -ENOMEM; } jrpriv->parentdev = ctrldev; /* point back to parent */ jrpriv->ridx = ring; /* save ring identity relative to detection */ /* * Derive a pointer to the detected JobRs regs * Driver has already iomapped the entire space, we just * need to add in the offset to this JobR. Don't know if I * like this long-term, but it'll run */ #ifdef CONFIG_OF jroffset = (u32 *)of_get_property(np, "reg", NULL); #else rname = kmalloc(strlen(JR_MEMRES_NAME_ROOT) + 1, 0); if (rname == NULL) { dev_err(ctrldev, "can't alloc resource detection buffer %d\n", ring); kfree(jrpriv); return -ENOMEM; } rname[0] = 0; rinst = '0' + ring; strcat(rname, JR_MEMRES_NAME_ROOT); strncat(rname, &rinst, 1); jroffset = (u32 *)platform_get_resource_byname(pdev, IORESOURCE_MEM, rname); kfree(rname); #endif jrpriv->rregs = (struct caam_job_ring __iomem *)((void *)ctrlpriv->ctrl + *jroffset); /* Build a local dev for each detected queue */ #ifdef CONFIG_OF jr_pdev = of_platform_device_create(np, NULL, ctrldev); #else jr_pdev = platform_device_register_data(ctrldev, "caam_jr", ring, jrpriv, sizeof(struct caam_drv_private_jr)); #endif if (jr_pdev == NULL) { kfree(jrpriv); return -EINVAL; } jrdev = &jr_pdev->dev; dev_set_drvdata(jrdev, jrpriv); ctrlpriv->jrdev[ring] = jrdev; /* Identify the interrupt */ #ifdef CONFIG_OF jrpriv->irq = of_irq_to_resource(np, 0, NULL); #else rname = kmalloc(strlen(JR_IRQRES_NAME_ROOT) + 1, 0); if (rname == NULL) { dev_err(ctrldev, "can't alloc resource detection buffer %d\n", ring); kfree(jrpriv); return -ENOMEM; } rname[0] = 0; strcat(rname, JR_IRQRES_NAME_ROOT); strncat(rname, &rinst, 1); irqres = (u32 *)platform_get_resource_byname(pdev, IORESOURCE_IRQ, rname); jrpriv->irq = *irqres; kfree(rname); #endif /* Now do the platform independent part */ error = caam_jr_init(jrdev); /* now turn on hardware */ if (error) { kfree(jrpriv); return error; } return error; }
static int cpm_uart_init_port(struct device_node *np, struct uart_cpm_port *pinfo) { const u32 *data; void __iomem *mem, *pram; int len; int ret; int i; data = of_get_property(np, "clock", NULL); if (data) { struct clk *clk = clk_get(NULL, (const char*)data); if (!IS_ERR(clk)) pinfo->clk = clk; } if (!pinfo->clk) { data = of_get_property(np, "fsl,cpm-brg", &len); if (!data || len != 4) { printk(KERN_ERR "CPM UART %s has no/invalid " "fsl,cpm-brg property.\n", np->name); return -EINVAL; } pinfo->brg = *data; } data = of_get_property(np, "fsl,cpm-command", &len); if (!data || len != 4) { printk(KERN_ERR "CPM UART %s has no/invalid " "fsl,cpm-command property.\n", np->name); return -EINVAL; } pinfo->command = *data; mem = of_iomap(np, 0); if (!mem) return -ENOMEM; if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") || of_device_is_compatible(np, "fsl,cpm2-scc-uart")) { pinfo->sccp = mem; pinfo->sccup = pram = cpm_uart_map_pram(pinfo, np); } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") || of_device_is_compatible(np, "fsl,cpm2-smc-uart")) { pinfo->flags |= FLAG_SMC; pinfo->smcp = mem; pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np); } else { ret = -ENODEV; goto out_mem; } if (!pram) { ret = -ENOMEM; goto out_mem; } pinfo->tx_nrfifos = TX_NUM_FIFO; pinfo->tx_fifosize = TX_BUF_SIZE; pinfo->rx_nrfifos = RX_NUM_FIFO; pinfo->rx_fifosize = RX_BUF_SIZE; pinfo->port.uartclk = ppc_proc_freq; pinfo->port.mapbase = (unsigned long)mem; pinfo->port.type = PORT_CPM; pinfo->port.ops = &cpm_uart_pops, pinfo->port.iotype = UPIO_MEM; pinfo->port.fifosize = pinfo->tx_nrfifos * pinfo->tx_fifosize; spin_lock_init(&pinfo->port.lock); pinfo->port.irq = of_irq_to_resource(np, 0, NULL); if (pinfo->port.irq == NO_IRQ) { ret = -EINVAL; goto out_pram; } for (i = 0; i < NUM_GPIOS; i++) pinfo->gpios[i] = of_get_gpio(np, i); return cpm_uart_request_port(&pinfo->port); out_pram: cpm_uart_unmap_pram(pinfo, pram); out_mem: iounmap(mem); return ret; }
static int wcd9xxx_map_irq(struct wcd9xxx_core_resource *wcd9xxx_res, int irq) { return of_irq_to_resource(wcd9xxx_res->dev->of_node, irq, NULL); }
static int __init cpm_uart_of_init(void) { struct device_node *np; unsigned int i; struct platform_device *cpm_uart_dev; int ret; for (np = NULL, i = 0; (np = of_find_compatible_node(np, "serial", "cpm_uart")) != NULL; i++) { struct resource r[3]; struct fs_uart_platform_info cpm_uart_data; const int *id; const char *model; memset(r, 0, sizeof(r)); memset(&cpm_uart_data, 0, sizeof(cpm_uart_data)); ret = of_address_to_resource(np, 0, &r[0]); if (ret) goto err; r[0].name = scc_regs; ret = of_address_to_resource(np, 1, &r[1]); if (ret) goto err; r[1].name = scc_pram; of_irq_to_resource(np, 0, &r[2]); cpm_uart_dev = platform_device_register_simple("fsl-cpm-scc:uart", i, &r[0], 3); if (IS_ERR(cpm_uart_dev)) { ret = PTR_ERR(cpm_uart_dev); goto err; } id = of_get_property(np, "device-id", NULL); cpm_uart_data.fs_no = *id; model = of_get_property(np, "model", NULL); strcpy(cpm_uart_data.fs_type, model); cpm_uart_data.uart_clk = ppc_proc_freq; cpm_uart_data.tx_num_fifo = 4; cpm_uart_data.tx_buf_size = 32; cpm_uart_data.rx_num_fifo = 4; cpm_uart_data.rx_buf_size = 32; cpm_uart_data.clk_rx = *((u32 *)of_get_property(np, "rx-clock", NULL)); cpm_uart_data.clk_tx = *((u32 *)of_get_property(np, "tx-clock", NULL)); ret = platform_device_add_data(cpm_uart_dev, &cpm_uart_data, sizeof(struct fs_uart_platform_info)); if (ret) goto unreg; } return 0; unreg: platform_device_unregister(cpm_uart_dev); err: return ret; }
static int __init mv64x60_eth_device_setup(struct device_node *np, int id) { struct resource r[1]; struct mv643xx_eth_platform_data pdata; struct platform_device *pdev; struct device_node *phy; const u8 *mac_addr; const int *prop; const phandle *ph; int err; /* only register the shared platform device the first time through */ if (id == 0 && (err = eth_register_shared_pdev(np))) return err;; memset(r, 0, sizeof(r)); of_irq_to_resource(np, 0, &r[0]); memset(&pdata, 0, sizeof(pdata)); prop = of_get_property(np, "block-index", NULL); if (!prop) return -ENODEV; pdata.port_number = *prop; mac_addr = of_get_mac_address(np); if (mac_addr) memcpy(pdata.mac_addr, mac_addr, 6); prop = of_get_property(np, "speed", NULL); if (prop) pdata.speed = *prop; prop = of_get_property(np, "tx_queue_size", NULL); if (prop) pdata.tx_queue_size = *prop; prop = of_get_property(np, "rx_queue_size", NULL); if (prop) pdata.rx_queue_size = *prop; prop = of_get_property(np, "tx_sram_addr", NULL); if (prop) pdata.tx_sram_addr = *prop; prop = of_get_property(np, "tx_sram_size", NULL); if (prop) pdata.tx_sram_size = *prop; prop = of_get_property(np, "rx_sram_addr", NULL); if (prop) pdata.rx_sram_addr = *prop; prop = of_get_property(np, "rx_sram_size", NULL); if (prop) pdata.rx_sram_size = *prop; ph = of_get_property(np, "phy", NULL); if (!ph) return -ENODEV; phy = of_find_node_by_phandle(*ph); if (phy == NULL) return -ENODEV; prop = of_get_property(phy, "reg", NULL); if (prop) { pdata.force_phy_addr = 1; pdata.phy_addr = *prop; } of_node_put(phy); pdev = platform_device_alloc(MV643XX_ETH_NAME, pdata.port_number); if (!pdev) return -ENOMEM; err = platform_device_add_resources(pdev, r, 1); if (err) goto error; err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); if (err) goto error; err = platform_device_add(pdev); if (err) goto error; return 0; error: platform_device_put(pdev); return err; }
/*####modified for marvell-bg2*/ static int drv_get_dts_for_gpu(void) { struct device_node *np; struct resource res; int rc = 0; u32 value; /* get the gpu3d information */ np = of_find_compatible_node(NULL, NULL, "marvell,berlin-gpu3d"); if (!np) { printk("gpu error: of_find_compatible_node for berlin-gpu3d failed!\n"); goto err_exit; } /* get the reg section */ rc = of_address_to_resource(np, 0, &res); if (rc) { printk("gpu warning: of_address_to_resource for berlin-gpu3d failed!\n"); } else { registerMemBase = res.start; registerMemSize = resource_size(&res); } /* get the interrupt section */ rc = of_irq_to_resource(np, 0, &res); if (!rc) { printk("gpu warning: of_irq_to_resource for berlin-gpu3d failed, rc=%d!\n", rc); } else { irqLine = rc; } /* get the nonsecure-mem-base section */ rc = of_property_read_u32(np, "marvell,nonsecure-mem-base", &value); if (rc) { printk("gpu warning: of_property_read_u32 for nonsecure-mem-base failed!\n"); } else { contiguousBase = value; } /* get the nonsecure-mem-size section */ rc = of_property_read_u32(np, "marvell,nonsecure-mem-size", &value); if (rc) { printk("gpu warning: of_property_read_u32 for nonsecure-mem-size failed!\n"); } else { contiguousSize = value; } /* get the phy-mem-size section */ rc = of_property_read_u32(np, "marvell,phy-mem-size", &value); if (rc) { printk("gpu warning: of_property_read_u32 for phy-mem-size failed!\n"); } else { physSize = value; } /* get the 3D clock registers and corresponding bitfields */ rc = of_property_read_u32(np, "marvell,core-clock-register", &value); if (rc) { printk("gpu warning: of_property_read_u32 for 3D core-clock-register failed!\n"); coreClkRegister3D = 0; } else { coreClkRegister3D = value; } rc = of_property_read_u32(np, "marvell,sys-clock-register", &value); if (rc) { printk("gpu warning: of_property_read_u32 for 3D sys-clock-register failed!\n"); sysClkRegister3D = 0; } else { sysClkRegister3D = value; } rc = of_property_read_u32(np, "marvell,core-clock-bitfield", &value); if (rc) { printk("gpu warning: of_property_read_u32 for 3D core-clock-bitfield failed!\n"); coreClkBitfield3D = 0; } else { coreClkBitfield3D = value; } rc = of_property_read_u32(np, "marvell,sys-clock-bitfield", &value); if (rc) { printk("gpu warning: of_property_read_u32 for 3D sys-clock-bitfield failed!\n"); sysClkBitfield3D = 0; } else { sysClkBitfield3D = value; } of_node_put(np); /* get the gpu2d information */ np = of_find_compatible_node(NULL, NULL, "marvell,berlin-gpu2d"); if (!np) { /* no 2d gpu, just goto exit */ goto err_exit; } /* get the reg section */ rc = of_address_to_resource(np, 0, &res); if (rc) { printk("gpu warning: of_address_to_resource for berlin-gpu2d failed!\n"); } else { registerMemBase2D = res.start; registerMemSize2D = resource_size(&res); } /* get the interrupt section */ rc = of_irq_to_resource(np, 0, &res); if (!rc) { printk("gpu warning: of_irq_to_resource for berlin-gpu2d failed!\n"); } else { irqLine2D = rc; } /* get 2D core clock register and corresponding bitfield */ rc = of_property_read_u32(np, "marvell,core-clock-register", &value); if (rc) { printk("gpu warning: of_property_read_u32 for 2D core-clock-register failed!\n"); coreClkRegister2D = 0; } else { coreClkRegister2D = value; } rc = of_property_read_u32(np, "marvell,core-clock-bitfield", &value); if (rc) { printk("gpu warning: of_property_read_u32 for 2D core-clock-bitfield failed!\n"); coreClkBitfield2D = 0; } else { coreClkBitfield2D = value; } of_node_put(np); return 0; err_exit: return -1; }
static int __init mv64x60_mpsc_device_setup(struct device_node *np, int id) { struct resource r[5]; struct mpsc_pdata pdata; struct platform_device *pdev; const unsigned int *prop; const phandle *ph; struct device_node *sdma, *brg; int err; int port_number; /* only register the shared platform device the first time through */ if (id == 0 && (err = mv64x60_mpsc_register_shared_pdev(np))) return err; memset(r, 0, sizeof(r)); err = of_address_to_resource(np, 0, &r[0]); if (err) return err; of_irq_to_resource(np, 0, &r[4]); ph = of_get_property(np, "sdma", NULL); sdma = of_find_node_by_phandle(*ph); if (!sdma) return -ENODEV; of_irq_to_resource(sdma, 0, &r[3]); err = of_address_to_resource(sdma, 0, &r[1]); of_node_put(sdma); if (err) return err; ph = of_get_property(np, "brg", NULL); brg = of_find_node_by_phandle(*ph); if (!brg) return -ENODEV; err = of_address_to_resource(brg, 0, &r[2]); of_node_put(brg); if (err) return err; prop = of_get_property(np, "block-index", NULL); if (!prop) return -ENODEV; port_number = *(int *)prop; memset(&pdata, 0, sizeof(pdata)); pdata.cache_mgmt = 1; /* All current revs need this set */ prop = of_get_property(np, "max_idle", NULL); if (prop) pdata.max_idle = *prop; prop = of_get_property(brg, "current-speed", NULL); if (prop) pdata.default_baud = *prop; /* Default is 8 bits, no parity, no flow control */ pdata.default_bits = 8; pdata.default_parity = 'n'; pdata.default_flow = 'n'; prop = of_get_property(np, "chr_1", NULL); if (prop) pdata.chr_1_val = *prop; prop = of_get_property(np, "chr_2", NULL); if (prop) pdata.chr_2_val = *prop; prop = of_get_property(np, "chr_10", NULL); if (prop) pdata.chr_10_val = *prop; prop = of_get_property(np, "mpcr", NULL); if (prop) pdata.mpcr_val = *prop; prop = of_get_property(brg, "bcr", NULL); if (prop) pdata.bcr_val = *prop; pdata.brg_can_tune = 1; /* All current revs need this set */ prop = of_get_property(brg, "clock-src", NULL); if (prop) pdata.brg_clk_src = *prop; prop = of_get_property(brg, "clock-frequency", NULL); if (prop) pdata.brg_clk_freq = *prop; pdev = platform_device_alloc(MPSC_CTLR_NAME, port_number); if (!pdev) return -ENOMEM; err = platform_device_add_resources(pdev, r, 5); if (err) goto error; err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); if (err) goto error; err = platform_device_add(pdev); if (err) goto error; return 0; error: platform_device_put(pdev); return err; }
/* * Create mv64x60_i2c platform devices */ static int __init mv64x60_i2c_device_setup(struct device_node *np, int id) { struct resource r[2]; struct platform_device *pdev; struct mv64xxx_i2c_pdata pdata; const unsigned int *prop; int err; memset(r, 0, sizeof(r)); err = of_address_to_resource(np, 0, &r[0]); if (err) return err; of_irq_to_resource(np, 0, &r[1]); memset(&pdata, 0, sizeof(pdata)); prop = of_get_property(np, "freq_m", NULL); if (!prop) return -ENODEV; pdata.freq_m = *prop; prop = of_get_property(np, "freq_n", NULL); if (!prop) return -ENODEV; pdata.freq_n = *prop; prop = of_get_property(np, "timeout", NULL); if (prop) pdata.timeout = *prop; else pdata.timeout = 1000; /* 1 second */ prop = of_get_property(np, "retries", NULL); if (prop) pdata.retries = *prop; else pdata.retries = 1; pdev = platform_device_alloc(MV64XXX_I2C_CTLR_NAME, id); if (!pdev) return -ENOMEM; err = platform_device_add_resources(pdev, r, 2); if (err) goto error; err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); if (err) goto error; err = platform_device_add(pdev); if (err) goto error; return 0; error: platform_device_put(pdev); return err; }
/// /// Probe device parameters from OF device tree /// /// This also involves allocating the osif_dev structs for our devices, and /// initializing them. /// int __devinit osif_of_probe( struct of_device *ofdev, const struct of_device_id *match) { struct osif_dev *osif_inst; struct resource r_irq_struct; struct resource *r_irq = &r_irq_struct; int start; int result = 0; PDEBUG("of_probe %s\n", ofdev->node->full_name); if(!strcmp(ofdev->node->name,"tlb")){ start = dcr_resource_start(ofdev->node, 0); PDEBUG("Found TLB @ %u\n", start); reconos_tlb_dcrn = start; return 0; } PDEBUG("probing IRQ\n"); // lookup interrupt number result = of_irq_to_resource(ofdev->node, 0, r_irq); if(result == NO_IRQ) { printk( KERN_WARNING "osif: no IRQ found.\n"); goto fail; } PDEBUG("IRQ = %lu\n", (unsigned long)r_irq->start); // allocate device data (TODO: does this need to be thread-safe?) osif_inst = kmalloc(sizeof(struct osif_dev), GFP_KERNEL); if (!osif_inst) { result = -ENOMEM; goto fail; /* Make this more graceful */ } memset(osif_inst, 0, sizeof(struct osif_dev)); PDEBUG("probing DCR\n"); // lookup dcr base address start = dcr_resource_start(ofdev->node, 0); osif_inst->dcr_len = dcr_resource_len(ofdev->node, 0); osif_inst->dcr_host = dcr_map(ofdev->node, start, osif_inst->dcr_len); if (!DCR_MAP_OK(osif_inst->dcr_host)) { printk( KERN_ERR "osif: invalid dcr address\n" ); result = -ENODEV; goto fail1; } PDEBUG("DCR from %u, len %u\n", start, osif_inst->dcr_len); // register device data with device dev_set_drvdata(&ofdev->dev, osif_inst); /* Initialize device data */ osif_inst->slot_num = osif_counter++; // FIXME: can we extract this from ofdev? // request interrupt result = request_irq(r_irq->start, osif_interrupt, 0, "osif", osif_inst); if (result) { printk(KERN_WARNING "osif: can't get assigned IRQ %lu\n", (unsigned long)r_irq->start); goto fail2; } osif_inst->irq = r_irq->start; osif_inst->next_read = 0; init_waitqueue_head(&osif_inst->read_queue); osif_inst->irq_count = 0; init_MUTEX(&osif_inst->sem); osif_setup_cdev(osif_inst, osif_inst->slot_num); // FIXME minor number // TODO: add to some kind of list for later reference? // or is the reference via the filp->private_data (in open()) and // the dev_set_drvdata() enough? return 0; fail2: dcr_unmap(osif_inst->dcr_host, osif_inst->dcr_len); fail1: kfree(osif_inst); fail: return result; }
/* The probe function for a single message register block. */ static __devinit int mpic_msgr_probe(struct platform_device *dev) { void __iomem *msgr_block_addr; int block_number; struct resource rsrc; unsigned int i; unsigned int irq_index; struct device_node *np = dev->dev.of_node; unsigned int receive_mask; const unsigned int *prop; if (!np) { dev_err(&dev->dev, "Device OF-Node is NULL"); return -EFAULT; } /* Allocate the message register array upon the first device * registered. */ if (!mpic_msgrs) { mpic_msgr_count = mpic_msgr_number_of_registers(); dev_info(&dev->dev, "Found %d message registers\n", mpic_msgr_count); mpic_msgrs = kzalloc(sizeof(struct mpic_msgr) * mpic_msgr_count, GFP_KERNEL); if (!mpic_msgrs) { dev_err(&dev->dev, "No memory for message register blocks\n"); return -ENOMEM; } } dev_info(&dev->dev, "Of-device full name %s\n", np->full_name); /* IO map the message register block. */ of_address_to_resource(np, 0, &rsrc); msgr_block_addr = ioremap(rsrc.start, rsrc.end - rsrc.start); if (!msgr_block_addr) { dev_err(&dev->dev, "Failed to iomap MPIC message registers"); return -EFAULT; } /* Ensure the block has a defined order. */ block_number = mpic_msgr_block_number(np); if (block_number < 0) { dev_err(&dev->dev, "Failed to find message register block alias\n"); return -ENODEV; } dev_info(&dev->dev, "Setting up message register block %d\n", block_number); /* Grab the receive mask which specifies what registers can receive * interrupts. */ prop = of_get_property(np, "mpic-msgr-receive-mask", NULL); receive_mask = (prop) ? *prop : 0xF; /* Build up the appropriate message register data structures. */ for (i = 0, irq_index = 0; i < MPIC_MSGR_REGISTERS_PER_BLOCK; ++i) { struct mpic_msgr *msgr; unsigned int reg_number; msgr = kzalloc(sizeof(struct mpic_msgr), GFP_KERNEL); if (!msgr) { dev_err(&dev->dev, "No memory for message register\n"); return -ENOMEM; } reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i; msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE; msgr->mer = (u32 *)((u8 *)msgr->base + MPIC_MSGR_MER_OFFSET); msgr->in_use = MSGR_FREE; msgr->num = i; raw_spin_lock_init(&msgr->lock); if (receive_mask & (1 << i)) { struct resource irq; if (of_irq_to_resource(np, irq_index, &irq) == NO_IRQ) { dev_err(&dev->dev, "Missing interrupt specifier"); kfree(msgr); return -EFAULT; } msgr->irq = irq.start; irq_index += 1; } else { msgr->irq = NO_IRQ; } mpic_msgrs[reg_number] = msgr; mpic_msgr_disable(msgr); dev_info(&dev->dev, "Register %d initialized: irq %d\n", reg_number, msgr->irq); } return 0; }
/** * xps2_of_probe - probe method for the PS/2 device. * @of_dev: pointer to OF device structure * @match: pointer to the structure used for matching a device * * This function probes the PS/2 device in the device tree. * It initializes the driver data structure and the hardware. * It returns 0, if the driver is bound to the PS/2 device, or a negative * value if there is an error. */ static int __devinit xps2_of_probe(struct platform_device *ofdev) { struct resource r_irq; /* Interrupt resources */ struct resource r_mem; /* IO mem resources */ struct xps2data *drvdata; struct serio *serio; struct device *dev = &ofdev->dev; resource_size_t remap_size, phys_addr; int error; dev_info(dev, "Device Tree Probing \'%s\'\n", ofdev->dev.of_node->name); /* Get iospace for the device */ error = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem); if (error) { dev_err(dev, "invalid address\n"); return error; } /* Get IRQ for the device */ if (of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq) == NO_IRQ) { dev_err(dev, "no IRQ found\n"); return -ENODEV; } drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL); if (!drvdata) { dev_err(dev, "Couldn't allocate device private record\n"); return -ENOMEM; } dev_set_drvdata(dev, drvdata); spin_lock_init(&drvdata->lock); drvdata->irq = r_irq.start; phys_addr = r_mem.start; remap_size = resource_size(&r_mem); if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) { dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", (unsigned long long)phys_addr); error = -EBUSY; goto failed1; } /* Fill in configuration data and add them to the list */ drvdata->base_address = ioremap(phys_addr, remap_size); if (drvdata->base_address == NULL) { dev_err(dev, "Couldn't ioremap memory at 0x%08llX\n", (unsigned long long)phys_addr); error = -EFAULT; goto failed2; } /* Disable all the interrupts, just in case */ out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0); /* Reset the PS2 device and abort any current transaction, to make sure * we have the PS2 in a good state */ out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET); dev_info(dev, "Xilinx PS2 at 0x%08llX mapped to 0x%p, irq=%d\n", (unsigned long long)phys_addr, drvdata->base_address, drvdata->irq); serio = &drvdata->serio; serio->id.type = SERIO_8042; serio->write = sxps2_write; serio->open = sxps2_open; serio->close = sxps2_close; serio->port_data = drvdata; serio->dev.parent = dev; snprintf(serio->name, sizeof(serio->name), "Xilinx XPS PS/2 at %08llX", (unsigned long long)phys_addr); snprintf(serio->phys, sizeof(serio->phys), "xilinxps2/serio at %08llX", (unsigned long long)phys_addr); serio_register_port(serio); return 0; /* success */ failed2: release_mem_region(phys_addr, remap_size); failed1: kfree(drvdata); dev_set_drvdata(dev, NULL); return error; }
static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk, struct spi_board_info *board_infos, unsigned int num_board_infos, void (*cs_control)(struct spi_device *dev, bool on)) { struct device_node *np; unsigned int i = 0; for_each_compatible_node(np, type, compatible) { int ret; unsigned int j; const void *prop; struct resource res[2]; struct platform_device *pdev; struct fsl_spi_platform_data pdata = { .cs_control = cs_control, }; memset(res, 0, sizeof(res)); pdata.sysclk = sysclk; prop = of_get_property(np, "reg", NULL); if (!prop) goto err; pdata.bus_num = *(u32 *)prop; prop = of_get_property(np, "cell-index", NULL); if (prop) i = *(u32 *)prop; prop = of_get_property(np, "mode", NULL); if (prop && !strcmp(prop, "cpu-qe")) pdata.qe_mode = 1; for (j = 0; j < num_board_infos; j++) { if (board_infos[j].bus_num == pdata.bus_num) pdata.max_chipselect++; } if (!pdata.max_chipselect) continue; ret = of_address_to_resource(np, 0, &res[0]); if (ret) goto err; ret = of_irq_to_resource(np, 0, &res[1]); if (ret == NO_IRQ) goto err; pdev = platform_device_alloc("mpc83xx_spi", i); if (!pdev) goto err; ret = platform_device_add_data(pdev, &pdata, sizeof(pdata)); if (ret) goto unreg; ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); if (ret) goto unreg; ret = platform_device_add(pdev); if (ret) goto unreg; goto next; unreg: platform_device_del(pdev); err: pr_err("%s: registration failed\n", np->full_name); next: i++; }
static int __devinit pata_of_platform_probe(struct of_device *ofdev, const struct of_device_id *match) { int ret; struct device_node *dn = ofdev->dev.of_node; struct resource io_res; struct resource ctl_res; struct resource irq_res; unsigned int reg_shift = 0; int pio_mode = 0; int pio_mask; const u32 *prop; ret = of_address_to_resource(dn, 0, &io_res); if (ret) { dev_err(&ofdev->dev, "can't get IO address from " "device tree\n"); return -EINVAL; } if (of_device_is_compatible(dn, "electra-ide")) { /* Altstatus is really at offset 0x3f6 from the primary window * on electra-ide. Adjust ctl_res and io_res accordingly. */ ctl_res = io_res; ctl_res.start = ctl_res.start+0x3f6; io_res.end = ctl_res.start-1; } else { ret = of_address_to_resource(dn, 1, &ctl_res); if (ret) { dev_err(&ofdev->dev, "can't get CTL address from " "device tree\n"); return -EINVAL; } } ret = of_irq_to_resource(dn, 0, &irq_res); if (ret == NO_IRQ) irq_res.start = irq_res.end = 0; else irq_res.flags = 0; prop = of_get_property(dn, "reg-shift", NULL); if (prop) reg_shift = *prop; prop = of_get_property(dn, "pio-mode", NULL); if (prop) { pio_mode = *prop; if (pio_mode > 6) { dev_err(&ofdev->dev, "invalid pio-mode\n"); return -EINVAL; } } else { dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n"); } pio_mask = 1 << pio_mode; pio_mask |= (1 << pio_mode) - 1; return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res, reg_shift, pio_mask); }
/* * Probe routine for each detected JobR subsystem. It assumes that * property detection was picked up externally. */ int caam_jr_probe(struct platform_device *pdev, struct device_node *np, int ring) { struct device *ctrldev, *jrdev; struct platform_device *jr_pdev; struct caam_drv_private *ctrlpriv; struct caam_drv_private_jr *jrpriv; u32 *jroffset; int error; ctrldev = &pdev->dev; ctrlpriv = dev_get_drvdata(ctrldev); jrpriv = kmalloc(sizeof(struct caam_drv_private_jr), GFP_KERNEL); if (jrpriv == NULL) { dev_err(ctrldev, "can't alloc private mem for job ring %d\n", ring); return -ENOMEM; } jrpriv->parentdev = ctrldev; /* point back to parent */ jrpriv->ridx = ring; /* save ring identity relative to detection */ /* * Derive a pointer to the detected JobRs regs * Driver has already iomapped the entire space, we just * need to add in the offset to this JobR. Don't know if I * like this long-term, but it'll run */ jroffset = (u32 *)of_get_property(np, "reg", NULL); jrpriv->rregs = (struct caam_job_ring __iomem *)((void *)ctrlpriv->ctrl + *jroffset); /* Build a local dev for each detected queue */ jr_pdev = of_platform_device_create(np, NULL, ctrldev); if (jr_pdev == NULL) { kfree(jrpriv); return -EINVAL; } jrdev = &jr_pdev->dev; dev_set_drvdata(jrdev, jrpriv); ctrlpriv->jrdev[ring] = jrdev; if (sizeof(dma_addr_t) == sizeof(u64)) if (of_device_is_compatible(np, "fsl,sec-v5.0-job-ring")) dma_set_mask(jrdev, DMA_BIT_MASK(40)); else dma_set_mask(jrdev, DMA_BIT_MASK(36)); else dma_set_mask(jrdev, DMA_BIT_MASK(32)); /* Identify the interrupt */ jrpriv->irq = of_irq_to_resource(np, 0, NULL); /* Now do the platform independent part */ error = caam_jr_init(jrdev); /* now turn on hardware */ if (error) { kfree(jrpriv); return error; } return error; }
static int __init xilinx_spi_of_probe(struct of_device *ofdev, const struct of_device_id *match) { struct spi_master *master; struct xilinx_spi *xspi; struct resource r_irq_struct; struct resource r_mem_struct; struct resource *r_irq = &r_irq_struct; struct resource *r_mem = &r_mem_struct; int rc = 0; const u32 *prop; int len; /* Get resources(memory, IRQ) associated with the device */ master = spi_alloc_master(&ofdev->dev, sizeof(struct xilinx_spi)); if (master == NULL) { return -ENOMEM; } dev_set_drvdata(&ofdev->dev, master); rc = of_address_to_resource(ofdev->node, 0, r_mem); if (rc) { dev_warn(&ofdev->dev, "invalid address\n"); goto put_master; } rc = of_irq_to_resource(ofdev->node, 0, r_irq); if (rc == NO_IRQ) { dev_warn(&ofdev->dev, "no IRQ found\n"); goto put_master; } xspi = spi_master_get_devdata(master); xspi->bitbang.master = spi_master_get(master); xspi->bitbang.chipselect = xilinx_spi_chipselect; xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer; xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; xspi->bitbang.master->setup = xilinx_spi_setup; init_completion(&xspi->done); xspi->irq = r_irq->start; if (!request_mem_region(r_mem->start, r_mem->end - r_mem->start + 1, XILINX_SPI_NAME)) { rc = -ENXIO; dev_warn(&ofdev->dev, "memory request failure\n"); goto put_master; } xspi->regs = ioremap(r_mem->start, r_mem->end - r_mem->start + 1); if (xspi->regs == NULL) { rc = -ENOMEM; dev_warn(&ofdev->dev, "ioremap failure\n"); goto put_master; } xspi->irq = r_irq->start; /* dynamic bus assignment */ master->bus_num = -1; /* number of slave select bits is required */ prop = of_get_property(ofdev->node, "xlnx,num-ss-bits", &len); if (!prop || len < sizeof(*prop)) { dev_warn(&ofdev->dev, "no 'xlnx,num-ss-bits' property\n"); goto put_master; } master->num_chipselect = *prop; /* SPI controller initializations */ xspi_init_hw(xspi->regs); /* Register for SPI Interrupt */ rc = request_irq(xspi->irq, xilinx_spi_irq, 0, XILINX_SPI_NAME, xspi); if (rc != 0) { dev_warn(&ofdev->dev, "irq request failure: %d\n", xspi->irq); goto unmap_io; } rc = spi_bitbang_start(&xspi->bitbang); if (rc != 0) { dev_err(&ofdev->dev, "spi_bitbang_start FAILED\n"); goto free_irq; } dev_info(&ofdev->dev, "at 0x%08X mapped to 0x%08X, irq=%d\n", (unsigned int)r_mem->start, (u32)xspi->regs, xspi->irq); /* Add any subnodes on the SPI bus */ of_register_spi_devices(master, ofdev->node); return rc; free_irq: free_irq(xspi->irq, xspi); unmap_io: iounmap(xspi->regs); put_master: spi_master_put(master); return rc; }