From patchwork Tue Nov 11 17:46:27 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 409583 X-Patchwork-Delegate: sjg@chromium.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 57484140100 for ; Wed, 12 Nov 2014 04:49:05 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B5FD64B985; Tue, 11 Nov 2014 18:49:03 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id qbOuLYj3Iil6; Tue, 11 Nov 2014 18:49:03 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 14FDB4B937; Tue, 11 Nov 2014 18:49:03 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D90034B989 for ; Tue, 11 Nov 2014 18:48:57 +0100 (CET) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Yg0QuvMrly1f for ; Tue, 11 Nov 2014 18:48:57 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-yh0-f74.google.com (mail-yh0-f74.google.com [209.85.213.74]) by theia.denx.de (Postfix) with ESMTPS id 871A74B985 for ; Tue, 11 Nov 2014 18:48:54 +0100 (CET) Received: by mail-yh0-f74.google.com with SMTP id a41so33803yho.1 for ; Tue, 11 Nov 2014 09:48:53 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Qm4D65EzYLJDE/3Wv6IYE7/VOcEuoI1ulryux+4UOCs=; b=YRJBgirB/ZivbOPCBvdvzsnp0A+eVNKmX6c+wjSncQcaOcHG+BN/AMS4voW3jlmAS1 /c1duWQl2nqCU6LBu5NmEqX3e5d7xDiNcTswt3yGCLAADMcONkkiXkYp7h/xIlOLcuo5 wQGLmN5EDUW1QqIfI76HXDIuQPDVYEFaNxDdUXynJtmcLmwbihflbVK/LvBOaFk9kG4N XZDd69HYL4dwWO6kdCaCEIpSjkQwKU1aaWCEeaF/krxHxyCX0UAZC2znK9m86NJjfoQ6 NHrhZr5XVT4WE8ZdolSLhDn+qhx3YG+AKT3RbWsA/5ZckJ5uIvoZI4MXVQ5MA0xp9nut 10dw== X-Gm-Message-State: ALoCoQlNDwYy5S5noWOBqkTGOWWBnPDMkBss4fxiUtNUVXSgKqFGpYQb2rAL8+bQcHhD5e5pm3o1 X-Received: by 10.236.45.65 with SMTP id o41mr31874166yhb.48.1415728132939; Tue, 11 Nov 2014 09:48:52 -0800 (PST) Received: from corpmail-nozzle1-2.hot.corp.google.com ([100.108.1.103]) by gmr-mx.google.com with ESMTPS id 5si827548yhd.6.2014.11.11.09.48.52 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 11 Nov 2014 09:48:52 -0800 (PST) Received: from kaki.bld.corp.google.com ([172.29.216.32]) by corpmail-nozzle1-2.hot.corp.google.com with ESMTP id NkXc0fg3.1; Tue, 11 Nov 2014 09:48:52 -0800 Received: by kaki.bld.corp.google.com (Postfix, from userid 121222) id A8E25220FD5; Tue, 11 Nov 2014 10:48:51 -0700 (MST) From: Simon Glass To: U-Boot Mailing List Date: Tue, 11 Nov 2014 10:46:27 -0700 Message-Id: <1415727993-22032-12-git-send-email-sjg@chromium.org> X-Mailer: git-send-email 2.1.0.rc2.206.gedb03e5 In-Reply-To: <1415727993-22032-1-git-send-email-sjg@chromium.org> References: <1415727993-22032-1-git-send-email-sjg@chromium.org> Cc: u-boot-review@google.com Subject: [U-Boot] [PATCH v2 11/17] dm: i2c: Add a sandbox I2C driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.13 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de This driver includes some test features such as only supporting certain bus speeds. It passes its I2C traffic through to an emulator. Signed-off-by: Simon Glass Reviewed-by: Tom Rini Acked-by: Heiko Schocher --- Changes in v2: None drivers/i2c/Makefile | 2 +- drivers/i2c/sandbox_i2c.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 drivers/i2c/sandbox_i2c.c diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 4c9db51..eba3a71 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -27,7 +27,7 @@ obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o obj-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o obj-$(CONFIG_SYS_I2C_RCAR) += rcar_i2c.o obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o -obj-$(CONFIG_SYS_I2C_SANDBOX) += i2c-emul-uclass.o +obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o obj-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o obj-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c new file mode 100644 index 0000000..3beb0f9 --- /dev/null +++ b/drivers/i2c/sandbox_i2c.c @@ -0,0 +1,148 @@ +/* + * Simulate an I2C port + * + * Copyright (c) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +struct dm_sandbox_i2c_emul_priv { + struct udevice *emul; +}; + +static int get_emul(struct udevice *bus, uint chip_addr, struct udevice **devp, + struct dm_i2c_ops **opsp) +{ + const void *blob = gd->fdt_blob; + struct dm_i2c_chip *priv; + struct udevice *dev; + int ret; + + ret = i2c_get_chip(bus, chip_addr, &dev); + if (ret) + return ret; + priv = dev_get_parentdata(dev); + if (!priv->emul) { + int node; + + debug("Scanning i2c bus '%s' for devices\n", dev->name); + for (node = fdt_first_subnode(blob, dev->of_offset); + node >= 0; + node = fdt_next_subnode(blob, node)) { + int ret; + + ret = lists_bind_fdt(dev, blob, node, &priv->emul); + if (ret) + return ret; + debug("Found emul '%s' for i2c device '%s'\n", + priv->emul->name, dev->name); + break; + } + } + + if (!priv->emul) + return -ENODEV; + ret = device_probe(priv->emul); + if (ret) + return ret; + *devp = priv->emul; + *opsp = i2c_get_ops(priv->emul); + + return 0; +} + +static int sandbox_i2c_probe_chip(struct udevice *bus, uint chip_addr) +{ + struct dm_i2c_ops *ops; + struct udevice *emul; + int ret; + + ret = get_emul(bus, chip_addr, &emul, &ops); + if (ret) + return ret; + + return ops->probe(emul, chip_addr); +} + +static int sandbox_i2c_read(struct udevice *bus, uint chip_addr, uint addr, + uint alen, uint8_t *buffer, int len) +{ + struct dm_i2c_bus *i2c = bus->uclass_priv; + struct dm_i2c_ops *ops; + struct udevice *emul; + int ret; + + ret = get_emul(bus, chip_addr, &emul, &ops); + if (ret) + return ret; + + /* For testing, don't allow reading above 400KHz */ + if (i2c->speed_hz > 400000 || alen != 1) + return -EINVAL; + return ops->read(emul, chip_addr, addr, alen, buffer, len); +} + +static int sandbox_i2c_write(struct udevice *bus, uint chip_addr, uint addr, + uint alen, const uint8_t *buffer, int len) +{ + struct dm_i2c_bus *i2c = bus->uclass_priv; + struct dm_i2c_ops *ops; + struct udevice *emul; + int ret; + + ret = get_emul(bus, chip_addr, &emul, &ops); + if (ret) + return ret; + + /* For testing, don't allow writing above 100KHz */ + if (i2c->speed_hz > 100000 || alen != 1) + return -EINVAL; + return ops->write(emul, chip_addr, addr, alen, buffer, len); +} + +static int sandbox_i2c_set_addr_len(struct udevice *dev, uint addr_len) +{ + if (addr_len == 3) + return -EINVAL; + + return 0; +} + +static const struct dm_i2c_ops sandbox_i2c_ops = { + .probe = sandbox_i2c_probe_chip, + .read = sandbox_i2c_read, + .write = sandbox_i2c_write, + .set_addr_len = sandbox_i2c_set_addr_len, +}; + +static int sandbox_i2c_child_pre_probe(struct udevice *dev) +{ + struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev); + + return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset, + i2c_chip); +} + +static const struct udevice_id sandbox_i2c_ids[] = { + { .compatible = "sandbox,i2c" }, + { } +}; + +U_BOOT_DRIVER(i2c_sandbox) = { + .name = "i2c_sandbox", + .id = UCLASS_I2C, + .of_match = sandbox_i2c_ids, + .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip), + .child_pre_probe = sandbox_i2c_child_pre_probe, + .ops = &sandbox_i2c_ops, +};