cregit-Linux how code gets into the kernel

Release 4.11 arch/arm/mach-pxa/pxa_cplds_irqs.c

/*
 * Intel Reference Systems cplds
 *
 * Copyright (C) 2014 Robert Jarzmik
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Cplds motherboard driver, supporting lubbock and mainstone SoC board.
 */

#include <linux/bitops.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of_platform.h>


#define FPGA_IRQ_MASK_EN 0x0

#define FPGA_IRQ_SET_CLR 0x10


#define CPLDS_NB_IRQ	32


struct cplds {
	
void __iomem *base;
	
int irq;
	
unsigned int irq_mask;
	
struct gpio_desc *gpio0;
	
struct irq_domain *irqdomain;
};


static irqreturn_t cplds_irq_handler(int in_irq, void *d) { struct cplds *fpga = d; unsigned long pending; unsigned int bit; do { pending = readl(fpga->base + FPGA_IRQ_SET_CLR) & fpga->irq_mask; for_each_set_bit(bit, &pending, CPLDS_NB_IRQ) { generic_handle_irq(irq_find_mapping(fpga->irqdomain, bit)); } } while (pending); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Jarzmik76100.00%2100.00%
Total76100.00%2100.00%


static void cplds_irq_mask(struct irq_data *d) { struct cplds *fpga = irq_data_get_irq_chip_data(d); unsigned int cplds_irq = irqd_to_hwirq(d); unsigned int bit = BIT(cplds_irq); fpga->irq_mask &= ~bit; writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Jarzmik59100.00%2100.00%
Total59100.00%2100.00%


static void cplds_irq_unmask(struct irq_data *d) { struct cplds *fpga = irq_data_get_irq_chip_data(d); unsigned int cplds_irq = irqd_to_hwirq(d); unsigned int set, bit = BIT(cplds_irq); set = readl(fpga->base + FPGA_IRQ_SET_CLR); writel(set & ~bit, fpga->base + FPGA_IRQ_SET_CLR); fpga->irq_mask |= bit; writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Jarzmik85100.00%2100.00%
Total85100.00%2100.00%

static struct irq_chip cplds_irq_chip = { .name = "pxa_cplds", .irq_ack = cplds_irq_mask, .irq_mask = cplds_irq_mask, .irq_unmask = cplds_irq_unmask, .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE, };
static int cplds_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hwirq) { struct cplds *fpga = d->host_data; irq_set_chip_and_handler(irq, &cplds_irq_chip, handle_level_irq); irq_set_chip_data(irq, fpga); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Jarzmik47100.00%1100.00%
Total47100.00%1100.00%

static const struct irq_domain_ops cplds_irq_domain_ops = { .xlate = irq_domain_xlate_twocell, .map = cplds_irq_domain_map, };
static int cplds_resume(struct platform_device *pdev) { struct cplds *fpga = platform_get_drvdata(pdev); writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Jarzmik37100.00%1100.00%
Total37100.00%1100.00%


static int cplds_probe(struct platform_device *pdev) { struct resource *res; struct cplds *fpga; int ret; int base_irq; unsigned long irqflags = 0; fpga = devm_kzalloc(&pdev->dev, sizeof(*fpga), GFP_KERNEL); if (!fpga) return -ENOMEM; fpga->irq = platform_get_irq(pdev, 0); if (fpga->irq <= 0) return fpga->irq; base_irq = platform_get_irq(pdev, 1); if (base_irq < 0) base_irq = 0; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); fpga->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(fpga->base)) return PTR_ERR(fpga->base); platform_set_drvdata(pdev, fpga); writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN); writel(0, fpga->base + FPGA_IRQ_SET_CLR); irqflags = irq_get_trigger_type(fpga->irq); ret = devm_request_irq(&pdev->dev, fpga->irq, cplds_irq_handler, irqflags, dev_name(&pdev->dev), fpga); if (ret == -ENOSYS) return -EPROBE_DEFER; if (ret) { dev_err(&pdev->dev, "couldn't request main irq%d: %d\n", fpga->irq, ret); return ret; } irq_set_irq_wake(fpga->irq, 1); fpga->irqdomain = irq_domain_add_linear(pdev->dev.of_node, CPLDS_NB_IRQ, &cplds_irq_domain_ops, fpga); if (!fpga->irqdomain) return -ENODEV; if (base_irq) { ret = irq_create_strict_mappings(fpga->irqdomain, base_irq, 0, CPLDS_NB_IRQ); if (ret) { dev_err(&pdev->dev, "couldn't create the irq mapping %d..%d\n", base_irq, base_irq + CPLDS_NB_IRQ); return ret; } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Jarzmik338100.00%2100.00%
Total338100.00%2100.00%


static int cplds_remove(struct platform_device *pdev) { struct cplds *fpga = platform_get_drvdata(pdev); irq_set_chip_and_handler(fpga->irq, NULL, NULL); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Jarzmik35100.00%1100.00%
Total35100.00%1100.00%

static const struct of_device_id cplds_id_table[] = { { .compatible = "intel,lubbock-cplds-irqs", }, { .compatible = "intel,mainstone-cplds-irqs", }, { } }; MODULE_DEVICE_TABLE(of, cplds_id_table); static struct platform_driver cplds_driver = { .driver = { .name = "pxa_cplds_irqs", .of_match_table = of_match_ptr(cplds_id_table), }, .probe = cplds_probe, .remove = cplds_remove, .resume = cplds_resume, }; module_platform_driver(cplds_driver); MODULE_DESCRIPTION("PXA Cplds interrupts driver"); MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
Robert Jarzmik891100.00%3100.00%
Total891100.00%3100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.