0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/bitfield.h>
0011 #include <linux/clk.h>
0012 #include <linux/err.h>
0013 #include <linux/io.h>
0014 #include <linux/irqchip.h>
0015 #include <linux/irqdomain.h>
0016 #include <linux/of_address.h>
0017 #include <linux/of_platform.h>
0018 #include <linux/pm_runtime.h>
0019 #include <linux/reset.h>
0020 #include <linux/spinlock.h>
0021
0022 #define IRQC_IRQ_START 1
0023 #define IRQC_IRQ_COUNT 8
0024 #define IRQC_TINT_START (IRQC_IRQ_START + IRQC_IRQ_COUNT)
0025 #define IRQC_TINT_COUNT 32
0026 #define IRQC_NUM_IRQ (IRQC_TINT_START + IRQC_TINT_COUNT)
0027
0028 #define ISCR 0x10
0029 #define IITSR 0x14
0030 #define TSCR 0x20
0031 #define TITSR0 0x24
0032 #define TITSR1 0x28
0033 #define TITSR0_MAX_INT 16
0034 #define TITSEL_WIDTH 0x2
0035 #define TSSR(n) (0x30 + ((n) * 4))
0036 #define TIEN BIT(7)
0037 #define TSSEL_SHIFT(n) (8 * (n))
0038 #define TSSEL_MASK GENMASK(7, 0)
0039 #define IRQ_MASK 0x3
0040
0041 #define TSSR_OFFSET(n) ((n) % 4)
0042 #define TSSR_INDEX(n) ((n) / 4)
0043
0044 #define TITSR_TITSEL_EDGE_RISING 0
0045 #define TITSR_TITSEL_EDGE_FALLING 1
0046 #define TITSR_TITSEL_LEVEL_HIGH 2
0047 #define TITSR_TITSEL_LEVEL_LOW 3
0048
0049 #define IITSR_IITSEL(n, sense) ((sense) << ((n) * 2))
0050 #define IITSR_IITSEL_LEVEL_LOW 0
0051 #define IITSR_IITSEL_EDGE_FALLING 1
0052 #define IITSR_IITSEL_EDGE_RISING 2
0053 #define IITSR_IITSEL_EDGE_BOTH 3
0054 #define IITSR_IITSEL_MASK(n) IITSR_IITSEL((n), 3)
0055
0056 #define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
0057 #define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
0058
0059 struct rzg2l_irqc_priv {
0060 void __iomem *base;
0061 struct irq_fwspec fwspec[IRQC_NUM_IRQ];
0062 raw_spinlock_t lock;
0063 };
0064
0065 static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data)
0066 {
0067 return data->domain->host_data;
0068 }
0069
0070 static void rzg2l_irq_eoi(struct irq_data *d)
0071 {
0072 unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START;
0073 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
0074 u32 bit = BIT(hw_irq);
0075 u32 reg;
0076
0077 reg = readl_relaxed(priv->base + ISCR);
0078 if (reg & bit)
0079 writel_relaxed(reg & ~bit, priv->base + ISCR);
0080 }
0081
0082 static void rzg2l_tint_eoi(struct irq_data *d)
0083 {
0084 unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_TINT_START;
0085 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
0086 u32 bit = BIT(hw_irq);
0087 u32 reg;
0088
0089 reg = readl_relaxed(priv->base + TSCR);
0090 if (reg & bit)
0091 writel_relaxed(reg & ~bit, priv->base + TSCR);
0092 }
0093
0094 static void rzg2l_irqc_eoi(struct irq_data *d)
0095 {
0096 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
0097 unsigned int hw_irq = irqd_to_hwirq(d);
0098
0099 raw_spin_lock(&priv->lock);
0100 if (hw_irq >= IRQC_IRQ_START && hw_irq <= IRQC_IRQ_COUNT)
0101 rzg2l_irq_eoi(d);
0102 else if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ)
0103 rzg2l_tint_eoi(d);
0104 raw_spin_unlock(&priv->lock);
0105 irq_chip_eoi_parent(d);
0106 }
0107
0108 static void rzg2l_irqc_irq_disable(struct irq_data *d)
0109 {
0110 unsigned int hw_irq = irqd_to_hwirq(d);
0111
0112 if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) {
0113 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
0114 u32 offset = hw_irq - IRQC_TINT_START;
0115 u32 tssr_offset = TSSR_OFFSET(offset);
0116 u8 tssr_index = TSSR_INDEX(offset);
0117 u32 reg;
0118
0119 raw_spin_lock(&priv->lock);
0120 reg = readl_relaxed(priv->base + TSSR(tssr_index));
0121 reg &= ~(TSSEL_MASK << tssr_offset);
0122 writel_relaxed(reg, priv->base + TSSR(tssr_index));
0123 raw_spin_unlock(&priv->lock);
0124 }
0125 irq_chip_disable_parent(d);
0126 }
0127
0128 static void rzg2l_irqc_irq_enable(struct irq_data *d)
0129 {
0130 unsigned int hw_irq = irqd_to_hwirq(d);
0131
0132 if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) {
0133 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
0134 unsigned long tint = (uintptr_t)d->chip_data;
0135 u32 offset = hw_irq - IRQC_TINT_START;
0136 u32 tssr_offset = TSSR_OFFSET(offset);
0137 u8 tssr_index = TSSR_INDEX(offset);
0138 u32 reg;
0139
0140 raw_spin_lock(&priv->lock);
0141 reg = readl_relaxed(priv->base + TSSR(tssr_index));
0142 reg |= (TIEN | tint) << TSSEL_SHIFT(tssr_offset);
0143 writel_relaxed(reg, priv->base + TSSR(tssr_index));
0144 raw_spin_unlock(&priv->lock);
0145 }
0146 irq_chip_enable_parent(d);
0147 }
0148
0149 static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
0150 {
0151 unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START;
0152 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
0153 u16 sense, tmp;
0154
0155 switch (type & IRQ_TYPE_SENSE_MASK) {
0156 case IRQ_TYPE_LEVEL_LOW:
0157 sense = IITSR_IITSEL_LEVEL_LOW;
0158 break;
0159
0160 case IRQ_TYPE_EDGE_FALLING:
0161 sense = IITSR_IITSEL_EDGE_FALLING;
0162 break;
0163
0164 case IRQ_TYPE_EDGE_RISING:
0165 sense = IITSR_IITSEL_EDGE_RISING;
0166 break;
0167
0168 case IRQ_TYPE_EDGE_BOTH:
0169 sense = IITSR_IITSEL_EDGE_BOTH;
0170 break;
0171
0172 default:
0173 return -EINVAL;
0174 }
0175
0176 raw_spin_lock(&priv->lock);
0177 tmp = readl_relaxed(priv->base + IITSR);
0178 tmp &= ~IITSR_IITSEL_MASK(hw_irq);
0179 tmp |= IITSR_IITSEL(hw_irq, sense);
0180 writel_relaxed(tmp, priv->base + IITSR);
0181 raw_spin_unlock(&priv->lock);
0182
0183 return 0;
0184 }
0185
0186 static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
0187 {
0188 struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
0189 unsigned int hwirq = irqd_to_hwirq(d);
0190 u32 titseln = hwirq - IRQC_TINT_START;
0191 u32 offset;
0192 u8 sense;
0193 u32 reg;
0194
0195 switch (type & IRQ_TYPE_SENSE_MASK) {
0196 case IRQ_TYPE_EDGE_RISING:
0197 sense = TITSR_TITSEL_EDGE_RISING;
0198 break;
0199
0200 case IRQ_TYPE_EDGE_FALLING:
0201 sense = TITSR_TITSEL_EDGE_FALLING;
0202 break;
0203
0204 default:
0205 return -EINVAL;
0206 }
0207
0208 offset = TITSR0;
0209 if (titseln >= TITSR0_MAX_INT) {
0210 titseln -= TITSR0_MAX_INT;
0211 offset = TITSR1;
0212 }
0213
0214 raw_spin_lock(&priv->lock);
0215 reg = readl_relaxed(priv->base + offset);
0216 reg &= ~(IRQ_MASK << (titseln * TITSEL_WIDTH));
0217 reg |= sense << (titseln * TITSEL_WIDTH);
0218 writel_relaxed(reg, priv->base + offset);
0219 raw_spin_unlock(&priv->lock);
0220
0221 return 0;
0222 }
0223
0224 static int rzg2l_irqc_set_type(struct irq_data *d, unsigned int type)
0225 {
0226 unsigned int hw_irq = irqd_to_hwirq(d);
0227 int ret = -EINVAL;
0228
0229 if (hw_irq >= IRQC_IRQ_START && hw_irq <= IRQC_IRQ_COUNT)
0230 ret = rzg2l_irq_set_type(d, type);
0231 else if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ)
0232 ret = rzg2l_tint_set_edge(d, type);
0233 if (ret)
0234 return ret;
0235
0236 return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
0237 }
0238
0239 static const struct irq_chip irqc_chip = {
0240 .name = "rzg2l-irqc",
0241 .irq_eoi = rzg2l_irqc_eoi,
0242 .irq_mask = irq_chip_mask_parent,
0243 .irq_unmask = irq_chip_unmask_parent,
0244 .irq_disable = rzg2l_irqc_irq_disable,
0245 .irq_enable = rzg2l_irqc_irq_enable,
0246 .irq_get_irqchip_state = irq_chip_get_parent_state,
0247 .irq_set_irqchip_state = irq_chip_set_parent_state,
0248 .irq_retrigger = irq_chip_retrigger_hierarchy,
0249 .irq_set_type = rzg2l_irqc_set_type,
0250 .flags = IRQCHIP_MASK_ON_SUSPEND |
0251 IRQCHIP_SET_TYPE_MASKED |
0252 IRQCHIP_SKIP_SET_WAKE,
0253 };
0254
0255 static int rzg2l_irqc_alloc(struct irq_domain *domain, unsigned int virq,
0256 unsigned int nr_irqs, void *arg)
0257 {
0258 struct rzg2l_irqc_priv *priv = domain->host_data;
0259 unsigned long tint = 0;
0260 irq_hw_number_t hwirq;
0261 unsigned int type;
0262 int ret;
0263
0264 ret = irq_domain_translate_twocell(domain, arg, &hwirq, &type);
0265 if (ret)
0266 return ret;
0267
0268
0269
0270
0271
0272
0273
0274
0275 if (hwirq > IRQC_IRQ_COUNT) {
0276 tint = TINT_EXTRACT_GPIOINT(hwirq);
0277 hwirq = TINT_EXTRACT_HWIRQ(hwirq);
0278
0279 if (hwirq < IRQC_TINT_START)
0280 return -EINVAL;
0281 }
0282
0283 if (hwirq > (IRQC_NUM_IRQ - 1))
0284 return -EINVAL;
0285
0286 ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &irqc_chip,
0287 (void *)(uintptr_t)tint);
0288 if (ret)
0289 return ret;
0290
0291 return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &priv->fwspec[hwirq]);
0292 }
0293
0294 static const struct irq_domain_ops rzg2l_irqc_domain_ops = {
0295 .alloc = rzg2l_irqc_alloc,
0296 .free = irq_domain_free_irqs_common,
0297 .translate = irq_domain_translate_twocell,
0298 };
0299
0300 static int rzg2l_irqc_parse_interrupts(struct rzg2l_irqc_priv *priv,
0301 struct device_node *np)
0302 {
0303 struct of_phandle_args map;
0304 unsigned int i;
0305 int ret;
0306
0307 for (i = 0; i < IRQC_NUM_IRQ; i++) {
0308 ret = of_irq_parse_one(np, i, &map);
0309 if (ret)
0310 return ret;
0311 of_phandle_args_to_fwspec(np, map.args, map.args_count,
0312 &priv->fwspec[i]);
0313 }
0314
0315 return 0;
0316 }
0317
0318 static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent)
0319 {
0320 struct irq_domain *irq_domain, *parent_domain;
0321 struct platform_device *pdev;
0322 struct reset_control *resetn;
0323 struct rzg2l_irqc_priv *priv;
0324 int ret;
0325
0326 pdev = of_find_device_by_node(node);
0327 if (!pdev)
0328 return -ENODEV;
0329
0330 parent_domain = irq_find_host(parent);
0331 if (!parent_domain) {
0332 dev_err(&pdev->dev, "cannot find parent domain\n");
0333 return -ENODEV;
0334 }
0335
0336 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0337 if (!priv)
0338 return -ENOMEM;
0339
0340 priv->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
0341 if (IS_ERR(priv->base))
0342 return PTR_ERR(priv->base);
0343
0344 ret = rzg2l_irqc_parse_interrupts(priv, node);
0345 if (ret) {
0346 dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret);
0347 return ret;
0348 }
0349
0350 resetn = devm_reset_control_get_exclusive(&pdev->dev, NULL);
0351 if (IS_ERR(resetn))
0352 return PTR_ERR(resetn);
0353
0354 ret = reset_control_deassert(resetn);
0355 if (ret) {
0356 dev_err(&pdev->dev, "failed to deassert resetn pin, %d\n", ret);
0357 return ret;
0358 }
0359
0360 pm_runtime_enable(&pdev->dev);
0361 ret = pm_runtime_resume_and_get(&pdev->dev);
0362 if (ret < 0) {
0363 dev_err(&pdev->dev, "pm_runtime_resume_and_get failed: %d\n", ret);
0364 goto pm_disable;
0365 }
0366
0367 raw_spin_lock_init(&priv->lock);
0368
0369 irq_domain = irq_domain_add_hierarchy(parent_domain, 0, IRQC_NUM_IRQ,
0370 node, &rzg2l_irqc_domain_ops,
0371 priv);
0372 if (!irq_domain) {
0373 dev_err(&pdev->dev, "failed to add irq domain\n");
0374 ret = -ENOMEM;
0375 goto pm_put;
0376 }
0377
0378 return 0;
0379
0380 pm_put:
0381 pm_runtime_put(&pdev->dev);
0382 pm_disable:
0383 pm_runtime_disable(&pdev->dev);
0384 reset_control_assert(resetn);
0385 return ret;
0386 }
0387
0388 IRQCHIP_PLATFORM_DRIVER_BEGIN(rzg2l_irqc)
0389 IRQCHIP_MATCH("renesas,rzg2l-irqc", rzg2l_irqc_init)
0390 IRQCHIP_PLATFORM_DRIVER_END(rzg2l_irqc)
0391 MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>");
0392 MODULE_DESCRIPTION("Renesas RZ/G2L IRQC Driver");
0393 MODULE_LICENSE("GPL");