Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/acpi acpi: sdhc: Add support for RK356x eMMC control...



details:   https://anonhg.NetBSD.org/src/rev/dde7c829edc4
branches:  trunk
changeset: 359649:dde7c829edc4
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Jan 15 14:49:43 2022 +0000

description:
acpi: sdhc: Add support for RK356x eMMC controller.

RK356x has a DesignWare eMMC controller that is somewhat SDHCI compliant,
with one major problem -- the clock divisor doesn't actually work. To
change the clock card on Rockchip SoCs, the clock frequency needs to be
adjusted in the Clock & Reset Unit (CRU) directly.

The RK356x UEFI implementation introduces a DSM that allows drivers to
request firmware assistance in setting the card clock rate, for instances
like this where the divisor is broken.

>From the UEFI README:

  Function 1: Set Card Clock

  The _DSM control method parameters for the Set Card Clock function are
  as follows:

  Arguments

   * Arg0: UUID = 434addb0-8ff3-49d5-a724-95844b79ad1f
   * Arg1: Revision = 0
   * Arg2: Function Index = 1
   * Arg3: Target card clock rate in Hz.

  Return

   The actual card clock rate in Hz. Will be less than or equal to the
   target clock rate. Returns 0 if the target clock rate could not be set.

diffstat:

 sys/dev/acpi/sdhc_acpi.c |  64 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 62 insertions(+), 2 deletions(-)

diffs (127 lines):

diff -r c9a10be22425 -r dde7c829edc4 sys/dev/acpi/sdhc_acpi.c
--- a/sys/dev/acpi/sdhc_acpi.c  Sat Jan 15 14:40:22 2022 +0000
+++ b/sys/dev/acpi/sdhc_acpi.c  Sat Jan 15 14:49:43 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: sdhc_acpi.c,v 1.16 2022/01/11 22:32:44 jmcneill Exp $  */
+/*     $NetBSD: sdhc_acpi.c,v 1.17 2022/01/15 14:49:43 jmcneill Exp $  */
 
 /*
  * Copyright (c) 2016 Kimihiro Nonaka <nonaka%NetBSD.org@localhost>
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sdhc_acpi.c,v 1.16 2022/01/11 22:32:44 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sdhc_acpi.c,v 1.17 2022/01/15 14:49:43 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -45,6 +45,14 @@
 #define        SDHC_ESDHC_FLAGS        \
     (SDHC_FLAG_HAVE_DVS|SDHC_FLAG_NO_PWR0|SDHC_FLAG_32BIT_ACCESS|SDHC_FLAG_ENHANCED)
 
+/* Rockchip eMMC device-specific method (_DSM) - 434addb0-8ff3-49d5-a724-95844b79ad1f */
+static UINT8 sdhc_acpi_rockchip_dsm_uuid[ACPI_UUID_LENGTH] = {
+       0xb0, 0xdd, 0x4a, 0x43, 0xf3, 0x8f, 0xd5, 0x49,
+       0xa7, 0x24, 0x95, 0x84, 0x4b, 0x79, 0xad, 0x1f
+};
+#define        ROCKCHIP_DSM_REV                        0
+#define        ROCKCHIP_DSM_FUNC_SET_CARD_CLOCK        1
+
 #define _COMPONENT     ACPI_RESOURCE_COMPONENT
 ACPI_MODULE_NAME       ("sdhc_acpi")
 
@@ -59,6 +67,7 @@
        bus_space_handle_t sc_memh;
        bus_size_t sc_memsize;
        void *sc_ih;
+       ACPI_HANDLE sc_handle;
 
        ACPI_HANDLE sc_crs, sc_srs;
        ACPI_BUFFER sc_crs_buffer;
@@ -70,6 +79,9 @@
 static void    sdhc_acpi_intel_emmc_hw_reset(struct sdhc_softc *,
                    struct sdhc_host *);
 
