0001
0002
0003
0004
0005
0006
0007 #define pr_fmt(fmt) "pch-pic: " fmt
0008
0009 #include <linux/interrupt.h>
0010 #include <linux/irq.h>
0011 #include <linux/irqchip.h>
0012 #include <linux/irqdomain.h>
0013 #include <linux/kernel.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/of_address.h>
0016 #include <linux/of_irq.h>
0017 #include <linux/of_platform.h>
0018
0019
0020 #define PCH_PIC_MASK 0x20
0021 #define PCH_PIC_HTMSI_EN 0x40
0022 #define PCH_PIC_EDGE 0x60
0023 #define PCH_PIC_CLR 0x80
0024 #define PCH_PIC_AUTO0 0xc0
0025 #define PCH_PIC_AUTO1 0xe0
0026 #define PCH_INT_ROUTE(irq) (0x100 + irq)
0027 #define PCH_INT_HTVEC(irq) (0x200 + irq)
0028 #define PCH_PIC_POL 0x3e0
0029
0030 #define PIC_COUNT_PER_REG 32
0031 #define PIC_REG_COUNT 2
0032 #define PIC_COUNT (PIC_COUNT_PER_REG * PIC_REG_COUNT)
0033 #define PIC_REG_IDX(irq_id) ((irq_id) / PIC_COUNT_PER_REG)
0034 #define PIC_REG_BIT(irq_id) ((irq_id) % PIC_COUNT_PER_REG)
0035
0036 static int nr_pics;
0037
0038 struct pch_pic {
0039 void __iomem *base;
0040 struct irq_domain *pic_domain;
0041 u32 ht_vec_base;
0042 raw_spinlock_t pic_lock;
0043 u32 vec_count;
0044 u32 gsi_base;
0045 };
0046
0047 static struct pch_pic *pch_pic_priv[MAX_IO_PICS];
0048
0049 struct fwnode_handle *pch_pic_handle[MAX_IO_PICS];
0050
0051 static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit)
0052 {
0053 u32 reg;
0054 void __iomem *addr = priv->base + offset + PIC_REG_IDX(bit) * 4;
0055
0056 raw_spin_lock(&priv->pic_lock);
0057 reg = readl(addr);
0058 reg |= BIT(PIC_REG_BIT(bit));
0059 writel(reg, addr);
0060 raw_spin_unlock(&priv->pic_lock);
0061 }
0062
0063 static void pch_pic_bitclr(struct pch_pic *priv, int offset, int bit)
0064 {
0065 u32 reg;
0066 void __iomem *addr = priv->base + offset + PIC_REG_IDX(bit) * 4;
0067
0068 raw_spin_lock(&priv->pic_lock);
0069 reg = readl(addr);
0070 reg &= ~BIT(PIC_REG_BIT(bit));
0071 writel(reg, addr);
0072 raw_spin_unlock(&priv->pic_lock);
0073 }
0074
0075 static void pch_pic_mask_irq(struct irq_data *d)
0076 {
0077 struct pch_pic *priv = irq_data_get_irq_chip_data(d);
0078
0079 pch_pic_bitset(priv, PCH_PIC_MASK, d->hwirq);
0080 irq_chip_mask_parent(d);
0081 }
0082
0083 static void pch_pic_unmask_irq(struct irq_data *d)
0084 {
0085 struct pch_pic *priv = irq_data_get_irq_chip_data(d);
0086
0087 writel(BIT(PIC_REG_BIT(d->hwirq)),
0088 priv->base + PCH_PIC_CLR + PIC_REG_IDX(d->hwirq) * 4);
0089
0090 irq_chip_unmask_parent(d);
0091 pch_pic_bitclr(priv, PCH_PIC_MASK, d->hwirq);
0092 }
0093
0094 static int pch_pic_set_type(struct irq_data *d, unsigned int type)
0095 {
0096 struct pch_pic *priv = irq_data_get_irq_chip_data(d);
0097 int ret = 0;
0098
0099 switch (type) {
0100 case IRQ_TYPE_EDGE_RISING:
0101 pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
0102 pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
0103 irq_set_handler_locked(d, handle_edge_irq);
0104 break;
0105 case IRQ_TYPE_EDGE_FALLING:
0106 pch_pic_bitset(priv, PCH_PIC_EDGE, d->hwirq);
0107 pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
0108 irq_set_handler_locked(d, handle_edge_irq);
0109 break;
0110 case IRQ_TYPE_LEVEL_HIGH:
0111 pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
0112 pch_pic_bitclr(priv, PCH_PIC_POL, d->hwirq);
0113 irq_set_handler_locked(d, handle_level_irq);
0114 break;
0115 case IRQ_TYPE_LEVEL_LOW:
0116 pch_pic_bitclr(priv, PCH_PIC_EDGE, d->hwirq);
0117 pch_pic_bitset(priv, PCH_PIC_POL, d->hwirq);
0118 irq_set_handler_locked(d, handle_level_irq);
0119 break;
0120 default:
0121 ret = -EINVAL;
0122 break;
0123 }
0124
0125 return ret;
0126 }
0127
0128 static void pch_pic_ack_irq(struct irq_data *d)
0129 {
0130 unsigned int reg;
0131 struct pch_pic *priv = irq_data_get_irq_chip_data(d);
0132
0133 reg = readl(priv->base + PCH_PIC_EDGE + PIC_REG_IDX(d->hwirq) * 4);
0134 if (reg & BIT(PIC_REG_BIT(d->hwirq))) {
0135 writel(BIT(PIC_REG_BIT(d->hwirq)),
0136 priv->base + PCH_PIC_CLR + PIC_REG_IDX(d->hwirq) * 4);
0137 }
0138 irq_chip_ack_parent(d);
0139 }
0140
0141 static struct irq_chip pch_pic_irq_chip = {
0142 .name = "PCH PIC",
0143 .irq_mask = pch_pic_mask_irq,
0144 .irq_unmask = pch_pic_unmask_irq,
0145 .irq_ack = pch_pic_ack_irq,
0146 .irq_set_affinity = irq_chip_set_affinity_parent,
0147 .irq_set_type = pch_pic_set_type,
0148 };
0149
0150 static int pch_pic_domain_translate(struct irq_domain *d,
0151 struct irq_fwspec *fwspec,
0152 unsigned long *hwirq,
0153 unsigned int *type)
0154 {
0155 struct pch_pic *priv = d->host_data;
0156 struct device_node *of_node = to_of_node(fwspec->fwnode);
0157
0158 if (fwspec->param_count < 1)
0159 return -EINVAL;
0160
0161 if (of_node) {
0162 *hwirq = fwspec->param[0] + priv->ht_vec_base;
0163 *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
0164 } else {
0165 *hwirq = fwspec->param[0] - priv->gsi_base;
0166 *type = IRQ_TYPE_NONE;
0167 }
0168
0169 return 0;
0170 }
0171
0172 static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq,
0173 unsigned int nr_irqs, void *arg)
0174 {
0175 int err;
0176 unsigned int type;
0177 unsigned long hwirq;
0178 struct irq_fwspec *fwspec = arg;
0179 struct irq_fwspec parent_fwspec;
0180 struct pch_pic *priv = domain->host_data;
0181
0182 err = pch_pic_domain_translate(domain, fwspec, &hwirq, &type);
0183 if (err)
0184 return err;
0185
0186 parent_fwspec.fwnode = domain->parent->fwnode;
0187 parent_fwspec.param_count = 1;
0188 parent_fwspec.param[0] = hwirq;
0189
0190 err = irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec);
0191 if (err)
0192 return err;
0193
0194 irq_domain_set_info(domain, virq, hwirq,
0195 &pch_pic_irq_chip, priv,
0196 handle_level_irq, NULL, NULL);
0197 irq_set_probe(virq);
0198
0199 return 0;
0200 }
0201
0202 static const struct irq_domain_ops pch_pic_domain_ops = {
0203 .translate = pch_pic_domain_translate,
0204 .alloc = pch_pic_alloc,
0205 .free = irq_domain_free_irqs_parent,
0206 };
0207
0208 static void pch_pic_reset(struct pch_pic *priv)
0209 {
0210 int i;
0211
0212 for (i = 0; i < PIC_COUNT; i++) {
0213
0214 writeb(priv->ht_vec_base + i, priv->base + PCH_INT_HTVEC(i));
0215
0216 writeb(1, priv->base + PCH_INT_ROUTE(i));
0217 }
0218
0219 for (i = 0; i < PIC_REG_COUNT; i++) {
0220
0221 writel_relaxed(0xFFFFFFFF, priv->base + PCH_PIC_MASK + 4 * i);
0222 writel_relaxed(0xFFFFFFFF, priv->base + PCH_PIC_CLR + 4 * i);
0223
0224 writel_relaxed(0, priv->base + PCH_PIC_AUTO0 + 4 * i);
0225 writel_relaxed(0, priv->base + PCH_PIC_AUTO1 + 4 * i);
0226
0227 writel_relaxed(0xFFFFFFFF, priv->base + PCH_PIC_HTMSI_EN + 4 * i);
0228 }
0229 }
0230
0231 static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base,
0232 struct irq_domain *parent_domain, struct fwnode_handle *domain_handle,
0233 u32 gsi_base)
0234 {
0235 struct pch_pic *priv;
0236
0237 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0238 if (!priv)
0239 return -ENOMEM;
0240
0241 raw_spin_lock_init(&priv->pic_lock);
0242 priv->base = ioremap(addr, size);
0243 if (!priv->base)
0244 goto free_priv;
0245
0246 priv->ht_vec_base = vec_base;
0247 priv->vec_count = ((readq(priv->base) >> 48) & 0xff) + 1;
0248 priv->gsi_base = gsi_base;
0249
0250 priv->pic_domain = irq_domain_create_hierarchy(parent_domain, 0,
0251 priv->vec_count, domain_handle,
0252 &pch_pic_domain_ops, priv);
0253
0254 if (!priv->pic_domain) {
0255 pr_err("Failed to create IRQ domain\n");
0256 goto iounmap_base;
0257 }
0258
0259 pch_pic_reset(priv);
0260 pch_pic_handle[nr_pics] = domain_handle;
0261 pch_pic_priv[nr_pics++] = priv;
0262
0263 return 0;
0264
0265 iounmap_base:
0266 iounmap(priv->base);
0267 free_priv:
0268 kfree(priv);
0269
0270 return -EINVAL;
0271 }
0272
0273 #ifdef CONFIG_OF
0274
0275 static int pch_pic_of_init(struct device_node *node,
0276 struct device_node *parent)
0277 {
0278 int err, vec_base;
0279 struct resource res;
0280 struct irq_domain *parent_domain;
0281
0282 if (of_address_to_resource(node, 0, &res))
0283 return -EINVAL;
0284
0285 parent_domain = irq_find_host(parent);
0286 if (!parent_domain) {
0287 pr_err("Failed to find the parent domain\n");
0288 return -ENXIO;
0289 }
0290
0291 if (of_property_read_u32(node, "loongson,pic-base-vec", &vec_base)) {
0292 pr_err("Failed to determine pic-base-vec\n");
0293 return -EINVAL;
0294 }
0295
0296 err = pch_pic_init(res.start, resource_size(&res), vec_base,
0297 parent_domain, of_node_to_fwnode(node), 0);
0298 if (err < 0)
0299 return err;
0300
0301 return 0;
0302 }
0303
0304 IRQCHIP_DECLARE(pch_pic, "loongson,pch-pic-1.0", pch_pic_of_init);
0305
0306 #endif
0307
0308 #ifdef CONFIG_ACPI
0309 int find_pch_pic(u32 gsi)
0310 {
0311 int i;
0312
0313
0314 for (i = 0; i < MAX_IO_PICS; i++) {
0315 struct pch_pic *priv = pch_pic_priv[i];
0316
0317 if (!priv)
0318 return -1;
0319
0320 if (gsi >= priv->gsi_base && gsi < (priv->gsi_base + priv->vec_count))
0321 return i;
0322 }
0323
0324 pr_err("ERROR: Unable to locate PCH_PIC for GSI %d\n", gsi);
0325 return -1;
0326 }
0327
0328 static int __init
0329 pch_lpc_parse_madt(union acpi_subtable_headers *header,
0330 const unsigned long end)
0331 {
0332 struct acpi_madt_lpc_pic *pchlpc_entry = (struct acpi_madt_lpc_pic *)header;
0333
0334 return pch_lpc_acpi_init(pch_pic_priv[0]->pic_domain, pchlpc_entry);
0335 }
0336
0337 static int __init acpi_cascade_irqdomain_init(void)
0338 {
0339 acpi_table_parse_madt(ACPI_MADT_TYPE_LPC_PIC,
0340 pch_lpc_parse_madt, 0);
0341 return 0;
0342 }
0343
0344 int __init pch_pic_acpi_init(struct irq_domain *parent,
0345 struct acpi_madt_bio_pic *acpi_pchpic)
0346 {
0347 int ret, vec_base;
0348 struct fwnode_handle *domain_handle;
0349
0350 vec_base = acpi_pchpic->gsi_base - GSI_MIN_PCH_IRQ;
0351
0352 domain_handle = irq_domain_alloc_fwnode(&acpi_pchpic->address);
0353 if (!domain_handle) {
0354 pr_err("Unable to allocate domain handle\n");
0355 return -ENOMEM;
0356 }
0357
0358 ret = pch_pic_init(acpi_pchpic->address, acpi_pchpic->size,
0359 vec_base, parent, domain_handle, acpi_pchpic->gsi_base);
0360
0361 if (ret < 0) {
0362 irq_domain_free_fwnode(domain_handle);
0363 return ret;
0364 }
0365
0366 if (acpi_pchpic->id == 0)
0367 acpi_cascade_irqdomain_init();
0368
0369 return ret;
0370 }
0371 #endif