Merge tag 'i2c-updates-for-v2023.04' of https://source.denx.de/u-boot/custodians/u-boot-i2c
i2c updates for v2023.04 - add new i2c driver ast2600 from Ryan Chen - i2c-cdns: make read fifo-depth configurable through device tree from Pei Yue Ho - mxc i2c driver: print base address in hex, not in decimal from Fabio
This commit is contained in:
		
						commit
						d7bcd6ee40
					
				| 
						 | 
					@ -774,6 +774,12 @@ S:	Maintained
 | 
				
			||||||
F:	drivers/pci/pcie_phytium.c
 | 
					F:	drivers/pci/pcie_phytium.c
 | 
				
			||||||
F:	arch/arm/dts/phytium-durian.dts
 | 
					F:	arch/arm/dts/phytium-durian.dts
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ASPEED AST2600 I2C DRIVER
 | 
				
			||||||
 | 
					M:	Ryan Chen <ryan_chen@aspeedtech.com>
 | 
				
			||||||
 | 
					R:	Aspeed BMC SW team <BMC-SW@aspeedtech.com>
 | 
				
			||||||
 | 
					S:	Maintained
 | 
				
			||||||
 | 
					F:	drivers/i2c/ast2600_i2c.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ASPEED FMC SPI DRIVER
 | 
					ASPEED FMC SPI DRIVER
 | 
				
			||||||
M:	Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>
 | 
					M:	Chin-Ting Kuo <chin-ting_kuo@aspeedtech.com>
 | 
				
			||||||
M:	Cédric Le Goater <clg@kaod.org>
 | 
					M:	Cédric Le Goater <clg@kaod.org>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -681,6 +681,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			i2c: bus@1e78a000 {
 | 
								i2c: bus@1e78a000 {
 | 
				
			||||||
				compatible = "simple-bus";
 | 
									compatible = "simple-bus";
 | 
				
			||||||
 | 
									reg = <0x1e78a000 0x1000>;
 | 
				
			||||||
				#address-cells = <1>;
 | 
									#address-cells = <1>;
 | 
				
			||||||
				#size-cells = <1>;
 | 
									#size-cells = <1>;
 | 
				
			||||||
				ranges = <0 0x1e78a000 0x1000>;
 | 
									ranges = <0 0x1e78a000 0x1000>;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,9 @@ Required properties:
 | 
				
			||||||
- interrupt-parent	: Must be core interrupt controller
 | 
					- interrupt-parent	: Must be core interrupt controller
 | 
				
			||||||
- clocks		: Clock phandles (see clock bindings for details).
 | 
					- clocks		: Clock phandles (see clock bindings for details).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Optional properties:
 | 
				
			||||||
 | 
					- fifo-depth		: To specify the FIFO depth of the controller.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example:
 | 
					Example:
 | 
				
			||||||
	i2c0: i2c@e0004000 {
 | 
						i2c0: i2c@e0004000 {
 | 
				
			||||||
		compatible = "cdns,i2c-r1p10";
 | 
							compatible = "cdns,i2c-r1p10";
 | 
				
			||||||
| 
						 | 
					@ -16,5 +19,6 @@ Example:
 | 
				
			||||||
		clocks = <&clkc 38>;
 | 
							clocks = <&clkc 38>;
 | 
				
			||||||
		interrupts = <0 25 4>;
 | 
							interrupts = <0 25 4>;
 | 
				
			||||||
		interrupt-parent = <&intc>;
 | 
							interrupt-parent = <&intc>;
 | 
				
			||||||
 | 
							fifo-depth = <32>;
 | 
				
			||||||
		status = "disabled";
 | 
							status = "disabled";
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -221,6 +221,16 @@ config SYS_I2C_DW
 | 
				
			||||||
	  controller is used in various SoCs, e.g. the ST SPEAr, Altera
 | 
						  controller is used in various SoCs, e.g. the ST SPEAr, Altera
 | 
				
			||||||
	  SoCFPGA, Synopsys ARC700 and some Intel x86 SoCs.
 | 
						  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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config SYS_I2C_ASPEED
 | 
					config SYS_I2C_ASPEED
 | 
				
			||||||
	bool "Aspeed I2C Controller"
 | 
						bool "Aspeed I2C Controller"
 | 
				
			||||||
	depends on DM_I2C && ARCH_ASPEED
 | 
						depends on DM_I2C && ARCH_ASPEED
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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_$(SPL_)SYS_I2C_LEGACY) += i2c_core.o
 | 
				
			||||||
obj-$(CONFIG_SYS_I2C_ASPEED) += ast_i2c.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_AT91) += at91_i2c.o
 | 
				
			||||||
obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 | 
					obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 | 
				
			||||||
obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
 | 
					obj-$(CONFIG_SYS_I2C_CA) += i2c-cortina.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,366 @@
 | 
				
			||||||
 | 
					// SPDX-License-Identifier: GPL-2.0+
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright ASPEED Technology Inc.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include <common.h>
 | 
				
			||||||
 | 
					#include <clk.h>
 | 
				
			||||||
 | 
					#include <dm.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <fdtdec.h>
 | 
				
			||||||
 | 
					#include <i2c.h>
 | 
				
			||||||
 | 
					#include <log.h>
 | 
				
			||||||
 | 
					#include <regmap.h>
 | 
				
			||||||
 | 
					#include <reset.h>
 | 
				
			||||||
 | 
					#include <asm/io.h>
 | 
				
			||||||
 | 
					#include <linux/iopoll.h>
 | 
				
			||||||
 | 
					#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);
 | 
				
			||||||
 | 
						ofnode i2c_global_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* find global base address */
 | 
				
			||||||
 | 
						i2c_global_node = ofnode_get_parent(dev_ofnode(dev));
 | 
				
			||||||
 | 
						priv->global = (void *)ofnode_get_addr(i2c_global_node);
 | 
				
			||||||
 | 
						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),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -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_ */
 | 
				
			||||||
| 
						 | 
					@ -78,7 +78,7 @@ struct cdns_i2c_regs {
 | 
				
			||||||
					CDNS_I2C_INTERRUPT_RXUNF | \
 | 
										CDNS_I2C_INTERRUPT_RXUNF | \
 | 
				
			||||||
					CDNS_I2C_INTERRUPT_ARBLOST)
 | 
										CDNS_I2C_INTERRUPT_ARBLOST)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CDNS_I2C_FIFO_DEPTH		16
 | 
					#define CDNS_I2C_FIFO_DEPTH_DEFAULT	16
 | 
				
			||||||
