Lines Matching +full:i2c +full:- +full:max +full:- +full:bus +full:- +full:freq
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Loongson-2K/Loongson LS7A I2C controller mode driver
6 * Copyright (C) 2014-2017 Lemote, Inc.
7 * Copyright (C) 2018-2022 Loongson Technology Corporation Limited.
18 #include <linux/i2c.h>
29 /* I2C Registers */
30 #define I2C_LS2X_PRER_LO 0x0 /* Freq Division Low Byte Register */
31 #define I2C_LS2X_PRER_HI 0x1 /* Freq Division High Byte Register */
48 #define LS2X_SR_BUSY BIT(6) /* Bus busy state */
54 #define LS2X_CTR_EN BIT(7) /* 0: I2c frequency setting 1: Normal */
55 #define LS2X_CTR_IEN BIT(6) /* Enable i2c interrupt */
63 /* The default bus frequency, which is an empirical value */
75 * This gets called whenever an I2C interrupt occurs.
81 if (!(readb(priv->base + I2C_LS2X_SR) & LS2X_SR_IF)) in ls2x_i2c_isr()
84 writeb(LS2X_CR_IACK, priv->base + I2C_LS2X_CR); in ls2x_i2c_isr()
85 complete(&priv->cmd_complete); in ls2x_i2c_isr()
90 * The ls2x i2c controller supports standard mode and fast mode, so the
91 * maximum bus frequency is '400kHz'.
92 * The bus frequency is set to the empirical value of '33KHz' by default,
99 struct i2c_timings *t = &priv->i2c_t; in ls2x_i2c_adjust_bus_speed()
100 struct device *dev = priv->adapter.dev.parent; in ls2x_i2c_adjust_bus_speed()
105 if (acpi_speed || t->bus_freq_hz) in ls2x_i2c_adjust_bus_speed()
106 t->bus_freq_hz = max(t->bus_freq_hz, acpi_speed); in ls2x_i2c_adjust_bus_speed()
108 t->bus_freq_hz = LS2X_I2C_FREQ_STD; in ls2x_i2c_adjust_bus_speed()
113 * So set the I2C frequency with a sequential writeb() instead of writew(). in ls2x_i2c_adjust_bus_speed()
115 val = LS2X_I2C_PCLK_FREQ / (5 * t->bus_freq_hz) - 1; in ls2x_i2c_adjust_bus_speed()
116 writeb(FIELD_GET(GENMASK(7, 0), val), priv->base + I2C_LS2X_PRER_LO); in ls2x_i2c_adjust_bus_speed()
117 writeb(FIELD_GET(GENMASK(15, 8), val), priv->base + I2C_LS2X_PRER_HI); in ls2x_i2c_adjust_bus_speed()
122 /* Set i2c frequency setting mode and disable interrupts. */ in ls2x_i2c_init()
123 writeb(readb(priv->base + I2C_LS2X_CTR) & ~CTR_FREQ_MASK, in ls2x_i2c_init()
124 priv->base + I2C_LS2X_CTR); in ls2x_i2c_init()
128 /* Set i2c normal operating mode and enable interrupts. */ in ls2x_i2c_init()
129 writeb(readb(priv->base + I2C_LS2X_CTR) | CTR_READY_MASK, in ls2x_i2c_init()
130 priv->base + I2C_LS2X_CTR); in ls2x_i2c_init()
138 writeb(txdata, priv->base + I2C_LS2X_CR); in ls2x_i2c_xfer_byte()
140 time_left = wait_for_completion_timeout(&priv->cmd_complete, in ls2x_i2c_xfer_byte()
141 priv->adapter.timeout); in ls2x_i2c_xfer_byte()
143 return -ETIMEDOUT; in ls2x_i2c_xfer_byte()
145 rxdata = readb(priv->base + I2C_LS2X_SR); in ls2x_i2c_xfer_byte()
162 return -EAGAIN; in ls2x_i2c_send_byte()
165 return -ENXIO; in ls2x_i2c_send_byte()
174 writeb(LS2X_CR_STOP, priv->base + I2C_LS2X_CR); in ls2x_i2c_stop()
175 return readb_poll_timeout(priv->base + I2C_LS2X_SR, value, in ls2x_i2c_stop()
177 jiffies_to_usecs(priv->adapter.timeout)); in ls2x_i2c_stop()
182 reinit_completion(&priv->cmd_complete); in ls2x_i2c_start()
184 writeb(i2c_8bit_addr_from_msg(msgs), priv->base + I2C_LS2X_TXR); in ls2x_i2c_start()
191 u8 rxdata, *buf = msg->buf; in ls2x_i2c_rx()
192 u16 len = msg->len; in ls2x_i2c_rx()
199 while (len--) { in ls2x_i2c_rx()
206 *buf++ = readb(priv->base + I2C_LS2X_RXR); in ls2x_i2c_rx()
215 u8 *buf = msg->buf; in ls2x_i2c_tx()
216 u16 len = msg->len; in ls2x_i2c_tx()
223 while (len--) { in ls2x_i2c_tx()
224 writeb(*buf++, priv->base + I2C_LS2X_TXR); in ls2x_i2c_tx()
239 if (msg->flags & I2C_M_RD) in ls2x_i2c_xfer_one()
246 if (ret == -ETIMEDOUT) in ls2x_i2c_xfer_one()
269 ret = ls2x_i2c_xfer_one(priv, msg, msg == emsg - 1); in ls2x_i2c_xfer()
292 struct device *dev = &pdev->dev; in ls2x_i2c_probe()
296 return -ENOMEM; in ls2x_i2c_probe()
299 priv->base = devm_platform_ioremap_resource(pdev, 0); in ls2x_i2c_probe()
300 if (IS_ERR(priv->base)) in ls2x_i2c_probe()
301 return PTR_ERR(priv->base); in ls2x_i2c_probe()
307 /* Add the i2c adapter */ in ls2x_i2c_probe()
308 adap = &priv->adapter; in ls2x_i2c_probe()
309 adap->retries = 5; in ls2x_i2c_probe()
310 adap->nr = pdev->id; in ls2x_i2c_probe()
311 adap->dev.parent = dev; in ls2x_i2c_probe()
312 adap->owner = THIS_MODULE; in ls2x_i2c_probe()
313 adap->algo = &ls2x_i2c_algo; in ls2x_i2c_probe()
314 adap->timeout = msecs_to_jiffies(100); in ls2x_i2c_probe()
315 device_set_node(&adap->dev, dev_fwnode(dev)); in ls2x_i2c_probe()
317 strscpy(adap->name, pdev->name, sizeof(adap->name)); in ls2x_i2c_probe()
318 init_completion(&priv->cmd_complete); in ls2x_i2c_probe()
323 ret = devm_request_irq(dev, irq, ls2x_i2c_isr, IRQF_SHARED, "ls2x-i2c", in ls2x_i2c_probe()
336 writeb(readb(priv->base + I2C_LS2X_CTR) & ~LS2X_CTR_IEN, in ls2x_i2c_suspend()
337 priv->base + I2C_LS2X_CTR); in ls2x_i2c_suspend()
352 { .compatible = "loongson,ls2k-i2c" },
353 { .compatible = "loongson,ls7a-i2c" },
367 .name = "ls2x-i2c",
375 MODULE_DESCRIPTION("Loongson LS2X I2C Bus driver");