Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137908931
D24339.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D24339.diff
View Options
Index: sys/dev/ofw/ofw_fdt.c
===================================================================
--- sys/dev/ofw/ofw_fdt.c
+++ sys/dev/ofw/ofw_fdt.c
@@ -79,6 +79,8 @@
static ssize_t ofw_fdt_instance_to_path(ofw_t, ihandle_t, char *, size_t);
static ssize_t ofw_fdt_package_to_path(ofw_t, phandle_t, char *, size_t);
static int ofw_fdt_interpret(ofw_t, const char *, int, cell_t *);
+static int ofw_fdt_model(ofw_t, char *, size_t);
+static int ofw_fdt_compatible(ofw_t, char *, size_t);
static ofw_method_t ofw_fdt_methods[] = {
OFWMETHOD(ofw_init, ofw_fdt_init),
@@ -95,6 +97,8 @@
OFWMETHOD(ofw_instance_to_path, ofw_fdt_instance_to_path),
OFWMETHOD(ofw_package_to_path, ofw_fdt_package_to_path),
OFWMETHOD(ofw_interpret, ofw_fdt_interpret),
+ OFWMETHOD(ofw_model, ofw_fdt_model),
+ OFWMETHOD(ofw_compatible, ofw_fdt_compatible),
{ 0, 0 }
};
@@ -105,6 +109,11 @@
};
OFW_DEF(ofw_fdt);
+#define FDT_MODEL_LEN 80
+static char model[FDT_MODEL_LEN];
+#define FDT_COMPAT_LEN 80
+static char compatible[FDT_COMPAT_LEN];
+
static void *fdtp = NULL;
static int
@@ -125,6 +134,15 @@
SYSCTL_ADD_PROC(NULL, SYSCTL_STATIC_CHILDREN(_hw_fdt), OID_AUTO, "dtb",
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
sysctl_handle_dtb, "", "Device Tree Blob");
+
+ if (*model != '\0')
+ SYSCTL_ADD_STRING(NULL, SYSCTL_STATIC_CHILDREN(_hw_fdt),
+ OID_AUTO, "model", CTLFLAG_RD,
+ model, FDT_MODEL_LEN, "Model as given by manufacturer");
+ if (*compatible != '\0')
+ SYSCTL_ADD_STRING(NULL, SYSCTL_STATIC_CHILDREN(_hw_fdt),
+ OID_AUTO, "compatible", CTLFLAG_RD,
+ compatible, FDT_COMPAT_LEN, "Compatibility string as given by manufacturer");
}
SYSINIT(dtb_oid, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_fdt_oid, NULL);
@@ -132,12 +150,27 @@
ofw_fdt_init(ofw_t ofw, void *data)
{
int err;
+ phandle_t root;
/* Check FDT blob integrity */
if ((err = fdt_check_header(data)) != 0)
return (err);
fdtp = data;
+
+ bzero(model, FDT_MODEL_LEN);
+ if ((root = ofw_fdt_finddevice(NULL, "/")) != -1) {
+ if (ofw_fdt_getproplen(NULL, root, "model") > 0)
+ ofw_fdt_getprop(NULL, root, "model", model,
+ FDT_MODEL_LEN);
+ }
+
+ bzero(compatible, FDT_COMPAT_LEN);
+ if ((root = ofw_fdt_finddevice(NULL, "/")) != -1) {
+ if (ofw_fdt_getproplen(NULL, root, "compatible") > 0)
+ ofw_fdt_getprop(NULL, root, "compatible", compatible,
+ FDT_COMPAT_LEN);
+ }
return (0);
}
@@ -274,7 +307,6 @@
return (-1);
prop = fdt_getprop(fdtp, offset, propname, &len);
-
if (prop == NULL && strcmp(propname, "name") == 0) {
/* Emulate the 'name' property */
name = fdt_get_name(fdtp, offset, &len);
@@ -296,7 +328,6 @@
if (prop == NULL)
return (-1);
-
bcopy(prop, buf, min(len, buflen));
return (len);
@@ -407,25 +438,35 @@
return (-1);
}
+/* Find the model string from the fdt */
+static int
+ofw_fdt_model(ofw_t ofw, char *buf, size_t buflen)
+{
+
+ if (buf != NULL)
+ strlcpy (buf, model, buflen);
+ return (0);
+}
+
+/* Find the compatible string from the fdt */
+static int
+ofw_fdt_compatible(ofw_t ofw, char *buf, size_t buflen)
+{
+
+ if (buf != NULL)
+ strlcpy(buf, compatible, buflen);
+ return (0);
+}
+
#if defined(FDT_MARVELL)
static int
ofw_fdt_fixup(ofw_t ofw)
{
-#define FDT_MODEL_LEN 80
- char model[FDT_MODEL_LEN];
phandle_t root;
- ssize_t len;
int i;
- if ((root = ofw_fdt_finddevice(ofw, "/")) == -1)
- return (ENODEV);
-
- if ((len = ofw_fdt_getproplen(ofw, root, "model")) <= 0)
- return (0);
-
- bzero(model, FDT_MODEL_LEN);
- if (ofw_fdt_getprop(ofw, root, "model", model, FDT_MODEL_LEN) <= 0)
- return (0);
+ if (*model == '\0')
+ return (ENOENT);
/*
* Search fixup table and call handler if appropriate.
Index: sys/dev/ofw/ofw_if.m
===================================================================
--- sys/dev/ofw/ofw_if.m
+++ sys/dev/ofw/ofw_if.m
@@ -247,6 +247,30 @@
cell_t *_returns;
};
+/**
+ * @brief return model name
+ *
+ * @param _model Buffer for model
+ * @param _size Size of buffer
+ */
+METHOD int model {
+ ofw_t _ofw;
+ char *_model;
+ size_t _size;
+};
+
+/**
+ * @brief return compatible string
+ *
+ * @param _compatible Buffer for compatible
+ * @param _size Size of buffer
+ */
+METHOD int compatible {
+ ofw_t _ofw;
+ char *_compatible;
+ size_t _size;
+};
+
# Device I/O Functions (optional)
/**
Index: sys/dev/ofw/openfirm.h
===================================================================
--- sys/dev/ofw/openfirm.h
+++ sys/dev/ofw/openfirm.h
@@ -174,6 +174,8 @@
/* User interface functions */
int OF_interpret(const char *cmd, int nreturns, ...);
+int OF_model(char *buf, size_t len);
+int OF_compatible(char *buf, size_t len);
/*
* Decode the Nth register property of the given device node and create a bus
Index: sys/dev/ofw/openfirm.c
===================================================================
--- sys/dev/ofw/openfirm.c
+++ sys/dev/ofw/openfirm.c
@@ -846,3 +846,26 @@
for (;;) /* just in case */
;
}
+
+/* Return model from fdt. */
+int
+OF_model(char *buf, size_t len)
+{
+
+ if (ofw_def_impl == NULL)
+ return (0);
+
+ return(OFW_MODEL(ofw_obj, buf, len));
+}
+
+/* Return compatible from fdt. */
+int
+OF_compatible(char *buf, size_t len)
+{
+
+ if (ofw_def_impl == NULL)
+ return (0);
+
+ return(OFW_COMPATIBLE(ofw_obj, buf, len));
+}
+
Index: sys/dev/uart/uart_dev_mu.c
===================================================================
--- sys/dev/uart/uart_dev_mu.c
+++ sys/dev/uart/uart_dev_mu.c
@@ -140,7 +140,11 @@
static void uart_mu_putc(struct uart_bas *bas, int);
static int uart_mu_rxready(struct uart_bas *bas);
static int uart_mu_getc(struct uart_bas *bas, struct mtx *);
+static int cpu_clock(void);
+#define RPI2_AND_3_CORE_CLOCK 250000000
+#define RPI4_CORE_CLOCK 500000000
+
static struct uart_ops uart_mu_ops = {
.probe = uart_mu_probe,
.init = uart_mu_init,
@@ -157,12 +161,6 @@
return (0);
}
-/*
- * According to the docs, the cpu clock is locked to 250Mhz when
- * the micro-uart is used
- */
-#define CPU_CLOCK 250000000
-
static void
uart_mu_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
int parity)
@@ -193,10 +191,7 @@
/* See 2.2.1 BCM2835-ARM-Peripherals baudrate */
if (baudrate != 0) {
- baud = CPU_CLOCK / (8 * baudrate);
- /* XXX
- * baud = cpu_clock() / (8 * baudrate);
- */
+ baud = cpu_clock() / (8 * baudrate);
__uart_setreg(bas, AUX_MU_BAUD_REG, ((uint32_t)(baud & 0xFFFF)));
}
@@ -518,4 +513,30 @@
__uart_setreg(bas, AUX_MU_CNTL_REG, CNTL_RXENAB|CNTL_TXENAB);
__uart_setreg(bas, AUX_MU_IER_REG, psc->aux_ier);
uart_unlock(sc->sc_hwmtx);
+}
+
+/*
+ * From www.raspberrypi.org/documentation/configuration/uart.md
+ *
+ * "The baud rate of the mini UART is linked to the core frequency of
+ * the VPU on the VC4 GPU. This means that, as the VPU frequency governor
+ * varies the core frequency, the baud rate of the mini UART also changes"
+ *
+ * Since this is rather unusable for a uart the core frequency is locked
+ * if this uart is enabled in the config. Unfortantely it is locked
+ * to 250Mhz on Rpi2 and Rpi3 but 500Mhz on Rpi4 so this driver needs
+ * to determine which is needed. This is one approach, another approach
+ * might be to query bcm2835_cpufreq.c directly.
+ */
+
+
+static int
+cpu_clock(void)
+{
+ char model[40];
+
+ OF_model(model, sizeof(model));
+ if (strncmp(model, "Raspberry Pi 4", 14) == 0)
+ return (RPI4_CORE_CLOCK);
+ return (RPI2_AND_3_CORE_CLOCK);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 28, 3:05 AM (5 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26272455
Default Alt Text
D24339.diff (7 KB)
Attached To
Mode
D24339: Aux uart gets wrong clock speed on RPi4
Attached
Detach File
Event Timeline
Log In to Comment