brintos

brintos / linux-shallow public Read only

0
0
Text · 8.8 KiB · d445eea Raw
326 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2017 Broadcom4 */5 6#include <linux/gpio/driver.h>7#include <linux/init.h>8#include <linux/interrupt.h>9#include <linux/io.h>10#include <linux/irq.h>11#include <linux/kernel.h>12#include <linux/module.h>13#include <linux/platform_device.h>14#include <linux/seq_file.h>15#include <linux/spinlock.h>16 17#define IPROC_CCA_INT_F_GPIOINT		BIT(0)18#define IPROC_CCA_INT_STS		0x2019#define IPROC_CCA_INT_MASK		0x2420 21#define IPROC_GPIO_CCA_DIN		0x022#define IPROC_GPIO_CCA_DOUT		0x423#define IPROC_GPIO_CCA_OUT_EN		0x824#define IPROC_GPIO_CCA_INT_LEVEL	0x1025#define IPROC_GPIO_CCA_INT_LEVEL_MASK	0x1426#define IPROC_GPIO_CCA_INT_EVENT	0x1827#define IPROC_GPIO_CCA_INT_EVENT_MASK	0x1C28#define IPROC_GPIO_CCA_INT_EDGE		0x2429 30struct iproc_gpio_chip {31	struct gpio_chip gc;32	spinlock_t lock;33	struct device *dev;34	void __iomem *base;35	void __iomem *intr;36};37 38static inline struct iproc_gpio_chip *39to_iproc_gpio(struct gpio_chip *gc)40{41	return container_of(gc, struct iproc_gpio_chip, gc);42}43 44static void iproc_gpio_irq_ack(struct irq_data *d)45{46	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);47	struct iproc_gpio_chip *chip = to_iproc_gpio(gc);48	int pin = d->hwirq;49	unsigned long flags;50	u32 irq = d->irq;51	u32 irq_type, event_status = 0;52 53	spin_lock_irqsave(&chip->lock, flags);54	irq_type = irq_get_trigger_type(irq);55	if (irq_type & IRQ_TYPE_EDGE_BOTH) {56		event_status |= BIT(pin);57		writel_relaxed(event_status,58			       chip->base + IPROC_GPIO_CCA_INT_EVENT);59	}60	spin_unlock_irqrestore(&chip->lock, flags);61}62 63static void iproc_gpio_irq_unmask(struct irq_data *d)64{65	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);66	struct iproc_gpio_chip *chip = to_iproc_gpio(gc);67	int pin = d->hwirq;68	unsigned long flags;69	u32 irq = d->irq;70	u32 int_mask, irq_type, event_mask;71 72	gpiochip_enable_irq(gc, pin);73	spin_lock_irqsave(&chip->lock, flags);74	irq_type = irq_get_trigger_type(irq);75	event_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);76	int_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);77 78	if (irq_type & IRQ_TYPE_EDGE_BOTH) {79		event_mask |= 1 << pin;80		writel_relaxed(event_mask,81			       chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);82	} else {83		int_mask |= 1 << pin;84		writel_relaxed(int_mask,85			       chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);86	}87	spin_unlock_irqrestore(&chip->lock, flags);88}89 90static void iproc_gpio_irq_mask(struct irq_data *d)91{92	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);93	struct iproc_gpio_chip *chip = to_iproc_gpio(gc);94	int pin = d->hwirq;95	unsigned long flags;96	u32 irq = d->irq;97	u32 irq_type, int_mask, event_mask;98 99	spin_lock_irqsave(&chip->lock, flags);100	irq_type = irq_get_trigger_type(irq);101	event_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);102	int_mask = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);103 104	if (irq_type & IRQ_TYPE_EDGE_BOTH) {105		event_mask &= ~BIT(pin);106		writel_relaxed(event_mask,107			       chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);108	} else {109		int_mask &= ~BIT(pin);110		writel_relaxed(int_mask,111			       chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);112	}113	spin_unlock_irqrestore(&chip->lock, flags);114	gpiochip_disable_irq(gc, pin);115}116 117static int iproc_gpio_irq_set_type(struct irq_data *d, u32 type)118{119	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);120	struct iproc_gpio_chip *chip = to_iproc_gpio(gc);121	int pin = d->hwirq;122	unsigned long flags;123	u32 irq = d->irq;124	u32 event_pol, int_pol;125	int ret = 0;126 127	spin_lock_irqsave(&chip->lock, flags);128	switch (type & IRQ_TYPE_SENSE_MASK) {129	case IRQ_TYPE_EDGE_RISING:130		event_pol = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EDGE);131		event_pol &= ~BIT(pin);132		writel_relaxed(event_pol, chip->base + IPROC_GPIO_CCA_INT_EDGE);133		break;134	case IRQ_TYPE_EDGE_FALLING:135		event_pol = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EDGE);136		event_pol |= BIT(pin);137		writel_relaxed(event_pol, chip->base + IPROC_GPIO_CCA_INT_EDGE);138		break;139	case IRQ_TYPE_LEVEL_HIGH:140		int_pol = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL);141		int_pol &= ~BIT(pin);142		writel_relaxed(int_pol, chip->base + IPROC_GPIO_CCA_INT_LEVEL);143		break;144	case IRQ_TYPE_LEVEL_LOW:145		int_pol = readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL);146		int_pol |= BIT(pin);147		writel_relaxed(int_pol, chip->base + IPROC_GPIO_CCA_INT_LEVEL);148		break;149	default:150		/* should not come here */151		ret = -EINVAL;152		goto out_unlock;153	}154 155	if (type & IRQ_TYPE_LEVEL_MASK)156		irq_set_handler_locked(irq_get_irq_data(irq), handle_level_irq);157	else if (type & IRQ_TYPE_EDGE_BOTH)158		irq_set_handler_locked(irq_get_irq_data(irq), handle_edge_irq);159 160out_unlock:161	spin_unlock_irqrestore(&chip->lock, flags);162 163	return ret;164}165 166static irqreturn_t iproc_gpio_irq_handler(int irq, void *data)167{168	struct gpio_chip *gc = (struct gpio_chip *)data;169	struct iproc_gpio_chip *chip = to_iproc_gpio(gc);170	int bit;171	unsigned long int_bits = 0;172	u32 int_status;173 174	/* go through the entire GPIOs and handle all interrupts */175	int_status = readl_relaxed(chip->intr + IPROC_CCA_INT_STS);176	if (int_status & IPROC_CCA_INT_F_GPIOINT) {177		u32 event, level;178 179		/* Get level and edge interrupts */180		event =181		    readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT_MASK);182		event &= readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_EVENT);183		level = readl_relaxed(chip->base + IPROC_GPIO_CCA_DIN);184		level ^= readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL);185		level &=186		    readl_relaxed(chip->base + IPROC_GPIO_CCA_INT_LEVEL_MASK);187		int_bits = level | event;188 189		for_each_set_bit(bit, &int_bits, gc->ngpio)190			generic_handle_domain_irq(gc->irq.domain, bit);191	}192 193	return int_bits ? IRQ_HANDLED : IRQ_NONE;194}195 196static void iproc_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)197{198	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);199	struct iproc_gpio_chip *chip = to_iproc_gpio(gc);200 201	seq_printf(p, dev_name(chip->dev));202}203 204static const struct irq_chip iproc_gpio_irq_chip = {205	.irq_ack = iproc_gpio_irq_ack,206	.irq_mask = iproc_gpio_irq_mask,207	.irq_unmask = iproc_gpio_irq_unmask,208	.irq_set_type = iproc_gpio_irq_set_type,209	.irq_print_chip = iproc_gpio_irq_print_chip,210	.flags = IRQCHIP_IMMUTABLE,211	GPIOCHIP_IRQ_RESOURCE_HELPERS,212};213 214static int iproc_gpio_probe(struct platform_device *pdev)215{216	struct device *dev = &pdev->dev;217	struct device_node *dn = pdev->dev.of_node;218	struct iproc_gpio_chip *chip;219	u32 num_gpios;220	int irq, ret;221 222	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);223	if (!chip)224		return -ENOMEM;225 226	chip->dev = dev;227	platform_set_drvdata(pdev, chip);228	spin_lock_init(&chip->lock);229 230	chip->base = devm_platform_ioremap_resource(pdev, 0);231	if (IS_ERR(chip->base))232		return PTR_ERR(chip->base);233 234	ret = bgpio_init(&chip->gc, dev, 4,235			 chip->base + IPROC_GPIO_CCA_DIN,236			 chip->base + IPROC_GPIO_CCA_DOUT,237			 NULL,238			 chip->base + IPROC_GPIO_CCA_OUT_EN,239			 NULL,240			 0);241	if (ret) {242		dev_err(dev, "unable to init GPIO chip\n");243		return ret;244	}245 246	chip->gc.label = dev_name(dev);247	if (!of_property_read_u32(dn, "ngpios", &num_gpios))248		chip->gc.ngpio = num_gpios;249 250	irq = platform_get_irq(pdev, 0);251	if (irq > 0) {252		struct gpio_irq_chip *girq;253		u32 val;254 255		chip->intr = devm_platform_ioremap_resource(pdev, 1);256		if (IS_ERR(chip->intr))257			return PTR_ERR(chip->intr);258 259		/* Enable GPIO interrupts for CCA GPIO */260		val = readl_relaxed(chip->intr + IPROC_CCA_INT_MASK);261		val |= IPROC_CCA_INT_F_GPIOINT;262		writel_relaxed(val, chip->intr + IPROC_CCA_INT_MASK);263 264		/*265		 * Directly request the irq here instead of passing266		 * a flow-handler because the irq is shared.267		 */268		ret = devm_request_irq(dev, irq, iproc_gpio_irq_handler,269				       IRQF_SHARED, chip->gc.label, &chip->gc);270		if (ret) {271			dev_err(dev, "Fail to request IRQ%d: %d\n", irq, ret);272			return ret;273		}274 275		girq = &chip->gc.irq;276		gpio_irq_chip_set_chip(girq, &iproc_gpio_irq_chip);277		/* This will let us handle the parent IRQ in the driver */278		girq->parent_handler = NULL;279		girq->num_parents = 0;280		girq->parents = NULL;281		girq->default_type = IRQ_TYPE_NONE;282		girq->handler = handle_simple_irq;283	}284 285	ret = devm_gpiochip_add_data(dev, &chip->gc, chip);286	if (ret) {287		dev_err(dev, "unable to add GPIO chip\n");288		return ret;289	}290 291	return 0;292}293 294static void iproc_gpio_remove(struct platform_device *pdev)295{296	struct iproc_gpio_chip *chip = platform_get_drvdata(pdev);297 298	if (chip->intr) {299		u32 val;300 301		val = readl_relaxed(chip->intr + IPROC_CCA_INT_MASK);302		val &= ~IPROC_CCA_INT_F_GPIOINT;303		writel_relaxed(val, chip->intr + IPROC_CCA_INT_MASK);304	}305}306 307static const struct of_device_id bcm_iproc_gpio_of_match[] = {308	{ .compatible = "brcm,iproc-gpio-cca" },309	{}310};311MODULE_DEVICE_TABLE(of, bcm_iproc_gpio_of_match);312 313static struct platform_driver bcm_iproc_gpio_driver = {314	.driver = {315		.name = "iproc-xgs-gpio",316		.of_match_table = bcm_iproc_gpio_of_match,317	},318	.probe = iproc_gpio_probe,319	.remove_new = iproc_gpio_remove,320};321 322module_platform_driver(bcm_iproc_gpio_driver);323 324MODULE_DESCRIPTION("XGS IPROC GPIO driver");325MODULE_LICENSE("GPL v2");326