summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorWolfram Sang <wsa+renesas@sang-engineering.com>2014-11-18 11:04:55 -0500
committerWolfram Sang <wsa@the-dreams.de>2014-12-11 16:25:55 -0500
commitde20d1857dd6b1a289d3b0476d6af36d12000d7e (patch)
tree984b59c97ade8ca0ea2a3842fcc2e64a13ff04b1 /drivers/i2c
parent389be323cfac383e4d71dfeeaa1b0c3aec722a5f (diff)
i2c: rcar: add slave support
The first I2C slave provider using the new generic interface. Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-rcar.c124
1 files changed, 115 insertions, 9 deletions
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index d826e82dd997..835057741aa6 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -48,6 +48,12 @@
48#define ICMAR 0x20 /* master address */ 48#define ICMAR 0x20 /* master address */
49#define ICRXTX 0x24 /* data port */ 49#define ICRXTX 0x24 /* data port */
50 50
51/* ICSCR */
52#define SDBS (1 << 3) /* slave data buffer select */
53#define SIE (1 << 2) /* slave interface enable */
54#define GCAE (1 << 1) /* general call address enable */
55#define FNA (1 << 0) /* forced non acknowledgment */
56
51/* ICMCR */ 57/* ICMCR */
52#define MDBS (1 << 7) /* non-fifo mode switch */ 58#define MDBS (1 << 7) /* non-fifo mode switch */
53#define FSCL (1 << 6) /* override SCL pin */ 59#define FSCL (1 << 6) /* override SCL pin */
@@ -58,6 +64,15 @@
58#define FSB (1 << 1) /* force stop bit */ 64#define FSB (1 << 1) /* force stop bit */
59#define ESG (1 << 0) /* en startbit gen */ 65#define ESG (1 << 0) /* en startbit gen */
60 66
67/* ICSSR (also for ICSIER) */
68#define GCAR (1 << 6) /* general call received */
69#define STM (1 << 5) /* slave transmit mode */
70#define SSR (1 << 4) /* stop received */
71#define SDE (1 << 3) /* slave data empty */
72#define SDT (1 << 2) /* slave data transmitted */
73#define SDR (1 << 1) /* slave data received */
74#define SAR (1 << 0) /* slave addr received */
75
61/* ICMSR (also for ICMIE) */ 76/* ICMSR (also for ICMIE) */
62#define MNR (1 << 6) /* nack received */ 77#define MNR (1 << 6) /* nack received */
63#define MAL (1 << 5) /* arbitration lost */ 78#define MAL (1 << 5) /* arbitration lost */
@@ -103,6 +118,7 @@ struct rcar_i2c_priv {
103 u32 icccr; 118 u32 icccr;
104 u32 flags; 119 u32 flags;
105 enum rcar_i2c_type devtype; 120 enum rcar_i2c_type devtype;
121 struct i2c_client *slave;
106}; 122};
107 123
108#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent) 124#define rcar_i2c_priv_to_dev(p) ((p)->adap.dev.parent)
@@ -126,15 +142,6 @@ static u32 rcar_i2c_read(struct rcar_i2c_priv *priv, int reg)
126 142
127static void rcar_i2c_init(struct rcar_i2c_priv *priv) 143static void rcar_i2c_init(struct rcar_i2c_priv *priv)
128{ 144{
129 /*
130 * reset slave mode.
131 * slave mode is not used on this driver
132 */
133 rcar_i2c_write(priv, ICSIER, 0);
134 rcar_i2c_write(priv, ICSAR, 0);
135 rcar_i2c_write(priv, ICSCR, 0);
136 rcar_i2c_write(priv, ICSSR, 0);
137
138 /* reset master mode */ 145 /* reset master mode */
139 rcar_i2c_write(priv, ICMIER, 0); 146 rcar_i2c_write(priv, ICMIER, 0);
140 rcar_i2c_write(priv, ICMCR, 0); 147 rcar_i2c_write(priv, ICMCR, 0);
@@ -360,6 +367,63 @@ static int rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
360 return 0; 367 return 0;
361} 368}
362 369
370static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv)
371{
372 u32 ssr_raw, ssr_filtered;
373 u8 value;
374
375 ssr_raw = rcar_i2c_read(priv, ICSSR) & 0xff;
376 ssr_filtered = ssr_raw & rcar_i2c_read(priv, ICSIER);
377
378 if (!ssr_filtered)
379 return false;
380
381 /* address detected */
382 if (ssr_filtered & SAR) {
383 /* read or write request */
384 if (ssr_raw & STM) {
385 i2c_slave_event(priv->slave, I2C_SLAVE_REQ_READ_START, &value);
386 rcar_i2c_write(priv, ICRXTX, value);
387 rcar_i2c_write(priv, ICSIER, SDE | SSR | SAR);
388 } else {
389 i2c_slave_event(priv->slave, I2C_SLAVE_REQ_WRITE_START, &value);
390 rcar_i2c_read(priv, ICRXTX); /* dummy read */
391 rcar_i2c_write(priv, ICSIER, SDR | SSR | SAR);
392 }
393
394 rcar_i2c_write(priv, ICSSR, ~SAR & 0xff);
395 }
396
397 /* master sent stop */
398 if (ssr_filtered & SSR) {
399 i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value);
400 rcar_i2c_write(priv, ICSIER, SAR | SSR);
401 rcar_i2c_write(priv, ICSSR, ~SSR & 0xff);
402 }
403
404 /* master wants to write to us */
405 if (ssr_filtered & SDR) {
406 int ret;
407
408 value = rcar_i2c_read(priv, ICRXTX);
409 ret = i2c_slave_event(priv->slave, I2C_SLAVE_REQ_WRITE_END, &value);
410 /* Send NACK in case of error */
411 rcar_i2c_write(priv, ICSCR, SIE | SDBS | (ret < 0 ? FNA : 0));
412 i2c_slave_event(priv->slave, I2C_SLAVE_REQ_WRITE_START, &value);
413 rcar_i2c_write(priv, ICSSR, ~SDR & 0xff);
414 }
415
416 /* master wants to read from us */
417 if (ssr_filtered & SDE) {
418 i2c_slave_event(priv->slave, I2C_SLAVE_REQ_READ_END, &value);
419 i2c_slave_event(priv->slave, I2C_SLAVE_REQ_READ_START, &value);
420 rcar_i2c_write(priv, ICRXTX, value);
421 rcar_i2c_write(priv, ICSSR, ~SDE & 0xff);
422 }
423
424 return true;
425}
426
363static irqreturn_t rcar_i2c_irq(int irq, void *ptr) 427static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
364{ 428{
365 struct rcar_i2c_priv *priv = ptr; 429 struct rcar_i2c_priv *priv = ptr;
@@ -369,6 +433,9 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
369 /*-------------- spin lock -----------------*/ 433 /*-------------- spin lock -----------------*/
370 spin_lock(&priv->lock); 434 spin_lock(&priv->lock);
371 435
436 if (rcar_i2c_slave_irq(priv))
437 goto exit;
438
372 msr = rcar_i2c_read(priv, ICMSR); 439 msr = rcar_i2c_read(priv, ICMSR);
373 440
374 /* Only handle interrupts that are currently enabled */ 441 /* Only handle interrupts that are currently enabled */
@@ -499,6 +566,43 @@ out:
499 return ret; 566 return ret;
500} 567}
501 568
569static int rcar_reg_slave(struct i2c_client *slave)
570{
571 struct rcar_i2c_priv *priv = i2c_get_adapdata(slave->adapter);
572
573 if (priv->slave)
574 return -EBUSY;
575
576 if (slave->flags & I2C_CLIENT_TEN)
577 return -EAFNOSUPPORT;
578
579 pm_runtime_forbid(rcar_i2c_priv_to_dev(priv));
580
581 priv->slave = slave;
582 rcar_i2c_write(priv, ICSAR, slave->addr);
583 rcar_i2c_write(priv, ICSSR, 0);
584 rcar_i2c_write(priv, ICSIER, SAR | SSR);
585 rcar_i2c_write(priv, ICSCR, SIE | SDBS);
586
587 return 0;
588}
589
590static int rcar_unreg_slave(struct i2c_client *slave)
591{
592 struct rcar_i2c_priv *priv = i2c_get_adapdata(slave->adapter);
593
594 WARN_ON(!priv->slave);
595
596 rcar_i2c_write(priv, ICSIER, 0);
597 rcar_i2c_write(priv, ICSCR, 0);
598
599 priv->slave = NULL;
600
601 pm_runtime_allow(rcar_i2c_priv_to_dev(priv));
602
603 return 0;
604}
605
502static u32 rcar_i2c_func(struct i2c_adapter *adap) 606static u32 rcar_i2c_func(struct i2c_adapter *adap)
503{ 607{
504 /* This HW can't do SMBUS_QUICK and NOSTART */ 608 /* This HW can't do SMBUS_QUICK and NOSTART */
@@ -508,6 +612,8 @@ static u32 rcar_i2c_func(struct i2c_adapter *adap)
508static const struct i2c_algorithm rcar_i2c_algo = { 612static const struct i2c_algorithm rcar_i2c_algo = {
509 .master_xfer = rcar_i2c_master_xfer, 613 .master_xfer = rcar_i2c_master_xfer,
510 .functionality = rcar_i2c_func, 614 .functionality = rcar_i2c_func,
615 .reg_slave = rcar_reg_slave,
616 .unreg_slave = rcar_unreg_slave,
511}; 617};
512 618
513static const struct of_device_id rcar_i2c_dt_ids[] = { 619static const struct of_device_id rcar_i2c_dt_ids[] = {