summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2005-11-21 02:13:14 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2005-11-21 02:13:14 +0000
commitdcb8df5180658a26ea681e905586afaffe019ce9 (patch)
tree1dab39f3068d39cbd8a57e7a35761269b8f4b75c
parent5124844e32954cb4e8103dc29b78df6dd5d6a556 (diff)
downloadrockbox-dcb8df5180658a26ea681e905586afaffe019ce9.tar.gz
rockbox-dcb8df5180658a26ea681e905586afaffe019ce9.zip
Added proper clock-stretching to the pcf50606 I2C driver
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8018 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/pcf50606.c38
1 files changed, 4 insertions, 34 deletions
diff --git a/firmware/drivers/pcf50606.c b/firmware/drivers/pcf50606.c
index a2045291ec..4fe04e6171 100644
--- a/firmware/drivers/pcf50606.c
+++ b/firmware/drivers/pcf50606.c
@@ -38,7 +38,7 @@
38#define SCL_INPUT and_l(~0x00001000, &GPIO_ENABLE) 38#define SCL_INPUT and_l(~0x00001000, &GPIO_ENABLE)
39#define SCL_OUTPUT or_l( 0x00001000, &GPIO_ENABLE) 39#define SCL_OUTPUT or_l( 0x00001000, &GPIO_ENABLE)
40#define SCL_LO and_l(~0x00001000, &GPIO_OUT) 40#define SCL_LO and_l(~0x00001000, &GPIO_OUT)
41#define SCL_HI or_l( 0x00001000, &GPIO_OUT) 41#define SCL_HI SCL_INPUT;while(!SCL){};or_l(0x1000, &GPIO_OUT);SCL_OUTPUT
42#define SCL ( 0x00001000 & GPIO_READ) 42#define SCL ( 0x00001000 & GPIO_READ)
43 43
44/* delay loop to achieve 400kHz at 120MHz CPU frequency */ 44/* delay loop to achieve 400kHz at 120MHz CPU frequency */
@@ -68,28 +68,13 @@ static void pcf50606_i2c_stop(void)
68 68
69static void pcf50606_i2c_ack(bool ack) 69static void pcf50606_i2c_ack(bool ack)
70{ 70{
71 /* Here's the deal. The slave is slow, and sometimes needs to wait
72 before it can receive the acknowledge. Therefore it forces the clock
73 low until it is ready. We need to poll the clock line until it goes
74 high before we release the ack.
75
76 In their infinite wisdom, iriver didn't pull up the SCL line, so
77 we have to drive the SCL high repeatedly to simulate a pullup. */
78
79 SCL_LO; /* Set the clock low */ 71 SCL_LO; /* Set the clock low */
80 if(ack) 72 if(ack)
81 SDA_LO; 73 SDA_LO;
82 else 74 else
83 SDA_HI; 75 SDA_HI;
84 76
85 SCL_INPUT; /* Set the clock to input */ 77 SCL_HI;
86 while(!SCL) /* and wait for the slave to release it */
87 {
88 SCL_OUTPUT; /* Set the clock to output */
89 SCL_HI;
90 SCL_INPUT; /* Set the clock to input */
91 DELAY;
92 }
93 78
94 DELAY; 79 DELAY;
95 SCL_OUTPUT; 80 SCL_OUTPUT;
@@ -100,23 +85,8 @@ static int pcf50606_i2c_getack(void)
100{ 85{
101 int ret = 1; 86 int ret = 1;
102 87
103 /* Here's the deal. The slave is slow, and sometimes needs to wait
104 before it can send the acknowledge. Therefore it forces the clock
105 low until it is ready. We need to poll the clock line until it goes
106 high before we read the ack.
107
108 In their infinite wisdom, iriver didn't pull up the SCL line, so
109 we have to drive the SCL high repeatedly to simulate a pullup. */
110
111 SDA_INPUT; /* And set to input */ 88 SDA_INPUT; /* And set to input */
112 SCL_INPUT; /* Set the clock to input */ 89 SCL_HI;
113 while(!SCL) /* and wait for the slave to release it */
114 {
115 SCL_OUTPUT; /* Set the clock to output */
116 SCL_HI;
117 SCL_INPUT; /* Set the clock to input */
118 DELAY;
119 }
120 90
121 if (SDA) 91 if (SDA)
122 /* ack failed */ 92 /* ack failed */