cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

irq-imgpdc.c (13402B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * IMG PowerDown Controller (PDC)
      4 *
      5 * Copyright 2010-2013 Imagination Technologies Ltd.
      6 *
      7 * Exposes the syswake and PDC peripheral wake interrupts to the system.
      8 *
      9 */
     10
     11#include <linux/bitops.h>
     12#include <linux/interrupt.h>
     13#include <linux/irqdomain.h>
     14#include <linux/io.h>
     15#include <linux/kernel.h>
     16#include <linux/of.h>
     17#include <linux/platform_device.h>
     18#include <linux/spinlock.h>
     19
     20/* PDC interrupt register numbers */
     21
     22#define PDC_IRQ_STATUS			0x310
     23#define PDC_IRQ_ENABLE			0x314
     24#define PDC_IRQ_CLEAR			0x318
     25#define PDC_IRQ_ROUTE			0x31c
     26#define PDC_SYS_WAKE_BASE		0x330
     27#define PDC_SYS_WAKE_STRIDE		0x8
     28#define PDC_SYS_WAKE_CONFIG_BASE	0x334
     29#define PDC_SYS_WAKE_CONFIG_STRIDE	0x8
     30
     31/* PDC interrupt register field masks */
     32
     33#define PDC_IRQ_SYS3			0x08
     34#define PDC_IRQ_SYS2			0x04
     35#define PDC_IRQ_SYS1			0x02
     36#define PDC_IRQ_SYS0			0x01
     37#define PDC_IRQ_ROUTE_WU_EN_SYS3	0x08000000
     38#define PDC_IRQ_ROUTE_WU_EN_SYS2	0x04000000
     39#define PDC_IRQ_ROUTE_WU_EN_SYS1	0x02000000
     40#define PDC_IRQ_ROUTE_WU_EN_SYS0	0x01000000
     41#define PDC_IRQ_ROUTE_WU_EN_WD		0x00040000
     42#define PDC_IRQ_ROUTE_WU_EN_IR		0x00020000
     43#define PDC_IRQ_ROUTE_WU_EN_RTC		0x00010000
     44#define PDC_IRQ_ROUTE_EXT_EN_SYS3	0x00000800
     45#define PDC_IRQ_ROUTE_EXT_EN_SYS2	0x00000400
     46#define PDC_IRQ_ROUTE_EXT_EN_SYS1	0x00000200
     47#define PDC_IRQ_ROUTE_EXT_EN_SYS0	0x00000100
     48#define PDC_IRQ_ROUTE_EXT_EN_WD		0x00000004
     49#define PDC_IRQ_ROUTE_EXT_EN_IR		0x00000002
     50#define PDC_IRQ_ROUTE_EXT_EN_RTC	0x00000001
     51#define PDC_SYS_WAKE_RESET		0x00000010
     52#define PDC_SYS_WAKE_INT_MODE		0x0000000e
     53#define PDC_SYS_WAKE_INT_MODE_SHIFT	1
     54#define PDC_SYS_WAKE_PIN_VAL		0x00000001
     55
     56/* PDC interrupt constants */
     57
     58#define PDC_SYS_WAKE_INT_LOW		0x0
     59#define PDC_SYS_WAKE_INT_HIGH		0x1
     60#define PDC_SYS_WAKE_INT_DOWN		0x2
     61#define PDC_SYS_WAKE_INT_UP		0x3
     62#define PDC_SYS_WAKE_INT_CHANGE		0x6
     63#define PDC_SYS_WAKE_INT_NONE		0x4
     64
     65/**
     66 * struct pdc_intc_priv - private pdc interrupt data.
     67 * @nr_perips:		Number of peripheral interrupt signals.
     68 * @nr_syswakes:	Number of syswake signals.
     69 * @perip_irqs:		List of peripheral IRQ numbers handled.
     70 * @syswake_irq:	Shared PDC syswake IRQ number.
     71 * @domain:		IRQ domain for PDC peripheral and syswake IRQs.
     72 * @pdc_base:		Base of PDC registers.
     73 * @irq_route:		Cached version of PDC_IRQ_ROUTE register.
     74 * @lock:		Lock to protect the PDC syswake registers and the cached
     75 *			values of those registers in this struct.
     76 */
     77struct pdc_intc_priv {
     78	unsigned int		nr_perips;
     79	unsigned int		nr_syswakes;
     80	unsigned int		*perip_irqs;
     81	unsigned int		syswake_irq;
     82	struct irq_domain	*domain;
     83	void __iomem		*pdc_base;
     84
     85	u32			irq_route;
     86	raw_spinlock_t		lock;
     87};
     88
     89static void pdc_write(struct pdc_intc_priv *priv, unsigned int reg_offs,
     90		      unsigned int data)
     91{
     92	iowrite32(data, priv->pdc_base + reg_offs);
     93}
     94
     95static unsigned int pdc_read(struct pdc_intc_priv *priv,
     96			     unsigned int reg_offs)
     97{
     98	return ioread32(priv->pdc_base + reg_offs);
     99}
    100
    101/* Generic IRQ callbacks */
    102
    103#define SYS0_HWIRQ	8
    104
    105static unsigned int hwirq_is_syswake(irq_hw_number_t hw)
    106{
    107	return hw >= SYS0_HWIRQ;
    108}
    109
    110static unsigned int hwirq_to_syswake(irq_hw_number_t hw)
    111{
    112	return hw - SYS0_HWIRQ;
    113}
    114
    115static irq_hw_number_t syswake_to_hwirq(unsigned int syswake)
    116{
    117	return SYS0_HWIRQ + syswake;
    118}
    119
    120static struct pdc_intc_priv *irqd_to_priv(struct irq_data *data)
    121{
    122	return (struct pdc_intc_priv *)data->domain->host_data;
    123}
    124
    125/*
    126 * perip_irq_mask() and perip_irq_unmask() use IRQ_ROUTE which also contains
    127 * wake bits, therefore we cannot use the generic irqchip mask callbacks as they
    128 * cache the mask.
    129 */
    130
    131static void perip_irq_mask(struct irq_data *data)
    132{
    133	struct pdc_intc_priv *priv = irqd_to_priv(data);
    134
    135	raw_spin_lock(&priv->lock);
    136	priv->irq_route &= ~data->mask;
    137	pdc_write(priv, PDC_IRQ_ROUTE, priv->irq_route);
    138	raw_spin_unlock(&priv->lock);
    139}
    140
    141static void perip_irq_unmask(struct irq_data *data)
    142{
    143	struct pdc_intc_priv *priv = irqd_to_priv(data);
    144
    145	raw_spin_lock(&priv->lock);
    146	priv->irq_route |= data->mask;
    147	pdc_write(priv, PDC_IRQ_ROUTE, priv->irq_route);
    148	raw_spin_unlock(&priv->lock);
    149}
    150
    151static int syswake_irq_set_type(struct irq_data *data, unsigned int flow_type)
    152{
    153	struct pdc_intc_priv *priv = irqd_to_priv(data);
    154	unsigned int syswake = hwirq_to_syswake(data->hwirq);
    155	unsigned int irq_mode;
    156	unsigned int soc_sys_wake_regoff, soc_sys_wake;
    157
    158	/* translate to syswake IRQ mode */
    159	switch (flow_type) {
    160	case IRQ_TYPE_EDGE_BOTH:
    161		irq_mode = PDC_SYS_WAKE_INT_CHANGE;
    162		break;
    163	case IRQ_TYPE_EDGE_RISING:
    164		irq_mode = PDC_SYS_WAKE_INT_UP;
    165		break;
    166	case IRQ_TYPE_EDGE_FALLING:
    167		irq_mode = PDC_SYS_WAKE_INT_DOWN;
    168		break;
    169	case IRQ_TYPE_LEVEL_HIGH:
    170		irq_mode = PDC_SYS_WAKE_INT_HIGH;
    171		break;
    172	case IRQ_TYPE_LEVEL_LOW:
    173		irq_mode = PDC_SYS_WAKE_INT_LOW;
    174		break;
    175	default:
    176		return -EINVAL;
    177	}
    178
    179	raw_spin_lock(&priv->lock);
    180
    181	/* set the IRQ mode */
    182	soc_sys_wake_regoff = PDC_SYS_WAKE_BASE + syswake*PDC_SYS_WAKE_STRIDE;
    183	soc_sys_wake = pdc_read(priv, soc_sys_wake_regoff);
    184	soc_sys_wake &= ~PDC_SYS_WAKE_INT_MODE;
    185	soc_sys_wake |= irq_mode << PDC_SYS_WAKE_INT_MODE_SHIFT;
    186	pdc_write(priv, soc_sys_wake_regoff, soc_sys_wake);
    187
    188	/* and update the handler */
    189	irq_setup_alt_chip(data, flow_type);
    190
    191	raw_spin_unlock(&priv->lock);
    192
    193	return 0;
    194}
    195
    196/* applies to both peripheral and syswake interrupts */
    197static int pdc_irq_set_wake(struct irq_data *data, unsigned int on)
    198{
    199	struct pdc_intc_priv *priv = irqd_to_priv(data);
    200	irq_hw_number_t hw = data->hwirq;
    201	unsigned int mask = (1 << 16) << hw;
    202	unsigned int dst_irq;
    203
    204	raw_spin_lock(&priv->lock);
    205	if (on)
    206		priv->irq_route |= mask;
    207	else
    208		priv->irq_route &= ~mask;
    209	pdc_write(priv, PDC_IRQ_ROUTE, priv->irq_route);
    210	raw_spin_unlock(&priv->lock);
    211
    212	/* control the destination IRQ wakeup too for standby mode */
    213	if (hwirq_is_syswake(hw))
    214		dst_irq = priv->syswake_irq;
    215	else
    216		dst_irq = priv->perip_irqs[hw];
    217	irq_set_irq_wake(dst_irq, on);
    218
    219	return 0;
    220}
    221
    222static void pdc_intc_perip_isr(struct irq_desc *desc)
    223{
    224	unsigned int irq = irq_desc_get_irq(desc);
    225	struct pdc_intc_priv *priv;
    226	unsigned int i;
    227
    228	priv = (struct pdc_intc_priv *)irq_desc_get_handler_data(desc);
    229
    230	/* find the peripheral number */
    231	for (i = 0; i < priv->nr_perips; ++i)
    232		if (irq == priv->perip_irqs[i])
    233			goto found;
    234
    235	/* should never get here */
    236	return;
    237found:
    238
    239	/* pass on the interrupt */
    240	generic_handle_domain_irq(priv->domain, i);
    241}
    242
    243static void pdc_intc_syswake_isr(struct irq_desc *desc)
    244{
    245	struct pdc_intc_priv *priv;
    246	unsigned int syswake;
    247	unsigned int status;
    248
    249	priv = (struct pdc_intc_priv *)irq_desc_get_handler_data(desc);
    250
    251	status = pdc_read(priv, PDC_IRQ_STATUS) &
    252		 pdc_read(priv, PDC_IRQ_ENABLE);
    253	status &= (1 << priv->nr_syswakes) - 1;
    254
    255	for (syswake = 0; status; status >>= 1, ++syswake) {
    256		/* Has this sys_wake triggered? */
    257		if (!(status & 1))
    258			continue;
    259
    260		generic_handle_domain_irq(priv->domain, syswake_to_hwirq(syswake));
    261	}
    262}
    263
    264static void pdc_intc_setup(struct pdc_intc_priv *priv)
    265{
    266	int i;
    267	unsigned int soc_sys_wake_regoff;
    268	unsigned int soc_sys_wake;
    269
    270	/*
    271	 * Mask all syswake interrupts before routing, or we could receive an
    272	 * interrupt before we're ready to handle it.
    273	 */
    274	pdc_write(priv, PDC_IRQ_ENABLE, 0);
    275
    276	/*
    277	 * Enable routing of all syswakes
    278	 * Disable all wake sources
    279	 */
    280	priv->irq_route = ((PDC_IRQ_ROUTE_EXT_EN_SYS0 << priv->nr_syswakes) -
    281				PDC_IRQ_ROUTE_EXT_EN_SYS0);
    282	pdc_write(priv, PDC_IRQ_ROUTE, priv->irq_route);
    283
    284	/* Initialise syswake IRQ */
    285	for (i = 0; i < priv->nr_syswakes; ++i) {
    286		/* set the IRQ mode to none */
    287		soc_sys_wake_regoff = PDC_SYS_WAKE_BASE + i*PDC_SYS_WAKE_STRIDE;
    288		soc_sys_wake = PDC_SYS_WAKE_INT_NONE
    289				<< PDC_SYS_WAKE_INT_MODE_SHIFT;
    290		pdc_write(priv, soc_sys_wake_regoff, soc_sys_wake);
    291	}
    292}
    293
    294static int pdc_intc_probe(struct platform_device *pdev)
    295{
    296	struct pdc_intc_priv *priv;
    297	struct device_node *node = pdev->dev.of_node;
    298	struct resource *res_regs;
    299	struct irq_chip_generic *gc;
    300	unsigned int i;
    301	int irq, ret;
    302	u32 val;
    303
    304	if (!node)
    305		return -ENOENT;
    306
    307	/* Get registers */
    308	res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    309	if (res_regs == NULL) {
    310		dev_err(&pdev->dev, "cannot find registers resource\n");
    311		return -ENOENT;
    312	}
    313
    314	/* Allocate driver data */
    315	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
    316	if (!priv)
    317		return -ENOMEM;
    318	raw_spin_lock_init(&priv->lock);
    319	platform_set_drvdata(pdev, priv);
    320
    321	/* Ioremap the registers */
    322	priv->pdc_base = devm_ioremap(&pdev->dev, res_regs->start,
    323				      resource_size(res_regs));
    324	if (!priv->pdc_base)
    325		return -EIO;
    326
    327	/* Get number of peripherals */
    328	ret = of_property_read_u32(node, "num-perips", &val);
    329	if (ret) {
    330		dev_err(&pdev->dev, "No num-perips node property found\n");
    331		return -EINVAL;
    332	}
    333	if (val > SYS0_HWIRQ) {
    334		dev_err(&pdev->dev, "num-perips (%u) out of range\n", val);
    335		return -EINVAL;
    336	}
    337	priv->nr_perips = val;
    338
    339	/* Get number of syswakes */
    340	ret = of_property_read_u32(node, "num-syswakes", &val);
    341	if (ret) {
    342		dev_err(&pdev->dev, "No num-syswakes node property found\n");
    343		return -EINVAL;
    344	}
    345	if (val > SYS0_HWIRQ) {
    346		dev_err(&pdev->dev, "num-syswakes (%u) out of range\n", val);
    347		return -EINVAL;
    348	}
    349	priv->nr_syswakes = val;
    350
    351	/* Get peripheral IRQ numbers */
    352	priv->perip_irqs = devm_kcalloc(&pdev->dev, 4, priv->nr_perips,
    353					GFP_KERNEL);
    354	if (!priv->perip_irqs)
    355		return -ENOMEM;
    356	for (i = 0; i < priv->nr_perips; ++i) {
    357		irq = platform_get_irq(pdev, 1 + i);
    358		if (irq < 0)
    359			return irq;
    360		priv->perip_irqs[i] = irq;
    361	}
    362	/* check if too many were provided */
    363	if (platform_get_irq(pdev, 1 + i) >= 0) {
    364		dev_err(&pdev->dev, "surplus perip IRQs detected\n");
    365		return -EINVAL;
    366	}
    367
    368	/* Get syswake IRQ number */
    369	irq = platform_get_irq(pdev, 0);
    370	if (irq < 0)
    371		return irq;
    372	priv->syswake_irq = irq;
    373
    374	/* Set up an IRQ domain */
    375	priv->domain = irq_domain_add_linear(node, 16, &irq_generic_chip_ops,
    376					     priv);
    377	if (unlikely(!priv->domain)) {
    378		dev_err(&pdev->dev, "cannot add IRQ domain\n");
    379		return -ENOMEM;
    380	}
    381
    382	/*
    383	 * Set up 2 generic irq chips with 2 chip types.
    384	 * The first one for peripheral irqs (only 1 chip type used)
    385	 * The second one for syswake irqs (edge and level chip types)
    386	 */
    387	ret = irq_alloc_domain_generic_chips(priv->domain, 8, 2, "pdc",
    388					     handle_level_irq, 0, 0,
    389					     IRQ_GC_INIT_NESTED_LOCK);
    390	if (ret)
    391		goto err_generic;
    392
    393	/* peripheral interrupt chip */
    394
    395	gc = irq_get_domain_generic_chip(priv->domain, 0);
    396	gc->unused	= ~(BIT(priv->nr_perips) - 1);
    397	gc->reg_base	= priv->pdc_base;
    398	/*
    399	 * IRQ_ROUTE contains wake bits, so we can't use the generic versions as
    400	 * they cache the mask
    401	 */
    402	gc->chip_types[0].regs.mask		= PDC_IRQ_ROUTE;
    403	gc->chip_types[0].chip.irq_mask		= perip_irq_mask;
    404	gc->chip_types[0].chip.irq_unmask	= perip_irq_unmask;
    405	gc->chip_types[0].chip.irq_set_wake	= pdc_irq_set_wake;
    406
    407	/* syswake interrupt chip */
    408
    409	gc = irq_get_domain_generic_chip(priv->domain, 8);
    410	gc->unused	= ~(BIT(priv->nr_syswakes) - 1);
    411	gc->reg_base	= priv->pdc_base;
    412
    413	/* edge interrupts */
    414	gc->chip_types[0].type			= IRQ_TYPE_EDGE_BOTH;
    415	gc->chip_types[0].handler		= handle_edge_irq;
    416	gc->chip_types[0].regs.ack		= PDC_IRQ_CLEAR;
    417	gc->chip_types[0].regs.mask		= PDC_IRQ_ENABLE;
    418	gc->chip_types[0].chip.irq_ack		= irq_gc_ack_set_bit;
    419	gc->chip_types[0].chip.irq_mask		= irq_gc_mask_clr_bit;
    420	gc->chip_types[0].chip.irq_unmask	= irq_gc_mask_set_bit;
    421	gc->chip_types[0].chip.irq_set_type	= syswake_irq_set_type;
    422	gc->chip_types[0].chip.irq_set_wake	= pdc_irq_set_wake;
    423	/* for standby we pass on to the shared syswake IRQ */
    424	gc->chip_types[0].chip.flags		= IRQCHIP_MASK_ON_SUSPEND;
    425
    426	/* level interrupts */
    427	gc->chip_types[1].type			= IRQ_TYPE_LEVEL_MASK;
    428	gc->chip_types[1].handler		= handle_level_irq;
    429	gc->chip_types[1].regs.ack		= PDC_IRQ_CLEAR;
    430	gc->chip_types[1].regs.mask		= PDC_IRQ_ENABLE;
    431	gc->chip_types[1].chip.irq_ack		= irq_gc_ack_set_bit;
    432	gc->chip_types[1].chip.irq_mask		= irq_gc_mask_clr_bit;
    433	gc->chip_types[1].chip.irq_unmask	= irq_gc_mask_set_bit;
    434	gc->chip_types[1].chip.irq_set_type	= syswake_irq_set_type;
    435	gc->chip_types[1].chip.irq_set_wake	= pdc_irq_set_wake;
    436	/* for standby we pass on to the shared syswake IRQ */
    437	gc->chip_types[1].chip.flags		= IRQCHIP_MASK_ON_SUSPEND;
    438
    439	/* Set up the hardware to enable interrupt routing */
    440	pdc_intc_setup(priv);
    441
    442	/* Setup chained handlers for the peripheral IRQs */
    443	for (i = 0; i < priv->nr_perips; ++i) {
    444		irq = priv->perip_irqs[i];
    445		irq_set_chained_handler_and_data(irq, pdc_intc_perip_isr,
    446						 priv);
    447	}
    448
    449	/* Setup chained handler for the syswake IRQ */
    450	irq_set_chained_handler_and_data(priv->syswake_irq,
    451					 pdc_intc_syswake_isr, priv);
    452
    453	dev_info(&pdev->dev,
    454		 "PDC IRQ controller initialised (%u perip IRQs, %u syswake IRQs)\n",
    455		 priv->nr_perips,
    456		 priv->nr_syswakes);
    457
    458	return 0;
    459err_generic:
    460	irq_domain_remove(priv->domain);
    461	return ret;
    462}
    463
    464static int pdc_intc_remove(struct platform_device *pdev)
    465{
    466	struct pdc_intc_priv *priv = platform_get_drvdata(pdev);
    467
    468	irq_domain_remove(priv->domain);
    469	return 0;
    470}
    471
    472static const struct of_device_id pdc_intc_match[] = {
    473	{ .compatible = "img,pdc-intc" },
    474	{}
    475};
    476
    477static struct platform_driver pdc_intc_driver = {
    478	.driver = {
    479		.name		= "pdc-intc",
    480		.of_match_table	= pdc_intc_match,
    481	},
    482	.probe = pdc_intc_probe,
    483	.remove = pdc_intc_remove,
    484};
    485
    486static int __init pdc_intc_init(void)
    487{
    488	return platform_driver_register(&pdc_intc_driver);
    489}
    490core_initcall(pdc_intc_init);