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>master
parent
958d55f26c
commit
6001985f92
@ -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), |
||||||
|
}; |
Loading…
Reference in new issue