make ahcisata(4) work on rk3399 (rockpro64) on rk3399, a marvell 9230 ahci sata card consistently takes between 1213 and 1216 milliseconds, the ahci spec says this should complete in 1000 or fewer. add a "pcie-slow-reset" bool property that ahcisata sees, and that the rockchip platform code sets and allow upto 2000ms reset. Index: sys/arch/arm/rockchip/rk_platform.c =================================================================== RCS file: /cvsroot/src/sys/arch/arm/rockchip/rk_platform.c,v retrieving revision 1.12 diff -p -u -r1.12 rk_platform.c --- sys/arch/arm/rockchip/rk_platform.c 24 Apr 2021 23:36:28 -0000 1.12 +++ sys/arch/arm/rockchip/rk_platform.c 22 Jun 2021 07:33:39 -0000 @@ -39,6 +39,8 @@ __KERNEL_RCSID(0, "$NetBSD: rk_platform. #include #include +#include + #include #include @@ -70,6 +72,13 @@ rk_platform_init_attach_args(struct fdt_ static void rk_platform_device_register(device_t self, void *aux) { + prop_dictionary_t dict = device_properties(self); + + if (device_is_a(self, "ahcisata")) { + if (!prop_dictionary_set_bool(dict, "pcie-slow-reset", true)) + printf("%s: Failed to set \"pcie-slow-reset\" property" + " on ahcisata\n", __func__); + } } static void Index: sys/dev/ic/ahcisata_core.c =================================================================== RCS file: /cvsroot/src/sys/dev/ic/ahcisata_core.c,v retrieving revision 1.98 diff -p -u -r1.98 ahcisata_core.c --- sys/dev/ic/ahcisata_core.c 24 Apr 2021 23:36:55 -0000 1.98 +++ sys/dev/ic/ahcisata_core.c 22 Jun 2021 07:33:39 -0000 @@ -144,19 +144,35 @@ static int ahci_reset(struct ahci_softc *sc) { int i; + uint32_t ctrl; + prop_dictionary_t dict; + bool slow_reset = false; /* reset controller */ - AHCI_WRITE(sc, AHCI_GHC, AHCI_GHC_HR); + ctrl = AHCI_READ(sc, AHCI_GHC); + if ((ctrl & AHCI_GHC_HR) == 0) { + AHCI_WRITE(sc, AHCI_GHC, ctrl | AHCI_GHC_HR); + } + + /* some systems (rockchip rk3399) need extra reset time for ahcisata. */ + dict = device_properties(sc->sc_atac.atac_dev); + if (dict) + prop_dictionary_get_bool(dict, "pcie-slow-reset", &slow_reset); + /* wait up to 1s for reset to complete */ - for (i = 0; i < 1000; i++) { + for (i = 0; i < (slow_reset ? 2000 : 1000); i++) { delay(1000); if ((AHCI_READ(sc, AHCI_GHC) & AHCI_GHC_HR) == 0) break; } - if ((AHCI_READ(sc, AHCI_GHC) & AHCI_GHC_HR)) { - aprint_error("%s: reset failed\n", AHCINAME(sc)); + if ((AHCI_READ(sc, AHCI_GHC) & AHCI_GHC_HR) != 0) { + aprint_error_dev(sc->sc_atac.atac_dev, "reset failed\n"); return -1; } + if (i > 1000) { + aprint_normal_dev(sc->sc_atac.atac_dev, + "reset took %d milliseconds\n", i); + } /* enable ahci mode */ ahci_enable(sc);