From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2297BC46467 for ; Wed, 11 Jan 2023 07:34:16 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 21033856B4; Wed, 11 Jan 2023 08:34:14 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=denx.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=denx.de; s=phobos-20191101; t=1673422454; bh=z0YeVSsFlB8Nnx1Pa7FhqplgcYYwFL6DY9XlKskWKjs=; h=Subject:To:References:From:Date:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: Reply-To:From; b=gqNvgwSEoTFxMnSw8G3KeopP+Efw/S4DBNF3TaucZX0mgr3NbMqcQOwDUbNggIzOt Zk9hKx4YmuxzKsPdNj4eT86wnQU4qtcFHl33BFXGNI7muWJ4JdVFpJaRYEB//1VMh/ xYvdT9BoQ77ljnVpTf2zAK8M6WZD+0vjnE7clq/UgHsjxGvJvFNG2vjvRthPa/bwLA x0b4+ol6JHlVUXCUQJYaExW6IHf+TSG9Ew7j3fSRdghMGmd7neMt+TN/JbTX9TUPae vENVT4bO7Nm0ZBxS1rxhTCFWpyaiLddDJe/zfMmzac15le/0jGkw7i6mAvVUYuuf6Q 3rCe6i4XR6xPw== Received: from [192.168.1.107] (fibhost-66-247-38.fibernet.hu [85.66.247.38]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: hs@denx.de) by phobos.denx.de (Postfix) with ESMTPSA id 753E985463; Wed, 11 Jan 2023 08:34:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=denx.de; s=phobos-20191101; t=1673422453; bh=z0YeVSsFlB8Nnx1Pa7FhqplgcYYwFL6DY9XlKskWKjs=; h=Reply-To:Subject:To:References:From:Date:In-Reply-To:From; b=xEXgJeCXQdlz3vBdayU4NX/o3aiFbmPVpXbGhOzkw8a4jirgxy2ftafOMDSdDOmK0 4yvXOLAywat5plqt8wVOxHEEZyurp8iz3tJHxW0j6k7cKbCVnA9Dq3+bEE5KeAwCyk bguAxvFoa5wr+yxAp9BG/OXDN8ebFZ93wQbwmmKk7aMyVpde8yibijW67bmMb8IQxT kOXi78Y0ydOF27JUgIZfvhvzxk5T/yC/M004TlhGhxiccVtUDBS/0AivG7S/yz0Xeh Tr9f9s/tob37lpJ/mM+uBv+Dm0yF75HHXDZkbfLUPj5ayj+xHHXwAEbN3CukY7YuCw 4wxTy4NIH43TQ== Subject: Re: [PATCH v2 1/1] i2c:aspeed:support ast2600 i2c new register mode driver To: ryan_chen , Aspeed BMC SW team , u-boot@lists.denx.de References: <20230111065236.4104204-1-ryan_chen@aspeedtech.com> <20230111065236.4104204-2-ryan_chen@aspeedtech.com> From: Heiko Schocher Message-ID: <07864e6b-e388-2aaa-77ee-7f7e95bf16c7@denx.de> Date: Wed, 11 Jan 2023 08:34:05 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.8.1 MIME-Version: 1.0 In-Reply-To: <20230111065236.4104204-2-ryan_chen@aspeedtech.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: hs@denx.de Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.6 at phobos.denx.de X-Virus-Status: Clean Hello Ryan, On 11.01.23 07:52, ryan_chen wrote: > Add i2c new register mode driver to support AST2600 i2c > new register mode. AST2600 i2c controller have legacy and > new register mode. The new register mode have global register > support 4 base clock for scl clock selection, and new clock > divider mode. > > Signed-off-by: ryan_chen > --- > MAINTAINERS | 6 + > drivers/i2c/Kconfig | 10 + > drivers/i2c/Makefile | 1 + > drivers/i2c/ast2600_i2c.c | 375 ++++++++++++++++++++++++++++++++++++++ > drivers/i2c/ast2600_i2c.h | 120 ++++++++++++ > 5 files changed, 512 insertions(+) > create mode 100644 drivers/i2c/ast2600_i2c.c > create mode 100644 drivers/i2c/ast2600_i2c.h Nitpick, please add a change log, what have changes from v1 -> v2 as described here: https://u-boot.readthedocs.io/en/latest/develop/sending_patches.html#sending-updated-patch-versions You may want to use patman tool, see: https://u-boot.readthedocs.io/en/latest/develop/patman.html > > diff --git a/MAINTAINERS b/MAINTAINERS > index 3fc4cd0f12..1cf54f0b4e 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -769,6 +769,12 @@ S: Maintained > F: drivers/pci/pcie_phytium.c > F: arch/arm/dts/phytium-durian.dts > > +ASPEED AST2600 I2C DRIVER > +M: Ryan Chen > +R: Aspeed BMC SW team > +S: Maintained > +F: drivers/i2c/ast2600_i2c.c > + > ASPEED FMC SPI DRIVER > M: Chin-Ting Kuo > M: Cédric Le Goater > diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig > index 08b6c7bdcc..77e2a1c4c0 100644 > --- a/drivers/i2c/Kconfig > +++ b/drivers/i2c/Kconfig > @@ -221,6 +221,16 @@ config SYS_I2C_DW > controller is used in various SoCs, e.g. the ST SPEAr, Altera > SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs. > > +config SYS_I2C_AST2600 > + bool "AST2600 I2C Controller" > + depends on DM_I2C && ARCH_ASPEED > + help > + Say yes here to select AST2600 I2C Host Controller. The driver > + support AST2600 I2C new mode register. This I2C controller supports: > + _Standard-mode (up to 100 kHz) > + _Fast-mode (up to 400 kHz) > + _Fast-mode Plus (up to 1 MHz) Please use minus instead underline. > + > config SYS_I2C_ASPEED > bool "Aspeed I2C Controller" > depends on DM_I2C && ARCH_ASPEED > diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile > index 920aafb91c..89db2d8e37 100644 > --- a/drivers/i2c/Makefile > +++ b/drivers/i2c/Makefile > @@ -12,6 +12,7 @@ obj-$(CONFIG_$(SPL_)I2C_CROS_EC_LDO) += cros_ec_ldo.o > > obj-$(CONFIG_$(SPL_)SYS_I2C_LEGACY) += i2c_core.o > obj-$(CONFIG_SYS_I2C_ASPEED) += ast_i2c.o > +obj-$(CONFIG_SYS_I2C_AST2600) += ast2600_i2c.o > obj-$(CONFIG_SYS_I2C_AT91) += at91_i2c.o > obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o > obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o > diff --git a/drivers/i2c/ast2600_i2c.c b/drivers/i2c/ast2600_i2c.c > new file mode 100644 > index 0000000000..0fad30b5a2 > --- /dev/null > +++ b/drivers/i2c/ast2600_i2c.c > @@ -0,0 +1,375 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright ASPEED Technology Inc. > + */ > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "ast2600_i2c.h" > + > +/* Device private data */ > +struct ast2600_i2c_priv { > + struct clk clk; > + struct ast2600_i2c_regs *regs; > + void __iomem *global; > +}; > + > +static int ast2600_i2c_read_data(struct ast2600_i2c_priv *priv, u8 chip_addr, > + u8 *buffer, size_t len, bool send_stop) > +{ > + int rx_cnt, ret = 0; > + u32 cmd, isr; > + > + for (rx_cnt = 0; rx_cnt < len; rx_cnt++, buffer++) { > + cmd = I2CM_PKT_EN | I2CM_PKT_ADDR(chip_addr) | > + I2CM_RX_CMD; > + if (!rx_cnt) > + cmd |= I2CM_START_CMD; > + > + if ((len - 1) == rx_cnt) > + cmd |= I2CM_RX_CMD_LAST; > + > + if (send_stop && ((len - 1) == rx_cnt)) > + cmd |= I2CM_STOP_CMD; > + > + writel(cmd, &priv->regs->cmd_sts); > + > + ret = readl_poll_timeout(&priv->regs->isr, isr, > + isr & I2CM_PKT_DONE, > + I2C_TIMEOUT_US); > + if (ret) > + return -ETIMEDOUT; > + > + *buffer = > + I2CC_GET_RX_BUFF(readl(&priv->regs->trx_buff)); > + > + writel(I2CM_PKT_DONE, &priv->regs->isr); > + > + if (isr & I2CM_TX_NAK) > + return -EREMOTEIO; > + } > + > + return 0; > +} > + > +static int ast2600_i2c_write_data(struct ast2600_i2c_priv *priv, u8 chip_addr, > + u8 *buffer, size_t len, bool send_stop) > +{ > + int tx_cnt, ret = 0; > + u32 cmd, isr; > + > + if (!len) { > + cmd = I2CM_PKT_EN | I2CM_PKT_ADDR(chip_addr) | > + I2CM_START_CMD; > + writel(cmd, &priv->regs->cmd_sts); > + ret = readl_poll_timeout(&priv->regs->isr, isr, > + isr & I2CM_PKT_DONE, > + I2C_TIMEOUT_US); > + if (ret) > + return -ETIMEDOUT; > + > + writel(I2CM_PKT_DONE, &priv->regs->isr); > + > + if (isr & I2CM_TX_NAK) > + return -EREMOTEIO; > + } > + > + for (tx_cnt = 0; tx_cnt < len; tx_cnt++, buffer++) { > + cmd = I2CM_PKT_EN | I2CM_PKT_ADDR(chip_addr); > + cmd |= I2CM_TX_CMD; > + > + if (!tx_cnt) > + cmd |= I2CM_START_CMD; > + > + if (send_stop && ((len - 1) == tx_cnt)) > + cmd |= I2CM_STOP_CMD; > + > + writel(*buffer, &priv->regs->trx_buff); > + writel(cmd, &priv->regs->cmd_sts); > + ret = readl_poll_timeout(&priv->regs->isr, isr, > + isr & I2CM_PKT_DONE, > + I2C_TIMEOUT_US); > + if (ret) > + return -ETIMEDOUT; > + > + writel(I2CM_PKT_DONE, &priv->regs->isr); > + > + if (isr & I2CM_TX_NAK) > + return -EREMOTEIO; > + } > + > + return 0; > +} > + > +static int ast2600_i2c_deblock(struct udevice *dev) > +{ > + struct ast2600_i2c_priv *priv = dev_get_priv(dev); > + u32 csr = readl(&priv->regs->cmd_sts); > + u32 isr; > + int ret; > + > + /* reinit */ > + writel(0, &priv->regs->fun_ctrl); > + /* Enable Master Mode. Assuming single-master */ > + writel(I2CC_BUS_AUTO_RELEASE | I2CC_MASTER_EN | > + I2CC_MULTI_MASTER_DIS, > + &priv->regs->fun_ctrl); > + > + csr = readl(&priv->regs->cmd_sts); > + > + if (!(csr & I2CC_SDA_LINE_STS) && > + (csr & I2CC_SCL_LINE_STS)) { > + debug("Bus stuck (%x), attempting recovery\n", csr); > + writel(I2CM_RECOVER_CMD_EN, &priv->regs->cmd_sts); > + ret = readl_poll_timeout(&priv->regs->isr, isr, > + isr & (I2CM_BUS_RECOVER_FAIL | > + I2CM_BUS_RECOVER), > + I2C_TIMEOUT_US); > + writel(~0, &priv->regs->isr); > + if (ret) > + return -EREMOTEIO; > + } > + > + return 0; > +} > + > +static int ast2600_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs) > +{ > + struct ast2600_i2c_priv *priv = dev_get_priv(dev); > + int ret; > + > + if (readl(&priv->regs->trx_buff) & I2CC_BUS_BUSY_STS) > + return -EREMOTEIO; > + > + for (; nmsgs > 0; nmsgs--, msg++) { > + if (msg->flags & I2C_M_RD) { > + debug("i2c_read: chip=0x%x, len=0x%x, flags=0x%x\n", > + msg->addr, msg->len, msg->flags); > + ret = ast2600_i2c_read_data(priv, msg->addr, msg->buf, > + msg->len, (nmsgs == 1)); > + } else { > + debug("i2c_write: chip=0x%x, len=0x%x, flags=0x%x\n", > + msg->addr, msg->len, msg->flags); > + ret = ast2600_i2c_write_data(priv, msg->addr, msg->buf, > + msg->len, (nmsgs == 1)); > + } > + if (ret) { > + debug("%s: error (%d)\n", __func__, ret); > + return -EREMOTEIO; > + } > + } > + > + return 0; > +} > + > +static int ast2600_i2c_set_speed(struct udevice *dev, unsigned int speed) > +{ > + struct ast2600_i2c_priv *priv = dev_get_priv(dev); > + unsigned long base_clk1, base_clk2, base_clk3, base_clk4; > + int multiply = 10; > + int baseclk_idx; > + u32 clk_div_reg; > + u32 apb_clk; > + u32 scl_low; > + u32 scl_high; > + int divisor; > + int inc = 0; > + u32 data; > + > + debug("Setting speed for I2C%d to <%u>\n", dev->seq_, speed); > + if (!speed) { > + debug("No valid speed specified\n"); > + return -EINVAL; > + } > + > + apb_clk = clk_get_rate(&priv->clk); > + > + clk_div_reg = readl(priv->global + I2CG_CLK_DIV_CTRL); > + > + base_clk1 = (apb_clk * multiply) / (((GET_CLK1_DIV(clk_div_reg) + 2) * multiply) / 2); > + base_clk2 = (apb_clk * multiply) / (((GET_CLK2_DIV(clk_div_reg) + 2) * multiply) / 2); > + base_clk3 = (apb_clk * multiply) / (((GET_CLK3_DIV(clk_div_reg) + 2) * multiply) / 2); > + base_clk4 = (apb_clk * multiply) / (((GET_CLK4_DIV(clk_div_reg) + 2) * multiply) / 2); > + > + if ((apb_clk / speed) <= 32) { > + baseclk_idx = 0; > + divisor = DIV_ROUND_UP(apb_clk, speed); > + } else if ((base_clk1 / speed) <= 32) { > + baseclk_idx = 1; > + divisor = DIV_ROUND_UP(base_clk1, speed); > + } else if ((base_clk2 / speed) <= 32) { > + baseclk_idx = 2; > + divisor = DIV_ROUND_UP(base_clk2, speed); > + } else if ((base_clk3 / speed) <= 32) { > + baseclk_idx = 3; > + divisor = DIV_ROUND_UP(base_clk3, speed); > + } else { > + baseclk_idx = 4; > + divisor = DIV_ROUND_UP(base_clk4, speed); > + inc = 0; > + while ((divisor + inc) > 32) { > + inc |= divisor & 0x1; > + divisor >>= 1; > + baseclk_idx++; > + } > + divisor += inc; > + } > + divisor = min_t(int, divisor, 32); > + baseclk_idx &= 0xf; > + scl_low = ((divisor * 9) / 16) - 1; > + scl_low = min_t(u32, scl_low, 0xf); > + scl_high = (divisor - scl_low - 2) & 0xf; > + /* Divisor : Base Clock : tCKHighMin : tCK High : tCK Low */ > + data = ((scl_high - 1) << 20) | (scl_high << 16) | (scl_low << 12) | > + baseclk_idx; > + /* Set AC Timing */ > + writel(data, &priv->regs->ac_timing); > + > + return 0; > +} > + > +static int ast2600_i2c_probe(struct udevice *dev) > +{ > + struct ast2600_i2c_priv *priv = dev_get_priv(dev); > + struct udevice *global_dev; > + int ret; > + > + /* find global base address */ > + ret = uclass_get_device_by_driver(UCLASS_MISC, > + DM_DRIVER_GET(aspeed_i2c_global), > + &global_dev); > + if (ret) { > + debug("i2c global not defined\n"); > + return ret; > + } > + > + priv->global = dev_read_addr_ptr(global_dev); > + if (IS_ERR(priv->global)) { > + debug("%s(): can't get global\n", __func__); > + return PTR_ERR(priv->global); > + } > + > + /* Reset device */ > + writel(0, &priv->regs->fun_ctrl); > + /* Enable Master Mode. Assuming single-master */ > + writel(I2CC_BUS_AUTO_RELEASE | I2CC_MASTER_EN | > + I2CC_MULTI_MASTER_DIS, > + &priv->regs->fun_ctrl); > + > + writel(0, &priv->regs->ier); > + /* Clear Interrupt */ > + writel(~0, &priv->regs->isr); > + > + return 0; > +} > + > +static int ast2600_i2c_of_to_plat(struct udevice *dev) > +{ > + struct ast2600_i2c_priv *priv = dev_get_priv(dev); > + int ret; > + > + priv->regs = dev_read_addr_ptr(dev); > + if (!priv->regs) > + return -EINVAL; > + > + ret = clk_get_by_index(dev, 0, &priv->clk); > + if (ret < 0) { > + debug("%s: Can't get clock for %s: %d\n", __func__, dev->name, > + ret); > + return ret; > + } > + > + return 0; > +} > + > +static const struct dm_i2c_ops ast2600_i2c_ops = { > + .xfer = ast2600_i2c_xfer, > + .deblock = ast2600_i2c_deblock, > + .set_bus_speed = ast2600_i2c_set_speed, > +}; > + > +static const struct udevice_id ast2600_i2c_ids[] = { > + { .compatible = "aspeed,ast2600-i2c" }, > + {}, > +}; > + > +U_BOOT_DRIVER(ast2600_i2c) = { > + .name = "ast2600_i2c", > + .id = UCLASS_I2C, > + .of_match = ast2600_i2c_ids, > + .probe = ast2600_i2c_probe, > + .of_to_plat = ast2600_i2c_of_to_plat, > + .priv_auto = sizeof(struct ast2600_i2c_priv), > + .ops = &ast2600_i2c_ops, > +}; > + > +struct ast2600_i2c_global_priv { > + void __iomem *regs; > + struct reset_ctl reset; > +}; > + > +/* > + * APB clk : 100Mhz > + * div : scl : baseclk [APB/((div/2) + 1)] : tBuf [1/bclk * 16] > + * I2CG10[31:24] base clk4 for i2c auto recovery timeout counter (0xC6) > + * I2CG10[23:16] base clk3 for Standard-mode (100Khz) min tBuf 4.7us > + * 0x3c : 100.8Khz : 3.225Mhz : 4.96us > + * 0x3d : 99.2Khz : 3.174Mhz : 5.04us > + * 0x3e : 97.65Khz : 3.125Mhz : 5.12us > + * 0x40 : 97.75Khz : 3.03Mhz : 5.28us > + * 0x41 : 99.5Khz : 2.98Mhz : 5.36us (default) > + * I2CG10[15:8] base clk2 for Fast-mode (400Khz) min tBuf 1.3us > + * 0x12 : 400Khz : 10Mhz : 1.6us > + * I2CG10[7:0] base clk1 for Fast-mode Plus (1Mhz) min tBuf 0.5us > + * 0x08 : 1Mhz : 20Mhz : 0.8us > + */ > + > +static int aspeed_i2c_global_probe(struct udevice *dev) > +{ > + struct ast2600_i2c_global_priv *i2c_global = dev_get_priv(dev); > + void __iomem *regs; > + int ret = 0; > + > + i2c_global->regs = dev_read_addr_ptr(dev); > + if (!i2c_global->regs) > + return -EINVAL; > + > + debug("%s(dev=%p)\n", __func__, dev); > + > + regs = i2c_global->regs; > + > + ret = reset_get_by_index(dev, 0, &i2c_global->reset); > + if (ret) { > + printf("%s(): Failed to get reset signal\n", __func__); > + return ret; > + } > + > + reset_deassert(&i2c_global->reset); > + > + writel(GLOBAL_INIT, regs + I2CG_CTRL); > + writel(I2CCG_DIV_CTRL, regs + I2CG_CLK_DIV_CTRL); > + > + return 0; > +} > + > +static const struct udevice_id aspeed_i2c_global_ids[] = { > + { .compatible = "aspeed,ast2600-i2c-global", }, > + { } > +}; > + > +U_BOOT_DRIVER(aspeed_i2c_global) = { > + .name = "aspeed_i2c_global", > + .id = UCLASS_MISC, > + .of_match = aspeed_i2c_global_ids, > + .probe = aspeed_i2c_global_probe, > + .priv_auto = sizeof(struct ast2600_i2c_global_priv), > +}; > + > diff --git a/drivers/i2c/ast2600_i2c.h b/drivers/i2c/ast2600_i2c.h > new file mode 100644 > index 0000000000..69699ba84c > --- /dev/null > +++ b/drivers/i2c/ast2600_i2c.h > @@ -0,0 +1,120 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * Copyright ASPEED Technology Inc. > + */ > +#ifndef __AST2600_I2C_H_ > +#define __AST2600_I2C_H_ > + > +struct ast2600_i2c_regs { > + u32 fun_ctrl; > + u32 ac_timing; > + u32 trx_buff; > + u32 icr; > + u32 ier; > + u32 isr; > + u32 cmd_sts; > +}; > + > +/* 0x00 : I2CC Master/Slave Function Control Register */ > +#define I2CC_SLAVE_ADDR_RX_EN BIT(20) > +#define I2CC_MASTER_RETRY_MASK GENMASK(19, 18) > +#define I2CC_MASTER_RETRY(x) (((x) & GENMASK(1, 0)) << 18) > +#define I2CC_BUS_AUTO_RELEASE BIT(17) > +#define I2CC_M_SDA_LOCK_EN BIT(16) > +#define I2CC_MULTI_MASTER_DIS BIT(15) > +#define I2CC_M_SCL_DRIVE_EN BIT(14) > +#define I2CC_MSB_STS BIT(9) > +#define I2CC_SDA_DRIVE_1T_EN BIT(8) > +#define I2CC_M_SDA_DRIVE_1T_EN BIT(7) > +#define I2CC_M_HIGH_SPEED_EN BIT(6) > +/* reserved 5 : 2 */ > +#define I2CC_SLAVE_EN BIT(1) > +#define I2CC_MASTER_EN BIT(0) > + > +/* 0x04 : I2CD Clock and AC Timing Control Register #1 */ > +/* Base register value. These bits are always set by the driver. */ > +#define I2CD_CACTC_BASE 0xfff00300 > +#define I2CD_TCKHIGH_SHIFT 16 > +#define I2CD_TCKLOW_SHIFT 12 > +#define I2CD_THDDAT_SHIFT 10 > +#define I2CD_TO_DIV_SHIFT 8 > +#define I2CD_BASE_DIV_SHIFT 0 > + > +/* 0x08 : I2CC Master/Slave Transmit/Receive Byte Buffer Register */ > +#define I2CC_TX_DIR_MASK GENMASK(31, 29) > +#define I2CC_SDA_OE BIT(28) > +#define I2CC_SDA_O BIT(27) > +#define I2CC_SCL_OE BIT(26) > +#define I2CC_SCL_O BIT(25) > + > +#define I2CC_SCL_LINE_STS BIT(18) > +#define I2CC_SDA_LINE_STS BIT(17) > +#define I2CC_BUS_BUSY_STS BIT(16) > +#define I2CC_GET_RX_BUFF(x) (((x) >> 8) & GENMASK(7, 0)) > + > +/* 0x10 : I2CM Master Interrupt Control Register */ > +/* 0x14 : I2CM Master Interrupt Status Register */ > +#define I2CM_PKT_TIMEOUT BIT(18) > +#define I2CM_PKT_ERROR BIT(17) > +#define I2CM_PKT_DONE BIT(16) > + > +#define I2CM_BUS_RECOVER_FAIL BIT(15) > +#define I2CM_SDA_DL_TO BIT(14) > +#define I2CM_BUS_RECOVER BIT(13) > +#define I2CM_SMBUS_ALT BIT(12) > + > +#define I2CM_SCL_LOW_TO BIT(6) > +#define I2CM_ABNORMAL BIT(5) > +#define I2CM_NORMAL_STOP BIT(4) > +#define I2CM_ARBIT_LOSS BIT(3) > +#define I2CM_RX_DONE BIT(2) > +#define I2CM_TX_NAK BIT(1) > +#define I2CM_TX_ACK BIT(0) > + > +/* 0x18 : I2CM Master Command/Status Register */ > +#define I2CM_PKT_ADDR(x) (((x) & GENMASK(6, 0)) << 24) > +#define I2CM_PKT_EN BIT(16) > +#define I2CM_SDA_OE_OUT_DIR BIT(15) > +#define I2CM_SDA_O_OUT_DIR BIT(14) > +#define I2CM_SCL_OE_OUT_DIR BIT(13) > +#define I2CM_SCL_O_OUT_DIR BIT(12) > +#define I2CM_RECOVER_CMD_EN BIT(11) > + > +#define I2CM_RX_DMA_EN BIT(9) > +#define I2CM_TX_DMA_EN BIT(8) > +/* Command Bit */ > +#define I2CM_RX_BUFF_EN BIT(7) > +#define I2CM_TX_BUFF_EN BIT(6) > +#define I2CM_STOP_CMD BIT(5) > +#define I2CM_RX_CMD_LAST BIT(4) > +#define I2CM_RX_CMD BIT(3) > + > +#define I2CM_TX_CMD BIT(1) > +#define I2CM_START_CMD BIT(0) > + > +#define I2C_TIMEOUT_US 100000 > + > +/* I2C Global Register */ > +#define I2CG_ISR 0x00 > +#define I2CG_SLAVE_ISR 0x04 > +#define I2CG_OWNER 0x08 > +#define I2CG_CTRL 0x0C > +#define I2CG_CLK_DIV_CTRL 0x10 > + > +#define I2CG_SLAVE_PKT_NAK BIT(4) > +#define I2CG_M_S_SEPARATE_INTR BIT(3) > +#define I2CG_CTRL_NEW_REG BIT(2) > +#define I2CG_CTRL_NEW_CLK_DIV BIT(1) > + > +#define GLOBAL_INIT \ > + (I2CG_SLAVE_PKT_NAK | \ > + I2CG_CTRL_NEW_REG | \ > + I2CG_CTRL_NEW_CLK_DIV) > +#define I2CCG_DIV_CTRL 0xc6411208 > + > +#define GET_CLK1_DIV(x) ((x) & 0xff) > +#define GET_CLK2_DIV(x) (((x) >> 8) & 0xff) > +#define GET_CLK3_DIV(x) (((x) >> 16) & 0xff) > +#define GET_CLK4_DIV(x) (((x) >> 24) & 0xff) > + > +#endif /* __AST2600_I2C_H_ */ > Thanks! bye, Heiko -- DENX Software Engineering GmbH, Managing Director: Erika Unter HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-52 Fax: +49-8142-66989-80 Email: hs@denx.de