8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
Hi Jocke, I changed the force_reinit() to // Disable interrupts. i2c-i2c_i2cmr = 0; i2c-i2c_i2cer = 0xff; // Clear enable i2c-i2c_i2mod = ~1; // Reset internal state iip-iic_rstate = 0; iip-iic_tstate = 0; This seems to work and is less code than my old force_reinit(). On the other hand: This kind of CPM timeout will only occur on heavy I2C bus conflicts. They should not appear at all. The code will not be executed if a slave device does not answer! The original driver is from the year 2001 and nobody has mentioned problems of this kind before. Without detailed knowledge of the CPM internals I feel much safer using my old force_reinit(), which does a complete re-init. Cajus
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
Hi Jocke, I changed the force_reinit() to // Disable interrupts. i2c-i2c_i2cmr = 0; i2c-i2c_i2cer = 0xff; // Clear enable i2c-i2c_i2mod = ~1; // Reset internal state iip-iic_rstate = 0; iip-iic_tstate = 0; This seems to work and is less code than my old force_reinit(). On the other hand: This kind of CPM timeout will only occur on heavy I2C bus conflicts. They should not appear at all. The code will not be executed if a slave device does not answer! The original driver is from the year 2001 and nobody has mentioned problems of this kind before. Without detailed knowledge of the CPM internals I feel much safer using my old force_reinit(), which does a complete re-init. Good, however I think we should try to it simple, the code that is, and avoid unneded bloat. I would like to see the shorter version in the kernel. Jocke
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
My description seems to be a little misleading. WITHOUT the force_reinit() my SPI driver reports transmission errors if the I2C bus has longer disturbances. WITH the force_reinit() my SPI driver works fine. This sounds like the I2C allocates a new buffer for every timed-out transmision. If all I2C buffers are full, the SPI buffers get overwritten !? I did not really trace back the problem, this is only my suspicion. Because the force_reinit() resets all the buffer pointer to their init values the problem with the SPI does not occur. Cajus I think the problem is that the CPM is still waiting on the SCL long after the timeout has happen. A complete reinit will reset the I2C part of the CPM. I think you should be able to get away with less, maybe it will enough to disable I2C (i2c-i2c_i2mod = ~1) and/or clear internal state (iip-iic_rstate = 0; iip-iic_tstate = 0;) after a timeout? Jocke
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
Hello, Tjernlund In message 2005-08-12 01:50:45 tjernlund at tjernlund.se you wrote: Try changing all i2c-i2c_i2com |= 0x80; /* Begin transmission */ to i2c-i2c_i2com |= 0x80 | 0x01; /* Begin transmission */ That should remove the need to do force_reinit(cpm) I hope. See http://ozlabs.org/pipermail/linuxppc-embedded/2005-August/019600.html for a litte more info. Also, I think you should remove the busy wait code. Its not needed IMHO. update i2c_algo_8xx.c as same = = = = = = = = = = = = = = = = = = = = Debora Liu deboralh at fel.com.cn 2005-08-12
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
Hello Tjernlund, Hello Debora Try changing all i2c-i2c_i2com |= 0x80; /* Begin transmission */ to i2c-i2c_i2com |= 0x80 | 0x01; /* Begin transmission */ That should remove the need to do force_reinit(cpm) I hope. This is NOT working in every case! It will work, on short bus-disturbances on the SCL line. I suggest adding the | 0x01 even this will not help on every transmission problem. If you have longer disturbances on SCL or SDA, something in the CPM will prevent the I2C bus to continue working after the disturbances are gone. Perhaps there is a problem with the buffer allocation. I changed the i2c-algo-8xx.c to work with your patch and without the force_reinit() code. Then I set the SCL line to ground to simulate a longer bus disturbance. After some timeouts my SPI bus, yes the SPI bus, reportet transmission errors. Both bus-interfaces use the CPM. It looks like the SPI buffer gets garbaged by the I2C interface. With the force_reinit() this problem did not occur. Cajus
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
In message OF29EF0D8D.F0A40A5C-ONC125705B.0028FA70-C125705B.002AF212 at de.abb.com you wrote: Then I set the SCL line to ground to simulate a longer bus disturbance. After some timeouts my SPI bus, yes the SPI bus, reportet transmission errors. Both bus-interfaces use the CPM. It looks like the SPI buffer gets garbaged by the I2C interface. This is normal. We see similar problems even with perfectly legal operations on the CPM. The SPI is running at lowest priority on the CPM, and anything that causes higher CPM load will starve SPI. Obviously your operation causes the CPM to go into some strange state. Best regards, Wolfgang Denk -- Software Engineering: Embedded and Realtime Systems, Embedded Linux Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de There are certain things men must do to remain men. -- Kirk, The Ultimate Computer, stardate 4929.4
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
Marcello, my old version is from the linuxppc_2_4_devel CVS archive on www.denx.de:/cvsroot. The i2c-algo-8xx.c there has the revision number 1.5. Regards Cajus --- ../../i2c-algo-8xx.c2005-08-10 16:19:09.0 +0200 +++ drivers/i2c/i2c-algo-8xx.c 2005-08-10 08:03:46.0 +0200 @@ -19,12 +19,19 @@ * moved into proper i2c interface; separated out platform specific * parts into i2c-rpx.c * Brad Parker (brad at heeltoe.com) + * + * added define for BUSY_WAIT and INTERRUPTIBLE_SLEEP, added I2C_ALGO_8XX_DATE + ..VERSION + * fixed bug in cpm_iic_read and cpm_iic_write (timeout never detected if count 16) + * added force_reinit(): in certain cases (disturbances on the I2C bus) a timeout will + * occur. After this a complete re-initialisation will be necessary, otherwise all + * following transmissions will have a timeout. + * Cajus Hahn, 09.08.2005 */ // XXX todo // timeout sleep? -/* $Id: i2c-algo-8xx.c,v 1.7 2002/08/03 22:48:18 ac9410 Exp $ */ +/* $Id: i2c-algo-8xx.c,v 1.2 2005/08/10 06:03:46 cajus Exp $ */ #include linux/kernel.h #include linux/module.h @@ -43,8 +50,16 @@ #include linux/i2c.h #include linux/i2c-algo-8xx.h +#define I2C_ALGO_8XX_DATE 20050809 +#define I2C_ALGO_8XX_VERSION 2.6.2 + #define CPM_MAX_READ 513 /* #define I2C_CHIP_ERRATA */ /* Try uncomment this if you have an older CPU(earlier than rev D4) */ +#define I2C_BUSY_WAIT /* Uncomment this if you want to do a busy wait in cpm_iic_read and + cpm_iic_write. In a timeout case the CPU load will be 99.9% ! */ +#define I2C_INTERRUPTIBLE_SLEEP /* Uncomment this if you want the waiting in cpm_iic_read and + cpm_iic_write being interruptable by signals */ + static wait_queue_head_t iic_wait; static ushort r_tbase, r_rbase; @@ -73,7 +88,11 @@ /* Get 'me going again. */ +#ifdef I2C_INTERRUPTIBLE_SLEEP wake_up_interruptible(iic_wait); +#else + wake_up(iic_wait); +#endif } static void @@ -201,20 +220,77 @@ static void force_close(struct i2c_algo_8xx_data *cpm) { volatile i2c8xx_t *i2c = cpm-i2c; + +if (cpm_debug) +printk(KERN_DEBUG force_close()); + if (cpm-reloc == 0) { /* micro code disabled */ volatile cpm8xx_t *cp = cpm-cp; - - if (cpm_debug) printk(KERN_DEBUG force_close()\n); cp-cp_cpcr = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_CLOSE_RXBD) | CPM_CR_FLG; while (cp-cp_cpcr CPM_CR_FLG); } + i2c-i2c_i2cmr = 0x00; /* Disable all interrupts */ i2c-i2c_i2cer = 0xff; } +static void force_reinit(struct i2c_algo_8xx_data *cpm) +{ + volatile iic_t *iip = cpm-iip; + volatile i2c8xx_t *i2c = cpm-i2c; + volatile cpm8xx_t *cp = cpm-cp; + unsigned char brg; + bd_t *bd = (bd_t *)__res; + + // Disable interrupts. + i2c-i2c_i2cmr = 0; + i2c-i2c_i2cer = 0xff; +// Clear enable + i2c-i2c_i2mod = ~1; + + // Initialize the parameter ram. + iip-iic_rstate = 0; + iip-iic_rdp = 0; + iip-iic_rbptr = 0; + iip-iic_rbc = 0; + iip-iic_rxtmp = 0; + iip-iic_tstate = 0; + iip-iic_tdp = 0; + iip-iic_tbptr = 0; + iip-iic_tbc = 0; + iip-iic_txtmp = 0; +iip-iic_tbase = r_tbase; + iip-iic_rbase = r_rbase; + iip-iic_tfcr = SMC_EB; + iip-iic_rfcr = SMC_EB; + iip-iic_mrblr = CPM_MAX_READ; + + if (cpm-reloc == 0) +{ + cp-cp_cpcr = mk_cr_cmd(CPM_CR_CH_I2C, CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp-cp_cpcr CPM_CR_FLG); + } +else +{ + iip-iic_rbptr = iip-iic_rbase; + iip-iic_tbptr = iip-iic_tbase; + iip-iic_rstate = 0; + iip-iic_tstate = 0; + } + + // Select an arbitrary address. Just make sure it is unique. + i2c-i2c_i2add = 0xfe; + + // Make clock run at 60 KHz. + brg = (unsigned char) (bd-bi_intfreq/(32*2*6) -3); + i2c-i2c_i2brg = brg; + + i2c-i2c_i2mod = 0x00; + i2c-i2c_i2com = 0x01; /* Master mode */ +} /* Read from IIC... * abyte = address byte, with r/w flag already set @@ -227,7 +303,7 @@ volatile cpm8xx_t *cp = cpm-cp; volatile cbd_t *tbdf, *rbdf; u_char *tb; - unsigned long flags, tmo; + unsigned long flags, tmo, timedout; if (count = CPM_MAX_READ) return -EINVAL; @@ -269,7 +345,10 @@ rbdf-cbd_bufaddr = __pa(buf); rbdf-cbd_sc = BD_SC_EMPTY | BD_SC_WRAP| BD_SC_INTRPT; +timedout = 0; +#ifdef I2C_BUSY_WAIT if(count 16){ +#endif /* Chip bug, set enable here */ local_irq_save(flags); i2c-i2c_i2cmr = 0x13; /* Enable some interupts */ @@ -278,23 +357,40 @@
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
Try changing all i2c-i2c_i2com |= 0x80; /* Begin transmission */ to i2c-i2c_i2com |= 0x80 | 0x01;/* Begin transmission */ That should remove the need to do force_reinit(cpm) I hope. See http://ozlabs.org/pipermail/linuxppc-embedded/2005-August/019600.html for a litte more info. Also, I think you should remove the busy wait code. Its not needed IMHO. Jocke
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
Hi all, I had some problems on my MPC855M based board when I tried to access the i2c bus. The cause were some disturbances on the i2c bus. If a slave device or another master device hold the SDA or SCL line low, the CPM will get into a state, where no more transmissions are made. The only way I found, to get the CPM back to work, was a complete re-initialisation. - force_reinit() In this case the busy-wait for transmissions with count 16 will lock the complete system (CPU load 99.9%) I added the define I2C_BUSY_WAIT to switch between faster access or safer system. I found out that the i2c-algo-8xx.c has a bug in cpm_iic_read() and cpm_iic_write(): the timeout detection will not work in the case of count 16. I also added the define I2C_INTERRUPTIBLE_SLEEP: the old driver reported IO-error (-EIO) if a timeout occured (which was not working, see above) or if a signal was pending. This caused some problems if the process receives user-signals. The driver will report IO-error, which is not correct. With the busy-wait this effect might not be seen, because there will be no process scheduling - no signals might be send. My modified file is appended. The defines for I2C_BUSY_WAIT and I2C_INTERRUPTIBLE_SLEEP are active, which let the driver act like the old one. Maybe this is helpful for others too and some of the modifications find it?s way into the official kernel tree. Cajus Hahn /* * i2c-algo-8xx.c i2x driver algorithms for MPC8XX CPM * Copyright (c) 1999 Dan Malek (dmalek at jlc.net). * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * moved into proper i2c interface; separated out platform specific * parts into i2c-rpx.c * Brad Parker (brad at heeltoe.com) * * added define for BUSY_WAIT and INTERRUPTIBLE_SLEEP, added I2C_ALGO_8XX_DATE + ..VERSION * fixed bug in cpm_iic_read and cpm_iic_write (timeout never detected if count 16) * added force_reinit(): in certain cases (disturbances on the I2C bus) a timeout will * occur. After this a complete re-initialisation will be necessary, otherwise all * following transmissions will have a timeout. * Cajus Hahn, 09.08.2005 */ // XXX todo // timeout sleep? /* $Id: i2c-algo-8xx.c,v 1.1.1.1 2004/12/10 08:44:35 cajus Exp $ */ #include linux/kernel.h #include linux/module.h #include linux/delay.h #include linux/slab.h #include linux/version.h #include linux/init.h #include asm/uaccess.h #include linux/ioport.h #include linux/errno.h #include linux/sched.h #include asm/mpc8xx.h #include asm/commproc.h #include linux/i2c.h #include linux/i2c-algo-8xx.h #define I2C_ALGO_8XX_DATE 20050809 #define I2C_ALGO_8XX_VERSION 2.6.2 #define CPM_MAX_READ513 /* #define I2C_CHIP_ERRATA */ /* Try uncomment this if you have an older CPU(earlier than rev D4) */ #define I2C_BUSY_WAIT /* Uncomment this if you want to do a busy wait in cpm_iic_read and cpm_iic_write */ #define I2C_INTERRUPTIBLE_SLEEP /* Uncomment this if you want the waiting in cpm_iic_read and cpm_iic_write beeing interruptable by signals */ static wait_queue_head_t iic_wait; static ushort r_tbase, r_rbase; int cpm_scan = 0; int cpm_debug = 0; static void cpm_iic_interrupt(void *dev_id, struct pt_regs *regs) { volatile i2c8xx_t *i2c = (i2c8xx_t *)dev_id; if (cpm_debug 1) printk(KERN_DEBUG cpm_iic_interrupt(dev_id=%p)\n, dev_id); #ifdef I2C_CHIP_ERRATA /* Chip errata, clear enable. * This seems to not be needed on rev D4 or newer CPUs. * Someone with an older CPU needs to verify this. */ i2c-i2c_i2mod = ~1; #endif /* Clear interrupt. */ i2c-i2c_i2cer = 0xff; /* Get 'me going again. */ #ifdef I2C_INTERRUPTIBLE_SLEEP wake_up_interruptible(iic_wait); #else wake_up(iic_wait); #endif } static void cpm_iic_init(struct i2c_algo_8xx_data *cpm_adap) { volatile iic_t *iip = cpm_adap-iip; volatile i2c8xx_t *i2c = cpm_adap-i2c; unsigned char brg; bd_t *bd = (bd_t *)__res; if (cpm_debug) printk(KERN_DEBUG cpm_iic_init() - iip=%p\n,iip); /* Initialize the parameter ram. * We need to make sure many things are initialized to zero, * especially in the case of a microcode patch. */ iip-iic_rstate = 0; iip-iic_rdp = 0;
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
Hello, cajus.hahn In message 2005-08-10 15:27:57 cajus.hahn at de.abb.com you wrote: Hi all, I had some problems on my MPC855M based board when I tried to access the i2c bus. Try update i2c-algo-8xx.c = = = = = = = = = = = = = = = = = = = = Debora Liu deboralh at fel.com.cn 2005-08-10 begin 600 i2c_algo_8xx-port_to_2_6.patch M.'AX.B!P;W)T(DR8RUA;=O7SAX!T;R`R+C8-@T*0F%S960@;VX at 5]M M(%)I;FDGR!A;F0 at 2F]A:VEM(%1J97)N;'5N9=S('=OFL-@T*4VEG;F5D M+6]F9BUB3H at 07)IW1E=2!397)G:[EMAIL PROTECTED]:VD at 1FEL:\@/%R:7-` M8V%T:5DF%L;%BRYOF^#0H-DEN95X.B`R+C8M.'AX+V1R:79EG,O M:3)C+V%L9V]S+VDR8RUA;=O+3AXYC#0H]/3T]/3T]/3T]/3T]/3T]/3T] M/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T]/3T] M/3T]#0HM+2T at +V1E=B]N=6QL3$Y-S`M,#$M,#$@,#`Z,#`Z,#`N,#`P,#`P M,#`P(LP,#`P#0HK*RL@,BXV+3AX]DFEV97)S+VDR8R]A;=OR]I,F,M M86QG;RTX'@N8PDR,#`U+3`X+3`X(#`Y.C4U.C,P+C`P,#`P,#`P,`M,#,P M,[EMAIL PROTECTED],`K,2PV,3@0$`-[EMAIL PROTECTED](DR8RUA;=O+3AXYC M(DR!DFEV97(@86QG;W)I=AMR!F;W(@35!#.%A8($-030T**R`J($-O M'ER:6=H=`H8RD@,3DY.2!$86X at [EMAIL PROTECTED]1M86QE:T!J;,N;F5T*2X- M[EMAIL PROTECTED]@T**R`@(!4:ES('!R;V=R86T@:7, at 9G)E92!S;V9T=V%R93L@6]U M(-A;B!R961IW1R:6)U=4@:70 at 86YD+V]R(UO9EF0T**R`@(!I=!U M;F1EB!T:[EMAIL PROTECTED]5R;7,@;[EMAIL PROTECTED]AE($=.52!'96YEF%L(%!U8FQI8R!,:6-E M;G-E(%S('!U8FQIVAE9!B0T**R`@(!T:4 at 1G)E92!3;V9T=V%R92! M;W5N9%T:6]N.R!E:71H97(@=F5RVEO;B`R(]F('1H92!,:6-E;G-E+!O M@T**R`@(`H870@6]UB!O'1I;VXI(%N2!L871EB!V97)S:6]N+ at T* M*PT**R`@(!4:ES('!R;V=R86T@:7, at 9ES=')I8G5T960@:[EMAIL PROTECTED]AE(AO M[EMAIL PROTECTED]AA=!I=!W:6QL()E('5S969U;P-BL@([EMAIL PROTECTED](%=)5$A/550@ M04Y9(%=!4E)!3E19.R!W:71H;W5T([EMAIL PROTECTED]AE(EM[EMAIL PROTECTED]F%N M='D@;V8-BL@([EMAIL PROTECTED],2519(]R($9)5$Y%4U, at 1D]2($$@ M4$%25$E#54Q!4B!055)[EMAIL PROTECTED]('1H90T**R`@(!'3E4 at 1V5N97)A M;!0=6)L:6, at 3EC96YS92!F;W(@;6]R92!D971A:6QS+ at T**PT**R`@(!9 M;W4@VAO=6QD(AA=F4@F5C96EV960 at 82!C;W!Y(]F('1H92!'3E4 at 1V5N M97)A;!0=6)L:6, at 3EC96YS90T**R`@(!A;]N9R!W:71H('1H:7,@')O M9W)A;3L@:68@;F]T+!WFET92!T;R!T:4 at 1G)E92!3;V9T=V%R90T**R`@ M(!;W5N9%T:6]N+!);F,N+`V-S4 at 36%SR!!=F4L($-A;6)R:61G92P@ M34$@,#(Q,SDL(%5302X-[EMAIL PROTECTED]@T**R`J(UO=F5D(EN=\@')O5R(DR M8R!I;G1EF9A8V4[('-E%R871E9!O=70@QA=9OFT@W!E8VEF:6,- M[EMAIL PROTECTED])TR!I;G1O(DR8RUR'@N8PT**R`J($)R860 at 4%R:V5R(AB MF%D0AE96QT;V4N8V]M*0T**R`J+PT**PT**R\O(%A86!T;V1O#0HK+R\@ M=EM96]U=!S;5E#\-BL-BLO*B`D260Z(DR8RUA;=O+3AXYC+'8@ M,2XW(#(P,#(O,[EMAIL PROTECTED],#,@,C([EMAIL PROTECTED],3@@86,Y-#$P($5X`D(HO#0HK#0HK M(VEN8VQU94@/QI;G5X+VMEFYE;YH/@T**R-I;F-L=61E(#QL:6YU]M M;V1U;4N:#X-BLC:6YC;'5D92`\;EN=7 at O95L87DN:#X-BLC:6YC;'5D M92`\;EN=7 at OVQA8BYH/@T**R-I;F-L=61E(#QL:6YU]V97)S:[EMAIL PROTECTED] M#0HK(VEN8VQU94@/QI;G5X+VEN:70N:#X-BLC:6YC;'5D92`\87-M+W5A M8V-EW,N:#X-BLC:6YC;'5D92`\;EN=7 at O:6]P;W)[EMAIL PROTECTED](VEN8VQU M94@/QI;G5X+V5R[EMAIL PROTECTED](VEN8VQU94@/QI;G5X+W-C:[EMAIL PROTECTED] M#0HK#0HK(VEN8VQU94@/%S;2]M,X'@N:#X-BLC:6YC;'5D92`\87-M M+V-O;6UP[EMAIL PROTECTED](VEN8VQU94@/QI;G5X+VDR8RYH/@T**R-I M;F-L=61E(#QL:6YU]I,F,M86QG;RTX'@N:#X-BL-BLC95F:6YE($-0 M35]-05A?4D5!1`DU,3,-BLO*B!4[EMAIL PROTECTED];VUM96YT('1H:7,@:68@6]U M(AA=F4 at 86X@;VQD97(@0U!5*5AFQI97(@=AA;B!R978 at 1#0I(HO#0HK M+RH@(V1E9FEN92!),D-?0TA)4%]%4E)[EMAIL PROTECTED]BL-BMS=%T:6, at 8VAA MB`J;6]D=6QE7VYA;64@/2`B:3)C7V%L9V]?.'AX(CL-BLC95F:6YE($1% M0E5'4AL979E;P@P@2XN+BD at 9\@R!#0HK0D)6EF(ACU?95B M=6@/CT@;5V96PI(%P-BL)0D)7!R:6YT:RA+15).7T1%0E5'((ESH@ M(B!X+!#0HK0D)0D@(`@(`@;6]D=6QE7VYA;64L(,C('DI.R!#0HK M0D)[EMAIL PROTECTED];4H,D-BL-BMS=%T:6,@=V%I=%]Q=65U95]H96%D7W0@ M:6EC7W=A:70[#0HKW1A=EC('5S:]R=!R7W1B87-E+!R7W)B87-E.PT* M*PT**VEN=!CU?V-A;B`](#`[#0HK:6YT(-P;5]D96)U9R`](#`[#0HK M#0HKW1A=EC(!V;VED#0HK8W!M7VEI8U]I;G1EG)U'0H=F]I9`J95V M7VED+!S=')U8W0@'1?F5GR`JF5GRD-BM[#0HK79O;%T:6QE(DR M8SAX%]T(II,F,@/2`H:3)C.'[EMAIL PROTECTED]:60[#0HK#0HK41%0E5' M4@R+`B8W!M7VEI8U]I;G1EG)U'0H95V7VED/25P*5QN(BP at 95V7VED M*3L-BL-BLC:69D968 at 23)#7T-(25!?15)2051!#0HK2\J($-H:[EMAIL PROTECTED])R M871A+!C;5AB!E;F%B;4N#0HK2`J(%1H:7,@V5E;7,@=\@;F]T()E M(YE961E9!O;B!R978 at 1#0@;W(@;F5W97(@0U!5RX-BL)(H at 4V]M96]N M92!W:71H(%N(]L95R($-052!N965DR!T;R!V97)[EMAIL PROTECTED]AIRX-BL) M(HO#0HK6DR8RT^:3)C7VDR;6]D(8]('XQ.PT**R-E;F1I9 at T**PT**PDO M*B!#;5AB!I;G1EG)U'0N#0HK2HO#0HK6DR8RT^:3)C7VDR8V5R(#T@ M,'AF9CL-BL-BL)+RH at 1V5T(=M92!G;VEN9R!A9V%I;BX-BL)*B\-BL) M=V%K95]U%]I;G1EG)U'1I8FQE*9I:6-?=V%I=D[#0HK?0T**PT**W-T M871I8R!V;VED#0HK8W!M7VEI8U]I;FET*'-TG5C=!I,F-?86QG;U\X'A? M9%T82`J8W!M7V%D87`I#0HKPT**PEV;VQA=EL92!I:6-?=`D)*FEI`] M(-P;5]A9%P+3YI:7`[#0HK79O;%T:6QE(DR8SAX%]T2II,F,@/2!C MU?861AT^:3)C.PT**PEU;G-I9VYE9!C:%R()R9SL-BL)8F1?=`J M8F0@/2`H8F1?=`J*5]?F5S.PT**PT**PE$14)51U`H,2P@(F-P;5]I:6-? M:6YI=@I(T@:6EP/25P7XB+!I:7`I.PT**PT**PDO*B!);FET:6%L:7IE M('1H92!P87)A;65T97(@F%M+ at [EMAIL PROTECTED]('1O(UA:V4@W5R M92!M86YY('1H:6YGR!AF4@:6YI=EA;[EMAIL PROTECTED]\@F5R;RP-BL)(H@ M97-P96-I86QL2!I;B!T:4 at 8V%S92!O9B!A(UI8W)O8V]D92!P871C:X-
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
Dear Debora, in message 20050810093254.3E98667EF5 at ozlabs.org you wrote: I had some problems on my MPC855M based board when I tried to access the i2c bus. Try update i2c-algo-8xx.c I guess this will not solve Cajus' problems. Please take the time and read his message again and you will see that his problems will still be present with your driver version. Best regards, Wolfgang Denk -- Software Engineering: Embedded and Realtime Systems, Embedded Linux Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de panic: can't find /
8xx: i2c-algo-8xx - fixed timeout detection and transmission errors
On Wed, Aug 10, 2005 at 09:27:57AM +0200, cajus.hahn at de.abb.com wrote: Hi all, I had some problems on my MPC855M based board when I tried to access the i2c bus. The cause were some disturbances on the i2c bus. If a slave device or another master device hold the SDA or SCL line low, the CPM will get into a state, where no more transmissions are made. The only way I found, to get the CPM back to work, was a complete re-initialisation. - force_reinit() In this case the busy-wait for transmissions with count 16 will lock the complete system (CPU load 99.9%) I added the define I2C_BUSY_WAIT to switch between faster access or safer system. I found out that the i2c-algo-8xx.c has a bug in cpm_iic_read() and cpm_iic_write(): the timeout detection will not work in the case of count 16. I also added the define I2C_INTERRUPTIBLE_SLEEP: the old driver reported IO-error (-EIO) if a timeout occured (which was not working, see above) or if a signal was pending. This caused some problems if the process receives user-signals. The driver will report IO-error, which is not correct. With the busy-wait this effect might not be seen, because there will be no process scheduling - no signals might be send. My modified file is appended. The defines for I2C_BUSY_WAIT and I2C_INTERRUPTIBLE_SLEEP are active, which let the driver act like the old one. Maybe this is helpful for others too and some of the modifications find it?s way into the official kernel tree. Cajus, Can you please prepare a diff with diff -u against the old version and your modified version of the driver? That way it becomes easier for everyone to stop the changes you have made. Thanks in advance. Cajus Hahn /* * i2c-algo-8xx.c i2x driver algorithms for MPC8XX CPM * Copyright (c) 1999 Dan Malek (dmalek at jlc.net). * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * moved into proper i2c interface; separated out platform specific * parts into i2c-rpx.c * Brad Parker (brad at heeltoe.com) * * added define for BUSY_WAIT and INTERRUPTIBLE_SLEEP, added I2C_ALGO_8XX_DATE + ..VERSION * fixed bug in cpm_iic_read and cpm_iic_write (timeout never detected if count 16) * added force_reinit(): in certain cases (disturbances on the I2C bus) a timeout will * occur. After this a complete re-initialisation will be necessary, otherwise all * following transmissions will have a timeout. * Cajus Hahn, 09.08.2005 */ // XXX todo // timeout sleep? /* $Id: i2c-algo-8xx.c,v 1.1.1.1 2004/12/10 08:44:35 cajus Exp $ */ #include linux/kernel.h #include linux/module.h #include linux/delay.h #include linux/slab.h #include linux/version.h #include linux/init.h #include asm/uaccess.h #include linux/ioport.h #include linux/errno.h #include linux/sched.h #include asm/mpc8xx.h #include asm/commproc.h #include linux/i2c.h #include linux/i2c-algo-8xx.h #define I2C_ALGO_8XX_DATE 20050809 #define I2C_ALGO_8XX_VERSION 2.6.2 #define CPM_MAX_READ513 /* #define I2C_CHIP_ERRATA */ /* Try uncomment this if you have an older CPU(earlier than rev D4) */ #define I2C_BUSY_WAIT /* Uncomment this if you want to do a busy wait in cpm_iic_read and cpm_iic_write */ #define I2C_INTERRUPTIBLE_SLEEP /* Uncomment this if you want the waiting in cpm_iic_read and cpm_iic_write beeing interruptable by signals */ static wait_queue_head_t iic_wait; static ushort r_tbase, r_rbase; int cpm_scan = 0; int cpm_debug = 0; static void cpm_iic_interrupt(void *dev_id, struct pt_regs *regs) { volatile i2c8xx_t *i2c = (i2c8xx_t *)dev_id; if (cpm_debug 1) printk(KERN_DEBUG cpm_iic_interrupt(dev_id=%p)\n, dev_id); #ifdef I2C_CHIP_ERRATA /* Chip errata, clear enable. * This seems to not be needed on rev D4 or newer CPUs. * Someone with an older CPU needs to verify this. */ i2c-i2c_i2mod = ~1; #endif /* Clear interrupt. */ i2c-i2c_i2cer = 0xff; /* Get 'me going again. */ #ifdef I2C_INTERRUPTIBLE_SLEEP wake_up_interruptible(iic_wait); #else wake_up(iic_wait); #endif } static void cpm_iic_init(struct i2c_algo_8xx_data *cpm_adap) { volatile iic_t *iip