hc
2024-10-12 a5969cabbb4660eab42b6ef0412cbbd1200cf14d
kernel/drivers/i2c/busses/i2c-jz4780.c
....@@ -1,18 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Ingenic JZ4780 I2C bus driver
34 *
45 * Copyright (C) 2006 - 2009 Ingenic Semiconductor Inc.
56 * Copyright (C) 2015 Imagination Technologies
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
7
+ * Copyright (C) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
168 */
179
1810 #include <linux/bitops.h>
....@@ -26,6 +18,7 @@
2618 #include <linux/io.h>
2719 #include <linux/kernel.h>
2820 #include <linux/module.h>
21
+#include <linux/of_device.h>
2922 #include <linux/platform_device.h>
3023 #include <linux/sched.h>
3124 #include <linux/slab.h>
....@@ -64,6 +57,7 @@
6457 #define JZ4780_I2C_ACKGC 0x98
6558 #define JZ4780_I2C_ENSTA 0x9C
6659 #define JZ4780_I2C_SDAHD 0xD0
60
+#define X1000_I2C_SDAHD 0x7C
6761
6862 #define JZ4780_I2C_CTRL_STPHLD BIT(7)
6963 #define JZ4780_I2C_CTRL_SLVDIS BIT(6)
....@@ -81,6 +75,8 @@
8175 #define JZ4780_I2C_STA_TFE BIT(2)
8276 #define JZ4780_I2C_STA_TFNF BIT(1)
8377 #define JZ4780_I2C_STA_ACT BIT(0)
78
+
79
+#define X1000_I2C_DC_STOP BIT(9)
8480
8581 #define JZ4780_I2C_INTST_IGC BIT(11)
8682 #define JZ4780_I2C_INTST_ISTT BIT(10)
....@@ -120,18 +116,33 @@
120116 #define JZ4780_I2CFLCNT_ADJUST(n) (((n) - 1) < 8 ? 8 : ((n) - 1))
121117
122118 #define JZ4780_I2C_FIFO_LEN 16
123
-#define TX_LEVEL 3
124
-#define RX_LEVEL (JZ4780_I2C_FIFO_LEN - TX_LEVEL - 1)
119
+
120
+#define X1000_I2C_FIFO_LEN 64
125121
126122 #define JZ4780_I2C_TIMEOUT 300
127123
128124 #define BUFSIZE 200
125
+
126
+enum ingenic_i2c_version {
127
+ ID_JZ4780,
128
+ ID_X1000,
129
+};
130
+
131
+/* ingenic_i2c_config: SoC specific config data. */
132
+struct ingenic_i2c_config {
133
+ enum ingenic_i2c_version version;
134
+
135
+ int fifosize;
136
+ int tx_level;
137
+ int rx_level;
138
+};
129139
130140 struct jz4780_i2c {
131141 void __iomem *iomem;
132142 int irq;
133143 struct clk *clk;
134144 struct i2c_adapter adap;
145
+ const struct ingenic_i2c_config *cdata;
135146
136147 /* lock to protect rbuf and wbuf between xfer_rd/wr and irq handler */
137148 spinlock_t lock;
....@@ -330,11 +341,18 @@
330341
331342 if (hold_time >= 0) {
332343 /*i2c hold time enable */
333
- hold_time |= JZ4780_I2C_SDAHD_HDENB;
334
- jz4780_i2c_writew(i2c, JZ4780_I2C_SDAHD, hold_time);
344
+ if (i2c->cdata->version >= ID_X1000) {
345
+ jz4780_i2c_writew(i2c, X1000_I2C_SDAHD, hold_time);
346
+ } else {
347
+ hold_time |= JZ4780_I2C_SDAHD_HDENB;
348
+ jz4780_i2c_writew(i2c, JZ4780_I2C_SDAHD, hold_time);
349
+ }
335350 } else {
336351 /* disable hold time */
337
- jz4780_i2c_writew(i2c, JZ4780_I2C_SDAHD, 0);
352
+ if (i2c->cdata->version >= ID_X1000)
353
+ jz4780_i2c_writew(i2c, X1000_I2C_SDAHD, 0);
354
+ else
355
+ jz4780_i2c_writew(i2c, JZ4780_I2C_SDAHD, 0);
338356 }
339357
340358 return 0;
....@@ -349,9 +367,11 @@
349367 spin_lock_irqsave(&i2c->lock, flags);
350368
351369 /* can send stop now if need */
352
- tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
353
- tmp &= ~JZ4780_I2C_CTRL_STPHLD;
354
- jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
370
+ if (i2c->cdata->version < ID_X1000) {
371
+ tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
372
+ tmp &= ~JZ4780_I2C_CTRL_STPHLD;
373
+ jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
374
+ }
355375
356376 /* disable all interrupts first */
357377 jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, 0);
....@@ -389,11 +409,19 @@
389409 return jz4780_i2c_enable(i2c);
390410 }
391411
392
-static void jz4780_i2c_send_rcmd(struct jz4780_i2c *i2c, int cmd_count)
412
+static void jz4780_i2c_send_rcmd(struct jz4780_i2c *i2c,
413
+ int cmd_count,
414
+ int cmd_left)
393415 {
394416 int i;
395417
396
- for (i = 0; i < cmd_count; i++)
418
+ for (i = 0; i < cmd_count - 1; i++)
419
+ jz4780_i2c_writew(i2c, JZ4780_I2C_DC, JZ4780_I2C_DC_READ);
420
+
421
+ if ((cmd_left == 0) && (i2c->cdata->version >= ID_X1000))
422
+ jz4780_i2c_writew(i2c, JZ4780_I2C_DC,
423
+ JZ4780_I2C_DC_READ | X1000_I2C_DC_STOP);
424
+ else
397425 jz4780_i2c_writew(i2c, JZ4780_I2C_DC, JZ4780_I2C_DC_READ);
398426 }
399427
....@@ -448,37 +476,44 @@
448476
449477 rd_left = i2c->rd_total_len - i2c->rd_data_xfered;
450478
451
- if (rd_left <= JZ4780_I2C_FIFO_LEN)
479
+ if (rd_left <= i2c->cdata->fifosize)
452480 jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, rd_left - 1);
453481 }
454482
455483 if (intst & JZ4780_I2C_INTST_TXEMP) {
456484 if (i2c->is_write == 0) {
457485 int cmd_left = i2c->rd_total_len - i2c->rd_cmd_xfered;
458
- int max_send = (JZ4780_I2C_FIFO_LEN - 1)
486
+ int max_send = (i2c->cdata->fifosize - 1)
459487 - (i2c->rd_cmd_xfered
460488 - i2c->rd_data_xfered);
461489 int cmd_to_send = min(cmd_left, max_send);
462490
463491 if (i2c->rd_cmd_xfered != 0)
464492 cmd_to_send = min(cmd_to_send,
465
- JZ4780_I2C_FIFO_LEN
466
- - TX_LEVEL - 1);
493
+ i2c->cdata->fifosize
494
+ - i2c->cdata->tx_level - 1);
467495
468496 if (cmd_to_send) {
469
- jz4780_i2c_send_rcmd(i2c, cmd_to_send);
470497 i2c->rd_cmd_xfered += cmd_to_send;
498
+ cmd_left = i2c->rd_total_len -
499
+ i2c->rd_cmd_xfered;
500
+ jz4780_i2c_send_rcmd(i2c,
501
+ cmd_to_send, cmd_left);
502
+
471503 }
472504
473
- cmd_left = i2c->rd_total_len - i2c->rd_cmd_xfered;
474505 if (cmd_left == 0) {
475506 intmsk = jz4780_i2c_readw(i2c, JZ4780_I2C_INTM);
476507 intmsk &= ~JZ4780_I2C_INTM_MTXEMP;
477508 jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, intmsk);
478509
479
- tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
480
- tmp &= ~JZ4780_I2C_CTRL_STPHLD;
481
- jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
510
+ if (i2c->cdata->version < ID_X1000) {
511
+ tmp = jz4780_i2c_readw(i2c,
512
+ JZ4780_I2C_CTRL);
513
+ tmp &= ~JZ4780_I2C_CTRL_STPHLD;
514
+ jz4780_i2c_writew(i2c,
515
+ JZ4780_I2C_CTRL, tmp);
516
+ }
482517 }
483518 } else {
484519 unsigned short data;
....@@ -487,23 +522,26 @@
487522 i2c_sta = jz4780_i2c_readw(i2c, JZ4780_I2C_STA);
488523
489524 while ((i2c_sta & JZ4780_I2C_STA_TFNF) &&
490
- (i2c->wt_len > 0)) {
525
+ (i2c->wt_len > 0)) {
491526 i2c_sta = jz4780_i2c_readw(i2c, JZ4780_I2C_STA);
492527 data = *i2c->wbuf;
493528 data &= ~JZ4780_I2C_DC_READ;
494
- jz4780_i2c_writew(i2c, JZ4780_I2C_DC,
495
- data);
529
+ if ((i2c->wt_len == 1) && (!i2c->stop_hold) &&
530
+ (i2c->cdata->version >= ID_X1000))
531
+ data |= X1000_I2C_DC_STOP;
532
+ jz4780_i2c_writew(i2c, JZ4780_I2C_DC, data);
496533 i2c->wbuf++;
497534 i2c->wt_len--;
498535 }
499536
500537 if (i2c->wt_len == 0) {
501
- if (!i2c->stop_hold) {
538
+ if ((!i2c->stop_hold) && (i2c->cdata->version <
539
+ ID_X1000)) {
502540 tmp = jz4780_i2c_readw(i2c,
503
- JZ4780_I2C_CTRL);
541
+ JZ4780_I2C_CTRL);
504542 tmp &= ~JZ4780_I2C_CTRL_STPHLD;
505
- jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL,
506
- tmp);
543
+ jz4780_i2c_writew(i2c,
544
+ JZ4780_I2C_CTRL, tmp);
507545 }
508546
509547 jz4780_i2c_trans_done(i2c);
....@@ -544,20 +582,22 @@
544582 i2c->rd_data_xfered = 0;
545583 i2c->rd_cmd_xfered = 0;
546584
547
- if (len <= JZ4780_I2C_FIFO_LEN)
585
+ if (len <= i2c->cdata->fifosize)
548586 jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, len - 1);
549587 else
550
- jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, RX_LEVEL);
588
+ jz4780_i2c_writew(i2c, JZ4780_I2C_RXTL, i2c->cdata->rx_level);
551589
552
- jz4780_i2c_writew(i2c, JZ4780_I2C_TXTL, TX_LEVEL);
590
+ jz4780_i2c_writew(i2c, JZ4780_I2C_TXTL, i2c->cdata->tx_level);
553591
554592 jz4780_i2c_writew(i2c, JZ4780_I2C_INTM,
555593 JZ4780_I2C_INTM_MRXFL | JZ4780_I2C_INTM_MTXEMP
556594 | JZ4780_I2C_INTM_MTXABT | JZ4780_I2C_INTM_MRXOF);
557595
558
- tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
559
- tmp |= JZ4780_I2C_CTRL_STPHLD;
560
- jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
596
+ if (i2c->cdata->version < ID_X1000) {
597
+ tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
598
+ tmp |= JZ4780_I2C_CTRL_STPHLD;
599
+ jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
600
+ }
561601
562602 spin_unlock_irqrestore(&i2c->lock, flags);
563603
....@@ -603,14 +643,16 @@
603643 i2c->wbuf = buf;
604644 i2c->wt_len = len;
605645
606
- jz4780_i2c_writew(i2c, JZ4780_I2C_TXTL, TX_LEVEL);
646
+ jz4780_i2c_writew(i2c, JZ4780_I2C_TXTL, i2c->cdata->tx_level);
607647
608648 jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, JZ4780_I2C_INTM_MTXEMP
609649 | JZ4780_I2C_INTM_MTXABT);
610650
611
- tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
612
- tmp |= JZ4780_I2C_CTRL_STPHLD;
613
- jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
651
+ if (i2c->cdata->version < ID_X1000) {
652
+ tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
653
+ tmp |= JZ4780_I2C_CTRL_STPHLD;
654
+ jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
655
+ }
614656
615657 spin_unlock_irqrestore(&i2c->lock, flags);
616658
....@@ -693,8 +735,26 @@
693735 .functionality = jz4780_i2c_functionality,
694736 };
695737
738
+static const struct ingenic_i2c_config jz4780_i2c_config = {
739
+ .version = ID_JZ4780,
740
+
741
+ .fifosize = JZ4780_I2C_FIFO_LEN,
742
+ .tx_level = JZ4780_I2C_FIFO_LEN / 2,
743
+ .rx_level = JZ4780_I2C_FIFO_LEN / 2 - 1,
744
+};
745
+
746
+static const struct ingenic_i2c_config x1000_i2c_config = {
747
+ .version = ID_X1000,
748
+
749
+ .fifosize = X1000_I2C_FIFO_LEN,
750
+ .tx_level = X1000_I2C_FIFO_LEN / 2,
751
+ .rx_level = X1000_I2C_FIFO_LEN / 2 - 1,
752
+};
753
+
696754 static const struct of_device_id jz4780_i2c_of_matches[] = {
697
- { .compatible = "ingenic,jz4780-i2c", },
755
+ { .compatible = "ingenic,jz4770-i2c", .data = &jz4780_i2c_config },
756
+ { .compatible = "ingenic,jz4780-i2c", .data = &jz4780_i2c_config },
757
+ { .compatible = "ingenic,x1000-i2c", .data = &x1000_i2c_config },
698758 { /* sentinel */ }
699759 };
700760 MODULE_DEVICE_TABLE(of, jz4780_i2c_of_matches);
....@@ -704,12 +764,17 @@
704764 int ret = 0;
705765 unsigned int clk_freq = 0;
706766 unsigned short tmp;
707
- struct resource *r;
708767 struct jz4780_i2c *i2c;
709768
710769 i2c = devm_kzalloc(&pdev->dev, sizeof(struct jz4780_i2c), GFP_KERNEL);
711770 if (!i2c)
712771 return -ENOMEM;
772
+
773
+ i2c->cdata = device_get_match_data(&pdev->dev);
774
+ if (!i2c->cdata) {
775
+ dev_err(&pdev->dev, "Error: No device match found\n");
776
+ return -ENODEV;
777
+ }
713778
714779 i2c->adap.owner = THIS_MODULE;
715780 i2c->adap.algo = &jz4780_i2c_algorithm;
....@@ -722,8 +787,7 @@
722787 init_completion(&i2c->trans_waitq);
723788 spin_lock_init(&i2c->lock);
724789
725
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
726
- i2c->iomem = devm_ioremap_resource(&pdev->dev, r);
790
+ i2c->iomem = devm_platform_ioremap_resource(pdev, 0);
727791 if (IS_ERR(i2c->iomem))
728792 return PTR_ERR(i2c->iomem);
729793
....@@ -754,9 +818,11 @@
754818
755819 dev_info(&pdev->dev, "Bus frequency is %d KHz\n", i2c->speed);
756820
757
- tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
758
- tmp &= ~JZ4780_I2C_CTRL_STPHLD;
759
- jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
821
+ if (i2c->cdata->version < ID_X1000) {
822
+ tmp = jz4780_i2c_readw(i2c, JZ4780_I2C_CTRL);
823
+ tmp &= ~JZ4780_I2C_CTRL_STPHLD;
824
+ jz4780_i2c_writew(i2c, JZ4780_I2C_CTRL, tmp);
825
+ }
760826
761827 jz4780_i2c_writew(i2c, JZ4780_I2C_INTM, 0x0);
762828
....@@ -794,7 +860,7 @@
794860 .remove = jz4780_i2c_remove,
795861 .driver = {
796862 .name = "jz4780-i2c",
797
- .of_match_table = of_match_ptr(jz4780_i2c_of_matches),
863
+ .of_match_table = jz4780_i2c_of_matches,
798864 },
799865 };
800866