if (param != PIN_CONFIG_INPUT_DEBOUNCE) return -ENOTSUPP;
/* * Debounce only works if interrupts are enabled. The manual * states that if PCLK is 66 MHz, and this is set to 0x7D0, then * PCLK is divided down to 33 kHz for the debounce timer. 0x7D0 is * 2000 decimal, so what they mean is simply that the PCLK is * divided by this value. * * As we get a debounce setting in microseconds, we calculate the * desired period time and see if we can get a suitable debounce * time.
*/
pclk_freq = clk_get_rate(g->clk);
deb_div = DIV_ROUND_CLOSEST(pclk_freq, arg);
/* This register is only 24 bits wide */ if (deb_div > (1 << 24)) return -ENOTSUPP;
dev_dbg(g->dev, "prescale divisor: %08x, resulting frequency %lu Hz\n",
deb_div, (pclk_freq/deb_div));
val = readl(g->base + GPIO_DEBOUNCE_PRESCALE); if (val == deb_div) { /* * The debounce timer happens to already be set to the * desirable value, what a coincidence! We can just enable * debounce on this GPIO line and return. This happens more * often than you think, for example when all GPIO keys * on a system are requesting the same debounce interval.
*/
val = readl(g->base + GPIO_DEBOUNCE_EN);
val |= BIT(offset);
writel(val, g->base + GPIO_DEBOUNCE_EN); return 0;
}
val = readl(g->base + GPIO_DEBOUNCE_EN); if (val) { /* * Oh no! Someone is already using the debounce with * another setting than what we need. Bummer.
*/ return -ENOTSUPP;
}
/* First come, first serve */
writel(deb_div, g->base + GPIO_DEBOUNCE_PRESCALE); /* Enable debounce */
val |= BIT(offset);
writel(val, g->base + GPIO_DEBOUNCE_EN);
staticint ftgpio_gpio_probe(struct platform_device *pdev)
{ struct device *dev = &pdev->dev; struct ftgpio_gpio *g; struct gpio_irq_chip *girq; int irq; int ret;
g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL); if (!g) return -ENOMEM;
g->dev = dev;
g->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(g->base)) return PTR_ERR(g->base);
irq = platform_get_irq(pdev, 0); if (irq < 0) return irq;
g->clk = devm_clk_get_enabled(dev, NULL); if (IS_ERR(g->clk) && PTR_ERR(g->clk) == -EPROBE_DEFER) /* * Percolate deferrals, for anything else, * just live without the clocking.
*/ return PTR_ERR(g->clk);
ret = bgpio_init(&g->gc, dev, 4,
g->base + GPIO_DATA_IN,
g->base + GPIO_DATA_SET,
g->base + GPIO_DATA_CLR,
g->base + GPIO_DIR,
NULL,
0); if (ret) return dev_err_probe(dev, ret, "unable to init generic GPIO\n");
g->gc.label = dev_name(dev);
g->gc.base = -1;
g->gc.parent = dev;
g->gc.owner = THIS_MODULE; /* ngpio is set by bgpio_init() */
/* We need a silicon clock to do debounce */ if (!IS_ERR(g->clk))
g->gc.set_config = ftgpio_gpio_set_config;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.