Lines Matching +full:meson6 +full:- +full:i2c
1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2017 - Beniamino Galvani <b.galvani@gmail.com>
9 #include <i2c.h>
47 struct i2c_msg *msg; /* Current I2C message */
55 static void meson_i2c_reset_tokens(struct meson_i2c *i2c) in meson_i2c_reset_tokens() argument
57 i2c->tokens[0] = 0; in meson_i2c_reset_tokens()
58 i2c->tokens[1] = 0; in meson_i2c_reset_tokens()
59 i2c->num_tokens = 0; in meson_i2c_reset_tokens()
62 static void meson_i2c_add_token(struct meson_i2c *i2c, int token) in meson_i2c_add_token() argument
64 if (i2c->num_tokens < 8) in meson_i2c_add_token()
65 i2c->tokens[0] |= (token & 0xf) << (i2c->num_tokens * 4); in meson_i2c_add_token()
67 i2c->tokens[1] |= (token & 0xf) << ((i2c->num_tokens % 8) * 4); in meson_i2c_add_token()
69 i2c->num_tokens++; in meson_i2c_add_token()
76 static void meson_i2c_get_data(struct meson_i2c *i2c, u8 *buf, int len) in meson_i2c_get_data() argument
81 rdata0 = readl(&i2c->regs->tok_rdata0); in meson_i2c_get_data()
82 rdata1 = readl(&i2c->regs->tok_rdata1); in meson_i2c_get_data()
84 debug("meson i2c: read data %08x %08x len %d\n", rdata0, rdata1, len); in meson_i2c_get_data()
90 *buf++ = (rdata1 >> (i - 4) * 8) & 0xff; in meson_i2c_get_data()
97 static void meson_i2c_put_data(struct meson_i2c *i2c, u8 *buf, int len) in meson_i2c_put_data() argument
106 wdata1 |= *buf++ << ((i - 4) * 8); in meson_i2c_put_data()
108 writel(wdata0, &i2c->regs->tok_wdata0); in meson_i2c_put_data()
109 writel(wdata1, &i2c->regs->tok_wdata1); in meson_i2c_put_data()
111 debug("meson i2c: write data %08x %08x len %d\n", wdata0, wdata1, len); in meson_i2c_put_data()
119 static void meson_i2c_prepare_xfer(struct meson_i2c *i2c) in meson_i2c_prepare_xfer() argument
121 bool write = !(i2c->msg->flags & I2C_M_RD); in meson_i2c_prepare_xfer()
124 i2c->count = min(i2c->msg->len - i2c->pos, 8u); in meson_i2c_prepare_xfer()
126 for (i = 0; i + 1 < i2c->count; i++) in meson_i2c_prepare_xfer()
127 meson_i2c_add_token(i2c, TOKEN_DATA); in meson_i2c_prepare_xfer()
129 if (i2c->count) { in meson_i2c_prepare_xfer()
130 if (write || i2c->pos + i2c->count < i2c->msg->len) in meson_i2c_prepare_xfer()
131 meson_i2c_add_token(i2c, TOKEN_DATA); in meson_i2c_prepare_xfer()
133 meson_i2c_add_token(i2c, TOKEN_DATA_LAST); in meson_i2c_prepare_xfer()
137 meson_i2c_put_data(i2c, i2c->msg->buf + i2c->pos, i2c->count); in meson_i2c_prepare_xfer()
139 if (i2c->last && i2c->pos + i2c->count >= i2c->msg->len) in meson_i2c_prepare_xfer()
140 meson_i2c_add_token(i2c, TOKEN_STOP); in meson_i2c_prepare_xfer()
142 writel(i2c->tokens[0], &i2c->regs->tok_list0); in meson_i2c_prepare_xfer()
143 writel(i2c->tokens[1], &i2c->regs->tok_list1); in meson_i2c_prepare_xfer()
146 static void meson_i2c_do_start(struct meson_i2c *i2c, struct i2c_msg *msg) in meson_i2c_do_start() argument
150 token = (msg->flags & I2C_M_RD) ? TOKEN_SLAVE_ADDR_READ : in meson_i2c_do_start()
153 writel(msg->addr << 1, &i2c->regs->slave_addr); in meson_i2c_do_start()
154 meson_i2c_add_token(i2c, TOKEN_START); in meson_i2c_do_start()
155 meson_i2c_add_token(i2c, token); in meson_i2c_do_start()
158 static int meson_i2c_xfer_msg(struct meson_i2c *i2c, struct i2c_msg *msg, in meson_i2c_xfer_msg() argument
163 debug("meson i2c: %s addr %u len %u\n", in meson_i2c_xfer_msg()
164 (msg->flags & I2C_M_RD) ? "read" : "write", in meson_i2c_xfer_msg()
165 msg->addr, msg->len); in meson_i2c_xfer_msg()
167 i2c->msg = msg; in meson_i2c_xfer_msg()
168 i2c->last = last; in meson_i2c_xfer_msg()
169 i2c->pos = 0; in meson_i2c_xfer_msg()
170 i2c->count = 0; in meson_i2c_xfer_msg()
172 meson_i2c_reset_tokens(i2c); in meson_i2c_xfer_msg()
173 meson_i2c_do_start(i2c, msg); in meson_i2c_xfer_msg()
176 meson_i2c_prepare_xfer(i2c); in meson_i2c_xfer_msg()
179 setbits_le32(&i2c->regs->ctrl, REG_CTRL_START); in meson_i2c_xfer_msg()
181 while (readl(&i2c->regs->ctrl) & REG_CTRL_STATUS) { in meson_i2c_xfer_msg()
183 clrbits_le32(&i2c->regs->ctrl, REG_CTRL_START); in meson_i2c_xfer_msg()
184 debug("meson i2c: timeout\n"); in meson_i2c_xfer_msg()
185 return -ETIMEDOUT; in meson_i2c_xfer_msg()
189 meson_i2c_reset_tokens(i2c); in meson_i2c_xfer_msg()
190 clrbits_le32(&i2c->regs->ctrl, REG_CTRL_START); in meson_i2c_xfer_msg()
192 if (readl(&i2c->regs->ctrl) & REG_CTRL_ERROR) { in meson_i2c_xfer_msg()
193 debug("meson i2c: error\n"); in meson_i2c_xfer_msg()
194 return -EREMOTEIO; in meson_i2c_xfer_msg()
197 if ((msg->flags & I2C_M_RD) && i2c->count) { in meson_i2c_xfer_msg()
198 meson_i2c_get_data(i2c, i2c->msg->buf + i2c->pos, in meson_i2c_xfer_msg()
199 i2c->count); in meson_i2c_xfer_msg()
201 i2c->pos += i2c->count; in meson_i2c_xfer_msg()
202 } while (i2c->pos < msg->len); in meson_i2c_xfer_msg()
210 struct meson_i2c *i2c = dev_get_priv(bus); in meson_i2c_xfer() local
214 ret = meson_i2c_xfer_msg(i2c, msg + i, i == nmsgs - 1); in meson_i2c_xfer()
224 struct meson_i2c *i2c = dev_get_priv(bus); in meson_i2c_set_bus_speed() local
228 clk_rate = clk_get_rate(&i2c->clk); in meson_i2c_set_bus_speed()
230 return -EINVAL; in meson_i2c_set_bus_speed()
236 debug("meson i2c: requested bus frequency too low\n"); in meson_i2c_set_bus_speed()
237 div = (1 << 12) - 1; in meson_i2c_set_bus_speed()
240 clrsetbits_le32(&i2c->regs->ctrl, REG_CTRL_CLKDIV_MASK, in meson_i2c_set_bus_speed()
243 clrsetbits_le32(&i2c->regs->ctrl, REG_CTRL_CLKDIVEXT_MASK, in meson_i2c_set_bus_speed()
246 debug("meson i2c: set clk %u, src %lu, div %u\n", speed, clk_rate, div); in meson_i2c_set_bus_speed()
253 struct meson_i2c *i2c = dev_get_priv(bus); in meson_i2c_probe() local
256 ret = clk_get_by_index(bus, 0, &i2c->clk); in meson_i2c_probe()
260 ret = clk_enable(&i2c->clk); in meson_i2c_probe()
264 i2c->regs = dev_read_addr_ptr(bus); in meson_i2c_probe()
265 clrbits_le32(&i2c->regs->ctrl, REG_CTRL_START); in meson_i2c_probe()
276 { .compatible = "amlogic,meson6-i2c" },
277 { .compatible = "amlogic,meson-gx-i2c" },
278 { .compatible = "amlogic,meson-gxbb-i2c" },