diff options
Diffstat (limited to 'arch/mips/cavium-octeon/octeon-irq.c')
-rw-r--r-- | arch/mips/cavium-octeon/octeon-irq.c | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index f97be32bf699..8425a6b38aa2 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -127,6 +127,16 @@ static void octeon_irq_free_cd(struct irq_domain *d, unsigned int irq) static int octeon_irq_force_ciu_mapping(struct irq_domain *domain, int irq, int line, int bit) { + struct device_node *of_node; + int ret; + + of_node = irq_domain_get_of_node(domain); + if (!of_node) + return -EINVAL; + ret = irq_alloc_desc_at(irq, of_node_to_nid(of_node)); + if (ret < 0) + return ret; + return irq_domain_associate(domain, irq, line << 6 | bit); } @@ -263,7 +273,7 @@ static int next_cpu_for_irq(struct irq_data *data) #ifdef CONFIG_SMP int cpu; - struct cpumask *mask = irq_data_get_affinity_mask(data); + const struct cpumask *mask = irq_data_get_affinity_mask(data); int weight = cpumask_weight(mask); struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data); @@ -758,7 +768,7 @@ static void octeon_irq_cpu_offline_ciu(struct irq_data *data) { int cpu = smp_processor_id(); cpumask_t new_affinity; - struct cpumask *mask = irq_data_get_affinity_mask(data); + const struct cpumask *mask = irq_data_get_affinity_mask(data); if (!cpumask_test_cpu(cpu, mask)) return; @@ -1274,13 +1284,13 @@ static int octeon_irq_gpio_map(struct irq_domain *d, return r; } -static struct irq_domain_ops octeon_irq_domain_ciu_ops = { +static const struct irq_domain_ops octeon_irq_domain_ciu_ops = { .map = octeon_irq_ciu_map, .unmap = octeon_irq_free_cd, .xlate = octeon_irq_ciu_xlat, }; -static struct irq_domain_ops octeon_irq_domain_gpio_ops = { +static const struct irq_domain_ops octeon_irq_domain_gpio_ops = { .map = octeon_irq_gpio_map, .unmap = octeon_irq_free_cd, .xlate = octeon_irq_gpio_xlat, @@ -1405,7 +1415,7 @@ static void octeon_irq_init_ciu2_percpu(void) * completed. * * There are 9 registers and 3 IPX levels with strides 0x1000 - * and 0x200 respectivly. Use loops to clear them. + * and 0x200 respectively. Use loops to clear them. */ for (regx = 0; regx <= 0x8000; regx += 0x1000) { for (ipx = 0; ipx <= 0x400; ipx += 0x200) @@ -1444,7 +1454,7 @@ static void octeon_irq_setup_secondary_ciu2(void) static int __init octeon_irq_init_ciu( struct device_node *ciu_node, struct device_node *parent) { - unsigned int i, r; + int i, r; struct irq_chip *chip; struct irq_chip *chip_edge; struct irq_chip *chip_mbox; @@ -1505,10 +1515,20 @@ static int __init octeon_irq_init_ciu( goto err; } + r = irq_alloc_desc_at(OCTEON_IRQ_MBOX0, -1); + if (r < 0) { + pr_err("Failed to allocate desc for %s\n", "OCTEON_IRQ_MBOX0"); + goto err; + } r = octeon_irq_set_ciu_mapping( OCTEON_IRQ_MBOX0, 0, 32, 0, chip_mbox, handle_percpu_irq); if (r) goto err; + r = irq_alloc_desc_at(OCTEON_IRQ_MBOX1, -1); + if (r < 0) { + pr_err("Failed to allocate desc for %s\n", "OCTEON_IRQ_MBOX1"); + goto err; + } r = octeon_irq_set_ciu_mapping( OCTEON_IRQ_MBOX1, 0, 33, 0, chip_mbox, handle_percpu_irq); if (r) @@ -1546,6 +1566,11 @@ static int __init octeon_irq_init_ciu( if (r) goto err; + r = irq_alloc_descs(OCTEON_IRQ_WDOG0, OCTEON_IRQ_WDOG0, 16, -1); + if (r < 0) { + pr_err("Failed to allocate desc for %s\n", "OCTEON_IRQ_WDOGx"); + goto err; + } /* CIU_1 */ for (i = 0; i < 16; i++) { r = octeon_irq_set_ciu_mapping( @@ -1959,7 +1984,7 @@ static int octeon_irq_ciu2_map(struct irq_domain *d, return 0; } -static struct irq_domain_ops octeon_irq_domain_ciu2_ops = { +static const struct irq_domain_ops octeon_irq_domain_ciu2_ops = { .map = octeon_irq_ciu2_map, .unmap = octeon_irq_free_cd, .xlate = octeon_irq_ciu2_xlat, @@ -2193,12 +2218,15 @@ static int octeon_irq_cib_map(struct irq_domain *d, struct octeon_irq_cib_chip_data *cd; if (hw >= host_data->max_bits) { - pr_err("ERROR: %s mapping %u is to big!\n", + pr_err("ERROR: %s mapping %u is too big!\n", irq_domain_get_of_node(d)->name, (unsigned)hw); return -EINVAL; } cd = kzalloc(sizeof(*cd), GFP_KERNEL); + if (!cd) + return -ENOMEM; + cd->host_data = host_data; cd->bit = hw; @@ -2208,7 +2236,7 @@ static int octeon_irq_cib_map(struct irq_domain *d, return 0; } -static struct irq_domain_ops octeon_irq_domain_cib_ops = { +static const struct irq_domain_ops octeon_irq_domain_cib_ops = { .map = octeon_irq_cib_map, .unmap = octeon_irq_free_cd, .xlate = octeon_irq_cib_xlat, @@ -2262,7 +2290,7 @@ static irqreturn_t octeon_irq_cib_handler(int my_irq, void *data) static int __init octeon_irq_init_cib(struct device_node *ciu_node, struct device_node *parent) { - const __be32 *addr; + struct resource res; u32 val; struct octeon_irq_cib_host_data *host_data; int parent_irq; @@ -2281,21 +2309,19 @@ static int __init octeon_irq_init_cib(struct device_node *ciu_node, return -ENOMEM; raw_spin_lock_init(&host_data->lock); - addr = of_get_address(ciu_node, 0, NULL, NULL); - if (!addr) { + r = of_address_to_resource(ciu_node, 0, &res); + if (r) { pr_err("ERROR: Couldn't acquire reg(0) %pOFn\n", ciu_node); - return -EINVAL; + return r; } - host_data->raw_reg = (u64)phys_to_virt( - of_translate_address(ciu_node, addr)); + host_data->raw_reg = (u64)phys_to_virt(res.start); - addr = of_get_address(ciu_node, 1, NULL, NULL); - if (!addr) { + r = of_address_to_resource(ciu_node, 1, &res); + if (r) { pr_err("ERROR: Couldn't acquire reg(1) %pOFn\n", ciu_node); - return -EINVAL; + return r; } - host_data->en_reg = (u64)phys_to_virt( - of_translate_address(ciu_node, addr)); + host_data->en_reg = (u64)phys_to_virt(res.start); r = of_property_read_u32(ciu_node, "cavium,max-bits", &val); if (r) { @@ -2560,7 +2586,7 @@ static int octeon_irq_ciu3_map(struct irq_domain *d, return octeon_irq_ciu3_mapx(d, virq, hw, &octeon_irq_chip_ciu3); } -static struct irq_domain_ops octeon_dflt_domain_ciu3_ops = { +static const struct irq_domain_ops octeon_dflt_domain_ciu3_ops = { .map = octeon_irq_ciu3_map, .unmap = octeon_irq_free_cd, .xlate = octeon_irq_ciu3_xlat, @@ -2591,7 +2617,10 @@ static void octeon_irq_ciu3_ip2(void) else hw = intsn; - ret = handle_domain_irq(domain, hw, NULL); + irq_enter(); + ret = generic_handle_domain_irq(domain, hw); + irq_exit(); + if (ret < 0) { union cvmx_ciu3_iscx_w1c isc_w1c; u64 isc_w1c_addr = ciu3_addr + CIU3_ISC_W1C(intsn); @@ -2843,11 +2872,11 @@ static struct irq_chip octeon_irq_chip_ciu3_mbox = { static int __init octeon_irq_init_ciu3(struct device_node *ciu_node, struct device_node *parent) { - int i; + int i, ret; int node; struct irq_domain *domain; struct octeon_ciu3_info *ciu3_info; - const __be32 *zero_addr; + struct resource res; u64 base_addr; union cvmx_ciu3_const consts; @@ -2857,14 +2886,11 @@ static int __init octeon_irq_init_ciu3(struct device_node *ciu_node, if (!ciu3_info) return -ENOMEM; - zero_addr = of_get_address(ciu_node, 0, NULL, NULL); - if (WARN_ON(!zero_addr)) - return -EINVAL; - - base_addr = of_translate_address(ciu_node, zero_addr); - base_addr = (u64)phys_to_virt(base_addr); + ret = of_address_to_resource(ciu_node, 0, &res); + if (WARN_ON(ret)) + return ret; - ciu3_info->ciu3_addr = base_addr; + ciu3_info->ciu3_addr = base_addr = (u64)phys_to_virt(res.start); ciu3_info->node = node; consts.u64 = cvmx_read_csr(base_addr + CIU3_CONST); |