uboot/drivers/serial/serial_bcm283x_pl011.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2018 Alexander Graf <agraf@suse.de>
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <asm/gpio.h>
   9#include <dm/pinctrl.h>
  10#include <dm/platform_data/serial_pl01x.h>
  11#include <serial.h>
  12#include "serial_pl01x_internal.h"
  13
  14/*
  15 * Check if this serial device is muxed
  16 *
  17 * The serial device will only work properly if it has been muxed to the serial
  18 * pins by firmware. Check whether that happened here.
  19 *
  20 * @return true if serial device is muxed, false if not
  21 */
  22static bool bcm283x_is_serial_muxed(void)
  23{
  24        int serial_gpio = 15;
  25        struct udevice *dev;
  26
  27        if (uclass_first_device(UCLASS_PINCTRL, &dev) || !dev)
  28                return false;
  29
  30        if (pinctrl_get_gpio_mux(dev, 0, serial_gpio) != BCM2835_GPIO_ALT0)
  31                return false;
  32
  33        return true;
  34}
  35
  36static int bcm283x_pl011_serial_probe(struct udevice *dev)
  37{
  38        struct pl01x_serial_plat *plat = dev_get_plat(dev);
  39        int ret;
  40
  41        /* Don't spawn the device if it's not muxed */
  42        if (!bcm283x_is_serial_muxed())
  43                return -ENODEV;
  44
  45        /*
  46         * Read the ofdata here rather than in an of_to_plat() method
  47         * since we need the soc simple-bus to be probed so that the 'ranges'
  48         * property is used.
  49         */
  50        ret = pl01x_serial_of_to_plat(dev);
  51        if (ret)
  52                return ret;
  53
  54        /*
  55         * TODO: Reinitialization doesn't always work for now, just skip
  56         *       init always - we know we're already initialized
  57         */
  58        plat->skip_init = true;
  59
  60        return pl01x_serial_probe(dev);
  61}
  62
  63static int bcm283x_pl011_serial_setbrg(struct udevice *dev, int baudrate)
  64{
  65        int r;
  66
  67        r = pl01x_serial_setbrg(dev, baudrate);
  68
  69        /*
  70         * We may have been muxed to a bogus line before. Drain the RX
  71         * queue so we start at a clean slate.
  72         */
  73        while (pl01x_serial_getc(dev) != -EAGAIN) ;
  74
  75        return r;
  76}
  77
  78static const struct dm_serial_ops bcm283x_pl011_serial_ops = {
  79        .putc = pl01x_serial_putc,
  80        .pending = pl01x_serial_pending,
  81        .getc = pl01x_serial_getc,
  82        .setbrg = bcm283x_pl011_serial_setbrg,
  83};
  84
  85static const struct udevice_id bcm283x_pl011_serial_id[] = {
  86        {.compatible = "brcm,bcm2835-pl011", .data = TYPE_PL011},
  87        {}
  88};
  89
  90U_BOOT_DRIVER(bcm283x_pl011_uart) = {
  91        .name   = "bcm283x_pl011",
  92        .id     = UCLASS_SERIAL,
  93        .of_match = of_match_ptr(bcm283x_pl011_serial_id),
  94        .probe  = bcm283x_pl011_serial_probe,
  95        .plat_auto      = sizeof(struct pl01x_serial_plat),
  96        .ops    = &bcm283x_pl011_serial_ops,
  97#if !CONFIG_IS_ENABLED(OF_CONTROL) || CONFIG_IS_ENABLED(OF_BOARD)
  98        .flags  = DM_FLAG_PRE_RELOC,
  99#endif
 100        .priv_auto      = sizeof(struct pl01x_priv),
 101};
 102