Home | History | Annotate | Download | only in serial
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Copyright (c) 2018 Alexander Graf <agraf (at) 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  */
     22 static 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 
     36 static int bcm283x_pl011_serial_ofdata_to_platdata(struct udevice *dev)
     37 {
     38 	struct pl01x_serial_platdata *plat = dev_get_platdata(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 	ret = pl01x_serial_ofdata_to_platdata(dev);
     46 	if (ret)
     47 		return ret;
     48 
     49 	/*
     50 	 * TODO: Reinitialization doesn't always work for now, just skip
     51 	 *       init always - we know we're already initialized
     52 	 */
     53 	plat->skip_init = true;
     54 
     55 	return 0;
     56 }
     57 
     58 static int bcm283x_pl011_serial_setbrg(struct udevice *dev, int baudrate)
     59 {
     60 	int r;
     61 
     62 	r = pl01x_serial_setbrg(dev, baudrate);
     63 
     64 	/*
     65 	 * We may have been muxed to a bogus line before. Drain the RX
     66 	 * queue so we start at a clean slate.
     67 	 */
     68 	while (pl01x_serial_getc(dev) != -EAGAIN) ;
     69 
     70 	return r;
     71 }
     72 
     73 static const struct dm_serial_ops bcm283x_pl011_serial_ops = {
     74 	.putc = pl01x_serial_putc,
     75 	.pending = pl01x_serial_pending,
     76 	.getc = pl01x_serial_getc,
     77 	.setbrg = bcm283x_pl011_serial_setbrg,
     78 };
     79 
     80 static const struct udevice_id bcm283x_pl011_serial_id[] = {
     81 	{.compatible = "brcm,bcm2835-pl011", .data = TYPE_PL011},
     82 	{}
     83 };
     84 
     85 U_BOOT_DRIVER(bcm283x_pl011_uart) = {
     86 	.name	= "bcm283x_pl011",
     87 	.id	= UCLASS_SERIAL,
     88 	.of_match = of_match_ptr(bcm283x_pl011_serial_id),
     89 	.ofdata_to_platdata = of_match_ptr(bcm283x_pl011_serial_ofdata_to_platdata),
     90 	.platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata),
     91 	.probe	= pl01x_serial_probe,
     92 	.ops	= &bcm283x_pl011_serial_ops,
     93 	.flags	= DM_FLAG_PRE_RELOC,
     94 	.priv_auto_alloc_size = sizeof(struct pl01x_priv),
     95 };
     96