qcom-pdc.c (c87866ede44ad7da6b296d732221dc34ce1b154d) | qcom-pdc.c (9d4f24bfe043274d9274bcfe223b901bd8fb7182) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. 4 */ 5 6#include <linux/err.h> 7#include <linux/init.h> 8#include <linux/interrupt.h> --- 39 unchanged lines hidden (view full) --- 48 writel_relaxed(val, pdc_base + reg + i * sizeof(u32)); 49} 50 51static u32 pdc_reg_read(int reg, u32 i) 52{ 53 return readl_relaxed(pdc_base + reg + i * sizeof(u32)); 54} 55 | 1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. 4 */ 5 6#include <linux/err.h> 7#include <linux/init.h> 8#include <linux/interrupt.h> --- 39 unchanged lines hidden (view full) --- 48 writel_relaxed(val, pdc_base + reg + i * sizeof(u32)); 49} 50 51static u32 pdc_reg_read(int reg, u32 i) 52{ 53 return readl_relaxed(pdc_base + reg + i * sizeof(u32)); 54} 55 |
56static int qcom_pdc_gic_get_irqchip_state(struct irq_data *d, 57 enum irqchip_irq_state which, 58 bool *state) 59{ 60 if (d->hwirq == GPIO_NO_WAKE_IRQ) 61 return 0; 62 63 return irq_chip_get_parent_state(d, which, state); 64} 65 66static int qcom_pdc_gic_set_irqchip_state(struct irq_data *d, 67 enum irqchip_irq_state which, 68 bool value) 69{ 70 if (d->hwirq == GPIO_NO_WAKE_IRQ) 71 return 0; 72 73 return irq_chip_set_parent_state(d, which, value); 74} 75 | |
76static void pdc_enable_intr(struct irq_data *d, bool on) 77{ 78 int pin_out = d->hwirq; 79 u32 index, mask; 80 u32 enable; 81 82 index = pin_out / 32; 83 mask = pin_out % 32; 84 85 raw_spin_lock(&pdc_lock); 86 enable = pdc_reg_read(IRQ_ENABLE_BANK, index); 87 enable = on ? ENABLE_INTR(enable, mask) : CLEAR_INTR(enable, mask); 88 pdc_reg_write(IRQ_ENABLE_BANK, index, enable); 89 raw_spin_unlock(&pdc_lock); 90} 91 92static void qcom_pdc_gic_disable(struct irq_data *d) 93{ | 56static void pdc_enable_intr(struct irq_data *d, bool on) 57{ 58 int pin_out = d->hwirq; 59 u32 index, mask; 60 u32 enable; 61 62 index = pin_out / 32; 63 mask = pin_out % 32; 64 65 raw_spin_lock(&pdc_lock); 66 enable = pdc_reg_read(IRQ_ENABLE_BANK, index); 67 enable = on ? ENABLE_INTR(enable, mask) : CLEAR_INTR(enable, mask); 68 pdc_reg_write(IRQ_ENABLE_BANK, index, enable); 69 raw_spin_unlock(&pdc_lock); 70} 71 72static void qcom_pdc_gic_disable(struct irq_data *d) 73{ |
94 if (d->hwirq == GPIO_NO_WAKE_IRQ) 95 return; 96 | |
97 pdc_enable_intr(d, false); 98 irq_chip_disable_parent(d); 99} 100 101static void qcom_pdc_gic_enable(struct irq_data *d) 102{ | 74 pdc_enable_intr(d, false); 75 irq_chip_disable_parent(d); 76} 77 78static void qcom_pdc_gic_enable(struct irq_data *d) 79{ |
103 if (d->hwirq == GPIO_NO_WAKE_IRQ) 104 return; 105 | |
106 pdc_enable_intr(d, true); 107 irq_chip_enable_parent(d); 108} 109 | 80 pdc_enable_intr(d, true); 81 irq_chip_enable_parent(d); 82} 83 |
110static void qcom_pdc_gic_mask(struct irq_data *d) 111{ 112 if (d->hwirq == GPIO_NO_WAKE_IRQ) 113 return; 114 115 irq_chip_mask_parent(d); 116} 117 118static void qcom_pdc_gic_unmask(struct irq_data *d) 119{ 120 if (d->hwirq == GPIO_NO_WAKE_IRQ) 121 return; 122 123 irq_chip_unmask_parent(d); 124} 125 | |
126/* 127 * GIC does not handle falling edge or active low. To allow falling edge and 128 * active low interrupts to be handled at GIC, PDC has an inverter that inverts 129 * falling edge into a rising edge and active low into an active high. 130 * For the inverter to work, the polarity bit in the IRQ_CONFIG register has to 131 * set as per the table below. 132 * Level sensitive active low LOW 133 * Rising edge sensitive NOT USED --- 20 unchanged lines hidden (view full) --- 154 * 155 * If @type is edge triggered, forward that as Rising edge as PDC 156 * takes care of converting falling edge to rising edge signal 157 * If @type is level, then forward that as level high as PDC 158 * takes care of converting falling edge to rising edge signal 159 */ 160static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type) 161{ | 84/* 85 * GIC does not handle falling edge or active low. To allow falling edge and 86 * active low interrupts to be handled at GIC, PDC has an inverter that inverts 87 * falling edge into a rising edge and active low into an active high. 88 * For the inverter to work, the polarity bit in the IRQ_CONFIG register has to 89 * set as per the table below. 90 * Level sensitive active low LOW 91 * Rising edge sensitive NOT USED --- 20 unchanged lines hidden (view full) --- 112 * 113 * If @type is edge triggered, forward that as Rising edge as PDC 114 * takes care of converting falling edge to rising edge signal 115 * If @type is level, then forward that as level high as PDC 116 * takes care of converting falling edge to rising edge signal 117 */ 118static int qcom_pdc_gic_set_type(struct irq_data *d, unsigned int type) 119{ |
162 int pin_out = d->hwirq; | |
163 enum pdc_irq_config_bits pdc_type; 164 enum pdc_irq_config_bits old_pdc_type; 165 int ret; 166 | 120 enum pdc_irq_config_bits pdc_type; 121 enum pdc_irq_config_bits old_pdc_type; 122 int ret; 123 |
167 if (pin_out == GPIO_NO_WAKE_IRQ) 168 return 0; 169 | |
170 switch (type) { 171 case IRQ_TYPE_EDGE_RISING: 172 pdc_type = PDC_EDGE_RISING; 173 break; 174 case IRQ_TYPE_EDGE_FALLING: 175 pdc_type = PDC_EDGE_FALLING; 176 type = IRQ_TYPE_EDGE_RISING; 177 break; --- 8 unchanged lines hidden (view full) --- 186 pdc_type = PDC_LEVEL_LOW; 187 type = IRQ_TYPE_LEVEL_HIGH; 188 break; 189 default: 190 WARN_ON(1); 191 return -EINVAL; 192 } 193 | 124 switch (type) { 125 case IRQ_TYPE_EDGE_RISING: 126 pdc_type = PDC_EDGE_RISING; 127 break; 128 case IRQ_TYPE_EDGE_FALLING: 129 pdc_type = PDC_EDGE_FALLING; 130 type = IRQ_TYPE_EDGE_RISING; 131 break; --- 8 unchanged lines hidden (view full) --- 140 pdc_type = PDC_LEVEL_LOW; 141 type = IRQ_TYPE_LEVEL_HIGH; 142 break; 143 default: 144 WARN_ON(1); 145 return -EINVAL; 146 } 147 |
194 old_pdc_type = pdc_reg_read(IRQ_i_CFG, pin_out); 195 pdc_reg_write(IRQ_i_CFG, pin_out, pdc_type); | 148 old_pdc_type = pdc_reg_read(IRQ_i_CFG, d->hwirq); 149 pdc_reg_write(IRQ_i_CFG, d->hwirq, pdc_type); |
196 197 ret = irq_chip_set_type_parent(d, type); 198 if (ret) 199 return ret; 200 201 /* 202 * When we change types the PDC can give a phantom interrupt. 203 * Clear it. Specifically the phantom shows up when reconfiguring --- 7 unchanged lines hidden (view full) --- 211 irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, false); 212 213 return 0; 214} 215 216static struct irq_chip qcom_pdc_gic_chip = { 217 .name = "PDC", 218 .irq_eoi = irq_chip_eoi_parent, | 150 151 ret = irq_chip_set_type_parent(d, type); 152 if (ret) 153 return ret; 154 155 /* 156 * When we change types the PDC can give a phantom interrupt. 157 * Clear it. Specifically the phantom shows up when reconfiguring --- 7 unchanged lines hidden (view full) --- 165 irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, false); 166 167 return 0; 168} 169 170static struct irq_chip qcom_pdc_gic_chip = { 171 .name = "PDC", 172 .irq_eoi = irq_chip_eoi_parent, |
219 .irq_mask = qcom_pdc_gic_mask, 220 .irq_unmask = qcom_pdc_gic_unmask, | 173 .irq_mask = irq_chip_mask_parent, 174 .irq_unmask = irq_chip_unmask_parent, |
221 .irq_disable = qcom_pdc_gic_disable, 222 .irq_enable = qcom_pdc_gic_enable, | 175 .irq_disable = qcom_pdc_gic_disable, 176 .irq_enable = qcom_pdc_gic_enable, |
223 .irq_get_irqchip_state = qcom_pdc_gic_get_irqchip_state, 224 .irq_set_irqchip_state = qcom_pdc_gic_set_irqchip_state, | 177 .irq_get_irqchip_state = irq_chip_get_parent_state, 178 .irq_set_irqchip_state = irq_chip_set_parent_state, |
225 .irq_retrigger = irq_chip_retrigger_hierarchy, 226 .irq_set_type = qcom_pdc_gic_set_type, 227 .flags = IRQCHIP_MASK_ON_SUSPEND | 228 IRQCHIP_SET_TYPE_MASKED | 229 IRQCHIP_SKIP_SET_WAKE | 230 IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND, 231 .irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent, 232 .irq_set_affinity = irq_chip_set_affinity_parent, --- 44 unchanged lines hidden (view full) --- 277 278 ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 279 &qcom_pdc_gic_chip, NULL); 280 if (ret) 281 return ret; 282 283 parent_hwirq = get_parent_hwirq(hwirq); 284 if (parent_hwirq == PDC_NO_PARENT_IRQ) | 179 .irq_retrigger = irq_chip_retrigger_hierarchy, 180 .irq_set_type = qcom_pdc_gic_set_type, 181 .flags = IRQCHIP_MASK_ON_SUSPEND | 182 IRQCHIP_SET_TYPE_MASKED | 183 IRQCHIP_SKIP_SET_WAKE | 184 IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND, 185 .irq_set_vcpu_affinity = irq_chip_set_vcpu_affinity_parent, 186 .irq_set_affinity = irq_chip_set_affinity_parent, --- 44 unchanged lines hidden (view full) --- 231 232 ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 233 &qcom_pdc_gic_chip, NULL); 234 if (ret) 235 return ret; 236 237 parent_hwirq = get_parent_hwirq(hwirq); 238 if (parent_hwirq == PDC_NO_PARENT_IRQ) |
285 return 0; | 239 return irq_domain_disconnect_hierarchy(domain->parent, virq); |
286 287 if (type & IRQ_TYPE_EDGE_BOTH) 288 type = IRQ_TYPE_EDGE_RISING; 289 290 if (type & IRQ_TYPE_LEVEL_MASK) 291 type = IRQ_TYPE_LEVEL_HIGH; 292 293 parent_fwspec.fwnode = domain->parent->fwnode; --- 20 unchanged lines hidden (view full) --- 314 irq_hw_number_t hwirq, parent_hwirq; 315 unsigned int type; 316 int ret; 317 318 ret = qcom_pdc_translate(domain, fwspec, &hwirq, &type); 319 if (ret) 320 return ret; 321 | 240 241 if (type & IRQ_TYPE_EDGE_BOTH) 242 type = IRQ_TYPE_EDGE_RISING; 243 244 if (type & IRQ_TYPE_LEVEL_MASK) 245 type = IRQ_TYPE_LEVEL_HIGH; 246 247 parent_fwspec.fwnode = domain->parent->fwnode; --- 20 unchanged lines hidden (view full) --- 268 irq_hw_number_t hwirq, parent_hwirq; 269 unsigned int type; 270 int ret; 271 272 ret = qcom_pdc_translate(domain, fwspec, &hwirq, &type); 273 if (ret) 274 return ret; 275 |
276 if (hwirq == GPIO_NO_WAKE_IRQ) 277 return irq_domain_disconnect_hierarchy(domain, virq); 278 |
|
322 ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 323 &qcom_pdc_gic_chip, NULL); 324 if (ret) 325 return ret; 326 | 279 ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 280 &qcom_pdc_gic_chip, NULL); 281 if (ret) 282 return ret; 283 |
327 if (hwirq == GPIO_NO_WAKE_IRQ) 328 return 0; 329 | |
330 parent_hwirq = get_parent_hwirq(hwirq); 331 if (parent_hwirq == PDC_NO_PARENT_IRQ) | 284 parent_hwirq = get_parent_hwirq(hwirq); 285 if (parent_hwirq == PDC_NO_PARENT_IRQ) |
332 return 0; | 286 return irq_domain_disconnect_hierarchy(domain->parent, virq); |
333 334 if (type & IRQ_TYPE_EDGE_BOTH) 335 type = IRQ_TYPE_EDGE_RISING; 336 337 if (type & IRQ_TYPE_LEVEL_MASK) 338 type = IRQ_TYPE_LEVEL_HIGH; 339 340 parent_fwspec.fwnode = domain->parent->fwnode; --- 128 unchanged lines hidden --- | 287 288 if (type & IRQ_TYPE_EDGE_BOTH) 289 type = IRQ_TYPE_EDGE_RISING; 290 291 if (type & IRQ_TYPE_LEVEL_MASK) 292 type = IRQ_TYPE_LEVEL_HIGH; 293 294 parent_fwspec.fwnode = domain->parent->fwnode; --- 128 unchanged lines hidden --- |