brintos

brintos / linux-shallow public Read only

0
0
Text · 9.3 KiB · 28a8a6a Raw
357 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// IXP4 GPIO driver4// Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>5//6// based on previous work and know-how from:7// Deepak Saxena <dsaxena@plexity.net>8 9#include <linux/bitops.h>10#include <linux/gpio/driver.h>11#include <linux/io.h>12#include <linux/irq.h>13#include <linux/irqdomain.h>14#include <linux/irqchip.h>15#include <linux/of_irq.h>16#include <linux/platform_device.h>17#include <linux/property.h>18 19#define IXP4XX_REG_GPOUT	0x0020#define IXP4XX_REG_GPOE		0x0421#define IXP4XX_REG_GPIN		0x0822#define IXP4XX_REG_GPIS		0x0C23#define IXP4XX_REG_GPIT1	0x1024#define IXP4XX_REG_GPIT2	0x1425#define IXP4XX_REG_GPCLK	0x1826#define IXP4XX_REG_GPDBSEL	0x1C27 28/*29 * The hardware uses 3 bits to indicate interrupt "style".30 * we clear and set these three bits accordingly. The lower 2431 * bits in two registers (GPIT1 and GPIT2) are used to set up32 * the style for 8 lines each for a total of 16 GPIO lines.33 */34#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH	0x035#define IXP4XX_GPIO_STYLE_ACTIVE_LOW	0x136#define IXP4XX_GPIO_STYLE_RISING_EDGE	0x237#define IXP4XX_GPIO_STYLE_FALLING_EDGE	0x338#define IXP4XX_GPIO_STYLE_TRANSITIONAL	0x439#define IXP4XX_GPIO_STYLE_MASK		GENMASK(2, 0)40#define IXP4XX_GPIO_STYLE_SIZE		341 42/*43 * Clock output control register defines.44 */45#define IXP4XX_GPCLK_CLK0DC_SHIFT	046#define IXP4XX_GPCLK_CLK0TC_SHIFT	447#define IXP4XX_GPCLK_CLK0_MASK		GENMASK(7, 0)48#define IXP4XX_GPCLK_MUX14		BIT(8)49#define IXP4XX_GPCLK_CLK1DC_SHIFT	1650#define IXP4XX_GPCLK_CLK1TC_SHIFT	2051#define IXP4XX_GPCLK_CLK1_MASK		GENMASK(23, 16)52#define IXP4XX_GPCLK_MUX15		BIT(24)53 54/**55 * struct ixp4xx_gpio - IXP4 GPIO state container56 * @dev: containing device for this instance57 * @gc: gpiochip for this instance58 * @base: remapped I/O-memory base59 * @irq_edge: Each bit represents an IRQ: 1: edge-triggered,60 * 0: level triggered61 */62struct ixp4xx_gpio {63	struct gpio_chip gc;64	struct device *dev;65	void __iomem *base;66	unsigned long long irq_edge;67};68 69static void ixp4xx_gpio_irq_ack(struct irq_data *d)70{71	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);72	struct ixp4xx_gpio *g = gpiochip_get_data(gc);73 74	__raw_writel(BIT(d->hwirq), g->base + IXP4XX_REG_GPIS);75}76 77static void ixp4xx_gpio_mask_irq(struct irq_data *d)78{79	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);80 81	irq_chip_mask_parent(d);82	gpiochip_disable_irq(gc, d->hwirq);83}84 85static void ixp4xx_gpio_irq_unmask(struct irq_data *d)86{87	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);88	struct ixp4xx_gpio *g = gpiochip_get_data(gc);89 90	/* ACK when unmasking if not edge-triggered */91	if (!(g->irq_edge & BIT(d->hwirq)))92		ixp4xx_gpio_irq_ack(d);93 94	gpiochip_enable_irq(gc, d->hwirq);95	irq_chip_unmask_parent(d);96}97 98static int ixp4xx_gpio_irq_set_type(struct irq_data *d, unsigned int type)99{100	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);101	struct ixp4xx_gpio *g = gpiochip_get_data(gc);102	int line = d->hwirq;103	unsigned long flags;104	u32 int_style;105	u32 int_reg;106	u32 val;107 108	switch (type) {109	case IRQ_TYPE_EDGE_BOTH:110		irq_set_handler_locked(d, handle_edge_irq);111		int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;112		g->irq_edge |= BIT(d->hwirq);113		break;114	case IRQ_TYPE_EDGE_RISING:115		irq_set_handler_locked(d, handle_edge_irq);116		int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;117		g->irq_edge |= BIT(d->hwirq);118		break;119	case IRQ_TYPE_EDGE_FALLING:120		irq_set_handler_locked(d, handle_edge_irq);121		int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;122		g->irq_edge |= BIT(d->hwirq);123		break;124	case IRQ_TYPE_LEVEL_HIGH:125		irq_set_handler_locked(d, handle_level_irq);126		int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;127		g->irq_edge &= ~BIT(d->hwirq);128		break;129	case IRQ_TYPE_LEVEL_LOW:130		irq_set_handler_locked(d, handle_level_irq);131		int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;132		g->irq_edge &= ~BIT(d->hwirq);133		break;134	default:135		return -EINVAL;136	}137 138	if (line >= 8) {139		/* pins 8-15 */140		line -= 8;141		int_reg = IXP4XX_REG_GPIT2;142	} else {143		/* pins 0-7 */144		int_reg = IXP4XX_REG_GPIT1;145	}146 147	raw_spin_lock_irqsave(&g->gc.bgpio_lock, flags);148 149	/* Clear the style for the appropriate pin */150	val = __raw_readl(g->base + int_reg);151	val &= ~(IXP4XX_GPIO_STYLE_MASK << (line * IXP4XX_GPIO_STYLE_SIZE));152	__raw_writel(val, g->base + int_reg);153 154	__raw_writel(BIT(line), g->base + IXP4XX_REG_GPIS);155 156	/* Set the new style */157	val = __raw_readl(g->base + int_reg);158	val |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));159	__raw_writel(val, g->base + int_reg);160 161	/* Force-configure this line as an input */162	val = __raw_readl(g->base + IXP4XX_REG_GPOE);163	val |= BIT(d->hwirq);164	__raw_writel(val, g->base + IXP4XX_REG_GPOE);165 166	raw_spin_unlock_irqrestore(&g->gc.bgpio_lock, flags);167 168	/* This parent only accept level high (asserted) */169	return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);170}171 172static const struct irq_chip ixp4xx_gpio_irqchip = {173	.name = "IXP4GPIO",174	.irq_ack = ixp4xx_gpio_irq_ack,175	.irq_mask = ixp4xx_gpio_mask_irq,176	.irq_unmask = ixp4xx_gpio_irq_unmask,177	.irq_set_type = ixp4xx_gpio_irq_set_type,178	.flags = IRQCHIP_IMMUTABLE,179	GPIOCHIP_IRQ_RESOURCE_HELPERS,180};181 182static int ixp4xx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,183					     unsigned int child,184					     unsigned int child_type,185					     unsigned int *parent,186					     unsigned int *parent_type)187{188	/* All these interrupts are level high in the CPU */189	*parent_type = IRQ_TYPE_LEVEL_HIGH;190 191	/* GPIO lines 0..12 have dedicated IRQs */192	if (child == 0) {193		*parent = 6;194		return 0;195	}196	if (child == 1) {197		*parent = 7;198		return 0;199	}200	if (child >= 2 && child <= 12) {201		*parent = child + 17;202		return 0;203	}204	return -EINVAL;205}206 207static int ixp4xx_gpio_probe(struct platform_device *pdev)208{209	unsigned long flags;210	struct device *dev = &pdev->dev;211	struct device_node *np = dev->of_node;212	struct irq_domain *parent;213	struct ixp4xx_gpio *g;214	struct gpio_irq_chip *girq;215	struct device_node *irq_parent;216	bool clk_14, clk_15;217	u32 val;218	int ret;219 220	g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);221	if (!g)222		return -ENOMEM;223	g->dev = dev;224 225	g->base = devm_platform_ioremap_resource(pdev, 0);226	if (IS_ERR(g->base))227		return PTR_ERR(g->base);228 229	irq_parent = of_irq_find_parent(np);230	if (!irq_parent) {231		dev_err(dev, "no IRQ parent node\n");232		return -ENODEV;233	}234	parent = irq_find_host(irq_parent);235	if (!parent) {236		dev_err(dev, "no IRQ parent domain\n");237		return -ENODEV;238	}239 240	/*241	 * If either clock output is enabled explicitly in the device tree242	 * we take full control of the clock by masking off all bits for243	 * the clock control and selectively enabling them. Otherwise244	 * we leave the hardware default settings.245	 *246	 * Enable clock outputs with default timings of requested clock.247	 * If you need control over TC and DC, add these to the device248	 * tree bindings and use them here.249	 */250	clk_14 = of_property_read_bool(np, "intel,ixp4xx-gpio14-clkout");251	clk_15 = of_property_read_bool(np, "intel,ixp4xx-gpio15-clkout");252 253	/*254	 * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on255	 * specific machines.256	 */257	if (of_machine_is_compatible("dlink,dsm-g600-a") ||258	    of_machine_is_compatible("iom,nas-100d"))259		val = 0;260	else {261		val = __raw_readl(g->base + IXP4XX_REG_GPCLK);262 263		if (clk_14 || clk_15) {264			val &= ~(IXP4XX_GPCLK_MUX14 | IXP4XX_GPCLK_MUX15);265			val &= ~IXP4XX_GPCLK_CLK0_MASK;266			val &= ~IXP4XX_GPCLK_CLK1_MASK;267			if (clk_14) {268				/* IXP4XX_GPCLK_CLK0DC implicit low */269				val |= (1 << IXP4XX_GPCLK_CLK0TC_SHIFT);270				val |= IXP4XX_GPCLK_MUX14;271			}272 273			if (clk_15) {274				/* IXP4XX_GPCLK_CLK1DC implicit low */275				val |= (1 << IXP4XX_GPCLK_CLK1TC_SHIFT);276				val |= IXP4XX_GPCLK_MUX15;277			}278		}279	}280 281	__raw_writel(val, g->base + IXP4XX_REG_GPCLK);282 283	/*284	 * This is a very special big-endian ARM issue: when the IXP4xx is285	 * run in big endian mode, all registers in the machine are switched286	 * around to the CPU-native endianness. As you see mostly in the287	 * driver we use __raw_readl()/__raw_writel() to access the registers288	 * in the appropriate order. With the GPIO library we need to specify289	 * byte order explicitly, so this flag needs to be set when compiling290	 * for big endian.291	 */292#if defined(CONFIG_CPU_BIG_ENDIAN)293	flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;294#else295	flags = 0;296#endif297 298	/* Populate and register gpio chip */299	ret = bgpio_init(&g->gc, dev, 4,300			 g->base + IXP4XX_REG_GPIN,301			 g->base + IXP4XX_REG_GPOUT,302			 NULL,303			 NULL,304			 g->base + IXP4XX_REG_GPOE,305			 flags);306	if (ret) {307		dev_err(dev, "unable to init generic GPIO\n");308		return ret;309	}310	g->gc.ngpio = 16;311	g->gc.label = "IXP4XX_GPIO_CHIP";312	/*313	 * TODO: when we have migrated to device tree and all GPIOs314	 * are fetched using phandles, set this to -1 to get rid of315	 * the fixed gpiochip base.316	 */317	g->gc.base = 0;318	g->gc.parent = &pdev->dev;319	g->gc.owner = THIS_MODULE;320 321	girq = &g->gc.irq;322	gpio_irq_chip_set_chip(girq, &ixp4xx_gpio_irqchip);323	girq->fwnode = dev_fwnode(dev);324	girq->parent_domain = parent;325	girq->child_to_parent_hwirq = ixp4xx_gpio_child_to_parent_hwirq;326	girq->handler = handle_bad_irq;327	girq->default_type = IRQ_TYPE_NONE;328 329	ret = devm_gpiochip_add_data(dev, &g->gc, g);330	if (ret) {331		dev_err(dev, "failed to add SoC gpiochip\n");332		return ret;333	}334 335	platform_set_drvdata(pdev, g);336	dev_info(dev, "IXP4 GPIO registered\n");337 338	return 0;339}340 341static const struct of_device_id ixp4xx_gpio_of_match[] = {342	{343		.compatible = "intel,ixp4xx-gpio",344	},345	{},346};347 348 349static struct platform_driver ixp4xx_gpio_driver = {350	.driver = {351		.name		= "ixp4xx-gpio",352		.of_match_table = ixp4xx_gpio_of_match,353	},354	.probe = ixp4xx_gpio_probe,355};356builtin_platform_driver(ixp4xx_gpio_driver);357