Lines Matching +full:wdt +full:- +full:gpio

1 // SPDX-License-Identifier: GPL-2.0-or-later
10 * for GPIO or can be used to raise interrupts. The timer function can
14 * This driver supports the GPIO and IRQ controller functions of the GPT
17 * The timer gpt0 can be used as watchdog (wdt). If the wdt mode is used,
19 * -EBUSY). Thus, the safety wdt function always has precedence over the gpt
21 * this means that gpt0 is locked in wdt mode until the next reboot - this
24 * To use the GPIO function, the following two properties must be added
27 * gpio-controller;
28 * #gpio-cells = < 2 >;
29 * This driver will register the GPIO pin if it finds the gpio-controller
34 * interrupt-controller;
35 * #interrupt-cells = < 1 >;
41 * The GPIO and the IRQ controller functions can be used at the same time,
43 * use it as a GPIO output will not work.
45 * When using the GPIO line as an output, it can either be driven as normal
51 #include <linux/gpio/driver.h>
77 * struct mpc52xx_gpt - Private data structure for MPC52xx GPT driver
81 * @gc: gpio_chip instance structure; used when GPIO is enabled
84 * if the gpt may be used as wdt, bit 1 (MPC52xx_GPT_IS_WDT) indicates
85 * if the timer is actively used as wdt which blocks gpt functions
133 /* ---------------------------------------------------------------------
142 raw_spin_lock_irqsave(&gpt->lock, flags); in mpc52xx_gpt_irq_unmask()
143 setbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_IRQ_EN); in mpc52xx_gpt_irq_unmask()
144 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_irq_unmask()
152 raw_spin_lock_irqsave(&gpt->lock, flags); in mpc52xx_gpt_irq_mask()
153 clrbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_IRQ_EN); in mpc52xx_gpt_irq_mask()
154 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_irq_mask()
161 out_be32(&gpt->regs->status, MPC52xx_GPT_STATUS_IRQMASK); in mpc52xx_gpt_irq_ack()
170 dev_dbg(gpt->dev, "%s: virq=%i type=%x\n", __func__, d->irq, flow_type); in mpc52xx_gpt_irq_set_type()
172 raw_spin_lock_irqsave(&gpt->lock, flags); in mpc52xx_gpt_irq_set_type()
173 reg = in_be32(&gpt->regs->mode) & ~MPC52xx_GPT_MODE_ICT_MASK; in mpc52xx_gpt_irq_set_type()
178 out_be32(&gpt->regs->mode, reg); in mpc52xx_gpt_irq_set_type()
179 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_irq_set_type()
197 status = in_be32(&gpt->regs->status) & MPC52xx_GPT_STATUS_IRQMASK; in mpc52xx_gpt_irq_cascade()
199 generic_handle_domain_irq(gpt->irqhost, 0); in mpc52xx_gpt_irq_cascade()
205 struct mpc52xx_gpt_priv *gpt = h->host_data; in mpc52xx_gpt_irq_map()
207 dev_dbg(gpt->dev, "%s: h=%p, virq=%i\n", __func__, h, virq); in mpc52xx_gpt_irq_map()
219 struct mpc52xx_gpt_priv *gpt = h->host_data; in mpc52xx_gpt_irq_xlate()
221 dev_dbg(gpt->dev, "%s: flags=%i\n", __func__, intspec[0]); in mpc52xx_gpt_irq_xlate()
224 dev_err(gpt->dev, "bad irq specifier in %pOF\n", ct); in mpc52xx_gpt_irq_xlate()
225 return -EINVAL; in mpc52xx_gpt_irq_xlate()
250 gpt->irqhost = irq_domain_create_linear(of_fwnode_handle(node), 1, &mpc52xx_gpt_irq_ops, gpt); in mpc52xx_gpt_irq_setup()
251 if (!gpt->irqhost) { in mpc52xx_gpt_irq_setup()
252 dev_err(gpt->dev, "irq_domain_create_linear() failed\n"); in mpc52xx_gpt_irq_setup()
260 * Capture mode. If the mode is non-zero, then the pin could be in mpc52xx_gpt_irq_setup()
262 raw_spin_lock_irqsave(&gpt->lock, flags); in mpc52xx_gpt_irq_setup()
263 mode = in_be32(&gpt->regs->mode); in mpc52xx_gpt_irq_setup()
265 out_be32(&gpt->regs->mode, mode | MPC52xx_GPT_MODE_MS_IC); in mpc52xx_gpt_irq_setup()
266 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_irq_setup()
268 dev_dbg(gpt->dev, "%s() complete. virq=%i\n", __func__, cascade_virq); in mpc52xx_gpt_irq_setup()
272 /* ---------------------------------------------------------------------
276 static int mpc52xx_gpt_gpio_get(struct gpio_chip *gc, unsigned int gpio) in mpc52xx_gpt_gpio_get() argument
280 return (in_be32(&gpt->regs->status) >> 8) & 1; in mpc52xx_gpt_gpio_get()
284 mpc52xx_gpt_gpio_set(struct gpio_chip *gc, unsigned int gpio, int v) in mpc52xx_gpt_gpio_set() argument
290 dev_dbg(gpt->dev, "%s: gpio:%d v:%d\n", __func__, gpio, v); in mpc52xx_gpt_gpio_set()
293 raw_spin_lock_irqsave(&gpt->lock, flags); in mpc52xx_gpt_gpio_set()
294 clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_GPIO_MASK, r); in mpc52xx_gpt_gpio_set()
295 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_gpio_set()
300 static int mpc52xx_gpt_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) in mpc52xx_gpt_gpio_dir_in() argument
305 dev_dbg(gpt->dev, "%s: gpio:%d\n", __func__, gpio); in mpc52xx_gpt_gpio_dir_in()
307 raw_spin_lock_irqsave(&gpt->lock, flags); in mpc52xx_gpt_gpio_dir_in()
308 clrbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_GPIO_MASK); in mpc52xx_gpt_gpio_dir_in()
309 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_gpio_dir_in()
315 mpc52xx_gpt_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) in mpc52xx_gpt_gpio_dir_out() argument
317 mpc52xx_gpt_gpio_set(gc, gpio, val); in mpc52xx_gpt_gpio_dir_out()
325 /* Only setup GPIO if the device claims the GPT is a GPIO controller */ in mpc52xx_gpt_gpio_setup()
326 if (!device_property_present(gpt->dev, "gpio-controller")) in mpc52xx_gpt_gpio_setup()
329 gpt->gc.label = kasprintf(GFP_KERNEL, "%pfw", dev_fwnode(gpt->dev)); in mpc52xx_gpt_gpio_setup()
330 if (!gpt->gc.label) { in mpc52xx_gpt_gpio_setup()
331 dev_err(gpt->dev, "out of memory\n"); in mpc52xx_gpt_gpio_setup()
335 gpt->gc.ngpio = 1; in mpc52xx_gpt_gpio_setup()
336 gpt->gc.direction_input = mpc52xx_gpt_gpio_dir_in; in mpc52xx_gpt_gpio_setup()
337 gpt->gc.direction_output = mpc52xx_gpt_gpio_dir_out; in mpc52xx_gpt_gpio_setup()
338 gpt->gc.get = mpc52xx_gpt_gpio_get; in mpc52xx_gpt_gpio_setup()
339 gpt->gc.set = mpc52xx_gpt_gpio_set; in mpc52xx_gpt_gpio_setup()
340 gpt->gc.base = -1; in mpc52xx_gpt_gpio_setup()
341 gpt->gc.parent = gpt->dev; in mpc52xx_gpt_gpio_setup()
343 /* Setup external pin in GPIO mode */ in mpc52xx_gpt_gpio_setup()
344 clrsetbits_be32(&gpt->regs->mode, MPC52xx_GPT_MODE_MS_MASK, in mpc52xx_gpt_gpio_setup()
347 rc = gpiochip_add_data(&gpt->gc, gpt); in mpc52xx_gpt_gpio_setup()
349 dev_err(gpt->dev, "gpiochip_add_data() failed; rc=%i\n", rc); in mpc52xx_gpt_gpio_setup()
351 dev_dbg(gpt->dev, "%s() complete.\n", __func__); in mpc52xx_gpt_gpio_setup()
362 * mpc52xx_gpt_from_irq - Return the GPT device associated with an IRQ number
374 if (gpt->irqhost && irq == irq_find_mapping(gpt->irqhost, 0)) { in mpc52xx_gpt_from_irq()
405 clocks = period * (u64)gpt->ipb_freq; in mpc52xx_gpt_do_start()
410 return -EINVAL; in mpc52xx_gpt_do_start()
429 return -EINVAL; in mpc52xx_gpt_do_start()
432 /* Set and enable the timer, reject an attempt to use a wdt as gpt */ in mpc52xx_gpt_do_start()
433 raw_spin_lock_irqsave(&gpt->lock, flags); in mpc52xx_gpt_do_start()
435 gpt->wdt_mode |= MPC52xx_GPT_IS_WDT; in mpc52xx_gpt_do_start()
436 else if ((gpt->wdt_mode & MPC52xx_GPT_IS_WDT) != 0) { in mpc52xx_gpt_do_start()
437 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_do_start()
438 return -EBUSY; in mpc52xx_gpt_do_start()
440 out_be32(&gpt->regs->count, prescale << 16 | clocks); in mpc52xx_gpt_do_start()
441 clrsetbits_be32(&gpt->regs->mode, clear, set); in mpc52xx_gpt_do_start()
442 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_do_start()
448 * mpc52xx_gpt_start_timer - Set and enable the GPT timer
463 * mpc52xx_gpt_stop_timer - Stop a gpt
466 * Returns an error if attempting to stop a wdt
473 raw_spin_lock_irqsave(&gpt->lock, flags); in mpc52xx_gpt_stop_timer()
474 if ((gpt->wdt_mode & MPC52xx_GPT_IS_WDT) != 0) { in mpc52xx_gpt_stop_timer()
475 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_stop_timer()
476 return -EBUSY; in mpc52xx_gpt_stop_timer()
479 clrbits32(&gpt->regs->mode, MPC52xx_GPT_MODE_COUNTER_ENABLE); in mpc52xx_gpt_stop_timer()
480 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_stop_timer()
486 * mpc52xx_gpt_timer_period - Read the timer period
497 raw_spin_lock_irqsave(&gpt->lock, flags); in mpc52xx_gpt_timer_period()
498 period = in_be32(&gpt->regs->count); in mpc52xx_gpt_timer_period()
499 raw_spin_unlock_irqrestore(&gpt->lock, flags); in mpc52xx_gpt_timer_period()
506 do_div(period, gpt->ipb_freq); in mpc52xx_gpt_timer_period()
521 /* wdt-capable gpt */
524 /* low-level wdt functions */
529 raw_spin_lock_irqsave(&gpt_wdt->lock, flags); in mpc52xx_gpt_wdt_ping()
530 out_8((u8 *) &gpt_wdt->regs->mode, MPC52xx_GPT_MODE_WDT_PING); in mpc52xx_gpt_wdt_ping()
531 raw_spin_unlock_irqrestore(&gpt_wdt->lock, flags); in mpc52xx_gpt_wdt_ping()
534 /* wdt misc device api */
538 struct mpc52xx_gpt_priv *gpt_wdt = file->private_data; in mpc52xx_wdt_write()
551 struct mpc52xx_gpt_priv *gpt_wdt = file->private_data; in mpc52xx_wdt_ioctl()
562 ret = -EFAULT; in mpc52xx_wdt_ioctl()
588 * - timeout requested is 1 second; in mpc52xx_wdt_ioctl()
589 * - real timeout @33MHz is 999997090ns in mpc52xx_wdt_ioctl()
590 * - the int divide by 10^9 will return 0. in mpc52xx_wdt_ioctl()
600 ret = -ENOTTY; in mpc52xx_wdt_ioctl()
611 return -ENODEV; in mpc52xx_wdt_open()
615 return -EBUSY; in mpc52xx_wdt_open()
625 file->private_data = mpc52xx_gpt_wdt; in mpc52xx_wdt_open()
631 /* note: releasing the wdt in NOWAYOUT-mode does not stop it */ in mpc52xx_wdt_release()
633 struct mpc52xx_gpt_priv *gpt_wdt = file->private_data; in mpc52xx_wdt_release()
636 raw_spin_lock_irqsave(&gpt_wdt->lock, flags); in mpc52xx_wdt_release()
637 clrbits32(&gpt_wdt->regs->mode, in mpc52xx_wdt_release()
639 gpt_wdt->wdt_mode &= ~MPC52xx_GPT_IS_WDT; in mpc52xx_wdt_release()
640 raw_spin_unlock_irqrestore(&gpt_wdt->lock, flags); in mpc52xx_wdt_release()
680 /* remember the gpt for the wdt operation */ in mpc52xx_gpt_wdt_setup()
683 /* configure the wdt if the device tree contained a timeout */ in mpc52xx_gpt_wdt_setup()
689 dev_warn(gpt->dev, "starting as wdt failed\n"); in mpc52xx_gpt_wdt_setup()
691 dev_info(gpt->dev, "watchdog set to %us timeout\n", *period); in mpc52xx_gpt_wdt_setup()
710 /* ---------------------------------------------------------------------
717 gpt = devm_kzalloc(&ofdev->dev, sizeof *gpt, GFP_KERNEL); in mpc52xx_gpt_probe()
719 return -ENOMEM; in mpc52xx_gpt_probe()
721 raw_spin_lock_init(&gpt->lock); in mpc52xx_gpt_probe()
722 gpt->dev = &ofdev->dev; in mpc52xx_gpt_probe()
723 gpt->ipb_freq = mpc5xxx_get_bus_frequency(&ofdev->dev); in mpc52xx_gpt_probe()
724 gpt->regs = of_iomap(ofdev->dev.of_node, 0); in mpc52xx_gpt_probe()
725 if (!gpt->regs) in mpc52xx_gpt_probe()
726 return -ENOMEM; in mpc52xx_gpt_probe()
728 dev_set_drvdata(&ofdev->dev, gpt); in mpc52xx_gpt_probe()
731 mpc52xx_gpt_irq_setup(gpt, ofdev->dev.of_node); in mpc52xx_gpt_probe()
734 list_add(&gpt->list, &mpc52xx_gpt_list); in mpc52xx_gpt_probe()
738 if (of_property_read_bool(ofdev->dev.of_node, "fsl,has-wdt") || in mpc52xx_gpt_probe()
739 of_property_read_bool(ofdev->dev.of_node, "has-wdt")) { in mpc52xx_gpt_probe()
742 gpt->wdt_mode = MPC52xx_GPT_CAN_WDT; in mpc52xx_gpt_probe()
743 on_boot_wdt = of_get_property(ofdev->dev.of_node, in mpc52xx_gpt_probe()
744 "fsl,wdt-on-boot", NULL); in mpc52xx_gpt_probe()
746 dev_info(gpt->dev, "used as watchdog\n"); in mpc52xx_gpt_probe()
747 gpt->wdt_mode |= MPC52xx_GPT_IS_WDT; in mpc52xx_gpt_probe()
749 dev_info(gpt->dev, "can function as watchdog\n"); in mpc52xx_gpt_probe()
757 { .compatible = "fsl,mpc5200-gpt", },
760 { .compatible = "fsl,mpc5200-gpt-gpio", },
761 { .compatible = "mpc5200-gpt", },
767 .name = "mpc52xx-gpt",