summaryrefslogtreecommitdiff
path: root/sys/dev/fdt
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2024-03-29 22:08:10 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2024-03-29 22:08:10 +0000
commitfe0ec10ac77ff60ed7f1e5500e6ca94b8c48ca0b (patch)
tree9464271cc92a1d208a269ed454eca58bb800aedb /sys/dev/fdt
parent3c247f0907266f60ab1437eb926539940a010a92 (diff)
Skip calculating timings if we can't determine the frequency of the clock.
This avoids programming the hardware with clearly wrong values. On the Milk-V Pioneer this means the I2C controller remains functional and rebooting using the appropriate SBI call still works. ok miod@
Diffstat (limited to 'sys/dev/fdt')
-rw-r--r--sys/dev/fdt/dwiic_fdt.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/sys/dev/fdt/dwiic_fdt.c b/sys/dev/fdt/dwiic_fdt.c
index 5f4de8d448c..c934b5ad022 100644
--- a/sys/dev/fdt/dwiic_fdt.c
+++ b/sys/dev/fdt/dwiic_fdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dwiic_fdt.c,v 1.1 2023/08/29 12:09:40 kettenis Exp $ */
+/* $OpenBSD: dwiic_fdt.c,v 1.2 2024/03/29 22:08:09 kettenis Exp $ */
/*
* Copyright (c) 2023 Patrick Wildt <patrick@blueri.se>
*
@@ -48,6 +48,7 @@ const struct cfattach dwiic_fdt_ca = {
sizeof(struct dwiic_fdt_softc), dwiic_fdt_match, dwiic_fdt_attach
};
+void dwiic_fdt_calc_timings(struct dwiic_fdt_softc *);
void dwiic_fdt_bus_scan(struct device *, struct i2cbus_attach_args *,
void *);
@@ -66,8 +67,6 @@ dwiic_fdt_attach(struct device *parent, struct device *self, void *aux)
struct dwiic_softc *sc = &fsc->sc_sc;
struct fdt_attach_args *faa = aux;
struct i2cbus_attach_args iba;
- uint32_t sda_hold, sda_fall, scl_fall;
- uint64_t freq;
if (faa->fa_nreg < 1)
return;
@@ -84,19 +83,7 @@ dwiic_fdt_attach(struct device *parent, struct device *self, void *aux)
reset_deassert_all(faa->fa_node);
clock_enable(faa->fa_node, NULL);
- freq = clock_get_frequency(faa->fa_node, NULL);
- sda_hold = OF_getpropint(faa->fa_node, "i2c-sda-hold-time-ns", 300);
- sda_fall = OF_getpropint(faa->fa_node, "i2c-sda-falling-time-ns", 300);
- scl_fall = OF_getpropint(faa->fa_node, "i2c-scl-falling-time-ns", 300);
-
- sc->sda_hold_time = round_closest(freq * sda_hold, 1000000000);
-
- /* Standard-mode: tHIGH = 4.0 us; tLOW = 4.7 us */
- sc->ss_hcnt = round_closest(freq * (4000 + sda_fall), 1000000000) - 3;
- sc->ss_lcnt = round_closest(freq * (4700 + scl_fall), 1000000000) - 1;
- /* Fast-mode: tHIGH = 0.6 us; tLOW = 1.3 us */
- sc->fs_hcnt = round_closest(freq * (600 + sda_fall), 1000000000) - 3;
- sc->fs_lcnt = round_closest(freq * (1300 + scl_fall), 1000000000) - 1;
+ dwiic_fdt_calc_timings(fsc);
if (dwiic_init(sc)) {
printf(": can't initialize\n");
@@ -130,6 +117,31 @@ dwiic_fdt_attach(struct device *parent, struct device *self, void *aux)
}
void
+dwiic_fdt_calc_timings(struct dwiic_fdt_softc *fsc)
+{
+ struct dwiic_softc *sc = &fsc->sc_sc;
+ uint32_t sda_hold, sda_fall, scl_fall;
+ uint64_t freq;
+
+ freq = clock_get_frequency(fsc->sc_node, NULL);
+ if (freq == 0)
+ return;
+
+ sda_hold = OF_getpropint(fsc->sc_node, "i2c-sda-hold-time-ns", 300);
+ sda_fall = OF_getpropint(fsc->sc_node, "i2c-sda-falling-time-ns", 300);
+ scl_fall = OF_getpropint(fsc->sc_node, "i2c-scl-falling-time-ns", 300);
+
+ sc->sda_hold_time = round_closest(freq * sda_hold, 1000000000);
+
+ /* Standard-mode: tHIGH = 4.0 us; tLOW = 4.7 us */
+ sc->ss_hcnt = round_closest(freq * (4000 + sda_fall), 1000000000) - 3;
+ sc->ss_lcnt = round_closest(freq * (4700 + scl_fall), 1000000000) - 1;
+ /* Fast-mode: tHIGH = 0.6 us; tLOW = 1.3 us */
+ sc->fs_hcnt = round_closest(freq * (600 + sda_fall), 1000000000) - 3;
+ sc->fs_lcnt = round_closest(freq * (1300 + scl_fall), 1000000000) - 1;
+}
+
+void
dwiic_fdt_bus_scan(struct device *self, struct i2cbus_attach_args *iba,
void *aux)
{