Version:  2.0.40 2.2.26 2.4.37 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6

Linux/drivers/i2c/busses/i2c-xlr.c

  1 /*
  2  * Copyright 2011, Netlogic Microsystems Inc.
  3  * Copyright 2004, Matt Porter <mporter@kernel.crashing.org>
  4  *
  5  * This file is licensed under the terms of the GNU General Public
  6  * License version 2.  This program is licensed "as is" without any
  7  * warranty of any kind, whether express or implied.
  8  */
  9 
 10 #include <linux/err.h>
 11 #include <linux/kernel.h>
 12 #include <linux/module.h>
 13 #include <linux/slab.h>
 14 #include <linux/ioport.h>
 15 #include <linux/delay.h>
 16 #include <linux/errno.h>
 17 #include <linux/i2c.h>
 18 #include <linux/io.h>
 19 #include <linux/platform_device.h>
 20 #include <linux/of_device.h>
 21 #include <linux/clk.h>
 22 #include <linux/interrupt.h>
 23 #include <linux/wait.h>
 24 
 25 /* XLR I2C REGISTERS */
 26 #define XLR_I2C_CFG             0x00
 27 #define XLR_I2C_CLKDIV          0x01
 28 #define XLR_I2C_DEVADDR         0x02
 29 #define XLR_I2C_ADDR            0x03
 30 #define XLR_I2C_DATAOUT         0x04
 31 #define XLR_I2C_DATAIN          0x05
 32 #define XLR_I2C_STATUS          0x06
 33 #define XLR_I2C_STARTXFR        0x07
 34 #define XLR_I2C_BYTECNT         0x08
 35 #define XLR_I2C_HDSTATIM        0x09
 36 
 37 /* Sigma Designs additional registers */
 38 #define XLR_I2C_INT_EN          0x09
 39 #define XLR_I2C_INT_STAT        0x0a
 40 
 41 /* XLR I2C REGISTERS FLAGS */
 42 #define XLR_I2C_BUS_BUSY        0x01
 43 #define XLR_I2C_SDOEMPTY        0x02
 44 #define XLR_I2C_RXRDY           0x04
 45 #define XLR_I2C_ACK_ERR         0x08
 46 #define XLR_I2C_ARB_STARTERR    0x30
 47 
 48 /* Register Values */
 49 #define XLR_I2C_CFG_ADDR        0xF8
 50 #define XLR_I2C_CFG_NOADDR      0xFA
 51 #define XLR_I2C_STARTXFR_ND     0x02    /* No Data */
 52 #define XLR_I2C_STARTXFR_RD     0x01    /* Read */
 53 #define XLR_I2C_STARTXFR_WR     0x00    /* Write */
 54 
 55 #define XLR_I2C_TIMEOUT         10      /* timeout per byte in msec */
 56 
 57 /*
 58  * On XLR/XLS, we need to use __raw_ IO to read the I2C registers
 59  * because they are in the big-endian MMIO area on the SoC.
 60  *
 61  * The readl/writel implementation on XLR/XLS byteswaps, because
 62  * those are for its little-endian PCI space (see arch/mips/Kconfig).
 63  */
 64 static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val)
 65 {
 66         __raw_writel(val, base + reg);
 67 }
 68 
 69 static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg)
 70 {
 71         return __raw_readl(base + reg);
 72 }
 73 
 74 #define XLR_I2C_FLAG_IRQ        1
 75 
 76 struct xlr_i2c_config {
 77         u32 flags;              /* optional feature support */
 78         u32 status_busy;        /* value of STATUS[0] when busy */
 79         u32 cfg_extra;          /* extra CFG bits to set */
 80 };
 81 
 82 struct xlr_i2c_private {
 83         struct i2c_adapter adap;
 84         u32 __iomem *iobase;
 85         int irq;
 86         int pos;
 87         struct i2c_msg *msg;
 88         const struct xlr_i2c_config *cfg;
 89         wait_queue_head_t wait;
 90         struct clk *clk;
 91 };
 92 
 93 static int xlr_i2c_busy(struct xlr_i2c_private *priv, u32 status)
 94 {
 95         return (status & XLR_I2C_BUS_BUSY) == priv->cfg->status_busy;
 96 }
 97 
 98 static int xlr_i2c_idle(struct xlr_i2c_private *priv)
 99 {
100         return !xlr_i2c_busy(priv, xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS));
101 }
102 
103 static int xlr_i2c_wait(struct xlr_i2c_private *priv, unsigned long timeout)
104 {
105         int status;
106         int t;
107 
108         t = wait_event_timeout(priv->wait, xlr_i2c_idle(priv),
109                                 msecs_to_jiffies(timeout));
110         if (!t)
111                 return -ETIMEDOUT;
112 
113         status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
114 
115         return status & XLR_I2C_ACK_ERR ? -EIO : 0;
116 }
117 
118 static void xlr_i2c_tx_irq(struct xlr_i2c_private *priv, u32 status)
119 {
120         struct i2c_msg *msg = priv->msg;
121 
122         if (status & XLR_I2C_SDOEMPTY)
123                 xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT,
124                                 msg->buf[priv->pos++]);
125 }
126 
127 static void xlr_i2c_rx_irq(struct xlr_i2c_private *priv, u32 status)
128 {
129         struct i2c_msg *msg = priv->msg;
130 
131         if (status & XLR_I2C_RXRDY)
132                 msg->buf[priv->pos++] =
133                         xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
134 }
135 
136 static irqreturn_t xlr_i2c_irq(int irq, void *dev_id)
137 {
138         struct xlr_i2c_private *priv = dev_id;
139         struct i2c_msg *msg = priv->msg;
140         u32 int_stat, status;
141 
142         int_stat = xlr_i2c_rdreg(priv->iobase, XLR_I2C_INT_STAT);
143         if (!int_stat)
144                 return IRQ_NONE;
145 
146         xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_STAT, int_stat);
147 
148         if (!msg)
149                 return IRQ_HANDLED;
150 
151         status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
152 
153         if (priv->pos < msg->len) {
154                 if (msg->flags & I2C_M_RD)
155                         xlr_i2c_rx_irq(priv, status);
156                 else
157                         xlr_i2c_tx_irq(priv, status);
158         }
159 
160         if (!xlr_i2c_busy(priv, status))
161                 wake_up(&priv->wait);
162 
163         return IRQ_HANDLED;
164 }
165 
166 static int xlr_i2c_tx(struct xlr_i2c_private *priv,  u16 len,
167         u8 *buf, u16 addr)
168 {
169         struct i2c_adapter *adap = &priv->adap;
170         unsigned long timeout, stoptime, checktime;
171         u32 i2c_status;
172         int pos, timedout;
173         u8 offset;
174         u32 xfer;
175 
176         if (!len)
177                 return -EOPNOTSUPP;
178 
179         offset = buf[0];
180         xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset);
181         xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
182         xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG,
183                         XLR_I2C_CFG_ADDR | priv->cfg->cfg_extra);
184 
185         timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
186         stoptime = jiffies + timeout;
187         timedout = 0;
188 
189         if (len == 1) {
190                 xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
191                 xfer = XLR_I2C_STARTXFR_ND;
192                 pos = 1;
193         } else {
194                 xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 2);
195                 xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[1]);
196                 xfer = XLR_I2C_STARTXFR_WR;
197                 pos = 2;
198         }
199 
200         priv->pos = pos;
201 
202 retry:
203         /* retry can only happen on the first byte */
204         xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, xfer);
205 
206         if (priv->irq > 0)
207                 return xlr_i2c_wait(priv, XLR_I2C_TIMEOUT * len);
208 
209         while (!timedout) {
210                 checktime = jiffies;
211                 i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
212 
213                 if ((i2c_status & XLR_I2C_SDOEMPTY) && pos < len) {
214                         xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos++]);
215 
216                         /* reset timeout on successful xmit */
217                         stoptime = jiffies + timeout;
218                 }
219                 timedout = time_after(checktime, stoptime);
220 
221                 if (i2c_status & XLR_I2C_ARB_STARTERR) {
222                         if (timedout)
223                                 break;
224                         goto retry;
225                 }
226 
227                 if (i2c_status & XLR_I2C_ACK_ERR)
228                         return -EIO;
229 
230                 if (!xlr_i2c_busy(priv, i2c_status) && pos >= len)
231                         return 0;
232         }
233         dev_err(&adap->dev, "I2C transmit timeout\n");
234         return -ETIMEDOUT;
235 }
236 
237 static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr)
238 {
239         struct i2c_adapter *adap = &priv->adap;
240         u32 i2c_status;
241         unsigned long timeout, stoptime, checktime;
242         int nbytes, timedout;
243 
244         if (!len)
245                 return -EOPNOTSUPP;
246 
247         xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG,
248                         XLR_I2C_CFG_NOADDR | priv->cfg->cfg_extra);
249         xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1);
250         xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr);
251 
252         priv->pos = 0;
253 
254         timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT);
255         stoptime = jiffies + timeout;
256         timedout = 0;
257         nbytes = 0;
258 retry:
259         xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD);
260 
261         if (priv->irq > 0)
262                 return xlr_i2c_wait(priv, XLR_I2C_TIMEOUT * len);
263 
264         while (!timedout) {
265                 checktime = jiffies;
266                 i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS);
267                 if (i2c_status & XLR_I2C_RXRDY) {
268                         if (nbytes >= len)
269                                 return -EIO;    /* should not happen */
270 
271                         buf[nbytes++] =
272                                 xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN);
273 
274                         /* reset timeout on successful read */
275                         stoptime = jiffies + timeout;
276                 }
277 
278                 timedout = time_after(checktime, stoptime);
279                 if (i2c_status & XLR_I2C_ARB_STARTERR) {
280                         if (timedout)
281                                 break;
282                         goto retry;
283                 }
284 
285                 if (i2c_status & XLR_I2C_ACK_ERR)
286                         return -EIO;
287 
288                 if (!xlr_i2c_busy(priv, i2c_status))
289                         return 0;
290         }
291 
292         dev_err(&adap->dev, "I2C receive timeout\n");
293         return -ETIMEDOUT;
294 }
295 
296 static int xlr_i2c_xfer(struct i2c_adapter *adap,
297         struct i2c_msg *msgs, int num)
298 {
299         struct i2c_msg *msg;
300         int i;
301         int ret = 0;
302         struct xlr_i2c_private *priv = i2c_get_adapdata(adap);
303 
304         ret = clk_enable(priv->clk);
305         if (ret)
306                 return ret;
307 
308         if (priv->irq)
309                 xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0xf);
310 
311 
312         for (i = 0; ret == 0 && i < num; i++) {
313                 msg = &msgs[i];
314                 priv->msg = msg;
315                 if (msg->flags & I2C_M_RD)
316                         ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0],
317                                         msg->addr);
318                 else
319                         ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0],
320                                         msg->addr);
321         }
322 
323         if (priv->irq)
324                 xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0);
325 
326         clk_disable(priv->clk);
327         priv->msg = NULL;
328 
329         return (ret != 0) ? ret : num;
330 }
331 
332 static u32 xlr_func(struct i2c_adapter *adap)
333 {
334         /* Emulate SMBUS over I2C */
335         return (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK) | I2C_FUNC_I2C;
336 }
337 
338 static struct i2c_algorithm xlr_i2c_algo = {
339         .master_xfer    = xlr_i2c_xfer,
340         .functionality  = xlr_func,
341 };
342 
343 static const struct xlr_i2c_config xlr_i2c_config_default = {
344         .status_busy    = XLR_I2C_BUS_BUSY,
345         .cfg_extra      = 0,
346 };
347 
348 static const struct xlr_i2c_config xlr_i2c_config_tangox = {
349         .flags          = XLR_I2C_FLAG_IRQ,
350         .status_busy    = 0,
351         .cfg_extra      = 1 << 8,
352 };
353 
354 static const struct of_device_id xlr_i2c_dt_ids[] = {
355         {
356                 .compatible     = "sigma,smp8642-i2c",
357                 .data           = &xlr_i2c_config_tangox,
358         },
359         { }
360 };
361 
362 static int xlr_i2c_probe(struct platform_device *pdev)
363 {
364         const struct of_device_id *match;
365         struct xlr_i2c_private  *priv;
366         struct resource *res;
367         struct clk *clk;
368         unsigned long clk_rate;
369         unsigned long clk_div;
370         u32 busfreq;
371         int irq;
372         int ret;
373 
374         priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
375         if (!priv)
376                 return -ENOMEM;
377 
378         match = of_match_device(xlr_i2c_dt_ids, &pdev->dev);
379         if (match)
380                 priv->cfg = match->data;
381         else
382                 priv->cfg = &xlr_i2c_config_default;
383 
384         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
385         priv->iobase = devm_ioremap_resource(&pdev->dev, res);
386         if (IS_ERR(priv->iobase))
387                 return PTR_ERR(priv->iobase);
388 
389         irq = platform_get_irq(pdev, 0);
390 
391         if (irq > 0 && (priv->cfg->flags & XLR_I2C_FLAG_IRQ)) {
392                 priv->irq = irq;
393 
394                 xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_EN, 0);
395                 xlr_i2c_wreg(priv->iobase, XLR_I2C_INT_STAT, 0xf);
396 
397                 ret = devm_request_irq(&pdev->dev, priv->irq, xlr_i2c_irq,
398                                         IRQF_SHARED, dev_name(&pdev->dev),
399                                         priv);
400                 if (ret)
401                         return ret;
402 
403                 init_waitqueue_head(&priv->wait);
404         }
405 
406         if (of_property_read_u32(pdev->dev.of_node, "clock-frequency",
407                                  &busfreq))
408                 busfreq = 100000;
409 
410         clk = devm_clk_get(&pdev->dev, NULL);
411         if (!IS_ERR(clk)) {
412                 ret = clk_prepare_enable(clk);
413                 if (ret)
414                         return ret;
415 
416                 clk_rate = clk_get_rate(clk);
417                 clk_div = DIV_ROUND_UP(clk_rate, 2 * busfreq);
418                 xlr_i2c_wreg(priv->iobase, XLR_I2C_CLKDIV, clk_div);
419 
420                 clk_disable(clk);
421                 priv->clk = clk;
422         }
423 
424         priv->adap.dev.parent = &pdev->dev;
425         priv->adap.dev.of_node  = pdev->dev.of_node;
426         priv->adap.owner        = THIS_MODULE;
427         priv->adap.algo_data    = priv;
428         priv->adap.algo         = &xlr_i2c_algo;
429         priv->adap.nr           = pdev->id;
430         priv->adap.class        = I2C_CLASS_HWMON;
431         snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c");
432 
433         i2c_set_adapdata(&priv->adap, priv);
434         ret = i2c_add_numbered_adapter(&priv->adap);
435         if (ret < 0) {
436                 dev_err(&priv->adap.dev, "Failed to add i2c bus.\n");
437                 return ret;
438         }
439 
440         platform_set_drvdata(pdev, priv);
441         dev_info(&priv->adap.dev, "Added I2C Bus.\n");
442         return 0;
443 }
444 
445 static int xlr_i2c_remove(struct platform_device *pdev)
446 {
447         struct xlr_i2c_private *priv;
448 
449         priv = platform_get_drvdata(pdev);
450         i2c_del_adapter(&priv->adap);
451         clk_unprepare(priv->clk);
452 
453         return 0;
454 }
455 
456 static struct platform_driver xlr_i2c_driver = {
457         .probe  = xlr_i2c_probe,
458         .remove = xlr_i2c_remove,
459         .driver = {
460                 .name   = "xlr-i2cbus",
461                 .of_match_table = xlr_i2c_dt_ids,
462         },
463 };
464 
465 module_platform_driver(xlr_i2c_driver);
466 
467 MODULE_AUTHOR("Ganesan Ramalingam <ganesanr@netlogicmicro.com>");
468 MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver");
469 MODULE_LICENSE("GPL v2");
470 MODULE_ALIAS("platform:xlr-i2cbus");
471 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us