00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <arch/arm.h>
00043 #include <dev/irqreg.h>
00044
00045 #include <sys/event.h>
00046 #include <sys/atom.h>
00047 #include <sys/timer.h>
00048 #include <sys/thread.h>
00049 #include <sys/heap.h>
00050
00051 #include <dev/twif.h>
00052
00057
00058
00059
00060
00061 #if defined(MCU_AT91SAM7X)
00062 #define TWI_TWD PA10_TWD_A
00063 #define TWI_TWCK PA11_TWCK_A
00064 #elif defined(MCU_AT91SAM7S) || defined(MCU_AT91SAM7SE)
00065 #define TWI_TWD PA3_TWD_A
00066 #define TWI_TWCK PA4_TWCK_A
00067 #elif defined (MCU_AT91SAM9260) || defined(MCU_AT91SAM9XE)
00068 #define TWI_TWD PA23_TWD_A
00069 #define TWI_TWCK PA24_TWCK_A
00070 #endif
00071
00072
00073
00074
00075 #ifndef TWI_PIO_ASR
00076 #define TWI_PIO_ASR PIOA_ASR
00077 #endif
00078 #ifndef TWI_PIO_PDR
00079 #define TWI_PIO_PDR PIOA_PDR
00080 #endif
00081 #ifndef TWI_PIO_MDER
00082 #define TWI_PIO_MDER PIOA_MDER
00083 #endif
00084
00085 static HANDLE tw_mm_mutex;
00086 static HANDLE tw_mm_que;
00087
00088 static volatile int tw_mm_err;
00089 static int tw_mm_error;
00090
00091 static uint8_t *tw_mm_buf;
00092 static volatile size_t tw_mm_len;
00093 static volatile size_t tw_mm_idx;
00094
00095
00096
00097
00098 static void TwInterrupt(void *arg)
00099 {
00100 register unsigned int twsr;
00101
00102
00103 twsr = inr(TWI_SR);
00104 if (twsr & (TWI_NACK | TWI_OVRE | TWI_ARBLST)) {
00105 if (twsr & TWI_NACK) {
00106 tw_mm_err = TWERR_SLA_NACK;
00107 } else {
00108 tw_mm_err = TWERR_BUS;
00109 }
00110 }
00111
00112
00113 twsr &= inr(TWI_IMR);
00114 if (twsr & TWI_TXRDY) {
00115
00116 if (tw_mm_idx < tw_mm_len) {
00117
00118 outb(TWI_THR, tw_mm_buf[tw_mm_idx]);
00119 tw_mm_idx++;
00120 } else {
00121
00122 outr(TWI_IDR, TWI_TXRDY);
00123 outr(TWI_IER, TWI_TXCOMP);
00124 }
00125 } else if (twsr & TWI_RXRDY) {
00126
00127 if (tw_mm_idx < tw_mm_len) {
00128
00129 tw_mm_buf[tw_mm_idx++] = inb(TWI_RHR);
00130 if (tw_mm_idx == tw_mm_len - 1) {
00131
00132 outr(TWI_CR, TWI_STOP);
00133 } else if (tw_mm_idx == tw_mm_len) {
00134
00135 outr(TWI_IDR, TWI_RXRDY);
00136 outr(TWI_IER, TWI_TXCOMP);
00137 }
00138 }
00139 } else if (twsr & TWI_TXCOMP) {
00140
00141
00142 outr(TWI_IDR, 0xFFFFFFFF);
00143 NutEventPostFromIrq(&tw_mm_que);
00144 }
00145 }
00146
00172 int TwMasterTransact(uint8_t sla, CONST void *txdata, uint16_t txlen, void *rxdata, uint16_t rxsiz, uint32_t tmo)
00173 {
00174 int rc = -1;
00175
00176
00177 if (NutEventWait(&tw_mm_mutex, tmo)) {
00178 tw_mm_error = TWERR_IF_LOCKED;
00179 return -1;
00180 }
00181
00182
00183 tw_mm_err = 0;
00184
00185
00186 if (txlen) {
00187
00188 tw_mm_buf = (uint8_t *) txdata;
00189 tw_mm_len = (size_t) txlen;
00190 tw_mm_idx = 1;
00191
00192
00193 outr(TWI_MMR, (unsigned int) sla << TWI_DADR_LSB);
00194 outr(TWI_THR, tw_mm_buf[0]);
00195 outr(TWI_IER, TWI_TXRDY);
00196
00197
00198 if (NutEventWait(&tw_mm_que, tmo)) {
00199 tw_mm_err = TWERR_TIMEOUT;
00200 }
00201 }
00202
00203 if (tw_mm_err == 0) {
00204
00205
00206 tw_mm_idx = 0;
00207
00208 if (rxsiz) {
00209
00210 tw_mm_buf = (uint8_t *) rxdata;
00211 tw_mm_len = (size_t) rxsiz;
00212
00213
00214 outr(TWI_MMR, ((unsigned int) sla << TWI_DADR_LSB) | TWI_MREAD);
00215 if (rxsiz == 1) {
00216
00217 outr(TWI_CR, TWI_START | TWI_STOP);
00218 } else {
00219 outr(TWI_CR, TWI_START);
00220 }
00221 outr(TWI_IER, TWI_RXRDY);
00222
00223
00224 if (NutEventWait(&tw_mm_que, tmo)) {
00225 tw_mm_err = TWERR_TIMEOUT;
00226 }
00227 }
00228 }
00229
00230 outr(TWI_IDR, 0xFFFFFFFF);
00231
00232
00233
00234 if (tw_mm_err) {
00235 tw_mm_error = tw_mm_err;
00236 } else {
00237 rc = (int) tw_mm_idx;
00238 }
00239
00240
00241 NutEventPost(&tw_mm_mutex);
00242
00243 return rc;
00244 }
00245
00268 int TwMasterRegRead(uint8_t sla, uint32_t iadr, uint8_t iadrlen, void *rxdata, uint16_t rxsiz, uint32_t tmo)
00269 {
00270 int rc = -1;
00271
00272 if (rxsiz == 0) {
00273 return -1;
00274 }
00275
00276 if (NutEventWait(&tw_mm_mutex, tmo)) {
00277 tw_mm_error = TWERR_IF_LOCKED;
00278 return -1;
00279 }
00280
00281 tw_mm_err = 0;
00282
00283 if (rxsiz) {
00284 tw_mm_buf = rxdata;
00285 tw_mm_len = (size_t) rxsiz;
00286 tw_mm_idx = 0;
00287
00288
00289 outr(TWI_IADRR, iadr);
00290
00291 outr(TWI_MMR, ((unsigned int) sla << TWI_DADR_LSB) | (((unsigned int) iadrlen & 3) << 8) | TWI_MREAD);
00292
00293 if (rxsiz == 1) {
00294 outr(TWI_CR, TWI_START | TWI_STOP);
00295 } else {
00296 outr(TWI_CR, TWI_START);
00297 }
00298 outr(TWI_IER, TWI_RXRDY);
00299
00300
00301 if (NutEventWait(&tw_mm_que, tmo)) {
00302 tw_mm_error = TWERR_TIMEOUT;
00303 } else if (tw_mm_err) {
00304 tw_mm_error = tw_mm_err;
00305 } else {
00306 rc = (int) tw_mm_idx;
00307 }
00308 outr(TWI_IDR, 0xFFFFFFFF);
00309 }
00310
00311
00312 NutEventPost(&tw_mm_mutex);
00313
00314 return rc;
00315 }
00316
00342 int TwMasterRegWrite(uint8_t sla, uint32_t iadr, uint8_t iadrlen, CONST void *txdata, uint16_t txsiz, uint32_t tmo)
00343 {
00344 int rc = -1;
00345
00346
00347 if (NutEventWait(&tw_mm_mutex, tmo)) {
00348 tw_mm_err = TWERR_IF_LOCKED;
00349 return -1;
00350 }
00351
00352 tw_mm_err = 0;
00353
00354 if (txsiz) {
00355 tw_mm_buf = (uint8_t *) txdata;
00356 tw_mm_len = (size_t) txsiz;
00357 tw_mm_idx = 1;
00358
00359
00360 outr(TWI_IADRR, iadr);
00361
00362 outr(TWI_MMR, ((unsigned int) sla << TWI_DADR_LSB) | (((unsigned int) iadrlen & 3) << 8));
00363 outb(TWI_THR, tw_mm_buf[0]);
00364 outr(TWI_IER, TWI_TXRDY);
00365
00366
00367 if (NutEventWait(&tw_mm_que, tmo)) {
00368 tw_mm_error = TWERR_TIMEOUT;
00369 } else if (tw_mm_err) {
00370 tw_mm_error = tw_mm_err;
00371 } else {
00372 rc = (int) tw_mm_idx;
00373 }
00374 outr(TWI_IDR, 0xFFFFFFFF);
00375 }
00376
00377
00378 NutEventPost(&tw_mm_mutex);
00379
00380 return rc;
00381 }
00382
00390 int TwMasterError(void)
00391 {
00392 int rc = tw_mm_error;
00393 tw_mm_error = 0;
00394 return rc;
00395 }
00396
00406 uint16_t TwMasterIndexes(uint8_t idx)
00407 {
00408 switch (idx) {
00409 case 0:
00410 return (uint16_t) tw_mm_idx;
00411 case 1:
00412 return (uint16_t) tw_mm_idx;
00413 case 2:
00414 return (uint16_t) tw_mm_len;
00415 default:
00416 return 0;
00417 }
00418 }
00419
00435 int TwIOCtl(int req, void *conf)
00436 {
00437 int rc = 0;
00438 unsigned int cldiv, ckdiv;
00439 unsigned int twi_clk;
00440 switch (req) {
00441
00442 case TWI_SETSPEED:
00443 ckdiv = 1;
00444 twi_clk = *((uint32_t *) conf);
00445
00446 if (twi_clk > 400000)
00447 return -1;
00448
00449
00450
00451
00452
00453
00454
00455 while ((cldiv = ((NutClockGet(NUT_HWCLK_PERIPHERAL) / (2 * twi_clk)) - 3) / (1 << ckdiv)) > 255) {
00456 ckdiv++;
00457 }
00458
00459
00460 if (cldiv * (1 << ckdiv) > 8191)
00461 return -1;
00462
00463 outr(TWI_CWGR, (ckdiv << 16) | ((unsigned int) cldiv << 8) | (unsigned int) cldiv);
00464 break;
00465
00466 case TWI_GETSPEED:
00467 ckdiv = 1;
00468 twi_clk = *((uint32_t *) conf);
00469
00470 cldiv = inr(TWI_CWGR) & 0x000000FF;
00471 ckdiv = (inr(TWI_CWGR) >> 16) & 0x00000007;
00472
00473 *((uint32_t *) conf) = NutGetCpuClock() * ((cldiv * 2 << ckdiv) - 3);
00474 break;
00475
00476 case TWI_GETSTATUS:
00477 break;
00478
00479 case TWI_SETSTATUS:
00480 break;
00481
00482 default:
00483 rc = -1;
00484 break;
00485 }
00486 return rc;
00487 }
00488
00500 int TwInit(uint8_t sla)
00501 {
00502 uint32_t speed = 4800;
00503
00504 if (NutRegisterIrqHandler(&sig_TWI, TwInterrupt, 0)) {
00505 return -1;
00506 }
00507
00508
00509 outr(TWI_PIO_ASR, _BV(TWI_TWD) | _BV(TWI_TWCK));
00510
00511 outr(TWI_PIO_PDR, _BV(TWI_TWD) | _BV(TWI_TWCK));
00512
00513 outr(TWI_PIO_MDER, _BV(TWI_TWD) | _BV(TWI_TWCK));
00514
00515 outr(PMC_PCER, _BV(TWI_ID));
00516
00517
00518 outr(TWI_IDR, 0xFFFFFFFF);
00519
00520 outr(TWI_CR, TWI_SWRST);
00521
00522 outr(TWI_CR, TWI_MSEN | TWI_SVDIS);
00523
00524 if (TwIOCtl(TWI_SETSPEED, &speed)) {
00525 return -1;
00526 }
00527
00528
00529 NutIrqSetMode(&sig_TWI, NUT_IRQMODE_LEVEL);
00530 NutIrqEnable(&sig_TWI);
00531
00532
00533 NutEventPost(&tw_mm_mutex);
00534
00535 return 0;
00536 }
00537