From patchwork Sun Apr 26 15:25:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1277102 X-Patchwork-Delegate: bmeng.cn@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=dyyTOLBP; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 499Bdr5ydDz9sRY for ; Mon, 27 Apr 2020 01:29:04 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id CB6BC81D62; Sun, 26 Apr 2020 17:27:38 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="dyyTOLBP"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 4EBA481D62; Sun, 26 Apr 2020 17:26:48 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-il1-x141.google.com (mail-il1-x141.google.com [IPv6:2607:f8b0:4864:20::141]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id BF43381D3C for ; Sun, 26 Apr 2020 17:26:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-il1-x141.google.com with SMTP id x2so14317127ilp.13 for ; Sun, 26 Apr 2020 08:26:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=K9i8/pgyoRFeRCgjmc9Tv1pLRDblQqTan0Y4H7DEPTk=; b=dyyTOLBPcHQH0IVb5mlnvpONFKFV1sY63P44xACNawNvpTFTLI5GcJwEFJk9zO4PmP JNaYy0Q9zv7d3K9Wxl4OOauw5c2VGfdcHkyYu08Vi9Dhd16mcjPznUBr2n+RNW1wzThb VSu0i4nyYv6uJ2imWk6KAFbLhC6D2rSYdXhyU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=K9i8/pgyoRFeRCgjmc9Tv1pLRDblQqTan0Y4H7DEPTk=; b=idQmQCiDGBNYAAru2Gq7yczkMwZXrdWjxjCcgYC/ALyDEZwPkKtkDW8N+9ZBiklHCm DkgzagJNsSF1ehiotBEdoEwI4/hd0zE8hNRNwoASypOS0wy8V55mva21lHn3FuR+Nfvs cJu9uPtDQ7TKOjovgJ1WBx8LHJruPi47twjmuR5S69OZ+zHd3w0TKhtO29/zJATLvm+k +2BQTbbRyz3adyM5KKYWaP2o88GXaVT3Zuu7693Nfy51l7L2jEMJr0Oy9ZZ4or768ZlH xJexNbhW7tfFuyf2q8Qx0emiSV6fgfd14FyLjcmRQxRj849WMNQwnHTz9Hn0oShEuYrG 7NVA== X-Gm-Message-State: AGi0PubOMAT8leOOr2WttOThbVg2i1lvmvmbb4xYbzAHeymphblrQ7I8 ZTQTlueXZey3o8JgNwvSWfLAVzSmLv6ECw== X-Google-Smtp-Source: APiQypL3uUE196WecNi2DPoG8t5He5PeufPMRVl5wgmG6FAPNak5aoeZf6ODSXvxzdQJUwhoVWbzHw== X-Received: by 2002:a92:9509:: with SMTP id y9mr17549687ilh.41.1587914794204; Sun, 26 Apr 2020 08:26:34 -0700 (PDT) Received: from localhost.localdomain (c-73-14-175-90.hsd1.co.comcast.net. [73.14.175.90]) by smtp.gmail.com with ESMTPSA id r16sm4437069ilb.32.2020.04.26.08.26.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 26 Apr 2020 08:26:33 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Wolfgang Wallner , Bin Meng , Andy Shevchenko , Simon Glass , Heiko Schocher Subject: [PATCH v8 11/35] acpi: Support generation of I2C descriptor Date: Sun, 26 Apr 2020 09:25:54 -0600 Message-Id: <20200426152618.125646-9-sjg@chromium.org> X-Mailer: git-send-email 2.26.2.303.gf8c07b1a785-goog In-Reply-To: <20200426152618.125646-1-sjg@chromium.org> References: <20200426152618.125646-1-sjg@chromium.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.30rc1 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.2 at phobos.denx.de X-Virus-Status: Clean Add a function to write a GPIO descriptor to the generated ACPI code. Signed-off-by: Simon Glass --- Changes in v8: None Changes in v3: None Changes in v2: None drivers/i2c/sandbox_i2c.c | 11 ++++ drivers/rtc/sandbox_rtc.c | 11 ++++ include/acpi/acpi_device.h | 37 +++++++++++++ lib/acpi/acpi_device.c | 103 +++++++++++++++++++++++++++++++++++++ test/dm/acpigen.c | 32 ++++++++++++ 5 files changed, 194 insertions(+) diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c index 1a4521d5b8..d4e74b281e 100644 --- a/drivers/i2c/sandbox_i2c.c +++ b/drivers/i2c/sandbox_i2c.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -82,6 +83,15 @@ static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, return ops->xfer(emul, msg, nmsgs); } +static int sandbox_i2c_get_name(const struct udevice *dev, char *out_name) +{ + return acpi_copy_name(out_name, "SI2C"); +} + +struct acpi_ops sandbox_i2c_acpi_ops = { + .get_name = sandbox_i2c_get_name, +}; + static const struct dm_i2c_ops sandbox_i2c_ops = { .xfer = sandbox_i2c_xfer, }; @@ -97,4 +107,5 @@ U_BOOT_DRIVER(i2c_sandbox) = { .of_match = sandbox_i2c_ids, .ops = &sandbox_i2c_ops, .priv_auto_alloc_size = sizeof(struct sandbox_i2c_priv), + ACPI_OPS_PTR(&sandbox_i2c_acpi_ops) }; diff --git a/drivers/rtc/sandbox_rtc.c b/drivers/rtc/sandbox_rtc.c index b08d758a74..660570d029 100644 --- a/drivers/rtc/sandbox_rtc.c +++ b/drivers/rtc/sandbox_rtc.c @@ -9,6 +9,7 @@ #include #include #include +#include #define REG_COUNT 0x80 @@ -84,6 +85,15 @@ static int sandbox_rtc_write8(struct udevice *dev, unsigned int reg, int val) return dm_i2c_reg_write(dev, reg, val); } +static int sandbox_rtc_get_name(const struct udevice *dev, char *out_name) +{ + return acpi_copy_name(out_name, "RTCC"); +} + +struct acpi_ops sandbox_rtc_acpi_ops = { + .get_name = sandbox_rtc_get_name, +}; + static const struct rtc_ops sandbox_rtc_ops = { .get = sandbox_rtc_get, .set = sandbox_rtc_set, @@ -102,4 +112,5 @@ U_BOOT_DRIVER(rtc_sandbox) = { .id = UCLASS_RTC, .of_match = sandbox_rtc_ids, .ops = &sandbox_rtc_ops, + ACPI_OPS_PTR(&sandbox_rtc_acpi_ops) }; diff --git a/include/acpi/acpi_device.h b/include/acpi/acpi_device.h index 1a8bbc81a8..2c57db8762 100644 --- a/include/acpi/acpi_device.h +++ b/include/acpi/acpi_device.h @@ -9,6 +9,8 @@ #ifndef __ACPI_DEVICE_H #define __ACPI_DEVICE_H +#include + struct acpi_ctx; struct gpio_desc; struct irq; @@ -181,6 +183,29 @@ struct acpi_gpio { enum acpi_gpio_polarity polarity; }; +/* ACPI Descriptors for Serial Bus interfaces */ +#define ACPI_SERIAL_BUS_TYPE_I2C 1 +#define ACPI_SERIAL_BUS_TYPE_SPI 2 +#define ACPI_I2C_SERIAL_BUS_REVISION_ID 1 /* TODO: upgrade to 2 */ +#define ACPI_I2C_TYPE_SPECIFIC_REVISION_ID 1 +#define ACPI_SPI_SERIAL_BUS_REVISION_ID 1 +#define ACPI_SPI_TYPE_SPECIFIC_REVISION_ID 1 + +/** + * struct acpi_i2c - representation of an ACPI I2C device + * + * @address: 7-bit or 10-bit I2C address + * @mode_10bit: Which address size is used + * @speed: Bus speed in Hz + * @resource: Resource name for the I2C controller + */ +struct acpi_i2c { + u16 address; + enum i2c_address_mode mode_10bit; + enum i2c_speed_rate speed; + const char *resource; +}; + /** * acpi_device_path() - Get the full path to an ACPI device * @@ -268,4 +293,16 @@ int acpi_device_write_gpio_desc(struct acpi_ctx *ctx, int acpi_device_write_interrupt_or_gpio(struct acpi_ctx *ctx, struct udevice *dev, const char *prop); +/** + * acpi_device_write_i2c_dev() - Write an I2C device to ACPI + * + * This creates a I2cSerialBus descriptor for an I2C device, including + * information ACPI needs to use it. + * + * @ctx: ACPI context pointer + * @dev: I2C device to write + * @return 0 if OK, -ve on error + */ +int acpi_device_write_i2c_dev(struct acpi_ctx *ctx, const struct udevice *dev); + #endif diff --git a/lib/acpi/acpi_device.c b/lib/acpi/acpi_device.c index 66e344e13a..4964196fac 100644 --- a/lib/acpi/acpi_device.c +++ b/lib/acpi/acpi_device.c @@ -380,3 +380,106 @@ int acpi_device_write_interrupt_or_gpio(struct acpi_ctx *ctx, return 0; } + +/* ACPI 6.3 section 6.4.3.8.2.1 - I2cSerialBus() */ +static void acpi_device_write_i2c(struct acpi_ctx *ctx, + const struct acpi_i2c *i2c) +{ + void *desc_length, *type_length; + + /* Byte 0: Descriptor Type */ + acpigen_emit_byte(ctx, ACPI_DESCRIPTOR_SERIAL_BUS); + + /* Byte 1+2: Length (filled in later) */ + desc_length = acpi_device_write_zero_len(ctx); + + /* Byte 3: Revision ID */ + acpigen_emit_byte(ctx, ACPI_I2C_SERIAL_BUS_REVISION_ID); + + /* Byte 4: Resource Source Index is Reserved */ + acpigen_emit_byte(ctx, 0); + + /* Byte 5: Serial Bus Type is I2C */ + acpigen_emit_byte(ctx, ACPI_SERIAL_BUS_TYPE_I2C); + + /* + * Byte 6: Flags + * [7:2]: 0 => Reserved + * [1]: 1 => ResourceConsumer + * [0]: 0 => ControllerInitiated + */ + acpigen_emit_byte(ctx, 1 << 1); + + /* + * Byte 7-8: Type Specific Flags + * [15:1]: 0 => Reserved + * [0]: 0 => 7bit, 1 => 10bit + */ + acpigen_emit_word(ctx, i2c->mode_10bit); + + /* Byte 9: Type Specific Revision ID */ + acpigen_emit_byte(ctx, ACPI_I2C_TYPE_SPECIFIC_REVISION_ID); + + /* Byte 10-11: I2C Type Data Length */ + type_length = acpi_device_write_zero_len(ctx); + + /* Byte 12-15: I2C Bus Speed */ + acpigen_emit_dword(ctx, i2c->speed); + + /* Byte 16-17: I2C Slave Address */ + acpigen_emit_word(ctx, i2c->address); + + /* Fill in Type Data Length */ + acpi_device_fill_len(ctx, type_length); + + /* Byte 18+: ResourceSource */ + acpigen_emit_string(ctx, i2c->resource); + + /* Fill in I2C Descriptor Length */ + acpi_device_fill_len(ctx, desc_length); +} + +/** + * acpi_device_set_i2c() - Set up an ACPI I2C struct from a device + * + * @dev: I2C device to convert + * @i2c: Place to put the new structure + * @scope: Scope of the I2C device (this is the controller path) + * @return 0 (always) + */ +static int acpi_device_set_i2c(const struct udevice *dev, struct acpi_i2c *i2c, + const char *scope) +{ + struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); + struct udevice *bus = dev_get_parent(dev); + + memset(i2c, '\0', sizeof(i2c)); + i2c->address = chip->chip_addr; + i2c->mode_10bit = 0; + + /* + * i2c_bus->speed_hz is set if this device is probed, but if not we + * must use the device tree + */ + i2c->speed = dev_read_u32_default(bus, "clock-frequency", 100000); + i2c->resource = scope; + + return 0; +} + +int acpi_device_write_i2c_dev(struct acpi_ctx *ctx, const struct udevice *dev) +{ + char scope[ACPI_PATH_MAX]; + struct acpi_i2c i2c; + int ret; + + ret = acpi_device_scope(dev, scope, sizeof(scope)); + if (ret) + return log_msg_ret("scope", ret); + ret = acpi_device_set_i2c(dev, &i2c, scope); + if (ret) + return log_msg_ret("set", ret); + acpi_device_write_i2c(ctx, &i2c); + + return 0; +} diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c index 6aefa6845d..de9996ab35 100644 --- a/test/dm/acpigen.c +++ b/test/dm/acpigen.c @@ -266,3 +266,35 @@ static int dm_test_acpi_interrupt_or_gpio(struct unit_test_state *uts) } DM_TEST(dm_test_acpi_interrupt_or_gpio, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test emitting an I2C descriptor */ +static int dm_test_acpi_i2c(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + + ptr = acpigen_get_current(ctx); + + ut_assertok(uclass_get_device(UCLASS_RTC, 0, &dev)); + ut_assertok(acpi_device_write_i2c_dev(ctx, dev)); + ut_asserteq(28, acpigen_get_current(ctx) - ptr); + ut_asserteq(ACPI_DESCRIPTOR_SERIAL_BUS, ptr[0]); + ut_asserteq(25, get_unaligned((u16 *)(ptr + 1))); + ut_asserteq(ACPI_I2C_SERIAL_BUS_REVISION_ID, ptr[3]); + ut_asserteq(0, ptr[4]); + ut_asserteq(ACPI_SERIAL_BUS_TYPE_I2C, ptr[5]); + ut_asserteq(0, get_unaligned((u16 *)(ptr + 7))); + ut_asserteq(ACPI_I2C_TYPE_SPECIFIC_REVISION_ID, ptr[9]); + ut_asserteq(6, get_unaligned((u16 *)(ptr + 10))); + ut_asserteq(100000, get_unaligned((u32 *)(ptr + 12))); + ut_asserteq(0x43, get_unaligned((u16 *)(ptr + 16))); + ut_asserteq_str("\\_SB.SI2C", (char *)ptr + 18); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_i2c, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);