diff options
-rw-r--r-- | drivers/i2c/busses/i2c-pxa.c | 64 | ||||
-rw-r--r-- | include/linux/i2c/pxa-i2c.h | 3 |
2 files changed, 66 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index fbafed29fb81..a61d9062bf7b 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -110,6 +110,8 @@ MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); | |||
110 | #define ICR_SADIE (1 << 13) /* slave address detected int enable */ | 110 | #define ICR_SADIE (1 << 13) /* slave address detected int enable */ |
111 | #define ICR_UR (1 << 14) /* unit reset */ | 111 | #define ICR_UR (1 << 14) /* unit reset */ |
112 | #define ICR_FM (1 << 15) /* fast mode */ | 112 | #define ICR_FM (1 << 15) /* fast mode */ |
113 | #define ICR_HS (1 << 16) /* High Speed mode */ | ||
114 | #define ICR_GPIOEN (1 << 19) /* enable GPIO mode for SCL in HS */ | ||
113 | 115 | ||
114 | #define ISR_RWM (1 << 0) /* read/write mode */ | 116 | #define ISR_RWM (1 << 0) /* read/write mode */ |
115 | #define ISR_ACKNAK (1 << 1) /* ack/nak status */ | 117 | #define ISR_ACKNAK (1 << 1) /* ack/nak status */ |
@@ -155,6 +157,10 @@ struct pxa_i2c { | |||
155 | int irq; | 157 | int irq; |
156 | unsigned int use_pio :1; | 158 | unsigned int use_pio :1; |
157 | unsigned int fast_mode :1; | 159 | unsigned int fast_mode :1; |
160 | unsigned int high_mode:1; | ||
161 | unsigned char master_code; | ||
162 | unsigned long rate; | ||
163 | bool highmode_enter; | ||
158 | }; | 164 | }; |
159 | 165 | ||
160 | #define _IBMR(i2c) ((i2c)->reg_ibmr) | 166 | #define _IBMR(i2c) ((i2c)->reg_ibmr) |
@@ -459,6 +465,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c) | |||
459 | 465 | ||
460 | /* set control register values */ | 466 | /* set control register values */ |
461 | writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c)); | 467 | writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c)); |
468 | writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c)); | ||
462 | 469 | ||
463 | #ifdef CONFIG_I2C_PXA_SLAVE | 470 | #ifdef CONFIG_I2C_PXA_SLAVE |
464 | dev_info(&i2c->adap.dev, "Enabling slave mode\n"); | 471 | dev_info(&i2c->adap.dev, "Enabling slave mode\n"); |
@@ -680,6 +687,34 @@ static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c) | |||
680 | return 0; | 687 | return 0; |
681 | } | 688 | } |
682 | 689 | ||
690 | /* | ||
691 | * PXA I2C send master code | ||
692 | * 1. Load master code to IDBR and send it. | ||
693 | * Note for HS mode, set ICR [GPIOEN]. | ||
694 | * 2. Wait until win arbitration. | ||
695 | */ | ||
696 | static int i2c_pxa_send_mastercode(struct pxa_i2c *i2c) | ||
697 | { | ||
698 | u32 icr; | ||
699 | long timeout; | ||
700 | |||
701 | spin_lock_irq(&i2c->lock); | ||
702 | i2c->highmode_enter = true; | ||
703 | writel(i2c->master_code, _IDBR(i2c)); | ||
704 | |||
705 | icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE); | ||
706 | icr |= ICR_GPIOEN | ICR_START | ICR_TB | ICR_ITEIE; | ||
707 | writel(icr, _ICR(i2c)); | ||
708 | |||
709 | spin_unlock_irq(&i2c->lock); | ||
710 | timeout = wait_event_timeout(i2c->wait, | ||
711 | i2c->highmode_enter == false, HZ * 1); | ||
712 | |||
713 | i2c->highmode_enter = false; | ||
714 | |||
715 | return (timeout == 0) ? I2C_RETRY : 0; | ||
716 | } | ||
717 | |||
683 | static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, | 718 | static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, |
684 | struct i2c_msg *msg, int num) | 719 | struct i2c_msg *msg, int num) |
685 | { | 720 | { |
@@ -743,6 +778,14 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) | |||
743 | goto out; | 778 | goto out; |
744 | } | 779 | } |
745 | 780 | ||
781 | if (i2c->high_mode) { | ||
782 | ret = i2c_pxa_send_mastercode(i2c); | ||
783 | if (ret) { | ||
784 | dev_err(&i2c->adap.dev, "i2c_pxa_send_mastercode timeout\n"); | ||
785 | goto out; | ||
786 | } | ||
787 | } | ||
788 | |||
746 | spin_lock_irq(&i2c->lock); | 789 | spin_lock_irq(&i2c->lock); |
747 | 790 | ||
748 | i2c->msg = msg; | 791 | i2c->msg = msg; |
@@ -990,11 +1033,14 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id) | |||
990 | i2c_pxa_slave_txempty(i2c, isr); | 1033 | i2c_pxa_slave_txempty(i2c, isr); |
991 | if (isr & ISR_IRF) | 1034 | if (isr & ISR_IRF) |
992 | i2c_pxa_slave_rxfull(i2c, isr); | 1035 | i2c_pxa_slave_rxfull(i2c, isr); |
993 | } else if (i2c->msg) { | 1036 | } else if (i2c->msg && (!i2c->highmode_enter)) { |
994 | if (isr & ISR_ITE) | 1037 | if (isr & ISR_ITE) |
995 | i2c_pxa_irq_txempty(i2c, isr); | 1038 | i2c_pxa_irq_txempty(i2c, isr); |
996 | if (isr & ISR_IRF) | 1039 | if (isr & ISR_IRF) |
997 | i2c_pxa_irq_rxfull(i2c, isr); | 1040 | i2c_pxa_irq_rxfull(i2c, isr); |
1041 | } else if ((isr & ISR_ITE) && i2c->highmode_enter) { | ||
1042 | i2c->highmode_enter = false; | ||
1043 | wake_up(&i2c->wait); | ||
998 | } else { | 1044 | } else { |
999 | i2c_pxa_scream_blue_murder(i2c, "spurious irq"); | 1045 | i2c_pxa_scream_blue_murder(i2c, "spurious irq"); |
1000 | } | 1046 | } |
@@ -1079,6 +1125,11 @@ static int i2c_pxa_probe_pdata(struct platform_device *pdev, | |||
1079 | if (plat) { | 1125 | if (plat) { |
1080 | i2c->use_pio = plat->use_pio; | 1126 | i2c->use_pio = plat->use_pio; |
1081 | i2c->fast_mode = plat->fast_mode; | 1127 | i2c->fast_mode = plat->fast_mode; |
1128 | i2c->high_mode = plat->high_mode; | ||
1129 | i2c->master_code = plat->master_code; | ||
1130 | if (!i2c->master_code) | ||
1131 | i2c->master_code = 0xe; | ||
1132 | i2c->rate = plat->rate; | ||
1082 | } | 1133 | } |
1083 | return 0; | 1134 | return 0; |
1084 | } | 1135 | } |
@@ -1151,6 +1202,7 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
1151 | i2c->irq = irq; | 1202 | i2c->irq = irq; |
1152 | 1203 | ||
1153 | i2c->slave_addr = I2C_PXA_SLAVE_ADDR; | 1204 | i2c->slave_addr = I2C_PXA_SLAVE_ADDR; |
1205 | i2c->highmode_enter = false; | ||
1154 | 1206 | ||
1155 | if (plat) { | 1207 | if (plat) { |
1156 | #ifdef CONFIG_I2C_PXA_SLAVE | 1208 | #ifdef CONFIG_I2C_PXA_SLAVE |
@@ -1160,6 +1212,16 @@ static int i2c_pxa_probe(struct platform_device *dev) | |||
1160 | i2c->adap.class = plat->class; | 1212 | i2c->adap.class = plat->class; |
1161 | } | 1213 | } |
1162 | 1214 | ||
1215 | if (i2c->high_mode) { | ||
1216 | if (i2c->rate) { | ||
1217 | clk_set_rate(i2c->clk, i2c->rate); | ||
1218 | pr_info("i2c: <%s> set rate to %ld\n", | ||
1219 | i2c->adap.name, clk_get_rate(i2c->clk)); | ||
1220 | } else | ||
1221 | pr_warn("i2c: <%s> clock rate not set\n", | ||
1222 | i2c->adap.name); | ||
1223 | } | ||
1224 | |||
1163 | clk_prepare_enable(i2c->clk); | 1225 | clk_prepare_enable(i2c->clk); |
1164 | 1226 | ||
1165 | if (i2c->use_pio) { | 1227 | if (i2c->use_pio) { |
diff --git a/include/linux/i2c/pxa-i2c.h b/include/linux/i2c/pxa-i2c.h index 1a9f65e6ec0f..53aab243cbd8 100644 --- a/include/linux/i2c/pxa-i2c.h +++ b/include/linux/i2c/pxa-i2c.h | |||
@@ -67,6 +67,9 @@ struct i2c_pxa_platform_data { | |||
67 | unsigned int class; | 67 | unsigned int class; |
68 | unsigned int use_pio :1; | 68 | unsigned int use_pio :1; |
69 | unsigned int fast_mode :1; | 69 | unsigned int fast_mode :1; |
70 | unsigned int high_mode:1; | ||
71 | unsigned char master_code; | ||
72 | unsigned long rate; | ||
70 | }; | 73 | }; |
71 | 74 | ||
72 | extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info); | 75 | extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info); |