[PATCH] serial: ns16550: Fix ordering of getting base address
Bin Meng
bmeng.cn at gmail.com
Fri Apr 3 14:33:37 CEST 2020
Hi Wolfgang,
On Fri, Apr 3, 2020 at 7:47 PM Wolfgang Wallner
<wolfgang.wallner at br-automation.com> wrote:
>
> Hi Bin,
>
> Thanks for taking care of this!
>
> -----"Bin Meng" <bmeng.cn at gmail.com> schrieb: -----
>
> >An: "Simon Glass" <sjg at chromium.org>, "Tom Rini"
> ><trini at konsulko.com>, "Andy Shevchenko"
> ><andriy.shevchenko at linux.intel.com>, "Wolfgang Wallner"
> ><wolfgang.wallner at br-automation.com>, "Chee Hong Ang"
> ><chee.hong.ang at intel.com>, "U-Boot Mailing List"
> ><u-boot at lists.denx.de>
> >Von: "Bin Meng" <bmeng.cn at gmail.com>
> >Datum: 03.04.2020 11:58
> >Betreff: [PATCH] serial: ns16550: Fix ordering of getting base
> >address
> >
> >Currently the driver gets ns16550 base address in the driver
> >probe() routine, which may potentially break any ns16550 wrapper
> >driver that does additional initialization before calling
> >ns16550_serial_probe().
> >
> >Things are complicated that we need consider ns16550 devices on
> >both simple-bus and PCI bus. To fix the issue we move the base
> >address assignment for simple-bus ns16550 device back to the
> >ofdata_to_platdata(), and assign base address for PCI ns16550
> >device in ns16550_serial_probe().
> >
> >This is still not perfect. Ideally if any PCI bus based ns16550
> >wrapper driver tries to access plat->base before calling probe(),
> >it is subject to break.
> >
> >Fixes: 720f9e1fdb0c9 ("serial: ns16550: Move PCI access from
> >ofdata_to_platdata() to probe()")
> >Reported-by: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
> >Signed-off-by: Bin Meng <bmeng.cn at gmail.com>
> >
> >---
> >
> > drivers/serial/ns16550.c | 51
> >+++++++++++++++++++++++-------------------------
> > 1 file changed, 24 insertions(+), 27 deletions(-)
> >
> >diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c
> >index c1b303f..5e3cd1c 100644
> >--- a/drivers/serial/ns16550.c
> >+++ b/drivers/serial/ns16550.c
> >@@ -479,39 +479,24 @@ static int ns16550_serial_getinfo(struct
> >udevice *dev,
> > return 0;
> > }
> >
> >-#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
> >-static int ns1655_serial_set_base_addr(struct udevice *dev)
> >-{
> >- fdt_addr_t addr;
> >- struct ns16550_platdata *plat;
> >-
> >- plat = dev_get_platdata(dev);
> >-
> >- addr = dev_read_addr_pci(dev);
> >- if (addr == FDT_ADDR_T_NONE)
> >- return -EINVAL;
> >-
> >-#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
> >- plat->base = addr;
> >-#else
> >- plat->base = (unsigned long)map_physmem(addr, 0, MAP_NOCACHE);
> >-#endif
> >-
> >- return 0;
> >-}
> >-#endif
> >-
> > int ns16550_serial_probe(struct udevice *dev)
> > {
> >+ struct ns16550_platdata *plat = dev->platdata;
> > struct NS16550 *const com_port = dev_get_priv(dev);
> > struct reset_ctl_bulk reset_bulk;
> >+ fdt_addr_t addr;
> > int ret;
> >
> >-#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
> >- ret = ns1655_serial_set_base_addr(dev);
> >- if (ret)
> >- return ret;
> >-#endif
> >+ /*
> >+ * If we are on PCI bus, either directly attached to a PCI root
> >port,
> >+ * or via a PCI bridge, assign platdata->base before probing
> >hardware.
> >+ */
> >+ if (device_is_on_pci_bus(dev)) {
> >+ addr = devfdt_get_addr_pci(dev);
> >+ if (addr == FDT_ADDR_T_NONE)
> >+ return -EINVAL;
> >+ plat->base = addr;
>
> The assignment here to plat->base does not distinguish any more based on
> CONFIG_SYS_NS16550_PORT_MAPPED. Is it not necessary any more in this case?
>
Yep, you are right. Both two cases should be handled consistently. I
will spin a v2.
> >+ }
> >
> > ret = reset_get_bulk(dev, &reset_bulk);
> > if (!ret)
> >@@ -535,9 +520,21 @@ int ns16550_serial_ofdata_to_platdata(struct
> >udevice *dev)
> > {
> > struct ns16550_platdata *plat = dev->platdata;
> > const u32 port_type = dev_get_driver_data(dev);
> >+ fdt_addr_t addr;
> > struct clk clk;
> > int err;
> >
> >+ addr = dev_read_addr(dev);
> >+ if (addr != FDT_ADDR_T_NONE) {
> >+#ifdef CONFIG_SYS_NS16550_PORT_MAPPED
> >+ plat->base = addr;
> >+#else
> >+ plat->base = (unsigned long)map_physmem(addr, 0, MAP_NOCACHE);
> >+#endif
> >+ } else if (!device_is_on_pci_bus(dev)) {
> >+ return -EINVAL;
> >+ }
> >+
> > plat->reg_offset = dev_read_u32_default(dev, "reg-offset", 0);
> > plat->reg_shift = dev_read_u32_default(dev, "reg-shift", 0);
> > plat->reg_width = dev_read_u32_default(dev, "reg-io-width", 1);
> >--
> >2.7.4
> >
> >
>
> Tested-by: Wolfgang Wallner <wolfgang.wallner at br-automation.com>
> Tested on an Intel Apollo Lake based board booting with Coreboot and using
> U-Boot as payload.
>
Thanks for testing!
> Reviewed-by: Wolfgang Wallner <wolfgang.wallner at br-automation.com>
>
Regards,
Bin
More information about the U-Boot
mailing list