356 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Faraday Technolog FTGPIO010 gpiochip and interrupt routines4 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>5 *6 * Based on arch/arm/mach-gemini/gpio.c:7 * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>8 *9 * Based on plat-mxc/gpio.c:10 * MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>11 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de12 */13#include <linux/gpio/driver.h>14#include <linux/io.h>15#include <linux/interrupt.h>16#include <linux/platform_device.h>17#include <linux/bitops.h>18#include <linux/clk.h>19 20/* GPIO registers definition */21#define GPIO_DATA_OUT 0x0022#define GPIO_DATA_IN 0x0423#define GPIO_DIR 0x0824#define GPIO_BYPASS_IN 0x0C25#define GPIO_DATA_SET 0x1026#define GPIO_DATA_CLR 0x1427#define GPIO_PULL_EN 0x1828#define GPIO_PULL_TYPE 0x1C29#define GPIO_INT_EN 0x2030#define GPIO_INT_STAT_RAW 0x2431#define GPIO_INT_STAT_MASKED 0x2832#define GPIO_INT_MASK 0x2C33#define GPIO_INT_CLR 0x3034#define GPIO_INT_TYPE 0x3435#define GPIO_INT_BOTH_EDGE 0x3836#define GPIO_INT_LEVEL 0x3C37#define GPIO_DEBOUNCE_EN 0x4038#define GPIO_DEBOUNCE_PRESCALE 0x4439 40/**41 * struct ftgpio_gpio - Gemini GPIO state container42 * @dev: containing device for this instance43 * @gc: gpiochip for this instance44 * @base: remapped I/O-memory base45 * @clk: silicon clock46 */47struct ftgpio_gpio {48 struct device *dev;49 struct gpio_chip gc;50 void __iomem *base;51 struct clk *clk;52};53 54static void ftgpio_gpio_ack_irq(struct irq_data *d)55{56 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);57 struct ftgpio_gpio *g = gpiochip_get_data(gc);58 59 writel(BIT(irqd_to_hwirq(d)), g->base + GPIO_INT_CLR);60}61 62static void ftgpio_gpio_mask_irq(struct irq_data *d)63{64 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);65 struct ftgpio_gpio *g = gpiochip_get_data(gc);66 u32 val;67 68 val = readl(g->base + GPIO_INT_EN);69 val &= ~BIT(irqd_to_hwirq(d));70 writel(val, g->base + GPIO_INT_EN);71 gpiochip_disable_irq(gc, irqd_to_hwirq(d));72}73 74static void ftgpio_gpio_unmask_irq(struct irq_data *d)75{76 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);77 struct ftgpio_gpio *g = gpiochip_get_data(gc);78 u32 val;79 80 gpiochip_enable_irq(gc, irqd_to_hwirq(d));81 val = readl(g->base + GPIO_INT_EN);82 val |= BIT(irqd_to_hwirq(d));83 writel(val, g->base + GPIO_INT_EN);84}85 86static int ftgpio_gpio_set_irq_type(struct irq_data *d, unsigned int type)87{88 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);89 struct ftgpio_gpio *g = gpiochip_get_data(gc);90 u32 mask = BIT(irqd_to_hwirq(d));91 u32 reg_both, reg_level, reg_type;92 93 reg_type = readl(g->base + GPIO_INT_TYPE);94 reg_level = readl(g->base + GPIO_INT_LEVEL);95 reg_both = readl(g->base + GPIO_INT_BOTH_EDGE);96 97 switch (type) {98 case IRQ_TYPE_EDGE_BOTH:99 irq_set_handler_locked(d, handle_edge_irq);100 reg_type &= ~mask;101 reg_both |= mask;102 break;103 case IRQ_TYPE_EDGE_RISING:104 irq_set_handler_locked(d, handle_edge_irq);105 reg_type &= ~mask;106 reg_both &= ~mask;107 reg_level &= ~mask;108 break;109 case IRQ_TYPE_EDGE_FALLING:110 irq_set_handler_locked(d, handle_edge_irq);111 reg_type &= ~mask;112 reg_both &= ~mask;113 reg_level |= mask;114 break;115 case IRQ_TYPE_LEVEL_HIGH:116 irq_set_handler_locked(d, handle_level_irq);117 reg_type |= mask;118 reg_level &= ~mask;119 break;120 case IRQ_TYPE_LEVEL_LOW:121 irq_set_handler_locked(d, handle_level_irq);122 reg_type |= mask;123 reg_level |= mask;124 break;125 default:126 irq_set_handler_locked(d, handle_bad_irq);127 return -EINVAL;128 }129 130 writel(reg_type, g->base + GPIO_INT_TYPE);131 writel(reg_level, g->base + GPIO_INT_LEVEL);132 writel(reg_both, g->base + GPIO_INT_BOTH_EDGE);133 134 ftgpio_gpio_ack_irq(d);135 136 return 0;137}138 139static void ftgpio_gpio_irq_handler(struct irq_desc *desc)140{141 struct gpio_chip *gc = irq_desc_get_handler_data(desc);142 struct ftgpio_gpio *g = gpiochip_get_data(gc);143 struct irq_chip *irqchip = irq_desc_get_chip(desc);144 int offset;145 unsigned long stat;146 147 chained_irq_enter(irqchip, desc);148 149 stat = readl(g->base + GPIO_INT_STAT_RAW);150 if (stat)151 for_each_set_bit(offset, &stat, gc->ngpio)152 generic_handle_domain_irq(gc->irq.domain, offset);153 154 chained_irq_exit(irqchip, desc);155}156 157static int ftgpio_gpio_set_config(struct gpio_chip *gc, unsigned int offset,158 unsigned long config)159{160 enum pin_config_param param = pinconf_to_config_param(config);161 u32 arg = pinconf_to_config_argument(config);162 struct ftgpio_gpio *g = gpiochip_get_data(gc);163 unsigned long pclk_freq;164 u32 deb_div;165 u32 val;166 167 if (param != PIN_CONFIG_INPUT_DEBOUNCE)168 return -ENOTSUPP;169 170 /*171 * Debounce only works if interrupts are enabled. The manual172 * states that if PCLK is 66 MHz, and this is set to 0x7D0, then173 * PCLK is divided down to 33 kHz for the debounce timer. 0x7D0 is174 * 2000 decimal, so what they mean is simply that the PCLK is175 * divided by this value.176 *177 * As we get a debounce setting in microseconds, we calculate the178 * desired period time and see if we can get a suitable debounce179 * time.180 */181 pclk_freq = clk_get_rate(g->clk);182 deb_div = DIV_ROUND_CLOSEST(pclk_freq, arg);183 184 /* This register is only 24 bits wide */185 if (deb_div > (1 << 24))186 return -ENOTSUPP;187 188 dev_dbg(g->dev, "prescale divisor: %08x, resulting frequency %lu Hz\n",189 deb_div, (pclk_freq/deb_div));190 191 val = readl(g->base + GPIO_DEBOUNCE_PRESCALE);192 if (val == deb_div) {193 /*194 * The debounce timer happens to already be set to the195 * desirable value, what a coincidence! We can just enable196 * debounce on this GPIO line and return. This happens more197 * often than you think, for example when all GPIO keys198 * on a system are requesting the same debounce interval.199 */200 val = readl(g->base + GPIO_DEBOUNCE_EN);201 val |= BIT(offset);202 writel(val, g->base + GPIO_DEBOUNCE_EN);203 return 0;204 }205 206 val = readl(g->base + GPIO_DEBOUNCE_EN);207 if (val) {208 /*209 * Oh no! Someone is already using the debounce with210 * another setting than what we need. Bummer.211 */212 return -ENOTSUPP;213 }214 215 /* First come, first serve */216 writel(deb_div, g->base + GPIO_DEBOUNCE_PRESCALE);217 /* Enable debounce */218 val |= BIT(offset);219 writel(val, g->base + GPIO_DEBOUNCE_EN);220 221 return 0;222}223 224static const struct irq_chip ftgpio_irq_chip = {225 .name = "FTGPIO010",226 .irq_ack = ftgpio_gpio_ack_irq,227 .irq_mask = ftgpio_gpio_mask_irq,228 .irq_unmask = ftgpio_gpio_unmask_irq,229 .irq_set_type = ftgpio_gpio_set_irq_type,230 .flags = IRQCHIP_IMMUTABLE,231 GPIOCHIP_IRQ_RESOURCE_HELPERS,232};233 234static int ftgpio_gpio_probe(struct platform_device *pdev)235{236 struct device *dev = &pdev->dev;237 struct ftgpio_gpio *g;238 struct gpio_irq_chip *girq;239 int irq;240 int ret;241 242 g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);243 if (!g)244 return -ENOMEM;245 246 g->dev = dev;247 248 g->base = devm_platform_ioremap_resource(pdev, 0);249 if (IS_ERR(g->base))250 return PTR_ERR(g->base);251 252 irq = platform_get_irq(pdev, 0);253 if (irq < 0)254 return irq;255 256 g->clk = devm_clk_get(dev, NULL);257 if (!IS_ERR(g->clk)) {258 ret = clk_prepare_enable(g->clk);259 if (ret)260 return ret;261 } else if (PTR_ERR(g->clk) == -EPROBE_DEFER) {262 /*263 * Percolate deferrals, for anything else,264 * just live without the clocking.265 */266 return PTR_ERR(g->clk);267 }268 269 ret = bgpio_init(&g->gc, dev, 4,270 g->base + GPIO_DATA_IN,271 g->base + GPIO_DATA_SET,272 g->base + GPIO_DATA_CLR,273 g->base + GPIO_DIR,274 NULL,275 0);276 if (ret) {277 dev_err(dev, "unable to init generic GPIO\n");278 goto dis_clk;279 }280 g->gc.label = dev_name(dev);281 g->gc.base = -1;282 g->gc.parent = dev;283 g->gc.owner = THIS_MODULE;284 /* ngpio is set by bgpio_init() */285 286 /* We need a silicon clock to do debounce */287 if (!IS_ERR(g->clk))288 g->gc.set_config = ftgpio_gpio_set_config;289 290 girq = &g->gc.irq;291 gpio_irq_chip_set_chip(girq, &ftgpio_irq_chip);292 girq->parent_handler = ftgpio_gpio_irq_handler;293 girq->num_parents = 1;294 girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents),295 GFP_KERNEL);296 if (!girq->parents) {297 ret = -ENOMEM;298 goto dis_clk;299 }300 girq->default_type = IRQ_TYPE_NONE;301 girq->handler = handle_bad_irq;302 girq->parents[0] = irq;303 304 /* Disable, unmask and clear all interrupts */305 writel(0x0, g->base + GPIO_INT_EN);306 writel(0x0, g->base + GPIO_INT_MASK);307 writel(~0x0, g->base + GPIO_INT_CLR);308 309 /* Clear any use of debounce */310 writel(0x0, g->base + GPIO_DEBOUNCE_EN);311 312 ret = devm_gpiochip_add_data(dev, &g->gc, g);313 if (ret)314 goto dis_clk;315 316 platform_set_drvdata(pdev, g);317 dev_info(dev, "FTGPIO010 @%p registered\n", g->base);318 319 return 0;320 321dis_clk:322 clk_disable_unprepare(g->clk);323 324 return ret;325}326 327static void ftgpio_gpio_remove(struct platform_device *pdev)328{329 struct ftgpio_gpio *g = platform_get_drvdata(pdev);330 331 clk_disable_unprepare(g->clk);332}333 334static const struct of_device_id ftgpio_gpio_of_match[] = {335 {336 .compatible = "cortina,gemini-gpio",337 },338 {339 .compatible = "moxa,moxart-gpio",340 },341 {342 .compatible = "faraday,ftgpio010",343 },344 {},345};346 347static struct platform_driver ftgpio_gpio_driver = {348 .driver = {349 .name = "ftgpio010-gpio",350 .of_match_table = ftgpio_gpio_of_match,351 },352 .probe = ftgpio_gpio_probe,353 .remove_new = ftgpio_gpio_remove,354};355builtin_platform_driver(ftgpio_gpio_driver);356