diff options
| author | Leilei Shang <shangll@marvell.com> | 2013-06-07 02:38:17 -0400 |
|---|---|---|
| committer | Wolfram Sang <wsa@the-dreams.de> | 2013-08-07 10:58:07 -0400 |
| commit | 9d3dda5c0d092d6bc9911bf24de81350d47c6be6 (patch) | |
| tree | 529b7d061971e6954807f74410b81e9fd5c85016 | |
| parent | f480adaf1b7130ad43760f627b762f771fcfc5f5 (diff) | |
i2c: pxa: enable high speed mode for i2c bus
To enter high speed mode, following steps should be done:
1. When running in high speed mode, i2c clock rate is different
from standard mode. Clock rate must be set according to
specification first.
2. When i2c controller sends a master code and wins arbitration,
high speed mode is entered.
If you want to enable high speed mode, the following members of
platform data should be set to proper value:
1. "high_mode" should be set to "1".
2. "master_code" should be set to "8'b 0000_1xxx"(x is 0 or 1).
If no master_code is set, set to default value 0xe.
3. "rate" should be set according to specification.
Signed-off-by: Leilei Shang <shangll@marvell.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
| -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); |
