brintos

brintos / linux-shallow public Read only

0
0
Text · 10.6 KiB · bbae3d3 Raw
488 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * arch/powerpc/sysdev/qe_lib/qe_ic.c4 *5 * Copyright (C) 2006 Freescale Semiconductor, Inc.  All rights reserved.6 *7 * Author: Li Yang <leoli@freescale.com>8 * Based on code from Shlomi Gridish <gridish@freescale.com>9 *10 * QUICC ENGINE Interrupt Controller11 */12 13#include <linux/of_irq.h>14#include <linux/of_address.h>15#include <linux/kernel.h>16#include <linux/init.h>17#include <linux/errno.h>18#include <linux/irq.h>19#include <linux/reboot.h>20#include <linux/slab.h>21#include <linux/stddef.h>22#include <linux/sched.h>23#include <linux/signal.h>24#include <linux/device.h>25#include <linux/spinlock.h>26#include <linux/platform_device.h>27#include <asm/irq.h>28#include <asm/io.h>29#include <soc/fsl/qe/qe.h>30 31#define NR_QE_IC_INTS		6432 33/* QE IC registers offset */34#define QEIC_CICR		0x0035#define QEIC_CIVEC		0x0436#define QEIC_CIPXCC		0x1037#define QEIC_CIPYCC		0x1438#define QEIC_CIPWCC		0x1839#define QEIC_CIPZCC		0x1c40#define QEIC_CIMR		0x2041#define QEIC_CRIMR		0x2442#define QEIC_CIPRTA		0x3043#define QEIC_CIPRTB		0x3444#define QEIC_CHIVEC		0x6045 46struct qe_ic {47	/* Control registers offset */48	__be32 __iomem *regs;49 50	/* The remapper for this QEIC */51	struct irq_domain *irqhost;52 53	/* The "linux" controller struct */54	struct irq_chip hc_irq;55 56	/* VIRQ numbers of QE high/low irqs */57	int virq_high;58	int virq_low;59};60 61/*62 * QE interrupt controller internal structure63 */64struct qe_ic_info {65	/* Location of this source at the QIMR register */66	u32	mask;67 68	/* Mask register offset */69	u32	mask_reg;70 71	/*72	 * For grouped interrupts sources - the interrupt code as73	 * appears at the group priority register74	 */75	u8	pri_code;76 77	/* Group priority register offset */78	u32	pri_reg;79};80 81static DEFINE_RAW_SPINLOCK(qe_ic_lock);82 83static struct qe_ic_info qe_ic_info[] = {84	[1] = {85	       .mask = 0x00008000,86	       .mask_reg = QEIC_CIMR,87	       .pri_code = 0,88	       .pri_reg = QEIC_CIPWCC,89	       },90	[2] = {91	       .mask = 0x00004000,92	       .mask_reg = QEIC_CIMR,93	       .pri_code = 1,94	       .pri_reg = QEIC_CIPWCC,95	       },96	[3] = {97	       .mask = 0x00002000,98	       .mask_reg = QEIC_CIMR,99	       .pri_code = 2,100	       .pri_reg = QEIC_CIPWCC,101	       },102	[10] = {103		.mask = 0x00000040,104		.mask_reg = QEIC_CIMR,105		.pri_code = 1,106		.pri_reg = QEIC_CIPZCC,107		},108	[11] = {109		.mask = 0x00000020,110		.mask_reg = QEIC_CIMR,111		.pri_code = 2,112		.pri_reg = QEIC_CIPZCC,113		},114	[12] = {115		.mask = 0x00000010,116		.mask_reg = QEIC_CIMR,117		.pri_code = 3,118		.pri_reg = QEIC_CIPZCC,119		},120	[13] = {121		.mask = 0x00000008,122		.mask_reg = QEIC_CIMR,123		.pri_code = 4,124		.pri_reg = QEIC_CIPZCC,125		},126	[14] = {127		.mask = 0x00000004,128		.mask_reg = QEIC_CIMR,129		.pri_code = 5,130		.pri_reg = QEIC_CIPZCC,131		},132	[15] = {133		.mask = 0x00000002,134		.mask_reg = QEIC_CIMR,135		.pri_code = 6,136		.pri_reg = QEIC_CIPZCC,137		},138	[20] = {139		.mask = 0x10000000,140		.mask_reg = QEIC_CRIMR,141		.pri_code = 3,142		.pri_reg = QEIC_CIPRTA,143		},144	[25] = {145		.mask = 0x00800000,146		.mask_reg = QEIC_CRIMR,147		.pri_code = 0,148		.pri_reg = QEIC_CIPRTB,149		},150	[26] = {151		.mask = 0x00400000,152		.mask_reg = QEIC_CRIMR,153		.pri_code = 1,154		.pri_reg = QEIC_CIPRTB,155		},156	[27] = {157		.mask = 0x00200000,158		.mask_reg = QEIC_CRIMR,159		.pri_code = 2,160		.pri_reg = QEIC_CIPRTB,161		},162	[28] = {163		.mask = 0x00100000,164		.mask_reg = QEIC_CRIMR,165		.pri_code = 3,166		.pri_reg = QEIC_CIPRTB,167		},168	[32] = {169		.mask = 0x80000000,170		.mask_reg = QEIC_CIMR,171		.pri_code = 0,172		.pri_reg = QEIC_CIPXCC,173		},174	[33] = {175		.mask = 0x40000000,176		.mask_reg = QEIC_CIMR,177		.pri_code = 1,178		.pri_reg = QEIC_CIPXCC,179		},180	[34] = {181		.mask = 0x20000000,182		.mask_reg = QEIC_CIMR,183		.pri_code = 2,184		.pri_reg = QEIC_CIPXCC,185		},186	[35] = {187		.mask = 0x10000000,188		.mask_reg = QEIC_CIMR,189		.pri_code = 3,190		.pri_reg = QEIC_CIPXCC,191		},192	[36] = {193		.mask = 0x08000000,194		.mask_reg = QEIC_CIMR,195		.pri_code = 4,196		.pri_reg = QEIC_CIPXCC,197		},198	[40] = {199		.mask = 0x00800000,200		.mask_reg = QEIC_CIMR,201		.pri_code = 0,202		.pri_reg = QEIC_CIPYCC,203		},204	[41] = {205		.mask = 0x00400000,206		.mask_reg = QEIC_CIMR,207		.pri_code = 1,208		.pri_reg = QEIC_CIPYCC,209		},210	[42] = {211		.mask = 0x00200000,212		.mask_reg = QEIC_CIMR,213		.pri_code = 2,214		.pri_reg = QEIC_CIPYCC,215		},216	[43] = {217		.mask = 0x00100000,218		.mask_reg = QEIC_CIMR,219		.pri_code = 3,220		.pri_reg = QEIC_CIPYCC,221		},222};223 224static inline u32 qe_ic_read(__be32  __iomem *base, unsigned int reg)225{226	return ioread32be(base + (reg >> 2));227}228 229static inline void qe_ic_write(__be32  __iomem *base, unsigned int reg,230			       u32 value)231{232	iowrite32be(value, base + (reg >> 2));233}234 235static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)236{237	return irq_get_chip_data(virq);238}239 240static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d)241{242	return irq_data_get_irq_chip_data(d);243}244 245static void qe_ic_unmask_irq(struct irq_data *d)246{247	struct qe_ic *qe_ic = qe_ic_from_irq_data(d);248	unsigned int src = irqd_to_hwirq(d);249	unsigned long flags;250	u32 temp;251 252	raw_spin_lock_irqsave(&qe_ic_lock, flags);253 254	temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);255	qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,256		    temp | qe_ic_info[src].mask);257 258	raw_spin_unlock_irqrestore(&qe_ic_lock, flags);259}260 261static void qe_ic_mask_irq(struct irq_data *d)262{263	struct qe_ic *qe_ic = qe_ic_from_irq_data(d);264	unsigned int src = irqd_to_hwirq(d);265	unsigned long flags;266	u32 temp;267 268	raw_spin_lock_irqsave(&qe_ic_lock, flags);269 270	temp = qe_ic_read(qe_ic->regs, qe_ic_info[src].mask_reg);271	qe_ic_write(qe_ic->regs, qe_ic_info[src].mask_reg,272		    temp & ~qe_ic_info[src].mask);273 274	/* Flush the above write before enabling interrupts; otherwise,275	 * spurious interrupts will sometimes happen.  To be 100% sure276	 * that the write has reached the device before interrupts are277	 * enabled, the mask register would have to be read back; however,278	 * this is not required for correctness, only to avoid wasting279	 * time on a large number of spurious interrupts.  In testing,280	 * a sync reduced the observed spurious interrupts to zero.281	 */282	mb();283 284	raw_spin_unlock_irqrestore(&qe_ic_lock, flags);285}286 287static struct irq_chip qe_ic_irq_chip = {288	.name = "QEIC",289	.irq_unmask = qe_ic_unmask_irq,290	.irq_mask = qe_ic_mask_irq,291	.irq_mask_ack = qe_ic_mask_irq,292};293 294static int qe_ic_host_match(struct irq_domain *h, struct device_node *node,295			    enum irq_domain_bus_token bus_token)296{297	/* Exact match, unless qe_ic node is NULL */298	struct device_node *of_node = irq_domain_get_of_node(h);299	return of_node == NULL || of_node == node;300}301 302static int qe_ic_host_map(struct irq_domain *h, unsigned int virq,303			  irq_hw_number_t hw)304{305	struct qe_ic *qe_ic = h->host_data;306	struct irq_chip *chip;307 308	if (hw >= ARRAY_SIZE(qe_ic_info)) {309		pr_err("%s: Invalid hw irq number for QEIC\n", __func__);310		return -EINVAL;311	}312 313	if (qe_ic_info[hw].mask == 0) {314		printk(KERN_ERR "Can't map reserved IRQ\n");315		return -EINVAL;316	}317	/* Default chip */318	chip = &qe_ic->hc_irq;319 320	irq_set_chip_data(virq, qe_ic);321	irq_set_status_flags(virq, IRQ_LEVEL);322 323	irq_set_chip_and_handler(virq, chip, handle_level_irq);324 325	return 0;326}327 328static const struct irq_domain_ops qe_ic_host_ops = {329	.match = qe_ic_host_match,330	.map = qe_ic_host_map,331	.xlate = irq_domain_xlate_onetwocell,332};333 334/* Return an interrupt vector or 0 if no interrupt is pending. */335static unsigned int qe_ic_get_low_irq(struct qe_ic *qe_ic)336{337	int irq;338 339	BUG_ON(qe_ic == NULL);340 341	/* get the interrupt source vector. */342	irq = qe_ic_read(qe_ic->regs, QEIC_CIVEC) >> 26;343 344	if (irq == 0)345		return 0;346 347	return irq_linear_revmap(qe_ic->irqhost, irq);348}349 350/* Return an interrupt vector or 0 if no interrupt is pending. */351static unsigned int qe_ic_get_high_irq(struct qe_ic *qe_ic)352{353	int irq;354 355	BUG_ON(qe_ic == NULL);356 357	/* get the interrupt source vector. */358	irq = qe_ic_read(qe_ic->regs, QEIC_CHIVEC) >> 26;359 360	if (irq == 0)361		return 0;362 363	return irq_linear_revmap(qe_ic->irqhost, irq);364}365 366static void qe_ic_cascade_low(struct irq_desc *desc)367{368	struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);369	unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);370	struct irq_chip *chip = irq_desc_get_chip(desc);371 372	if (cascade_irq != 0)373		generic_handle_irq(cascade_irq);374 375	if (chip->irq_eoi)376		chip->irq_eoi(&desc->irq_data);377}378 379static void qe_ic_cascade_high(struct irq_desc *desc)380{381	struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);382	unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);383	struct irq_chip *chip = irq_desc_get_chip(desc);384 385	if (cascade_irq != 0)386		generic_handle_irq(cascade_irq);387 388	if (chip->irq_eoi)389		chip->irq_eoi(&desc->irq_data);390}391 392static void qe_ic_cascade_muxed_mpic(struct irq_desc *desc)393{394	struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);395	unsigned int cascade_irq;396	struct irq_chip *chip = irq_desc_get_chip(desc);397 398	cascade_irq = qe_ic_get_high_irq(qe_ic);399	if (cascade_irq == 0)400		cascade_irq = qe_ic_get_low_irq(qe_ic);401 402	if (cascade_irq != 0)403		generic_handle_irq(cascade_irq);404 405	chip->irq_eoi(&desc->irq_data);406}407 408static int qe_ic_init(struct platform_device *pdev)409{410	struct device *dev = &pdev->dev;411	void (*low_handler)(struct irq_desc *desc);412	void (*high_handler)(struct irq_desc *desc);413	struct qe_ic *qe_ic;414	struct resource *res;415	struct device_node *node = pdev->dev.of_node;416 417	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);418	if (res == NULL) {419		dev_err(dev, "no memory resource defined\n");420		return -ENODEV;421	}422 423	qe_ic = devm_kzalloc(dev, sizeof(*qe_ic), GFP_KERNEL);424	if (qe_ic == NULL)425		return -ENOMEM;426 427	qe_ic->regs = devm_ioremap(dev, res->start, resource_size(res));428	if (qe_ic->regs == NULL) {429		dev_err(dev, "failed to ioremap() registers\n");430		return -ENODEV;431	}432 433	qe_ic->hc_irq = qe_ic_irq_chip;434 435	qe_ic->virq_high = platform_get_irq(pdev, 0);436	qe_ic->virq_low = platform_get_irq(pdev, 1);437 438	if (qe_ic->virq_low <= 0)439		return -ENODEV;440 441	if (qe_ic->virq_high > 0 && qe_ic->virq_high != qe_ic->virq_low) {442		low_handler = qe_ic_cascade_low;443		high_handler = qe_ic_cascade_high;444	} else {445		low_handler = qe_ic_cascade_muxed_mpic;446		high_handler = NULL;447	}448 449	qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS,450					       &qe_ic_host_ops, qe_ic);451	if (qe_ic->irqhost == NULL) {452		dev_err(dev, "failed to add irq domain\n");453		return -ENODEV;454	}455 456	qe_ic_write(qe_ic->regs, QEIC_CICR, 0);457 458	irq_set_handler_data(qe_ic->virq_low, qe_ic);459	irq_set_chained_handler(qe_ic->virq_low, low_handler);460 461	if (high_handler) {462		irq_set_handler_data(qe_ic->virq_high, qe_ic);463		irq_set_chained_handler(qe_ic->virq_high, high_handler);464	}465	return 0;466}467static const struct of_device_id qe_ic_ids[] = {468	{ .compatible = "fsl,qe-ic"},469	{ .type = "qeic"},470	{},471};472 473static struct platform_driver qe_ic_driver =474{475	.driver	= {476		.name		= "qe-ic",477		.of_match_table	= qe_ic_ids,478	},479	.probe	= qe_ic_init,480};481 482static int __init qe_ic_of_init(void)483{484	platform_driver_register(&qe_ic_driver);485	return 0;486}487subsys_initcall(qe_ic_of_init);488