#define CDNS_I2C_TRANSFER_SIZE_MAX	255 /* Controller transfer limit */
 | 
					#define CDNS_I2C_TRANSFER_SIZE_MAX	255 /* Controller transfer limit */
 | 
				
			||||||
#define CDNS_I2C_TRANSFER_SIZE		(CDNS_I2C_TRANSFER_SIZE_MAX - 3)
 | 
					#define CDNS_I2C_TRANSFER_SIZE		(CDNS_I2C_TRANSFER_SIZE_MAX - 3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,6 +135,7 @@ struct i2c_cdns_bus {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int hold_flag;
 | 
						int hold_flag;
 | 
				
			||||||
	u32 quirks;
 | 
						u32 quirks;
 | 
				
			||||||
 | 
						u32 fifo_depth;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct cdns_i2c_platform_data {
 | 
					struct cdns_i2c_platform_data {
 | 
				
			||||||
| 
						 | 
					@ -277,7 +278,7 @@ static int cdns_i2c_write_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
 | 
				
			||||||
			writel(addr, ®s->address);
 | 
								writel(addr, ®s->address);
 | 
				
			||||||
			start = 0;
 | 
								start = 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (len && readl(®s->transfer_size) == CDNS_I2C_FIFO_DEPTH) {
 | 
							if (len && readl(®s->transfer_size) == i2c_bus->fifo_depth) {
 | 
				
			||||||
			ret = cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
 | 
								ret = cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
 | 
				
			||||||
					    CDNS_I2C_INTERRUPT_ARBLOST);
 | 
										    CDNS_I2C_INTERRUPT_ARBLOST);
 | 
				
			||||||
			if (ret & CDNS_I2C_INTERRUPT_ARBLOST)
 | 
								if (ret & CDNS_I2C_INTERRUPT_ARBLOST)
 | 
				
			||||||
| 
						 | 
					@ -310,9 +311,10 @@ static int cdns_i2c_write_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool cdns_is_hold_quirk(int hold_quirk, int curr_recv_count)
 | 
					static inline bool cdns_is_hold_quirk(struct i2c_cdns_bus *i2c_bus, int hold_quirk,
 | 
				
			||||||
 | 
									      int curr_recv_count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return hold_quirk && (curr_recv_count == CDNS_I2C_FIFO_DEPTH + 1);
 | 
						return hold_quirk && (curr_recv_count == i2c_bus->fifo_depth + 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
 | 
					static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
 | 
				
			||||||
| 
						 | 
					@ -327,7 +329,7 @@ static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
 | 
				
			||||||
	curr_recv_count = recv_count;
 | 
						curr_recv_count = recv_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Check for the message size against the FIFO depth */
 | 
						/* Check for the message size against the FIFO depth */
 | 
				
			||||||
	if (recv_count > CDNS_I2C_FIFO_DEPTH)
 | 
						if (recv_count > i2c_bus->fifo_depth)
 | 
				
			||||||
		setbits_le32(®s->control, CDNS_I2C_CONTROL_HOLD);
 | 
							setbits_le32(®s->control, CDNS_I2C_CONTROL_HOLD);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	setbits_le32(®s->control, CDNS_I2C_CONTROL_CLR_FIFO |
 | 
						setbits_le32(®s->control, CDNS_I2C_CONTROL_CLR_FIFO |
 | 
				
			||||||
| 
						 | 
					@ -349,7 +351,7 @@ static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (recv_count && !is_arbitration_lost(regs)) {
 | 
						while (recv_count && !is_arbitration_lost(regs)) {
 | 
				
			||||||
		while (readl(®s->status) & CDNS_I2C_STATUS_RXDV) {
 | 
							while (readl(®s->status) & CDNS_I2C_STATUS_RXDV) {
 | 
				
			||||||
			if (recv_count < CDNS_I2C_FIFO_DEPTH &&
 | 
								if (recv_count < i2c_bus->fifo_depth &&
 | 
				
			||||||
			    !i2c_bus->hold_flag) {
 | 
								    !i2c_bus->hold_flag) {
 | 
				
			||||||
				clrbits_le32(®s->control,
 | 
									clrbits_le32(®s->control,
 | 
				
			||||||
					     CDNS_I2C_CONTROL_HOLD);
 | 
										     CDNS_I2C_CONTROL_HOLD);
 | 
				
			||||||
| 
						 | 
					@ -358,27 +360,27 @@ static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
 | 
				
			||||||
			recv_count--;
 | 
								recv_count--;
 | 
				
			||||||
			curr_recv_count--;
 | 
								curr_recv_count--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (cdns_is_hold_quirk(hold_quirk, curr_recv_count))
 | 
								if (cdns_is_hold_quirk(i2c_bus, hold_quirk, curr_recv_count))
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (cdns_is_hold_quirk(hold_quirk, curr_recv_count)) {
 | 
							if (cdns_is_hold_quirk(i2c_bus, hold_quirk, curr_recv_count)) {
 | 
				
			||||||
			/* wait while fifo is full */
 | 
								/* wait while fifo is full */
 | 
				
			||||||
			while (readl(®s->transfer_size) !=
 | 
								while (readl(®s->transfer_size) !=
 | 
				
			||||||
				     (curr_recv_count - CDNS_I2C_FIFO_DEPTH))
 | 
									     (curr_recv_count - i2c_bus->fifo_depth))
 | 
				
			||||||
				;
 | 
									;
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * Check number of bytes to be received against maximum
 | 
								 * Check number of bytes to be received against maximum
 | 
				
			||||||
			 * transfer size and update register accordingly.
 | 
								 * transfer size and update register accordingly.
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			if ((recv_count - CDNS_I2C_FIFO_DEPTH) >
 | 
								if ((recv_count - i2c_bus->fifo_depth) >
 | 
				
			||||||
			    CDNS_I2C_TRANSFER_SIZE) {
 | 
								    CDNS_I2C_TRANSFER_SIZE) {
 | 
				
			||||||
				writel(CDNS_I2C_TRANSFER_SIZE,
 | 
									writel(CDNS_I2C_TRANSFER_SIZE,
 | 
				
			||||||
				       ®s->transfer_size);
 | 
									       ®s->transfer_size);
 | 
				
			||||||
				curr_recv_count = CDNS_I2C_TRANSFER_SIZE +
 | 
									curr_recv_count = CDNS_I2C_TRANSFER_SIZE +
 | 
				
			||||||
					CDNS_I2C_FIFO_DEPTH;
 | 
										i2c_bus->fifo_depth;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				writel(recv_count - CDNS_I2C_FIFO_DEPTH,
 | 
									writel(recv_count - i2c_bus->fifo_depth,
 | 
				
			||||||
				       ®s->transfer_size);
 | 
									       ®s->transfer_size);
 | 
				
			||||||
				curr_recv_count = recv_count;
 | 
									curr_recv_count = recv_count;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -496,6 +498,10 @@ static int cdns_i2c_of_to_plat(struct udevice *dev)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Update FIFO depth based on device tree entry */
 | 
				
			||||||
 | 
						i2c_bus->fifo_depth = dev_read_u32_default(dev, "fifo-depth",
 | 
				
			||||||
 | 
											   CDNS_I2C_FIFO_DEPTH_DEFAULT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -938,7 +938,7 @@ static int mxc_i2c_probe(struct udevice *bus)
 | 
				
			||||||
	 * we can set pinmux here in probe function.
 | 
						 * we can set pinmux here in probe function.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	debug("i2c : controller bus %d at %lu , speed %d: ",
 | 
						debug("i2c : controller bus %d at 0x%lx , speed %d: ",
 | 
				
			||||||
	      dev_seq(bus), i2c_bus->base,
 | 
						      dev_seq(bus), i2c_bus->base,
 | 
				
			||||||
	      i2c_bus->speed);
 | 
						      i2c_bus->speed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue