Figuring out the clock frequency that is used for a com(4) device on
armv7 is hard.  If you're lucky, the device tree contains a
"clock-frequency" property that gives you the answer.  But if that
property isn't there you're supposed to traverse the clock tree to
find out the base frequency and apply the proper clock scaling.  In
many cases that requires reading hardware registers of a clock control
unit.  And during the early boot stages the driver for such a clock
control unit isn't there yet.

The clock frequency is necessary to set up the proper baud rate.
However, on armv7 u-boot will have configured the console serial port.
So we can simply skip configuring the baud rate and such for the early
console and deal with it later, when the com(4) driver properly
attaches.  Reading and writing single characters from the serial port
will work just fine, and that is all the serial console does.

I think this makes it much more likely to have a working early boot
console (which will help bringing up new boards) and gets rid of the
duplicated code to guess the right clock frequency that we currently
have.

The diff also installs its own cngetc and cnputc functions.  For now,
these are copies of comcngetc() and comcnputc().  But a future patch
will replace them with versions that account for the fact that
register access is on 32-bit boundaries such that we can get rid of
the armv7_a4x_bs_tag hack.

ok?


Index: arch/armv7/dev/com_fdt.c
===================================================================
RCS file: /cvs/src/sys/arch/armv7/dev/com_fdt.c,v
retrieving revision 1.6
diff -u -p -r1.6 com_fdt.c
--- arch/armv7/dev/com_fdt.c    17 Aug 2016 13:44:48 -0000      1.6
+++ arch/armv7/dev/com_fdt.c    19 Aug 2016 12:16:58 -0000
@@ -26,6 +26,7 @@
 
 #include <dev/ic/comreg.h>
 #include <dev/ic/comvar.h>
+#include <dev/cons.h>
 
 /* pick up armv7_a4x_bs_tag */
 #include <arch/arm/armv7/armv7var.h>
@@ -55,12 +56,20 @@ struct cfattach com_fdt_ca = {
        sizeof (struct com_fdt_softc), com_fdt_match, com_fdt_attach
 };
 
+int com_fdt_cngetc(dev_t);
+void com_fdt_cnputc(dev_t, int);
+void com_fdt_cnpollc(dev_t, int);
+
+struct consdev com_fdt_cons = {
+       NULL, NULL, com_fdt_cngetc, com_fdt_cnputc, com_fdt_cnpollc, NULL,
+       NODEV, CN_LOWPRI
+};
+
 void
 com_fdt_init_cons(void)
 {
        struct fdt_reg reg;
        void *node;
-       int freq = 48000000;
 
        if ((node = fdt_find_cons("ti,omap3-uart")) == NULL &&
            (node = fdt_find_cons("ti,omap4-uart")) == NULL &&
@@ -69,16 +78,21 @@ com_fdt_init_cons(void)
        if (fdt_get_reg(node, 0, &reg))
                return;
 
-       if ((node = fdt_find_node("/")) != NULL &&
-           (fdt_is_compatible(node, "allwinner,sun4i-a10") ||
-           fdt_is_compatible(node, "allwinner,sun5i-a10s") ||
-           fdt_is_compatible(node, "allwinner,sun5i-r8") ||
-           fdt_is_compatible(node, "allwinner,sun7i-a20")))
-               freq = 24000000;
-
-       comcnattach(&armv7_a4x_bs_tag, reg.addr, comcnspeed, freq,
-           comcnmode);
-       comdefaultrate = comcnspeed;
+       /*
+        * Figuring out the clock frequency is rather complicated as
+        * om many SoCs this requires traversing a fair amount of the
+        * clock tree.  Instead we rely on the firmware to set up the
+        * console for us and bypass the cominit() call that
+        * comcnattach() does by doing the minimal setup here.
+        */
+
+       comconsiot = &armv7_a4x_bs_tag;
+       if (bus_space_map(comconsiot, reg.addr, reg.size, 0, &comconsioh))
+               return;
+
+       comconsrate = comcnspeed;
+       comconscflag = comcnmode;
+       cn_tab = &com_fdt_cons;
 }
 
 int
@@ -130,6 +144,7 @@ com_fdt_attach(struct device *parent, st
        if (stdout_node == faa->fa_node) {
                SET(sc->sc.sc_hwflags, COM_HW_CONSOLE);
                SET(sc->sc.sc_swflags, COM_SW_SOFTCAR);
+               comconsfreq = sc->sc.sc_frequency;
        }
 
        if (bus_space_map(sc->sc.sc_iot, sc->sc.sc_iobase,
@@ -154,4 +169,21 @@ com_fdt_intr_designware(void *cookie)
        bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_usr);
 
        return comintr(sc);
+}
+
+int
+com_fdt_cngetc(dev_t dev)
+{
+       return com_common_getc(comconsiot, comconsioh);
+}
+
+void
+com_fdt_cnputc(dev_t dev, int c)
+{
+       com_common_putc(comconsiot, comconsioh, c);
+}
+
+void
+com_fdt_cnpollc(dev_t dev, int on)
+{
 }

Reply via email to