xref: /rk3399_rockchip-uboot/drivers/i2c/ast_i2c.c (revision a821c4af79e4f5ce9b629b20473863397bbe9b10)
14dc038f3Smaxims@google.com /*
24dc038f3Smaxims@google.com  * Copyright (C) 2012-2020  ASPEED Technology Inc.
34dc038f3Smaxims@google.com  * Copyright 2016 IBM Corporation
44dc038f3Smaxims@google.com  * Copyright 2017 Google, Inc.
54dc038f3Smaxims@google.com  *
64dc038f3Smaxims@google.com  * SPDX-License-Identifier:	GPL-2.0+
74dc038f3Smaxims@google.com  */
84dc038f3Smaxims@google.com 
94dc038f3Smaxims@google.com #include <common.h>
104dc038f3Smaxims@google.com #include <clk.h>
114dc038f3Smaxims@google.com #include <dm.h>
124dc038f3Smaxims@google.com #include <errno.h>
134dc038f3Smaxims@google.com #include <fdtdec.h>
144dc038f3Smaxims@google.com #include <i2c.h>
154dc038f3Smaxims@google.com #include <asm/io.h>
164dc038f3Smaxims@google.com #include <asm/arch/scu_ast2500.h>
174dc038f3Smaxims@google.com 
184dc038f3Smaxims@google.com #include "ast_i2c.h"
194dc038f3Smaxims@google.com 
204dc038f3Smaxims@google.com #define I2C_TIMEOUT_US 100000
214dc038f3Smaxims@google.com #define I2C_SLEEP_STEP_US 20
224dc038f3Smaxims@google.com 
234dc038f3Smaxims@google.com #define HIGHSPEED_TTIMEOUT		3
244dc038f3Smaxims@google.com 
254dc038f3Smaxims@google.com DECLARE_GLOBAL_DATA_PTR;
264dc038f3Smaxims@google.com 
274dc038f3Smaxims@google.com /*
284dc038f3Smaxims@google.com  * Device private data
294dc038f3Smaxims@google.com  */
304dc038f3Smaxims@google.com struct ast_i2c_priv {
314dc038f3Smaxims@google.com 	/* This device's clock */
324dc038f3Smaxims@google.com 	struct clk clk;
334dc038f3Smaxims@google.com 	/* Device registers */
344dc038f3Smaxims@google.com 	struct ast_i2c_regs *regs;
354dc038f3Smaxims@google.com 	/* I2C speed in Hz */
364dc038f3Smaxims@google.com 	int speed;
374dc038f3Smaxims@google.com };
384dc038f3Smaxims@google.com 
394dc038f3Smaxims@google.com /*
404dc038f3Smaxims@google.com  * Given desired divider ratio, return the value that needs to be set
414dc038f3Smaxims@google.com  * in Clock and AC Timing Control register
424dc038f3Smaxims@google.com  */
get_clk_reg_val(ulong divider_ratio)434dc038f3Smaxims@google.com static u32 get_clk_reg_val(ulong divider_ratio)
444dc038f3Smaxims@google.com {
454dc038f3Smaxims@google.com 	ulong inc = 0, div;
464dc038f3Smaxims@google.com 	ulong scl_low, scl_high, data;
474dc038f3Smaxims@google.com 
484dc038f3Smaxims@google.com 	for (div = 0; divider_ratio >= 16; div++) {
494dc038f3Smaxims@google.com 		inc |= (divider_ratio & 1);
504dc038f3Smaxims@google.com 		divider_ratio >>= 1;
514dc038f3Smaxims@google.com 	}
524dc038f3Smaxims@google.com 	divider_ratio += inc;
534dc038f3Smaxims@google.com 	scl_low = (divider_ratio >> 1) - 1;
544dc038f3Smaxims@google.com 	scl_high = divider_ratio - scl_low - 2;
554dc038f3Smaxims@google.com 	data = I2CD_CACTC_BASE
564dc038f3Smaxims@google.com 			| (scl_high << I2CD_TCKHIGH_SHIFT)
574dc038f3Smaxims@google.com 			| (scl_low << I2CD_TCKLOW_SHIFT)
584dc038f3Smaxims@google.com 			| (div << I2CD_BASE_DIV_SHIFT);
594dc038f3Smaxims@google.com 
604dc038f3Smaxims@google.com 	return data;
614dc038f3Smaxims@google.com }
624dc038f3Smaxims@google.com 
ast_i2c_clear_interrupts(struct udevice * dev)634dc038f3Smaxims@google.com static void ast_i2c_clear_interrupts(struct udevice *dev)
644dc038f3Smaxims@google.com {
654dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
664dc038f3Smaxims@google.com 
674dc038f3Smaxims@google.com 	writel(~0, &priv->regs->isr);
684dc038f3Smaxims@google.com }
694dc038f3Smaxims@google.com 
ast_i2c_init_bus(struct udevice * dev)704dc038f3Smaxims@google.com static void ast_i2c_init_bus(struct udevice *dev)
714dc038f3Smaxims@google.com {
724dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
734dc038f3Smaxims@google.com 
744dc038f3Smaxims@google.com 	/* Reset device */
754dc038f3Smaxims@google.com 	writel(0, &priv->regs->fcr);
764dc038f3Smaxims@google.com 	/* Enable Master Mode. Assuming single-master */
774dc038f3Smaxims@google.com 	writel(I2CD_MASTER_EN
784dc038f3Smaxims@google.com 	       | I2CD_M_SDA_LOCK_EN
794dc038f3Smaxims@google.com 	       | I2CD_MULTI_MASTER_DIS | I2CD_M_SCL_DRIVE_EN,
804dc038f3Smaxims@google.com 	       &priv->regs->fcr);
814dc038f3Smaxims@google.com 	/* Enable Interrupts */
824dc038f3Smaxims@google.com 	writel(I2CD_INTR_TX_ACK
834dc038f3Smaxims@google.com 	       | I2CD_INTR_TX_NAK
844dc038f3Smaxims@google.com 	       | I2CD_INTR_RX_DONE
854dc038f3Smaxims@google.com 	       | I2CD_INTR_BUS_RECOVER_DONE
864dc038f3Smaxims@google.com 	       | I2CD_INTR_NORMAL_STOP
874dc038f3Smaxims@google.com 	       | I2CD_INTR_ABNORMAL, &priv->regs->icr);
884dc038f3Smaxims@google.com }
894dc038f3Smaxims@google.com 
ast_i2c_ofdata_to_platdata(struct udevice * dev)904dc038f3Smaxims@google.com static int ast_i2c_ofdata_to_platdata(struct udevice *dev)
914dc038f3Smaxims@google.com {
924dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
934dc038f3Smaxims@google.com 	int ret;
944dc038f3Smaxims@google.com 
95*a821c4afSSimon Glass 	priv->regs = devfdt_get_addr_ptr(dev);
964dc038f3Smaxims@google.com 	if (IS_ERR(priv->regs))
974dc038f3Smaxims@google.com 		return PTR_ERR(priv->regs);
984dc038f3Smaxims@google.com 
994dc038f3Smaxims@google.com 	ret = clk_get_by_index(dev, 0, &priv->clk);
1004dc038f3Smaxims@google.com 	if (ret < 0) {
1014dc038f3Smaxims@google.com 		debug("%s: Can't get clock for %s: %d\n", __func__, dev->name,
1024dc038f3Smaxims@google.com 		      ret);
1034dc038f3Smaxims@google.com 		return ret;
1044dc038f3Smaxims@google.com 	}
1054dc038f3Smaxims@google.com 
1064dc038f3Smaxims@google.com 	return 0;
1074dc038f3Smaxims@google.com }
1084dc038f3Smaxims@google.com 
ast_i2c_probe(struct udevice * dev)1094dc038f3Smaxims@google.com static int ast_i2c_probe(struct udevice *dev)
1104dc038f3Smaxims@google.com {
1114dc038f3Smaxims@google.com 	struct ast2500_scu *scu;
1124dc038f3Smaxims@google.com 
1134dc038f3Smaxims@google.com 	debug("Enabling I2C%u\n", dev->seq);
1144dc038f3Smaxims@google.com 
1154dc038f3Smaxims@google.com 	/*
1164dc038f3Smaxims@google.com 	 * Get all I2C devices out of Reset.
1174dc038f3Smaxims@google.com 	 * Only needs to be done once, but doing it for every
1184dc038f3Smaxims@google.com 	 * device does not hurt.
1194dc038f3Smaxims@google.com 	 */
1204dc038f3Smaxims@google.com 	scu = ast_get_scu();
1214dc038f3Smaxims@google.com 	ast_scu_unlock(scu);
1224dc038f3Smaxims@google.com 	clrbits_le32(&scu->sysreset_ctrl1, SCU_SYSRESET_I2C);
1234dc038f3Smaxims@google.com 	ast_scu_lock(scu);
1244dc038f3Smaxims@google.com 
1254dc038f3Smaxims@google.com 	ast_i2c_init_bus(dev);
1264dc038f3Smaxims@google.com 
1274dc038f3Smaxims@google.com 	return 0;
1284dc038f3Smaxims@google.com }
1294dc038f3Smaxims@google.com 
ast_i2c_wait_isr(struct udevice * dev,u32 flag)1304dc038f3Smaxims@google.com static int ast_i2c_wait_isr(struct udevice *dev, u32 flag)
1314dc038f3Smaxims@google.com {
1324dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
1334dc038f3Smaxims@google.com 	int timeout = I2C_TIMEOUT_US;
1344dc038f3Smaxims@google.com 
1354dc038f3Smaxims@google.com 	while (!(readl(&priv->regs->isr) & flag) && timeout > 0) {
1364dc038f3Smaxims@google.com 		udelay(I2C_SLEEP_STEP_US);
1374dc038f3Smaxims@google.com 		timeout -= I2C_SLEEP_STEP_US;
1384dc038f3Smaxims@google.com 	}
1394dc038f3Smaxims@google.com 
1404dc038f3Smaxims@google.com 	ast_i2c_clear_interrupts(dev);
1414dc038f3Smaxims@google.com 	if (timeout <= 0)
1424dc038f3Smaxims@google.com 		return -ETIMEDOUT;
1434dc038f3Smaxims@google.com 
1444dc038f3Smaxims@google.com 	return 0;
1454dc038f3Smaxims@google.com }
1464dc038f3Smaxims@google.com 
ast_i2c_send_stop(struct udevice * dev)1474dc038f3Smaxims@google.com static int ast_i2c_send_stop(struct udevice *dev)
1484dc038f3Smaxims@google.com {
1494dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
1504dc038f3Smaxims@google.com 
1514dc038f3Smaxims@google.com 	writel(I2CD_M_STOP_CMD, &priv->regs->csr);
1524dc038f3Smaxims@google.com 
1534dc038f3Smaxims@google.com 	return ast_i2c_wait_isr(dev, I2CD_INTR_NORMAL_STOP);
1544dc038f3Smaxims@google.com }
1554dc038f3Smaxims@google.com 
ast_i2c_wait_tx(struct udevice * dev)1564dc038f3Smaxims@google.com static int ast_i2c_wait_tx(struct udevice *dev)
1574dc038f3Smaxims@google.com {
1584dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
1594dc038f3Smaxims@google.com 	int timeout = I2C_TIMEOUT_US;
1604dc038f3Smaxims@google.com 	u32 flag = I2CD_INTR_TX_ACK | I2CD_INTR_TX_NAK;
1614dc038f3Smaxims@google.com 	u32 status = readl(&priv->regs->isr) & flag;
1624dc038f3Smaxims@google.com 	int ret = 0;
1634dc038f3Smaxims@google.com 
1644dc038f3Smaxims@google.com 	while (!status && timeout > 0) {
1654dc038f3Smaxims@google.com 		status = readl(&priv->regs->isr) & flag;
1664dc038f3Smaxims@google.com 		udelay(I2C_SLEEP_STEP_US);
1674dc038f3Smaxims@google.com 		timeout -= I2C_SLEEP_STEP_US;
1684dc038f3Smaxims@google.com 	}
1694dc038f3Smaxims@google.com 
1704dc038f3Smaxims@google.com 	if (status == I2CD_INTR_TX_NAK)
1714dc038f3Smaxims@google.com 		ret = -EREMOTEIO;
1724dc038f3Smaxims@google.com 
1734dc038f3Smaxims@google.com 	if (timeout <= 0)
1744dc038f3Smaxims@google.com 		ret = -ETIMEDOUT;
1754dc038f3Smaxims@google.com 
1764dc038f3Smaxims@google.com 	ast_i2c_clear_interrupts(dev);
1774dc038f3Smaxims@google.com 
1784dc038f3Smaxims@google.com 	return ret;
1794dc038f3Smaxims@google.com }
1804dc038f3Smaxims@google.com 
ast_i2c_start_txn(struct udevice * dev,uint devaddr)1814dc038f3Smaxims@google.com static int ast_i2c_start_txn(struct udevice *dev, uint devaddr)
1824dc038f3Smaxims@google.com {
1834dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
1844dc038f3Smaxims@google.com 
1854dc038f3Smaxims@google.com 	/* Start and Send Device Address */
1864dc038f3Smaxims@google.com 	writel(devaddr, &priv->regs->trbbr);
1874dc038f3Smaxims@google.com 	writel(I2CD_M_START_CMD | I2CD_M_TX_CMD, &priv->regs->csr);
1884dc038f3Smaxims@google.com 
1894dc038f3Smaxims@google.com 	return ast_i2c_wait_tx(dev);
1904dc038f3Smaxims@google.com }
1914dc038f3Smaxims@google.com 
ast_i2c_read_data(struct udevice * dev,u8 chip_addr,u8 * buffer,size_t len,bool send_stop)1924dc038f3Smaxims@google.com static int ast_i2c_read_data(struct udevice *dev, u8 chip_addr, u8 *buffer,
1934dc038f3Smaxims@google.com 			     size_t len, bool send_stop)
1944dc038f3Smaxims@google.com {
1954dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
1964dc038f3Smaxims@google.com 	u32 i2c_cmd = I2CD_M_RX_CMD;
1974dc038f3Smaxims@google.com 	int ret;
1984dc038f3Smaxims@google.com 
1994dc038f3Smaxims@google.com 	ret = ast_i2c_start_txn(dev, (chip_addr << 1) | I2C_M_RD);
2004dc038f3Smaxims@google.com 	if (ret < 0)
2014dc038f3Smaxims@google.com 		return ret;
2024dc038f3Smaxims@google.com 
2034dc038f3Smaxims@google.com 	for (; len > 0; len--, buffer++) {
2044dc038f3Smaxims@google.com 		if (len == 1)
2054dc038f3Smaxims@google.com 			i2c_cmd |= I2CD_M_S_RX_CMD_LAST;
2064dc038f3Smaxims@google.com 		writel(i2c_cmd, &priv->regs->csr);
2074dc038f3Smaxims@google.com 		ret = ast_i2c_wait_isr(dev, I2CD_INTR_RX_DONE);
2084dc038f3Smaxims@google.com 		if (ret < 0)
2094dc038f3Smaxims@google.com 			return ret;
2104dc038f3Smaxims@google.com 		*buffer = (readl(&priv->regs->trbbr) & I2CD_RX_DATA_MASK)
2114dc038f3Smaxims@google.com 				>> I2CD_RX_DATA_SHIFT;
2124dc038f3Smaxims@google.com 	}
2134dc038f3Smaxims@google.com 	ast_i2c_clear_interrupts(dev);
2144dc038f3Smaxims@google.com 
2154dc038f3Smaxims@google.com 	if (send_stop)
2164dc038f3Smaxims@google.com 		return ast_i2c_send_stop(dev);
2174dc038f3Smaxims@google.com 
2184dc038f3Smaxims@google.com 	return 0;
2194dc038f3Smaxims@google.com }
2204dc038f3Smaxims@google.com 
ast_i2c_write_data(struct udevice * dev,u8 chip_addr,u8 * buffer,size_t len,bool send_stop)2214dc038f3Smaxims@google.com static int ast_i2c_write_data(struct udevice *dev, u8 chip_addr, u8
2224dc038f3Smaxims@google.com 			      *buffer, size_t len, bool send_stop)
2234dc038f3Smaxims@google.com {
2244dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
2254dc038f3Smaxims@google.com 	int ret;
2264dc038f3Smaxims@google.com 
2274dc038f3Smaxims@google.com 	ret = ast_i2c_start_txn(dev, (chip_addr << 1));
2284dc038f3Smaxims@google.com 	if (ret < 0)
2294dc038f3Smaxims@google.com 		return ret;
2304dc038f3Smaxims@google.com 
2314dc038f3Smaxims@google.com 	for (; len > 0; len--, buffer++) {
2324dc038f3Smaxims@google.com 		writel(*buffer, &priv->regs->trbbr);
2334dc038f3Smaxims@google.com 		writel(I2CD_M_TX_CMD, &priv->regs->csr);
2344dc038f3Smaxims@google.com 		ret = ast_i2c_wait_tx(dev);
2354dc038f3Smaxims@google.com 		if (ret < 0)
2364dc038f3Smaxims@google.com 			return ret;
2374dc038f3Smaxims@google.com 	}
2384dc038f3Smaxims@google.com 
2394dc038f3Smaxims@google.com 	if (send_stop)
2404dc038f3Smaxims@google.com 		return ast_i2c_send_stop(dev);
2414dc038f3Smaxims@google.com 
2424dc038f3Smaxims@google.com 	return 0;
2434dc038f3Smaxims@google.com }
2444dc038f3Smaxims@google.com 
ast_i2c_deblock(struct udevice * dev)2454dc038f3Smaxims@google.com static int ast_i2c_deblock(struct udevice *dev)
2464dc038f3Smaxims@google.com {
2474dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
2484dc038f3Smaxims@google.com 	struct ast_i2c_regs *regs = priv->regs;
2494dc038f3Smaxims@google.com 	u32 csr = readl(&regs->csr);
2504dc038f3Smaxims@google.com 	bool sda_high = csr & I2CD_SDA_LINE_STS;
2514dc038f3Smaxims@google.com 	bool scl_high = csr & I2CD_SCL_LINE_STS;
2524dc038f3Smaxims@google.com 	int ret = 0;
2534dc038f3Smaxims@google.com 
2544dc038f3Smaxims@google.com 	if (sda_high && scl_high) {
2554dc038f3Smaxims@google.com 		/* Bus is idle, no deblocking needed. */
2564dc038f3Smaxims@google.com 		return 0;
2574dc038f3Smaxims@google.com 	} else if (sda_high) {
2584dc038f3Smaxims@google.com 		/* Send stop command */
2594dc038f3Smaxims@google.com 		debug("Unterminated TXN in (%x), sending stop\n", csr);
2604dc038f3Smaxims@google.com 		ret = ast_i2c_send_stop(dev);
2614dc038f3Smaxims@google.com 	} else if (scl_high) {
2624dc038f3Smaxims@google.com 		/* Possibly stuck slave */
2634dc038f3Smaxims@google.com 		debug("Bus stuck (%x), attempting recovery\n", csr);
2644dc038f3Smaxims@google.com 		writel(I2CD_BUS_RECOVER_CMD, &regs->csr);
2654dc038f3Smaxims@google.com 		ret = ast_i2c_wait_isr(dev, I2CD_INTR_BUS_RECOVER_DONE);
2664dc038f3Smaxims@google.com 	} else {
2674dc038f3Smaxims@google.com 		/* Just try to reinit the device. */
2684dc038f3Smaxims@google.com 		ast_i2c_init_bus(dev);
2694dc038f3Smaxims@google.com 	}
2704dc038f3Smaxims@google.com 
2714dc038f3Smaxims@google.com 	return ret;
2724dc038f3Smaxims@google.com }
2734dc038f3Smaxims@google.com 
ast_i2c_xfer(struct udevice * dev,struct i2c_msg * msg,int nmsgs)2744dc038f3Smaxims@google.com static int ast_i2c_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)
2754dc038f3Smaxims@google.com {
2764dc038f3Smaxims@google.com 	int ret;
2774dc038f3Smaxims@google.com 
2784dc038f3Smaxims@google.com 	ret = ast_i2c_deblock(dev);
2794dc038f3Smaxims@google.com 	if (ret < 0)
2804dc038f3Smaxims@google.com 		return ret;
2814dc038f3Smaxims@google.com 
2824dc038f3Smaxims@google.com 	debug("i2c_xfer: %d messages\n", nmsgs);
2834dc038f3Smaxims@google.com 	for (; nmsgs > 0; nmsgs--, msg++) {
2844dc038f3Smaxims@google.com 		if (msg->flags & I2C_M_RD) {
2854dc038f3Smaxims@google.com 			debug("i2c_read: chip=0x%x, len=0x%x, flags=0x%x\n",
2864dc038f3Smaxims@google.com 			      msg->addr, msg->len, msg->flags);
2874dc038f3Smaxims@google.com 			ret = ast_i2c_read_data(dev, msg->addr, msg->buf,
2884dc038f3Smaxims@google.com 						msg->len, (nmsgs == 1));
2894dc038f3Smaxims@google.com 		} else {
2904dc038f3Smaxims@google.com 			debug("i2c_write: chip=0x%x, len=0x%x, flags=0x%x\n",
2914dc038f3Smaxims@google.com 			      msg->addr, msg->len, msg->flags);
2924dc038f3Smaxims@google.com 			ret = ast_i2c_write_data(dev, msg->addr, msg->buf,
2934dc038f3Smaxims@google.com 						 msg->len, (nmsgs == 1));
2944dc038f3Smaxims@google.com 		}
2954dc038f3Smaxims@google.com 		if (ret) {
2964dc038f3Smaxims@google.com 			debug("%s: error (%d)\n", __func__, ret);
2974dc038f3Smaxims@google.com 			return -EREMOTEIO;
2984dc038f3Smaxims@google.com 		}
2994dc038f3Smaxims@google.com 	}
3004dc038f3Smaxims@google.com 
3014dc038f3Smaxims@google.com 	return 0;
3024dc038f3Smaxims@google.com }
3034dc038f3Smaxims@google.com 
ast_i2c_set_speed(struct udevice * dev,unsigned int speed)3044dc038f3Smaxims@google.com static int ast_i2c_set_speed(struct udevice *dev, unsigned int speed)
3054dc038f3Smaxims@google.com {
3064dc038f3Smaxims@google.com 	struct ast_i2c_priv *priv = dev_get_priv(dev);
3074dc038f3Smaxims@google.com 	struct ast_i2c_regs *regs = priv->regs;
3084dc038f3Smaxims@google.com 	ulong i2c_rate, divider;
3094dc038f3Smaxims@google.com 
3104dc038f3Smaxims@google.com 	debug("Setting speed for I2C%d to <%u>\n", dev->seq, speed);
3114dc038f3Smaxims@google.com 	if (!speed) {
3124dc038f3Smaxims@google.com 		debug("No valid speed specified\n");
3134dc038f3Smaxims@google.com 		return -EINVAL;
3144dc038f3Smaxims@google.com 	}
3154dc038f3Smaxims@google.com 
3164dc038f3Smaxims@google.com 	i2c_rate = clk_get_rate(&priv->clk);
3174dc038f3Smaxims@google.com 	divider = i2c_rate / speed;
3184dc038f3Smaxims@google.com 
3194dc038f3Smaxims@google.com 	priv->speed = speed;
3204dc038f3Smaxims@google.com 	if (speed > I2C_HIGHSPEED_RATE) {
3214dc038f3Smaxims@google.com 		debug("Enable High Speed\n");
3224dc038f3Smaxims@google.com 		setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
3234dc038f3Smaxims@google.com 			     | I2CD_M_SDA_DRIVE_1T_EN
3244dc038f3Smaxims@google.com 			     | I2CD_SDA_DRIVE_1T_EN);
3254dc038f3Smaxims@google.com 		writel(HIGHSPEED_TTIMEOUT, &regs->cactcr2);
3264dc038f3Smaxims@google.com 	} else {
3274dc038f3Smaxims@google.com 		debug("Enabling Normal Speed\n");
3284dc038f3Smaxims@google.com 		writel(I2CD_NO_TIMEOUT_CTRL, &regs->cactcr2);
3294dc038f3Smaxims@google.com 	}
3304dc038f3Smaxims@google.com 
3314dc038f3Smaxims@google.com 	writel(get_clk_reg_val(divider), &regs->cactcr1);
3324dc038f3Smaxims@google.com 	ast_i2c_clear_interrupts(dev);
3334dc038f3Smaxims@google.com 
3344dc038f3Smaxims@google.com 	return 0;
3354dc038f3Smaxims@google.com }
3364dc038f3Smaxims@google.com 
3374dc038f3Smaxims@google.com static const struct dm_i2c_ops ast_i2c_ops = {
3384dc038f3Smaxims@google.com 	.xfer = ast_i2c_xfer,
3394dc038f3Smaxims@google.com 	.set_bus_speed = ast_i2c_set_speed,
3404dc038f3Smaxims@google.com 	.deblock = ast_i2c_deblock,
3414dc038f3Smaxims@google.com };
3424dc038f3Smaxims@google.com 
3434dc038f3Smaxims@google.com static const struct udevice_id ast_i2c_ids[] = {
3444dc038f3Smaxims@google.com 	{ .compatible = "aspeed,ast2400-i2c-bus" },
3454dc038f3Smaxims@google.com 	{ .compatible = "aspeed,ast2500-i2c-bus" },
3464dc038f3Smaxims@google.com 	{ },
3474dc038f3Smaxims@google.com };
3484dc038f3Smaxims@google.com 
3494dc038f3Smaxims@google.com U_BOOT_DRIVER(ast_i2c) = {
3504dc038f3Smaxims@google.com 	.name = "ast_i2c",
3514dc038f3Smaxims@google.com 	.id = UCLASS_I2C,
3524dc038f3Smaxims@google.com 	.of_match = ast_i2c_ids,
3534dc038f3Smaxims@google.com 	.probe = ast_i2c_probe,
3544dc038f3Smaxims@google.com 	.ofdata_to_platdata = ast_i2c_ofdata_to_platdata,
3554dc038f3Smaxims@google.com 	.priv_auto_alloc_size = sizeof(struct ast_i2c_priv),
3564dc038f3Smaxims@google.com 	.ops = &ast_i2c_ops,
3574dc038f3Smaxims@google.com };
358