Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Renesas RZ/G2L IRQC Driver
0004  *
0005  * Copyright (C) 2022 Renesas Electronics Corporation.
0006  *
0007  * Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
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      * For TINT interrupts ie where pinctrl driver is child of irqc domain
0270      * the hwirq and TINT are encoded in fwspec->param[0].
0271      * hwirq for TINT range from 9-40, hwirq is embedded 0-15 bits and TINT
0272      * from 16-31 bits. TINT from the pinctrl driver needs to be programmed
0273      * in IRQC registers to enable a given gpio pin as interrupt.
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");