Remove from wizart i2c backend selection. Add deprecate switch to disable old i2c...
[bertos.git] / bertos / cpu / avr / drv / i2c_avr.c
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2003, 2004, 2005 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \brief Driver for the AVR ATMega TWI (implementation)
34  *
35  * \author Stefano Fedrigo <aleph@develer.com>
36  * \author Bernie Innocenti <bernie@codewiz.org>
37  * \author Daniele Basile <asterix@develer.com>
38  */
39
40
41 #include "cfg/cfg_i2c.h"
42
43 #include <hw/hw_cpufreq.h>  /* CPU_FREQ */
44
45 #define LOG_LEVEL  I2C_LOG_LEVEL
46 #define LOG_FORMAT I2C_LOG_FORMAT
47
48 #include <cfg/log.h>
49
50 #include <cfg/debug.h>
51 #include <cfg/macros.h> // BV()
52 #include <cfg/module.h>
53
54 #include <cpu/detect.h>
55 #include <cpu/irq.h>
56 #include <drv/timer.h>
57 #include <drv/i2c.h>
58
59 #include <cpu/power.h>
60
61 #include <compat/twi.h>
62
63 #if !CONFIG_I2C_DISABLE_OLD_API
64
65 /* Wait for TWINT flag set: bus is ready */
66 #define WAIT_TWI_READY  do {} while (!(TWCR & BV(TWINT)))
67
68 /**
69  * Send START condition on the bus.
70  *
71  * \return true on success, false otherwise.
72  */
73 static bool i2c_builtin_start(void)
74 {
75         TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
76         WAIT_TWI_READY;
77
78         if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
79                 return true;
80
81         LOG_ERR("!TW_(REP)START: %x\n", TWSR);
82         return false;
83 }
84
85
86 /**
87  * Send START condition and select slave for write.
88  * \c id is the device id comprehensive of address left shifted by 1.
89  * The LSB of \c id is ignored and reset to 0 for write operation.
90  *
91  * \return true on success, false otherwise.
92  */
93 bool i2c_builtin_start_w(uint8_t id)
94 {
95         /*
96          * Loop on the select write sequence: when the eeprom is busy
97          * writing previously sent data it will reply to the SLA_W
98          * control byte with a NACK.  In this case, we must
99          * keep trying until the eeprom responds with an ACK.
100          */
101         ticks_t start = timer_clock();
102         while (i2c_builtin_start())
103         {
104                 TWDR = id & ~I2C_READBIT;
105                 TWCR = BV(TWINT) | BV(TWEN);
106                 WAIT_TWI_READY;
107
108                 if (TW_STATUS == TW_MT_SLA_ACK)
109                         return true;
110                 else if (TW_STATUS != TW_MT_SLA_NACK)
111                 {
112                         LOG_ERR("!TW_MT_SLA_(N)ACK: %x\n", TWSR);
113                         break;
114                 }
115                 else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
116                 {
117                         LOG_ERR("Timeout on TWI_MT_START\n");
118                         break;
119                 }
120         }
121
122         return false;
123 }
124
125
126 /**
127  * Send START condition and select slave for read.
128  * \c id is the device id comprehensive of address left shifted by 1.
129  * The LSB of \c id is ignored and set to 1 for read operation.
130  *
131  * \return true on success, false otherwise.
132  */
133 bool i2c_builtin_start_r(uint8_t id)
134 {
135         if (i2c_builtin_start())
136         {
137                 TWDR = id | I2C_READBIT;
138                 TWCR = BV(TWINT) | BV(TWEN);
139                 WAIT_TWI_READY;
140
141                 if (TW_STATUS == TW_MR_SLA_ACK)
142                         return true;
143
144                 LOG_ERR("!TW_MR_SLA_ACK: %x\n", TWSR);
145         }
146
147         return false;
148 }
149
150
151 /**
152  * Send STOP condition.
153  */
154 void i2c_builtin_stop(void)
155 {
156         TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
157 }
158
159
160 /**
161  * Put a single byte in master transmitter mode
162  * to the selected slave device through the TWI bus.
163  *
164  * \return true on success, false on error.
165  */
166 bool i2c_builtin_put(const uint8_t data)
167 {
168         TWDR = data;
169         TWCR = BV(TWINT) | BV(TWEN);
170         WAIT_TWI_READY;
171         if (TW_STATUS != TW_MT_DATA_ACK)
172         {
173                 LOG_ERR("!TW_MT_DATA_ACK: %x\n", TWSR);
174                 return false;
175         }
176         return true;
177 }
178
179 /**
180  * Get 1 byte from slave in master transmitter mode
181  * to the selected slave device through the TWI bus.
182  * If \a ack is true issue a ACK after getting the byte,
183  * otherwise a NACK is issued.
184  *
185  * \return the byte read if ok, EOF on errors.
186  */
187 int i2c_builtin_get(bool ack)
188 {
189         TWCR = BV(TWINT) | BV(TWEN) | (ack ? BV(TWEA) : 0);
190         WAIT_TWI_READY;
191
192         if (ack)
193         {
194                 if (TW_STATUS != TW_MR_DATA_ACK)
195                 {
196                         LOG_ERR("!TW_MR_DATA_ACK: %x\n", TWSR);
197                         return EOF;
198                 }
199         }
200         else
201         {
202                 if (TW_STATUS != TW_MR_DATA_NACK)
203                 {
204                         LOG_ERR("!TW_MR_DATA_NACK: %x\n", TWSR);
205                         return EOF;
206                 }
207         }
208
209         /* avoid sign extension */
210         return (int)(uint8_t)TWDR;
211 }
212
213
214 MOD_DEFINE(i2c);
215
216 /**
217  * Initialize TWI module.
218  */
219 void i2c_builtin_init(void)
220 {
221         ATOMIC(
222                 /*
223                  * This is pretty useless according to AVR's datasheet,
224                  * but it helps us driving the TWI data lines on boards
225                  * where the bus pull-up resistors are missing.  This is
226                  * probably due to some unwanted interaction between the
227                  * port pin and the TWI lines.
228                  */
229 #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281
230                 PORTD |= BV(PD0) | BV(PD1);
231                 DDRD  |= BV(PD0) | BV(PD1);
232 #elif CPU_AVR_ATMEGA8
233                 PORTC |= BV(PC4) | BV(PC5);
234                 DDRC  |= BV(PC4) | BV(PC5);
235 #elif CPU_AVR_ATMEGA32
236                 PORTC |= BV(PC1) | BV(PC0);
237                 DDRC  |= BV(PC1) | BV(PC0);
238 #else
239                 #error Unsupported architecture
240 #endif
241
242                 /*
243                  * Set speed:
244                  * F = CPU_FREQ / (16 + 2*TWBR * 4^TWPS)
245                  */
246                 #ifndef CONFIG_I2C_FREQ
247                         #warning Using default value of 300000L for CONFIG_I2C_FREQ
248                         #define CONFIG_I2C_FREQ  300000L /* ~300 kHz */
249                 #endif
250                 #define TWI_PRESC 1       /* 4 ^ TWPS */
251
252                 TWBR = (CPU_FREQ / (2 * CONFIG_I2C_FREQ * TWI_PRESC)) - (8 / TWI_PRESC);
253                 TWSR = 0;
254                 TWCR = BV(TWEN);
255         );
256         MOD_INIT(i2c);
257 }
258
259 #endif /* !CONFIG_I2C_DISABLE_OLD_API */
260
261 /*
262  * New Api
263  */
264 struct I2cHardware
265 {
266 };
267
268
269 /* Wait for TWINT flag set: bus is ready */
270 #define WAIT_READY() \
271         do { \
272                 while (!(TWCR & BV(TWINT))) \
273                         cpu_relax(); \
274         } while (0)
275
276 /**
277  * Send START condition on the bus.
278  */
279 INLINE bool i2c_hw_start(void)
280 {
281         TWCR = BV(TWINT) | BV(TWSTA) | BV(TWEN);
282         WAIT_READY();
283
284         if (TW_STATUS == TW_START || TW_STATUS == TW_REP_START)
285                 return true;
286
287         return false;
288 }
289
290 /**
291  * Send STOP condition.
292  */
293 INLINE void i2c_hw_stop(void)
294 {
295         TWCR = BV(TWINT) | BV(TWEN) | BV(TWSTO);
296 }
297
298 static void i2c_avr_start(I2c *i2c, uint16_t slave_addr)
299 {
300         /*
301          * Loop on the select write sequence: when the eeprom is busy
302          * writing previously sent data it will reply to the SLA_W
303          * control byte with a NACK.  In this case, we must
304          * keep trying until the slave responds with an ACK.
305          */
306         ticks_t start = timer_clock();
307         while (i2c_hw_start())
308         {
309                 uint8_t sla_ack = 0;
310                 uint8_t sla_nack = 0;
311                 if (I2C_TEST_START(i2c->flags) == I2C_START_W)
312                 {
313                         TWDR = slave_addr & ~I2C_READBIT;
314                         sla_ack = TW_MT_SLA_ACK;
315                         sla_nack = TW_MT_SLA_NACK;
316                 }
317                 else
318                 {
319                         TWDR = slave_addr | I2C_READBIT;
320                         sla_ack = TW_MR_SLA_ACK;
321                         sla_nack = TW_MR_SLA_NACK;
322                 }
323
324                 TWCR = BV(TWINT) | BV(TWEN);
325                 WAIT_READY();
326
327                 if (TW_STATUS == sla_ack)
328                         return;
329                 else if (TW_STATUS != sla_nack)
330                 {
331                         LOG_ERR("Start addr NACK[%x]\n", TWSR);
332                         i2c->errors |= I2C_NO_ACK;
333                         i2c_hw_stop();
334                         break;
335                 }
336                 else if (timer_clock() - start > ms_to_ticks(CONFIG_I2C_START_TIMEOUT))
337                 {
338                         LOG_ERR("Start timeout\n");
339                         i2c->errors |= I2C_START_TIMEOUT;
340                         i2c_hw_stop();
341                         break;
342                 }
343         }
344
345         LOG_ERR("I2c error\n");
346         i2c->errors |= I2C_ERR;
347         i2c_hw_stop();
348 }
349
350 static void i2c_avr_putc(I2c *i2c, const uint8_t data)
351 {
352
353         TWDR = data;
354         TWCR = BV(TWINT) | BV(TWEN);
355         WAIT_READY();
356
357         if (TW_STATUS != TW_MT_DATA_ACK)
358         {
359                 LOG_ERR("Data nack[%x]\n", TWSR);
360                 i2c->errors |= I2C_DATA_NACK;
361                 i2c_hw_stop();
362         }
363
364         if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP))
365                 i2c_hw_stop();
366 }
367
368 static uint8_t i2c_avr_getc(I2c *i2c)
369 {
370         uint8_t data_flag = 0;
371         if (i2c->xfer_size == 1)
372         {
373                 TWCR = BV(TWINT) | BV(TWEN);
374                 data_flag = TW_MR_DATA_NACK;
375         }
376         else
377         {
378                 TWCR = BV(TWINT) | BV(TWEN) | BV(TWEA);
379                 data_flag = TW_MR_DATA_ACK;
380         }
381
382         WAIT_READY();
383
384         if (TW_STATUS != data_flag)
385         {
386                 LOG_ERR("Data nack[%x]\n", TWSR);
387                 i2c->errors |= I2C_DATA_NACK;
388                 i2c_hw_stop();
389
390                 return 0xFF;
391         }
392
393         uint8_t data = TWDR;
394
395         if ((i2c->xfer_size == 1) && (I2C_TEST_STOP(i2c->flags) == I2C_STOP))
396                 i2c_hw_stop();
397
398         return data;
399 }
400
401
402 static const I2cVT i2c_avr_vt =
403 {
404         .start = i2c_avr_start,
405         .getc = i2c_avr_getc,
406         .putc = i2c_avr_putc,
407         .write = i2c_genericWrite,
408         .read = i2c_genericRead,
409 };
410
411 struct I2cHardware i2c_avr_hw[] =
412 {
413         { /* I2C0 */
414         },
415 };
416
417 /**
418  * Initialize I2C module.
419  */
420 void i2c_hw_init(I2c *i2c, int dev, uint32_t clock)
421 {
422         i2c->hw = &i2c_avr_hw[dev];
423         i2c->vt = &i2c_avr_vt;
424
425         ATOMIC(
426                 /*
427                  * This is pretty useless according to AVR's datasheet,
428                  * but it helps us driving the TWI data lines on boards
429                  * where the bus pull-up resistors are missing.  This is
430                  * probably due to some unwanted interaction between the
431                  * port pin and the TWI lines.
432                  */
433         #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281
434                 PORTD |= BV(PD0) | BV(PD1);
435                 DDRD  |= BV(PD0) | BV(PD1);
436         #elif CPU_AVR_ATMEGA8
437                 PORTC |= BV(PC4) | BV(PC5);
438                 DDRC  |= BV(PC4) | BV(PC5);
439         #elif CPU_AVR_ATMEGA32
440                 PORTC |= BV(PC1) | BV(PC0);
441                 DDRC  |= BV(PC1) | BV(PC0);
442         #else
443                 #error Unsupported architecture
444         #endif
445
446                 /*
447                  * Set speed:
448                  * F = CPU_FREQ / (16 + 2*TWBR * 4^TWPS)
449                  */
450                 ASSERT(clock);
451                 #define TWI_PRESC    1       /* 4 ^ TWPS */
452
453                 TWBR = (CPU_FREQ / (2 * clock * TWI_PRESC)) - (8 / TWI_PRESC);
454                 TWSR = 0;
455                 TWCR = BV(TWEN);
456         );
457 }