+static int     sdhc_acpi_rockchip_bus_clock(struct sdhc_softc *,
+                   int);
+
 static const struct sdhc_acpi_slot {
        const char *hid;
        const char *uid;
@@ -93,6 +105,11 @@
                                         .flags = SDHC_ESDHC_FLAGS },
        { .hid = "NXP0003",  .uid = "1", .type = SLOT_TYPE_EMMC,
                                         .flags = SDHC_ESDHC_FLAGS },
+       { .hid = "RKCP0D40",             .type = SLOT_TYPE_SD,
+                                        .flags = SDHC_FLAG_32BIT_ACCESS |
+                                                 SDHC_FLAG_8BIT_MODE |
+                                                 SDHC_FLAG_USE_ADMA2 |
+                                                 SDHC_FLAG_SINGLE_POWER_WRITE },
 
        /* Generic IDs last */
        { .hid = "PNP0D40",              .type = SLOT_TYPE_SD },
@@ -149,16 +166,25 @@
        ACPI_STATUS rv;
        ACPI_INTEGER clock_freq;
        ACPI_INTEGER caps, caps_mask;
+       ACPI_INTEGER funcs;
 
        sc->sc.sc_dev = self;
        sc->sc.sc_dmat = aa->aa_dmat;
        sc->sc.sc_host = NULL;
        sc->sc_memt = aa->aa_memt;
+       sc->sc_handle = aa->aa_node->ad_handle;
 
        slot = sdhc_acpi_find_slot(aa->aa_node->ad_devinfo);
        if (slot->type == SLOT_TYPE_EMMC)
                sc->sc.sc_vendor_hw_reset = sdhc_acpi_intel_emmc_hw_reset;
 
+       rv = acpi_dsm_query(sc->sc_handle, sdhc_acpi_rockchip_dsm_uuid, 
+           ROCKCHIP_DSM_REV, &funcs);
+       if (ACPI_SUCCESS(rv) &&
+           ISSET(funcs, __BIT(ROCKCHIP_DSM_FUNC_SET_CARD_CLOCK))) {
+               sc->sc.sc_vendor_bus_clock = sdhc_acpi_rockchip_bus_clock;
+       }
+
        rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS",
            &res, &acpi_resource_parse_ops_default);
        if (ACPI_FAILURE(rv))
@@ -330,3 +356,37 @@
 
        mutex_exit(plock);
 }
+
+static int
+sdhc_acpi_rockchip_bus_clock(struct sdhc_softc *sc, int freq)
+{
+       struct sdhc_acpi_softc *asc = (struct sdhc_acpi_softc *)sc;
+       ACPI_STATUS rv;
+       ACPI_OBJECT targetfreq;
+       ACPI_OBJECT arg3;
+       ACPI_INTEGER actfreq;
+
+       targetfreq.Integer.Type = ACPI_TYPE_INTEGER;
+       targetfreq.Integer.Value = freq * 1000;
+       arg3.Package.Type = ACPI_TYPE_PACKAGE;
+       arg3.Package.Count = 1;
+       arg3.Package.Elements = &targetfreq;
+
+       rv = acpi_dsm_integer(asc->sc_handle, sdhc_acpi_rockchip_dsm_uuid,
+           ROCKCHIP_DSM_REV, ROCKCHIP_DSM_FUNC_SET_CARD_CLOCK, &arg3,
+           &actfreq);
+       if (ACPI_FAILURE(rv)) {
+               aprint_error_dev(sc->sc_dev,
+                   "eMMC Set Card Clock DSM failed: %s\n",
+                   AcpiFormatException(rv));
+               return ENXIO;
+       }
+
+       aprint_debug_dev(sc->sc_dev,
+           "eMMC Set Card Clock DSM returned %lu Hz\n", actfreq);
+       if (actfreq == 0) {
+               return EINVAL;
+       }
+
+       return 0;
+}



Home | Main Index | Thread Index | Old Index