diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/i2c-pp.c | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/firmware/target/arm/i2c-pp.c b/firmware/target/arm/i2c-pp.c index 3db25c027c..175e2effd1 100644 --- a/firmware/target/arm/i2c-pp.c +++ b/firmware/target/arm/i2c-pp.c | |||
@@ -54,35 +54,46 @@ static int pp_i2c_wait_not_busy(void) | |||
54 | return -1; | 54 | return -1; |
55 | } | 55 | } |
56 | 56 | ||
57 | static int pp_i2c_read_byte(unsigned int addr, unsigned int *data) | 57 | static int pp_i2c_read_bytes(unsigned int addr, int len, unsigned char *data) |
58 | { | 58 | { |
59 | if (pp_i2c_wait_not_busy() < 0) | 59 | int i; |
60 | |||
61 | if (len < 1 || len > 4) | ||
60 | { | 62 | { |
61 | return -1; | 63 | return -1; |
62 | } | 64 | } |
63 | 65 | ||
66 | if (pp_i2c_wait_not_busy() < 0) | ||
67 | { | ||
68 | return -2; | ||
69 | } | ||
70 | |||
64 | { | 71 | { |
65 | unsigned int byte; | ||
66 | int old_irq_level = disable_irq_save(); | 72 | int old_irq_level = disable_irq_save(); |
67 | 73 | ||
68 | /* clear top 15 bits, left shift 1, or in 0x1 for a read */ | 74 | /* clear top 15 bits, left shift 1, or in 0x1 for a read */ |
69 | I2C_ADDR = ((addr << 17) >> 16) | 0x1 ; | 75 | I2C_ADDR = ((addr << 17) >> 16) | 0x1; |
70 | 76 | ||
71 | I2C_CTRL |= 0x20; | 77 | I2C_CTRL |= 0x20; |
72 | 78 | ||
79 | I2C_CTRL = (I2C_CTRL & ~0x6) | ((len-1) << 1); | ||
80 | |||
73 | I2C_CTRL |= I2C_SEND; | 81 | I2C_CTRL |= I2C_SEND; |
74 | 82 | ||
75 | restore_irq(old_irq_level); | 83 | restore_irq(old_irq_level); |
84 | |||
76 | if (pp_i2c_wait_not_busy() < 0) | 85 | if (pp_i2c_wait_not_busy() < 0) |
77 | { | 86 | { |
78 | return -1; | 87 | return -2; |
79 | } | 88 | } |
80 | old_irq_level = disable_irq_save(); | ||
81 | 89 | ||
82 | byte = I2C_DATA(0); | 90 | old_irq_level = disable_irq_save(); |
83 | 91 | ||
84 | if (data) | 92 | if (data) |
85 | *data = byte; | 93 | { |
94 | for ( i = 0; i < len; i++ ) | ||
95 | *data++ = I2C_DATA(i); | ||
96 | } | ||
86 | 97 | ||
87 | restore_irq(old_irq_level); | 98 | restore_irq(old_irq_level); |
88 | } | 99 | } |
@@ -90,9 +101,9 @@ static int pp_i2c_read_byte(unsigned int addr, unsigned int *data) | |||
90 | return 0; | 101 | return 0; |
91 | } | 102 | } |
92 | 103 | ||
93 | static int pp_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data) | 104 | static int pp_i2c_send_bytes(unsigned int addr, int len, unsigned char *data) |
94 | { | 105 | { |
95 | unsigned int i; | 106 | int i; |
96 | 107 | ||
97 | if (len < 1 || len > 4) | 108 | if (len < 1 || len > 4) |
98 | { | 109 | { |
@@ -117,14 +128,14 @@ static int pp_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char | |||
117 | I2C_DATA(i) = *data++; | 128 | I2C_DATA(i) = *data++; |
118 | } | 129 | } |
119 | 130 | ||
120 | I2C_CTRL = (I2C_CTRL & ~0x26) | ((len-1) << 1); | 131 | I2C_CTRL = (I2C_CTRL & ~0x6) | ((len-1) << 1); |
121 | 132 | ||
122 | I2C_CTRL |= I2C_SEND; | 133 | I2C_CTRL |= I2C_SEND; |
123 | 134 | ||
124 | restore_irq(old_irq_level); | 135 | restore_irq(old_irq_level); |
125 | } | 136 | } |
126 | 137 | ||
127 | return 0x0; | 138 | return 0; |
128 | } | 139 | } |
129 | 140 | ||
130 | static int pp_i2c_send_byte(unsigned int addr, int data0) | 141 | static int pp_i2c_send_byte(unsigned int addr, int data0) |
@@ -147,29 +158,42 @@ void i2c_unlock(void) | |||
147 | mutex_unlock(&i2c_mtx); | 158 | mutex_unlock(&i2c_mtx); |
148 | } | 159 | } |
149 | 160 | ||
150 | int i2c_readbytes(unsigned int dev_addr, int addr, int len, unsigned char *data) { | 161 | int i2c_readbytes(unsigned int dev_addr, int addr, int len, unsigned char *data) |
151 | unsigned int temp; | 162 | { |
152 | int i; | 163 | int i, n; |
164 | |||
153 | mutex_lock(&i2c_mtx); | 165 | mutex_lock(&i2c_mtx); |
154 | pp_i2c_send_byte(dev_addr, addr); | 166 | |
155 | for (i = 0; i < len; i++) { | 167 | if (addr >= 0) |
156 | pp_i2c_read_byte(dev_addr, &temp); | 168 | pp_i2c_send_byte(dev_addr, addr); |
157 | data[i] = temp; | 169 | |
170 | i = 0; | ||
171 | while (len > 0) | ||
172 | { | ||
173 | n = (len < 4) ? len : 4; | ||
174 | |||
175 | if (pp_i2c_read_bytes(dev_addr, n, data + i) < 0) | ||
176 | break; | ||
177 | |||
178 | len -= n; | ||
179 | i += n; | ||
158 | } | 180 | } |
181 | |||
159 | mutex_unlock(&i2c_mtx); | 182 | mutex_unlock(&i2c_mtx); |
183 | |||
160 | return i; | 184 | return i; |
161 | } | 185 | } |
162 | 186 | ||
163 | int i2c_readbyte(unsigned int dev_addr, int addr) | 187 | int i2c_readbyte(unsigned int dev_addr, int addr) |
164 | { | 188 | { |
165 | int data; | 189 | unsigned char data; |
166 | 190 | ||
167 | mutex_lock(&i2c_mtx); | 191 | mutex_lock(&i2c_mtx); |
168 | pp_i2c_send_byte(dev_addr, addr); | 192 | pp_i2c_send_byte(dev_addr, addr); |
169 | pp_i2c_read_byte(dev_addr, &data); | 193 | pp_i2c_read_bytes(dev_addr, 1, &data); |
170 | mutex_unlock(&i2c_mtx); | 194 | mutex_unlock(&i2c_mtx); |
171 | 195 | ||
172 | return data; | 196 | return (int)data; |
173 | } | 197 | } |
174 | 198 | ||
175 | int pp_i2c_send(unsigned int addr, int data0, int data1) | 199 | int pp_i2c_send(unsigned int addr, int data0, int data1) |