blob: 58e88506cecf69efc502447065cc6cc4bb16e462 [file] [log] [blame]
Sagar Dharia7c927c02016-11-23 11:51:43 -07001/*
2 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#include <linux/clk.h>
16#include <linux/delay.h>
17#include <linux/err.h>
18#include <linux/i2c.h>
19#include <linux/interrupt.h>
20#include <linux/io.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/platform_device.h>
Sagar Dhariab44003b2017-03-10 15:34:26 -070024#include <linux/pm_runtime.h>
Sagar Dharia7c927c02016-11-23 11:51:43 -070025#include <linux/qcom-geni-se.h>
26
27#define SE_I2C_TX_TRANS_LEN (0x26C)
28#define SE_I2C_RX_TRANS_LEN (0x270)
29#define SE_I2C_SCL_COUNTERS (0x278)
30
31#define SE_I2C_ERR (M_CMD_OVERRUN_EN | M_ILLEGAL_CMD_EN | M_CMD_FAILURE_EN |\
32 M_GP_IRQ_1_EN | M_GP_IRQ_3_EN | M_GP_IRQ_4_EN)
33#define SE_I2C_ABORT (1U << 1)
34/* M_CMD OP codes for I2C */
35#define I2C_WRITE (0x1)
36#define I2C_READ (0x2)
37#define I2C_WRITE_READ (0x3)
38#define I2C_ADDR_ONLY (0x4)
39#define I2C_BUS_CLEAR (0x6)
40#define I2C_STOP_ON_BUS (0x7)
41/* M_CMD params for I2C */
42#define PRE_CMD_DELAY (BIT(0))
43#define TIMESTAMP_BEFORE (BIT(1))
44#define STOP_STRETCH (BIT(2))
45#define TIMESTAMP_AFTER (BIT(3))
46#define POST_COMMAND_DELAY (BIT(4))
47#define IGNORE_ADD_NACK (BIT(6))
48#define READ_FINISHED_WITH_ACK (BIT(7))
49#define BYPASS_ADDR_PHASE (BIT(8))
50#define SLV_ADDR_MSK (GENMASK(15, 9))
51#define SLV_ADDR_SHFT (9)
52
53struct geni_i2c_dev {
54 struct device *dev;
55 void __iomem *base;
56 int irq;
57 int err;
58 struct i2c_adapter adap;
59 struct completion xfer;
60 struct i2c_msg *cur;
Sagar Dhariab44003b2017-03-10 15:34:26 -070061 struct se_geni_rsc i2c_rsc;
Sagar Dharia7c927c02016-11-23 11:51:43 -070062 int cur_wr;
63 int cur_rd;
64};
65
66static inline void qcom_geni_i2c_conf(void __iomem *base, int dfs, int div)
67{
68 geni_write_reg(dfs, base, SE_GENI_CLK_SEL);
69 geni_write_reg((div << 4) | 1, base, GENI_SER_M_CLK_CFG);
70 geni_write_reg(((5 << 20) | (0xC << 10) | 0x18),
71 base, SE_I2C_SCL_COUNTERS);
72 /*
73 * Ensure Clk config completes before return.
74 */
75 mb();
76}
77
78static irqreturn_t geni_i2c_irq(int irq, void *dev)
79{
80 struct geni_i2c_dev *gi2c = dev;
81 int i, j;
82 u32 m_stat = readl_relaxed(gi2c->base + SE_GENI_M_IRQ_STATUS);
83 u32 tx_stat = readl_relaxed(gi2c->base + SE_GENI_TX_FIFO_STATUS);
84 u32 rx_stat = readl_relaxed(gi2c->base + SE_GENI_RX_FIFO_STATUS);
85 struct i2c_msg *cur = gi2c->cur;
86
87 dev_dbg(gi2c->dev,
88 "got i2c irq:%d, stat:0x%x, tx stat:0x%x, rx stat:0x%x\n",
89 irq, m_stat, tx_stat, rx_stat);
90 if (!cur || m_stat & SE_I2C_ERR) {
91 dev_err(gi2c->dev, "i2c txn err");
92 writel_relaxed(0, (gi2c->base + SE_GENI_TX_WATERMARK_REG));
93 gi2c->err = -EIO;
94 goto irqret;
95 }
96 if (((m_stat & M_RX_FIFO_WATERMARK_EN) ||
97 (m_stat & M_RX_FIFO_LAST_EN)) && (cur->flags & I2C_M_RD)) {
98 u32 rxcnt = rx_stat & RX_FIFO_WC_MSK;
99
100 for (j = 0; j < rxcnt; j++) {
101 u32 temp;
102 int p;
103
104 temp = readl_relaxed(gi2c->base + SE_GENI_RX_FIFOn);
105 for (i = gi2c->cur_rd, p = 0; (i < cur->len && p < 4);
106 i++, p++)
107 cur->buf[i] = (u8) ((temp >> (p * 8)) & 0xff);
108 gi2c->cur_rd = i;
109 if (gi2c->cur_rd == cur->len) {
110 dev_dbg(gi2c->dev, "i:%d,read 0x%x\n", i, temp);
111 break;
112 }
113 dev_dbg(gi2c->dev, "i: %d, read 0x%x\n", i, temp);
114 }
115 } else if ((m_stat & M_TX_FIFO_WATERMARK_EN) &&
116 !(cur->flags & I2C_M_RD)) {
117 for (j = 0; j < 0x1f; j++) {
118 u32 temp = 0;
119 int p;
120
121 for (i = gi2c->cur_wr, p = 0; (i < cur->len && p < 4);
122 i++, p++)
123 temp |= (((u32)(cur->buf[i]) << (p * 8)));
124 writel_relaxed(temp, gi2c->base + SE_GENI_TX_FIFOn);
125 gi2c->cur_wr = i;
126 dev_dbg(gi2c->dev, "i:%d,wrote 0x%x\n", i, temp);
127 if (gi2c->cur_wr == cur->len) {
128 dev_dbg(gi2c->dev, "i2c bytes done writing\n");
129 writel_relaxed(0,
130 (gi2c->base + SE_GENI_TX_WATERMARK_REG));
131 break;
132 }
133 }
134 }
135irqret:
136 writel_relaxed(m_stat, gi2c->base + SE_GENI_M_IRQ_CLEAR);
137 /* Ensure all writes are done before returning from ISR. */
138 wmb();
139 /* if this is err with done-bit not set, handle that thr' timeout. */
140 if (m_stat & M_CMD_DONE_EN) {
141 dev_dbg(gi2c->dev, "i2c irq: err:%d, stat:0x%x\n",
142 gi2c->err, m_stat);
143 complete(&gi2c->xfer);
144 }
145 return IRQ_HANDLED;
146}
147
148static int geni_i2c_xfer(struct i2c_adapter *adap,
149 struct i2c_msg msgs[],
150 int num)
151{
152 struct geni_i2c_dev *gi2c = i2c_get_adapdata(adap);
153 int i, ret = 0, timeout = 0;
154
155 gi2c->err = 0;
156 gi2c->cur = &msgs[0];
157 reinit_completion(&gi2c->xfer);
Sagar Dhariab44003b2017-03-10 15:34:26 -0700158 ret = pm_runtime_get_sync(gi2c->dev);
159 if (ret < 0) {
160 dev_err(gi2c->dev, "error turning SE resources:%d\n", ret);
161 pm_runtime_put_noidle(gi2c->dev);
162 /* Set device in suspended since resume failed */
163 pm_runtime_set_suspended(gi2c->dev);
164 return ret;
165 }
166 geni_se_init(gi2c->base, FIFO_MODE, 0xF, 0x10);
Sagar Dharia7c927c02016-11-23 11:51:43 -0700167 qcom_geni_i2c_conf(gi2c->base, 0, 2);
168 se_config_packing(gi2c->base, 8, 4, true);
169 dev_dbg(gi2c->dev, "i2c xfer:num:%d, msgs:len:%d,flg:%d\n",
170 num, msgs[0].len, msgs[0].flags);
171 for (i = 0; i < num; i++) {
172 int stretch = (i < (num - 1));
173 u32 m_param = 0;
174 u32 m_cmd = 0;
175
Girish Mahadevand5890b22017-03-30 13:20:02 -0600176 m_param |= (stretch ? STOP_STRETCH : 0);
Sagar Dharia7c927c02016-11-23 11:51:43 -0700177 m_param |= ((msgs[i].addr & 0x7F) << SLV_ADDR_SHFT);
178
179 gi2c->cur = &msgs[i];
180 if (msgs[i].flags & I2C_M_RD) {
181 dev_dbg(gi2c->dev,
182 "READ,n:%d,i:%d len:%d, stretch:%d\n",
183 num, i, msgs[i].len, stretch);
184 geni_write_reg(msgs[i].len,
185 gi2c->base, SE_I2C_RX_TRANS_LEN);
186 m_cmd = I2C_READ;
187 geni_setup_m_cmd(gi2c->base, m_cmd, m_param);
188 } else {
189 dev_dbg(gi2c->dev,
190 "WRITE:n:%d,i%d len:%d, stretch:%d\n",
191 num, i, msgs[i].len, stretch);
192 geni_write_reg(msgs[i].len, gi2c->base,
193 SE_I2C_TX_TRANS_LEN);
194 m_cmd = I2C_WRITE;
195 geni_setup_m_cmd(gi2c->base, m_cmd, m_param);
196 /* Get FIFO IRQ */
197 geni_write_reg(1, gi2c->base, SE_GENI_TX_WATERMARK_REG);
198 }
199 /* Ensure FIFO write go through before waiting for Done evet */
200 mb();
201 timeout = wait_for_completion_timeout(&gi2c->xfer, HZ);
202 if (!timeout) {
203 dev_err(gi2c->dev, "Timed out\n");
204 gi2c->err = -ETIMEDOUT;
205 gi2c->cur = NULL;
206 geni_abort_m_cmd(gi2c->base);
207 timeout = wait_for_completion_timeout(&gi2c->xfer, HZ);
208 }
209 gi2c->cur_wr = 0;
210 gi2c->cur_rd = 0;
211 if (gi2c->err) {
212 dev_err(gi2c->dev, "i2c error :%d\n", gi2c->err);
213 ret = gi2c->err;
214 break;
215 }
216 }
217 if (ret == 0)
218 ret = i;
Sagar Dhariab44003b2017-03-10 15:34:26 -0700219 pm_runtime_put_sync(gi2c->dev);
Sagar Dharia7c927c02016-11-23 11:51:43 -0700220 gi2c->cur = NULL;
221 gi2c->err = 0;
222 dev_dbg(gi2c->dev, "i2c txn ret:%d\n", ret);
223 return ret;
224}
225
226static u32 geni_i2c_func(struct i2c_adapter *adap)
227{
228 return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
229}
230
231static const struct i2c_algorithm geni_i2c_algo = {
232 .master_xfer = geni_i2c_xfer,
233 .functionality = geni_i2c_func,
234};
235
236static int geni_i2c_probe(struct platform_device *pdev)
237{
238 struct geni_i2c_dev *gi2c;
239 struct resource *res;
240 int ret;
241
242 gi2c = devm_kzalloc(&pdev->dev, sizeof(*gi2c), GFP_KERNEL);
243 if (!gi2c)
244 return -ENOMEM;
245
246 gi2c->dev = &pdev->dev;
247
248 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
249 if (!res)
250 return -EINVAL;
251
Sagar Dhariab44003b2017-03-10 15:34:26 -0700252 gi2c->i2c_rsc.se_clk = devm_clk_get(&pdev->dev, "se-clk");
253 if (IS_ERR(gi2c->i2c_rsc.se_clk)) {
254 ret = PTR_ERR(gi2c->i2c_rsc.se_clk);
255 dev_err(&pdev->dev, "Err getting SE Core clk %d\n", ret);
256 return ret;
257 }
258
259 gi2c->i2c_rsc.m_ahb_clk = devm_clk_get(&pdev->dev, "m-ahb");
260 if (IS_ERR(gi2c->i2c_rsc.m_ahb_clk)) {
261 ret = PTR_ERR(gi2c->i2c_rsc.m_ahb_clk);
262 dev_err(&pdev->dev, "Err getting M AHB clk %d\n", ret);
263 return ret;
264 }
265
266 gi2c->i2c_rsc.s_ahb_clk = devm_clk_get(&pdev->dev, "s-ahb");
267 if (IS_ERR(gi2c->i2c_rsc.s_ahb_clk)) {
268 ret = PTR_ERR(gi2c->i2c_rsc.s_ahb_clk);
269 dev_err(&pdev->dev, "Err getting S AHB clk %d\n", ret);
270 return ret;
271 }
272
Sagar Dharia7c927c02016-11-23 11:51:43 -0700273 gi2c->base = devm_ioremap_resource(gi2c->dev, res);
274 if (IS_ERR(gi2c->base))
275 return PTR_ERR(gi2c->base);
276
Sagar Dhariab44003b2017-03-10 15:34:26 -0700277 gi2c->i2c_rsc.geni_pinctrl = devm_pinctrl_get(&pdev->dev);
278 if (IS_ERR_OR_NULL(gi2c->i2c_rsc.geni_pinctrl)) {
279 dev_err(&pdev->dev, "No pinctrl config specified\n");
280 ret = PTR_ERR(gi2c->i2c_rsc.geni_pinctrl);
281 return ret;
282 }
283 gi2c->i2c_rsc.geni_gpio_active =
284 pinctrl_lookup_state(gi2c->i2c_rsc.geni_pinctrl,
285 PINCTRL_DEFAULT);
286 if (IS_ERR_OR_NULL(gi2c->i2c_rsc.geni_gpio_active)) {
287 dev_err(&pdev->dev, "No default config specified\n");
288 ret = PTR_ERR(gi2c->i2c_rsc.geni_gpio_active);
289 return ret;
290 }
291 gi2c->i2c_rsc.geni_gpio_sleep =
292 pinctrl_lookup_state(gi2c->i2c_rsc.geni_pinctrl,
293 PINCTRL_SLEEP);
294 if (IS_ERR_OR_NULL(gi2c->i2c_rsc.geni_gpio_sleep)) {
295 dev_err(&pdev->dev, "No sleep config specified\n");
296 ret = PTR_ERR(gi2c->i2c_rsc.geni_gpio_sleep);
297 return ret;
298 }
299
Sagar Dharia7c927c02016-11-23 11:51:43 -0700300 gi2c->irq = platform_get_irq(pdev, 0);
301 if (gi2c->irq < 0) {
302 dev_err(gi2c->dev, "IRQ error for i2c-geni\n");
303 return gi2c->irq;
304 }
305
306 gi2c->adap.algo = &geni_i2c_algo;
307 init_completion(&gi2c->xfer);
308 platform_set_drvdata(pdev, gi2c);
309 ret = devm_request_irq(gi2c->dev, gi2c->irq, geni_i2c_irq,
310 IRQF_TRIGGER_HIGH, "i2c_geni", gi2c);
311 if (ret) {
312 dev_err(gi2c->dev, "Request_irq failed:%d: err:%d\n",
313 gi2c->irq, ret);
314 return ret;
315 }
316 disable_irq(gi2c->irq);
317 i2c_set_adapdata(&gi2c->adap, gi2c);
318 gi2c->adap.dev.parent = gi2c->dev;
319 gi2c->adap.dev.of_node = pdev->dev.of_node;
320
321 strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
322
Sagar Dhariab44003b2017-03-10 15:34:26 -0700323 pm_runtime_set_suspended(gi2c->dev);
324 pm_runtime_enable(gi2c->dev);
Sagar Dharia7c927c02016-11-23 11:51:43 -0700325 i2c_add_adapter(&gi2c->adap);
Sagar Dharia7c927c02016-11-23 11:51:43 -0700326
327 return 0;
328}
329
330static int geni_i2c_remove(struct platform_device *pdev)
331{
332 struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
333
Sagar Dhariab44003b2017-03-10 15:34:26 -0700334 pm_runtime_disable(gi2c->dev);
Sagar Dharia7c927c02016-11-23 11:51:43 -0700335 i2c_del_adapter(&gi2c->adap);
336 return 0;
337}
338
Sagar Dhariab44003b2017-03-10 15:34:26 -0700339static int geni_i2c_resume_noirq(struct device *device)
Sagar Dharia7c927c02016-11-23 11:51:43 -0700340{
341 return 0;
342}
343
Sagar Dhariab44003b2017-03-10 15:34:26 -0700344#ifdef CONFIG_PM
345static int geni_i2c_runtime_suspend(struct device *dev)
346{
347 struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
348
349 disable_irq(gi2c->irq);
350 se_geni_resources_off(&gi2c->i2c_rsc);
351 return 0;
352}
353
354static int geni_i2c_runtime_resume(struct device *dev)
355{
356 int ret;
357 struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
358
359 ret = se_geni_resources_on(&gi2c->i2c_rsc);
360 if (ret)
361 return ret;
362
363 enable_irq(gi2c->irq);
364 return 0;
365}
366
367static int geni_i2c_suspend_noirq(struct device *device)
368{
369 if (!pm_runtime_status_suspended(device))
370 return -EBUSY;
371 return 0;
372}
373#else
374static int geni_i2c_runtime_suspend(struct device *dev)
375{
376 return 0;
377}
378
379static int geni_i2c_runtime_resume(struct device *dev)
380{
381 return 0;
382}
383
384static int geni_i2c_suspend_noirq(struct device *device)
Sagar Dharia7c927c02016-11-23 11:51:43 -0700385{
386 return 0;
387}
388#endif
389
390static const struct dev_pm_ops geni_i2c_pm_ops = {
Sagar Dhariab44003b2017-03-10 15:34:26 -0700391 .suspend_noirq = geni_i2c_suspend_noirq,
392 .resume_noirq = geni_i2c_resume_noirq,
393 .runtime_suspend = geni_i2c_runtime_suspend,
394 .runtime_resume = geni_i2c_runtime_resume,
Sagar Dharia7c927c02016-11-23 11:51:43 -0700395};
396
397static const struct of_device_id geni_i2c_dt_match[] = {
398 { .compatible = "qcom,i2c-geni" },
399 {}
400};
401MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
402
403static struct platform_driver geni_i2c_driver = {
404 .probe = geni_i2c_probe,
405 .remove = geni_i2c_remove,
406 .driver = {
407 .name = "i2c_geni",
408 .pm = &geni_i2c_pm_ops,
409 .of_match_table = geni_i2c_dt_match,
410 },
411};
412
413module_platform_driver(geni_i2c_driver);
414
415MODULE_LICENSE("GPL v2");
416MODULE_ALIAS("platform:i2c_geni");