summaryrefslogtreecommitdiff
path: root/drivers/serial/serial_bcm283x_pl011.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2018-01-25 12:05:55 +0100
committerTom Rini <trini@konsulko.com>2018-01-28 12:27:36 -0500
commit6001985f92e4a99504343485bfe2c18940a41011 (patch)
tree49cd40e00fef73d73f5b4544336f098f74aa4ad6 /drivers/serial/serial_bcm283x_pl011.c
parent958d55f26ce4cde87a0f7cc5d5379b193a90d816 (diff)
bcm2835_pl011_serial: Add BCM2835 specific serial driver
On bcm2835 we need to ensure we only access serial devices that are muxed to the serial output pins of the pin header. To achieve this for the pl011 device, add a bcm2835 specific pl011 wrapper device that does this check but otherwise behaves like a pl011 device. Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'drivers/serial/serial_bcm283x_pl011.c')
-rw-r--r--drivers/serial/serial_bcm283x_pl011.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/drivers/serial/serial_bcm283x_pl011.c b/drivers/serial/serial_bcm283x_pl011.c
new file mode 100644
index 0000000000..bfd39f84f3
--- /dev/null
+++ b/drivers/serial/serial_bcm283x_pl011.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2018 Alexander Graf <agraf@suse.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/gpio.h>
+#include <dm/pinctrl.h>
+#include <dm/platform_data/serial_pl01x.h>
+#include "serial_pl01x_internal.h"
+
+/*
+ * Check if this serial device is muxed
+ *
+ * The serial device will only work properly if it has been muxed to the serial
+ * pins by firmware. Check whether that happened here.
+ *
+ * @return true if serial device is muxed, false if not
+ */
+static bool bcm283x_is_serial_muxed(void)
+{
+ int serial_gpio = 15;
+ struct udevice *dev;
+
+ if (uclass_first_device(UCLASS_PINCTRL, &dev) || !dev)
+ return false;
+
+ if (pinctrl_get_gpio_mux(dev, 0, serial_gpio) != BCM2835_GPIO_ALT0)
+ return false;
+
+ return true;
+}
+
+static int bcm283x_pl011_serial_ofdata_to_platdata(struct udevice *dev)
+{
+ struct pl01x_serial_platdata *plat = dev_get_platdata(dev);
+ int ret;
+
+ /* Don't spawn the device if it's not muxed */
+ if (!bcm283x_is_serial_muxed())
+ return -ENODEV;
+
+ ret = pl01x_serial_ofdata_to_platdata(dev);
+ if (ret)
+ return ret;
+
+ /*
+ * TODO: Reinitialization doesn't always work for now, just skip
+ * init always - we know we're already initialized
+ */
+ plat->skip_init = true;
+
+ return 0;
+}
+
+static const struct udevice_id bcm283x_pl011_serial_id[] = {
+ {.compatible = "brcm,bcm2835-pl011", .data = TYPE_PL011},
+ {}
+};
+
+U_BOOT_DRIVER(bcm283x_pl011_uart) = {
+ .name = "bcm283x_pl011",
+ .id = UCLASS_SERIAL,
+ .of_match = of_match_ptr(bcm283x_pl011_serial_id),
+ .ofdata_to_platdata = of_match_ptr(bcm283x_pl011_serial_ofdata_to_platdata),
+ .platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata),
+ .probe = pl01x_serial_probe,
+ .ops = &pl01x_serial_ops,
+ .flags = DM_FLAG_PRE_RELOC,
+ .priv_auto_alloc_size = sizeof(struct pl01x_priv),
+};