summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/sandbox/dts/test.dts1
-rw-r--r--doc/README.serial_dt_baud41
-rw-r--r--drivers/core/ofnode.c18
-rw-r--r--drivers/serial/Kconfig9
-rw-r--r--drivers/serial/serial-uclass.c49
-rw-r--r--include/dm/ofnode.h14
-rw-r--r--include/env_default.h6
-rw-r--r--include/serial.h7
-rw-r--r--test/dm/serial.c1
9 files changed, 143 insertions, 3 deletions
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 2887f6c0e71..c7197795efb 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -1572,6 +1572,7 @@
other-node = "/some-bus/c-test@5";
int-values = <0x1937 72993>;
u-boot,acpi-ssdt-order = <&acpi_test2 &acpi_test1>;
+ stdout-path = "serial0:115200n8";
chosen-test {
compatible = "denx,u-boot-fdt-test";
reg = <9 1>;
diff --git a/doc/README.serial_dt_baud b/doc/README.serial_dt_baud
new file mode 100644
index 00000000000..f8768d0e1bc
--- /dev/null
+++ b/doc/README.serial_dt_baud
@@ -0,0 +1,41 @@
+Fetch serial baudrate from DT
+-----------------------------
+
+To support fetching of baudrate from DT, the following is done:-
+
+The baudrate configured in Kconfig symbol CONFIG_BAUDRATE is taken by default by serial.
+If change of baudrate is required then the Kconfig symbol CONFIG_BAUDRATE needs to
+changed and U-Boot recompilation is required or the U-Boot environment needs to be updated.
+
+To avoid this, add support to fetch the baudrate directly from the device tree file and
+update the environment.
+
+The default environment stores the default baudrate value. When default baudrate and dtb
+baudrate are not same glitches are seen on the serial.
+So, the environment also needs to be updated with the dtb baudrate to avoid the glitches on
+the serial which is enabled by OF_SERIAL_BAUD.
+
+The Kconfig SPL_ENV_SUPPORT needs to be enabled to allow patching in SPL.
+
+The Kconfig DEFAULT_ENV_IS_RW which is enabled by OF_SERIAL_BAUD with making the environment
+writable.
+
+The ofnode_read_baud() function parses and fetches the baudrate value from the DT. This value
+is validated and updated to baudrate during serial init. Padding is added at the end of the
+default environment and the dt baudrate is updated with the latest value.
+
+Example:-
+
+The serial port options are of the form "bbbbpnf", where "bbbb" is the baud rate, "p" is parity ("n", "o", or "e"),
+"n" is number of bits, and "f" is flow control ("r" for RTS or omit it). Default is "115200n8".
+
+chosen {
+ bootargs = "earlycon console=ttyPS0,115200 clk_ignore_unused root=/dev/ram0 rw init_fatal_sh=1";
+ stdout-path = "serial0:115200n8";
+ };
+
+From the chosen node, stdout-path property is obtained as string.
+
+ stdout-path = "serial0:115200n8";
+
+The string is parsed to get the baudrate 115200. This string is converted to integer and updated to the environment.
diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c
index 29a42945102..f72ea416cf1 100644
--- a/drivers/core/ofnode.c
+++ b/drivers/core/ofnode.c
@@ -991,6 +991,24 @@ ofnode ofnode_get_chosen_node(const char *name)
return ofnode_path(prop);
}
+int ofnode_read_baud(void)
+{
+ const char *str, *p;
+ u32 baud;
+
+ str = ofnode_read_chosen_string("stdout-path");
+ if (!str)
+ return -EINVAL;
+
+ /* Parse string serial0:115200n8 */
+ p = strchr(str, ':');
+ if (!p)
+ return -EINVAL;
+
+ baud = dectoul(p + 1, NULL);
+ return baud;
+}
+
const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
{
ofnode node;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 8761a645407..6628a887de7 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -24,6 +24,15 @@ config BAUDRATE
in the SPL stage (most drivers) or for choosing a default baudrate
in the absence of an environment setting (serial_mxc.c).
+config OF_SERIAL_BAUD
+ bool "Fetch serial baudrate from device tree"
+ depends on DM_SERIAL && SPL_ENV_SUPPORT
+ select DEFAULT_ENV_IS_RW
+ help
+ Select this to enable fetching and setting of the baudrate
+ configured in the DT. Replace the default baudrate with the DT
+ baudrate and also set it to the environment.
+
config DEFAULT_ENV_IS_RW
bool "Make default environment as writable"
help
diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c
index df6a387284a..e4fa3933bc8 100644
--- a/drivers/serial/serial-uclass.c
+++ b/drivers/serial/serial-uclass.c
@@ -155,12 +155,61 @@ static void serial_find_console_or_panic(void)
}
#endif /* CONFIG_SERIAL_PRESENT */
+/**
+ * check_valid_baudrate() - Check whether baudrate is valid or not
+ *
+ * @baud: baud rate to check
+ * Return: 0 if OK, -ve on error
+ */
+static int check_valid_baudrate(int baud)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(baudrate_table); ++i) {
+ if (baud == baudrate_table[i])
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+int fetch_baud_from_dtb(void)
+{
+ int baud_value, ret;
+
+ baud_value = ofnode_read_baud();
+ ret = check_valid_baudrate(baud_value);
+ if (ret)
+ return ret;
+
+ return baud_value;
+}
+
/* Called prior to relocation */
int serial_init(void)
{
#if CONFIG_IS_ENABLED(SERIAL_PRESENT)
serial_find_console_or_panic();
gd->flags |= GD_FLG_SERIAL_READY;
+
+ if (IS_ENABLED(CONFIG_OF_SERIAL_BAUD)) {
+ int ret = 0;
+ char *ptr = (char*)&default_environment[0];
+
+ /*
+ * Fetch the baudrate from the dtb and update the value in the
+ * default environment.
+ */
+ ret = fetch_baud_from_dtb();
+ if (ret != -EINVAL && ret != -EFAULT) {
+ gd->baudrate = ret;
+
+ while (*ptr != '\0' && *(ptr + 1) != '\0')
+ ptr++;
+ ptr += 2;
+ sprintf(ptr, "baudrate=%d", gd->baudrate);
+ }
+ }
serial_setbrg();
#endif
diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h
index 19e97a90327..5795115c490 100644
--- a/include/dm/ofnode.h
+++ b/include/dm/ofnode.h
@@ -977,12 +977,22 @@ const char *ofnode_read_chosen_string(const char *propname);
ofnode ofnode_get_chosen_node(const char *propname);
/**
- * ofnode_read_aliases_prop() - get the value of a aliases property
+ * ofnode_read_baud() - get the baudrate from string value of chosen property
*
- * This looks for a property within the /aliases node and returns its value
+ * This looks for stdout-path property within the /chosen node and parses its
+ * value to return baudrate.
*
* This only works with the control FDT.
*
+ * Return: baudrate value if found, else -ve error code
+ */
+int ofnode_read_baud(void);
+
+/**
+ * ofnode_read_aliases_prop() - get the value of a aliases property
+ *
+ * This looks for a property within the /aliases node and returns its value
+ *
* @propname: Property name to look for
* @sizep: Returns size of property, or `FDT_ERR_...` error code if function
* returns NULL
diff --git a/include/env_default.h b/include/env_default.h
index 227cad7c340..2ca4a087d3b 100644
--- a/include/env_default.h
+++ b/include/env_default.h
@@ -42,7 +42,7 @@ const char default_environment[] = {
#if defined(CONFIG_BOOTDELAY)
"bootdelay=" __stringify(CONFIG_BOOTDELAY) "\0"
#endif
-#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
+#if !defined(CONFIG_OF_SERIAL_BAUD) && defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
"baudrate=" __stringify(CONFIG_BAUDRATE) "\0"
#endif
#ifdef CONFIG_LOADS_ECHO
@@ -119,6 +119,10 @@ const char default_environment[] = {
#ifdef CFG_EXTRA_ENV_SETTINGS
CFG_EXTRA_ENV_SETTINGS
#endif
+#ifdef CONFIG_OF_SERIAL_BAUD
+ /* Padding for baudrate at the end when environment is writable */
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+#endif
"\0"
#else /* CONFIG_USE_DEFAULT_ENV_FILE */
#include "generated/defaultenv_autogenerated.h"
diff --git a/include/serial.h b/include/serial.h
index 205889d28be..d129dc3253c 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -339,6 +339,13 @@ int serial_setconfig(struct udevice *dev, uint config);
*/
int serial_getinfo(struct udevice *dev, struct serial_device_info *info);
+/**
+ * fetch_baud_from_dtb() - Fetch the baudrate value from DT
+ *
+ * Return: baudrate if OK, -ve on error
+ */
+int fetch_baud_from_dtb(void);
+
void atmel_serial_initialize(void);
void mcf_serial_initialize(void);
void mpc85xx_serial_initialize(void);
diff --git a/test/dm/serial.c b/test/dm/serial.c
index 37d17a65f16..34b783e062e 100644
--- a/test/dm/serial.c
+++ b/test/dm/serial.c
@@ -29,6 +29,7 @@ static int dm_test_serial(struct unit_test_state *uts)
&dev_serial));
ut_assertok(serial_tstc());
+ ut_asserteq(115200, fetch_baud_from_dtb());
/*
* test with default config which is the only one supported by
* sandbox_serial driver