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