/** * of_device_alloc - Allocate and initialize an of_device * @np: device node to assign to device * @bus_id: Name to assign to the device. May be null to use default name. * @parent: Parent device. */ struct platform_device *of_device_alloc(struct device_node *np, const char *bus_id, struct device *parent) { struct platform_device *dev; int rc, i, num_reg = 0, num_irq; struct resource *res, temp_res; dev = platform_device_alloc("", -1); if (!dev) return NULL; /* count the io and irq resources */ if (of_can_translate_address(np)) while (of_address_to_resource(np, num_reg, &temp_res) == 0) num_reg++; num_irq = of_irq_count(np); /* Populate the resource table */ if (num_irq || num_reg) { res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL); if (!res) { platform_device_put(dev); return NULL; } dev->num_resources = num_reg + num_irq; dev->resource = res; for (i = 0; i < num_reg; i++, res++) { rc = of_address_to_resource(np, i, res); WARN_ON(rc); } WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq); } dev->dev.of_node = of_node_get(np); #if defined(CONFIG_MICROBLAZE) dev->dev.dma_mask = &dev->archdata.dma_mask; #endif dev->dev.parent = parent; if (bus_id) dev_set_name(&dev->dev, "%s", bus_id); else of_device_make_bus_id(&dev->dev); return dev; }
/** * of_device_alloc - Allocate and initialize an of_device * @np: device node to assign to device * @bus_id: Name to assign to the device. May be null to use default name. * @parent: Parent device. */ struct platform_device *of_device_alloc(struct device_node *np, const char *bus_id, struct device *parent) { struct platform_device *dev; int rc, i, num_reg = 0, num_irq; struct resource *res, temp_res; dev = platform_device_alloc("", -1); if (!dev) return NULL; /* count the io and irq resources */ while (of_address_to_resource(np, num_reg, &temp_res) == 0) num_reg++; num_irq = of_irq_count(np); /* Populate the resource table */ if (num_irq || num_reg) { res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL); if (!res) { platform_device_put(dev); return NULL; } dev->num_resources = num_reg + num_irq; dev->resource = res; for (i = 0; i < num_reg; i++, res++) { rc = of_address_to_resource(np, i, res); WARN_ON(rc); } if (of_irq_to_resource_table(np, res, num_irq) != num_irq) pr_debug("not all legacy IRQ resources mapped for %s\n", np->name); } dev->dev.of_node = of_node_get(np); dev->dev.fwnode = &np->fwnode; dev->dev.parent = parent ? : &platform_bus; if (bus_id) dev_set_name(&dev->dev, "%s", bus_id); else of_device_make_bus_id(&dev->dev); return dev; }
int __init icu_of_init(struct device_node *node, struct device_node *parent) { struct device_node *eiu_node; struct resource res; int i, ret; for (i = 0; i < MAX_IM; i++) { if (of_address_to_resource(node, i, &res)) panic("Failed to get icu memory range"); if (request_mem_region(res.start, resource_size(&res), res.name) < 0) pr_err("Failed to request icu memory"); ltq_icu_membase[i] = ioremap_nocache(res.start, resource_size(&res)); if (!ltq_icu_membase[i]) panic("Failed to remap icu memory"); } /* the external interrupts are optional and xway only */ eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway"); if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) { /* find out how many external irq sources we have */ exin_avail = of_irq_count(eiu_node); if (exin_avail > MAX_EIU) exin_avail = MAX_EIU; ret = of_irq_to_resource_table(eiu_node, ltq_eiu_irq, exin_avail); if (ret != exin_avail) panic("failed to load external irq resources"); if (request_mem_region(res.start, resource_size(&res), res.name) < 0) pr_err("Failed to request eiu memory"); ltq_eiu_membase = ioremap_nocache(res.start, resource_size(&res)); if (!ltq_eiu_membase) panic("Failed to remap eiu memory"); } /* turn off all irqs by default */ for (i = 0; i < MAX_IM; i++) { /* make sure all irqs are turned off by default */ ltq_icu_w32(i, 0, LTQ_ICU_IM0_IER); /* clear all possibly pending interrupts */ ltq_icu_w32(i, ~0, LTQ_ICU_IM0_ISR); } mips_cpu_irq_init(); for (i = 0; i < MAX_IM; i++) setup_irq(i + 2, &cascade); if (cpu_has_vint) { pr_info("Setting up vectored interrupts\n"); set_vi_handler(2, ltq_hw0_irqdispatch); set_vi_handler(3, ltq_hw1_irqdispatch); set_vi_handler(4, ltq_hw2_irqdispatch); set_vi_handler(5, ltq_hw3_irqdispatch); set_vi_handler(6, ltq_hw4_irqdispatch); set_vi_handler(7, ltq_hw5_irqdispatch); } ltq_domain = irq_domain_add_linear(node, (MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE, &irq_domain_ops, 0); #if defined(CONFIG_MIPS_MT_SMP) if (cpu_has_vint) { pr_info("Setting up IPI vectored interrupts\n"); set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ltq_sw0_irqdispatch); set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ltq_sw1_irqdispatch); } arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ, &irq_resched); arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call); #endif #if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC) set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5); #else set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5); #endif /* tell oprofile which irq to use */ cp0_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ); /* * if the timer irq is not one of the mips irqs we need to * create a mapping */ if (MIPS_CPU_TIMER_IRQ != 7) irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ); return 0; }