From fe0ec10ac77ff60ed7f1e5500e6ca94b8c48ca0b Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Fri, 29 Mar 2024 22:08:10 +0000 Subject: 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@ --- sys/dev/fdt/dwiic_fdt.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) (limited to 'sys/dev/fdt') 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 * @@ -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"); @@ -129,6 +116,31 @@ dwiic_fdt_attach(struct device *parent, struct device *self, void *aux) config_found(&sc->sc_dev, &iba, iicbus_print); } +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) -- cgit v1.2.3