diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-sh_mobile.c')
-rw-r--r-- | drivers/i2c/busses/i2c-sh_mobile.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c index d2fabd9dbf80..598c49acaeb5 100644 --- a/drivers/i2c/busses/i2c-sh_mobile.c +++ b/drivers/i2c/busses/i2c-sh_mobile.c | |||
@@ -119,8 +119,10 @@ struct sh_mobile_i2c_data { | |||
119 | struct i2c_adapter adap; | 119 | struct i2c_adapter adap; |
120 | 120 | ||
121 | struct clk *clk; | 121 | struct clk *clk; |
122 | u_int8_t icic; | ||
122 | u_int8_t iccl; | 123 | u_int8_t iccl; |
123 | u_int8_t icch; | 124 | u_int8_t icch; |
125 | u_int8_t flags; | ||
124 | 126 | ||
125 | spinlock_t lock; | 127 | spinlock_t lock; |
126 | wait_queue_head_t wait; | 128 | wait_queue_head_t wait; |
@@ -129,6 +131,8 @@ struct sh_mobile_i2c_data { | |||
129 | int sr; | 131 | int sr; |
130 | }; | 132 | }; |
131 | 133 | ||
134 | #define IIC_FLAG_HAS_ICIC67 (1 << 0) | ||
135 | |||
132 | #define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ | 136 | #define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ |
133 | 137 | ||
134 | /* Register offsets */ | 138 | /* Register offsets */ |
@@ -155,6 +159,8 @@ struct sh_mobile_i2c_data { | |||
155 | #define ICSR_WAIT 0x02 | 159 | #define ICSR_WAIT 0x02 |
156 | #define ICSR_DTE 0x01 | 160 | #define ICSR_DTE 0x01 |
157 | 161 | ||
162 | #define ICIC_ICCLB8 0x80 | ||
163 | #define ICIC_ICCHB8 0x40 | ||
158 | #define ICIC_ALE 0x08 | 164 | #define ICIC_ALE 0x08 |
159 | #define ICIC_TACKE 0x04 | 165 | #define ICIC_TACKE 0x04 |
160 | #define ICIC_WAITE 0x02 | 166 | #define ICIC_WAITE 0x02 |
@@ -162,6 +168,9 @@ struct sh_mobile_i2c_data { | |||
162 | 168 | ||
163 | static void iic_wr(struct sh_mobile_i2c_data *pd, int offs, unsigned char data) | 169 | static void iic_wr(struct sh_mobile_i2c_data *pd, int offs, unsigned char data) |
164 | { | 170 | { |
171 | if (offs == ICIC) | ||
172 | data |= pd->icic; | ||
173 | |||
165 | iowrite8(data, pd->reg + offs); | 174 | iowrite8(data, pd->reg + offs); |
166 | } | 175 | } |
167 | 176 | ||
@@ -203,6 +212,14 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) | |||
203 | else | 212 | else |
204 | pd->iccl = (u_int8_t)(num/denom); | 213 | pd->iccl = (u_int8_t)(num/denom); |
205 | 214 | ||
215 | /* one more bit of ICCL in ICIC */ | ||
216 | if (pd->flags & IIC_FLAG_HAS_ICIC67) { | ||
217 | if ((num/denom) > 0xff) | ||
218 | pd->icic |= ICIC_ICCLB8; | ||
219 | else | ||
220 | pd->icic &= ~ICIC_ICCLB8; | ||
221 | } | ||
222 | |||
206 | /* Calculate the value for icch. From the data sheet: | 223 | /* Calculate the value for icch. From the data sheet: |
207 | icch = (p clock / transfer rate) * (H / (L + H)) */ | 224 | icch = (p clock / transfer rate) * (H / (L + H)) */ |
208 | num = i2c_clk * 4; | 225 | num = i2c_clk * 4; |
@@ -212,6 +229,14 @@ static void activate_ch(struct sh_mobile_i2c_data *pd) | |||
212 | else | 229 | else |
213 | pd->icch = (u_int8_t)(num/denom); | 230 | pd->icch = (u_int8_t)(num/denom); |
214 | 231 | ||
232 | /* one more bit of ICCH in ICIC */ | ||
233 | if (pd->flags & IIC_FLAG_HAS_ICIC67) { | ||
234 | if ((num/denom) > 0xff) | ||
235 | pd->icic |= ICIC_ICCHB8; | ||
236 | else | ||
237 | pd->icic &= ~ICIC_ICCHB8; | ||
238 | } | ||
239 | |||
215 | /* Enable channel and configure rx ack */ | 240 | /* Enable channel and configure rx ack */ |
216 | iic_set_clr(pd, ICCR, ICCR_ICE, 0); | 241 | iic_set_clr(pd, ICCR, ICCR_ICE, 0); |
217 | 242 | ||
@@ -592,6 +617,12 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) | |||
592 | goto err_irq; | 617 | goto err_irq; |
593 | } | 618 | } |
594 | 619 | ||
620 | /* The IIC blocks on SH-Mobile ARM processors | ||
621 | * come with two new bits in ICIC. | ||
622 | */ | ||
623 | if (size > 0x17) | ||
624 | pd->flags |= IIC_FLAG_HAS_ICIC67; | ||
625 | |||
595 | /* Enable Runtime PM for this device. | 626 | /* Enable Runtime PM for this device. |
596 | * | 627 | * |
597 | * Also tell the Runtime PM core to ignore children | 628 | * Also tell the Runtime PM core to ignore children |