1 |
Here is an answer from Ben, I still have to test it myself. |
2 |
|
3 |
|
4 |
|
5 |
Benjamin Herrenschmidt wrote: |
6 |
> On Tue, 2006-05-30 at 21:09 +0100, Konstantin V. Gavrilenko wrote: |
7 |
> SNIP < |
8 |
|
9 |
|
10 |
> Does this help ? |
11 |
> |
12 |
> Ben. |
13 |
> |
14 |
> ------ |
15 |
> From: Linux Kernel Mailing List <linux-kernel@×××××××××××.org> |
16 |
> To: git-commits-head@×××××××××××.org |
17 |
> Subject: [PATCH] powermac: Fix i2c on keywest based chips |
18 |
> Date: Sun, 23 Apr 2006 17:11:14 GMT |
19 |
> |
20 |
> commit 60162e498e220d1f03bbee5bac0a9ddd6de60ae7 |
21 |
> tree 8cbcbea6060eb2b9f7d39784385efdfc6e947b52 |
22 |
> parent 28897731318dc8f63f683eed9091e446916ad706 |
23 |
> author Benjamin Herrenschmidt <benh@×××××××××××××××.org> Tue, 18 Apr |
24 |
2006 14:11:53 +1000 |
25 |
> committer Paul Mackerras <paulus@×××××.org> Fri, 21 Apr 2006 22:29:46 |
26 |
+1000 |
27 |
> |
28 |
> [PATCH] powermac: Fix i2c on keywest based chips |
29 |
> |
30 |
> The new i2c implementation for PowerMac has a regression that causes the |
31 |
> hardware to go out of state when probing non-existent devices. While |
32 |
> fixing that, I also found & fixed a couple of other corner cases. This |
33 |
> fixes booting with a pbbuttons version that scans the i2c bus for an LMU |
34 |
> controller among others. Tested on a dual G5 with thermal control (which |
35 |
> has heavy i2c activity) with no problem so far. |
36 |
> |
37 |
> Signed-off-by: Benjamin Herrenschmidt <benh@×××××××××××××××.org> |
38 |
> Signed-off-by: Paul Mackerras <paulus@×××××.org> |
39 |
> |
40 |
> arch/powerpc/platforms/powermac/low_i2c.c | 78 |
41 |
+++++++++++++----------------- |
42 |
> 1 files changed, 35 insertions(+), 43 deletions(-) |
43 |
> |
44 |
> diff --git a/arch/powerpc/platforms/powermac/low_i2c.c |
45 |
b/arch/powerpc/platforms/powermac/low_i2c.c |
46 |
> index e14f9ac..df2343e 100644 |
47 |
> --- a/arch/powerpc/platforms/powermac/low_i2c.c |
48 |
> +++ b/arch/powerpc/platforms/powermac/low_i2c.c |
49 |
> @@ -231,6 +231,14 @@ static u8 kw_i2c_wait_interrupt(struct p |
50 |
> return isr; |
51 |
> } |
52 |
> |
53 |
> +static void kw_i2c_do_stop(struct pmac_i2c_host_kw *host, int result) |
54 |
> +{ |
55 |
> + kw_write_reg(reg_control, KW_I2C_CTL_STOP); |
56 |
> + host->state = state_stop; |
57 |
> + host->result = result; |
58 |
> +} |
59 |
> + |
60 |
> + |
61 |
> static void kw_i2c_handle_interrupt(struct pmac_i2c_host_kw *host, u8 |
62 |
isr) |
63 |
> { |
64 |
> u8 ack; |
65 |
> @@ -246,42 +254,36 @@ static void kw_i2c_handle_interrupt(stru |
66 |
> } |
67 |
> |
68 |
> if (isr == 0) { |
69 |
> + printk(KERN_WARNING "low_i2c: Timeout in i2c transfer" |
70 |
> + " on keywest !\n"); |
71 |
> if (host->state != state_stop) { |
72 |
> - DBG_LOW("KW: Timeout !\n"); |
73 |
> - host->result = -EIO; |
74 |
> - goto stop; |
75 |
> - } |
76 |
> - if (host->state == state_stop) { |
77 |
> - ack = kw_read_reg(reg_status); |
78 |
> - if (ack & KW_I2C_STAT_BUSY) |
79 |
> - kw_write_reg(reg_status, 0); |
80 |
> - host->state = state_idle; |
81 |
> - kw_write_reg(reg_ier, 0x00); |
82 |
> - if (!host->polled) |
83 |
> - complete(&host->complete); |
84 |
> + kw_i2c_do_stop(host, -EIO); |
85 |
> + return; |
86 |
> } |
87 |
> + ack = kw_read_reg(reg_status); |
88 |
> + if (ack & KW_I2C_STAT_BUSY) |
89 |
> + kw_write_reg(reg_status, 0); |
90 |
> + host->state = state_idle; |
91 |
> + kw_write_reg(reg_ier, 0x00); |
92 |
> + if (!host->polled) |
93 |
> + complete(&host->complete); |
94 |
> return; |
95 |
> } |
96 |
> |
97 |
> if (isr & KW_I2C_IRQ_ADDR) { |
98 |
> ack = kw_read_reg(reg_status); |
99 |
> if (host->state != state_addr) { |
100 |
> - kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); |
101 |
> WRONG_STATE("KW_I2C_IRQ_ADDR"); |
102 |
> - host->result = -EIO; |
103 |
> - goto stop; |
104 |
> + kw_i2c_do_stop(host, -EIO); |
105 |
> } |
106 |
> if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { |
107 |
> - host->result = -ENODEV; |
108 |
> - DBG_LOW("KW: NAK on address\n"); |
109 |
> + host->result = -ENXIO; |
110 |
> host->state = state_stop; |
111 |
> - return; |
112 |
> + DBG_LOW("KW: NAK on address\n"); |
113 |
> } else { |
114 |
> - if (host->len == 0) { |
115 |
> - kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); |
116 |
> - goto stop; |
117 |
> - } |
118 |
> - if (host->rw) { |
119 |
> + if (host->len == 0) |
120 |
> + kw_i2c_do_stop(host, 0); |
121 |
> + else if (host->rw) { |
122 |
> host->state = state_read; |
123 |
> if (host->len > 1) |
124 |
> kw_write_reg(reg_control, |
125 |
> @@ -308,25 +310,19 @@ static void kw_i2c_handle_interrupt(stru |
126 |
> ack = kw_read_reg(reg_status); |
127 |
> if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { |
128 |
> DBG_LOW("KW: nack on data write\n"); |
129 |
> - host->result = -EIO; |
130 |
> - goto stop; |
131 |
> + host->result = -EFBIG; |
132 |
> + host->state = state_stop; |
133 |
> } else if (host->len) { |
134 |
> kw_write_reg(reg_data, *(host->data++)); |
135 |
> host->len--; |
136 |
> - } else { |
137 |
> - kw_write_reg(reg_control, KW_I2C_CTL_STOP); |
138 |
> - host->state = state_stop; |
139 |
> - host->result = 0; |
140 |
> - } |
141 |
> - kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); |
142 |
> + } else |
143 |
> + kw_i2c_do_stop(host, 0); |
144 |
> } else { |
145 |
> - kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); |
146 |
> WRONG_STATE("KW_I2C_IRQ_DATA"); |
147 |
> - if (host->state != state_stop) { |
148 |
> - host->result = -EIO; |
149 |
> - goto stop; |
150 |
> - } |
151 |
> + if (host->state != state_stop) |
152 |
> + kw_i2c_do_stop(host, -EIO); |
153 |
> } |
154 |
> + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); |
155 |
> } |
156 |
> |
157 |
> if (isr & KW_I2C_IRQ_STOP) { |
158 |
> @@ -340,14 +336,10 @@ static void kw_i2c_handle_interrupt(stru |
159 |
> complete(&host->complete); |
160 |
> } |
161 |
> |
162 |
> + /* Below should only happen in manual mode which we don't use ... */ |
163 |
> if (isr & KW_I2C_IRQ_START) |
164 |
> kw_write_reg(reg_isr, KW_I2C_IRQ_START); |
165 |
> |
166 |
> - return; |
167 |
> - stop: |
168 |
> - kw_write_reg(reg_control, KW_I2C_CTL_STOP); |
169 |
> - host->state = state_stop; |
170 |
> - return; |
171 |
> } |
172 |
> |
173 |
> /* Interrupt handler */ |
174 |
> @@ -544,11 +536,11 @@ static struct pmac_i2c_host_kw *__init k |
175 |
> return NULL; |
176 |
> } |
177 |
> |
178 |
> - /* Make sure IRA is disabled */ |
179 |
> + /* Make sure IRQ is disabled */ |
180 |
> kw_write_reg(reg_ier, 0); |
181 |
> |
182 |
> /* Request chip interrupt */ |
183 |
> - if (request_irq(host->irq, kw_i2c_irq, SA_SHIRQ, "keywest i2c", host)) |
184 |
> + if (request_irq(host->irq, kw_i2c_irq, 0, "keywest i2c", host)) |
185 |
> host->irq = NO_IRQ; |
186 |
> |
187 |
> printk(KERN_INFO "KeyWest i2c @0x%08x irq %d %s\n", |
188 |
> - |
189 |
> To unsubscribe from this list: send the line "unsubscribe |
190 |
git-commits-head" in |
191 |
> the body of a message to majordomo@×××××××××××.org |
192 |
> More majordomo info at http://vger.kernel.org/majordomo-info.html |
193 |
> |
194 |
|
195 |
|
196 |
|
197 |
|
198 |
-- |
199 |
Respectfully, |
200 |
Konstantin V. Gavrilenko |
201 |
|
202 |
Managing Director |
203 |
Arhont Ltd - Information Security |
204 |
|
205 |
web: http://www.arhont.com |
206 |
http://www.wi-foo.com |
207 |
e-mail: k.gavrilenko@××××××.com |
208 |
|
209 |
tel: +44 (0) 870 44 31337 |
210 |
fax: +44 (0) 117 969 0141 |
211 |
|
212 |
PGP: Key ID - 0xE81824F4 |
213 |
PGP: Server - keyserver.pgp.com |
214 |
-- |
215 |
gentoo-ppc-user@g.o mailing list |