Changeset ba938b8d in rtems for c/src/lib/libbsp/arm/lpc24xx/ssp
- Timestamp:
- 09/18/09 08:05:40 (15 years ago)
- Branches:
- 4.10, 4.11, 5, master
- Children:
- 091705c
- Parents:
- f90c5fb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
c/src/lib/libbsp/arm/lpc24xx/ssp/ssp.c
rf90c5fb rba938b8d 2 2 * @file 3 3 * 4 * @ingroup lpc24xx 4 * @ingroup lpc24xx_libi2c 5 5 * 6 6 * @brief LibI2C bus driver for the Synchronous Serial Port (SSP). … … 75 75 static uint32_t lpc24xx_ssp_trash = 0; 76 76 77 static inline bool lpc24xx_ssp_is_busy( 77 static inline bool lpc24xx_ssp_is_busy(const lpc24xx_ssp_bus_entry *bus) 78 78 { 79 79 return lpc24xx_ssp_dma_data.bus == bus … … 81 81 } 82 82 83 static void lpc24xx_ssp_handler( 83 static void lpc24xx_ssp_handler(rtems_vector_number vector, void *arg) 84 84 { 85 85 lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) arg; … … 88 88 uint32_t icr = 0; 89 89 90 if (IS_FLAG_SET( 90 if (IS_FLAG_SET(mis, SSP_MIS_RORRIS)) { 91 91 /* TODO */ 92 printk( 92 printk("%s: Receiver overrun!\n", __func__); 93 93 icr |= SSP_ICR_RORRIS; 94 94 } … … 97 97 } 98 98 99 static void lpc24xx_ssp_dma_handler( 99 static void lpc24xx_ssp_dma_handler(rtems_vector_number vector, void *arg) 100 100 { 101 101 lpc24xx_ssp_dma_entry *e = (lpc24xx_ssp_dma_entry *) arg; … … 106 106 107 107 /* Return if we are not in a transfer status */ 108 if (IS_FLAG_CLEARED( 108 if (IS_FLAG_CLEARED(status, LPC24XX_SSP_DMA_TRANSFER_FLAG)) { 109 109 return; 110 110 } … … 122 122 switch (status) { 123 123 case LPC24XX_SSP_DMA_WAIT: 124 if (ARE_FLAGS_SET( 124 if (ARE_FLAGS_SET(tc, GPDMA_STATUS_CH_0 | GPDMA_STATUS_CH_1)) { 125 125 status = LPC24XX_SSP_DMA_DONE; 126 } else if (IS_FLAG_SET( 126 } else if (IS_FLAG_SET(tc, GPDMA_STATUS_CH_0)) { 127 127 status = LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_1; 128 } else if (IS_FLAG_SET( 128 } else if (IS_FLAG_SET(tc, GPDMA_STATUS_CH_1)) { 129 129 status = LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_0; 130 130 } 131 131 break; 132 132 case LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_0: 133 if (IS_FLAG_SET( 133 if (IS_FLAG_SET(tc, GPDMA_STATUS_CH_1)) { 134 134 status = LPC24XX_SSP_DMA_ERROR; 135 } else if (IS_FLAG_SET( 135 } else if (IS_FLAG_SET(tc, GPDMA_STATUS_CH_0)) { 136 136 status = LPC24XX_SSP_DMA_DONE; 137 137 } 138 138 break; 139 139 case LPC24XX_SSP_DMA_WAIT_FOR_CHANNEL_1: 140 if (IS_FLAG_SET( 140 if (IS_FLAG_SET(tc, GPDMA_STATUS_CH_0)) { 141 141 status = LPC24XX_SSP_DMA_ERROR; 142 } else if (IS_FLAG_SET( 142 } else if (IS_FLAG_SET(tc, GPDMA_STATUS_CH_1)) { 143 143 status = LPC24XX_SSP_DMA_DONE; 144 144 } … … 154 154 /* Error cleanup */ 155 155 if (status == LPC24XX_SSP_DMA_ERROR) { 156 lpc24xx_dma_channel_disable( 157 lpc24xx_dma_channel_disable( 156 lpc24xx_dma_channel_disable(0, true); 157 lpc24xx_dma_channel_disable(1, true); 158 158 status = LPC24XX_SSP_DMA_DONE; 159 159 rv = -RTEMS_IO_ERROR; … … 164 164 status = LPC24XX_SSP_DMA_AVAILABLE; 165 165 if (e->done != NULL) { 166 e->done( 166 e->done(rv, e->n, e->arg); 167 167 e->done = NULL; 168 168 } … … 173 173 } 174 174 175 static rtems_status_code lpc24xx_ssp_init( 175 static rtems_status_code lpc24xx_ssp_init(rtems_libi2c_bus_t *bus) 176 176 { 177 177 rtems_status_code sc = RTEMS_SUCCESSFUL; … … 188 188 189 189 /* Test and set DMA support status */ 190 rtems_interrupt_disable( 190 rtems_interrupt_disable(level); 191 191 status = lpc24xx_ssp_dma_data.status; 192 192 if (status == LPC24XX_SSP_DMA_NOT_INITIALIZED) { 193 193 lpc24xx_ssp_dma_data.status = LPC24XX_SSP_DMA_INITIALIZATION; 194 194 } 195 rtems_interrupt_enable( 195 rtems_interrupt_enable(level); 196 196 197 197 if (status == LPC24XX_SSP_DMA_NOT_INITIALIZED) { … … 204 204 &lpc24xx_ssp_dma_data 205 205 ); 206 RTEMS_CHECK_SC( sc, "Install DMA interrupt handler");206 RTEMS_CHECK_SC(sc, "install DMA interrupt handler"); 207 207 208 208 /* Set DMA support status */ … … 217 217 switch ((uintptr_t) regs) { 218 218 case SSP0_BASE_ADDR: 219 rtems_interrupt_disable( 220 PCLKSEL1 = SET_PCLKSEL1_PCLK_SSP0( 221 rtems_interrupt_enable( 219 rtems_interrupt_disable(level); 220 PCLKSEL1 = SET_PCLKSEL1_PCLK_SSP0(PCLKSEL1, 1); 221 rtems_interrupt_enable(level); 222 222 223 223 vector = LPC24XX_IRQ_SPI_SSP_0; 224 224 break; 225 225 case SSP1_BASE_ADDR: 226 rtems_interrupt_disable( 227 PCLKSEL0 = SET_PCLKSEL0_PCLK_SSP1( 228 rtems_interrupt_enable( 226 rtems_interrupt_disable(level); 227 PCLKSEL0 = SET_PCLKSEL0_PCLK_SSP1(PCLKSEL0, 1); 228 rtems_interrupt_enable(level); 229 229 230 230 vector = LPC24XX_IRQ_SSP_1; … … 235 235 236 236 /* Set serial clock rate to save value */ 237 regs->cr0 = SET_SSP_CR0_SCR( 237 regs->cr0 = SET_SSP_CR0_SCR(0, 255); 238 238 239 239 /* Set clock prescaler */ … … 259 259 e 260 260 ); 261 RTEMS_CHECK_SC( sc, "Install interrupt handler");261 RTEMS_CHECK_SC(sc, "install interrupt handler"); 262 262 263 263 /* Enable receiver overrun interrupts */ … … 267 267 } 268 268 269 static rtems_status_code lpc24xx_ssp_send_start( 269 static rtems_status_code lpc24xx_ssp_send_start(rtems_libi2c_bus_t *bus) 270 270 { 271 271 return RTEMS_SUCCESSFUL; 272 272 } 273 273 274 static rtems_status_code lpc24xx_ssp_send_stop( 274 static rtems_status_code lpc24xx_ssp_send_stop(rtems_libi2c_bus_t *bus) 275 275 { 276 276 lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) bus; … … 279 279 if (lpc24xx_ssp_dma_data.bus == e) { 280 280 if (lpc24xx_ssp_dma_data.status == LPC24XX_SSP_DMA_AVAILABLE) { 281 lpc24xx_dma_channel_release( 282 lpc24xx_dma_channel_release( 281 lpc24xx_dma_channel_release(0); 282 lpc24xx_dma_channel_release(1); 283 283 lpc24xx_ssp_dma_data.bus = NULL; 284 284 } else { … … 298 298 lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) bus; 299 299 300 if (lpc24xx_ssp_is_busy( 300 if (lpc24xx_ssp_is_busy(e)) { 301 301 return RTEMS_RESOURCE_IN_USE; 302 302 } … … 316 316 unsigned scr = (clk + br - 1) / br; 317 317 318 if (lpc24xx_ssp_is_busy( 318 if (lpc24xx_ssp_is_busy(e)) { 319 319 return -RTEMS_RESOURCE_IN_USE; 320 320 } … … 364 364 e->idle_char = mode->idle_char; 365 365 366 while (IS_FLAG_CLEARED( 366 while (IS_FLAG_CLEARED(regs->sr, SSP_SR_TFE)) { 367 367 /* Wait */ 368 368 } 369 369 370 regs->cr0 = SET_SSP_CR0_DSS( 371 | SET_SSP_CR0_SCR( 370 regs->cr0 = SET_SSP_CR0_DSS(0, 0x7) 371 | SET_SSP_CR0_SCR(0, scr) 372 372 | (mode->clock_inv ? SSP_CR0_CPOL : 0) 373 373 | (mode->clock_phs ? SSP_CR0_CPHA : 0); … … 394 394 unsigned char idle_char = (unsigned char) e->idle_char; 395 395 396 if (lpc24xx_ssp_is_busy( 396 if (lpc24xx_ssp_is_busy(e)) { 397 397 return -RTEMS_RESOURCE_IN_USE; 398 398 } … … 427 427 428 428 /* Write */ 429 if (IS_FLAG_SET( 429 if (IS_FLAG_SET(sr, SSP_SR_TNF) && m < LPC24XX_SSP_FIFO_SIZE) { 430 430 regs->dr = *out; 431 431 ++w; … … 434 434 435 435 /* Read */ 436 if (IS_FLAG_SET( 436 if (IS_FLAG_SET(sr, SSP_SR_RNE)) { 437 437 *in = (unsigned char) regs->dr; 438 438 ++r; … … 449 449 do { 450 450 sr = regs->sr; 451 } while (IS_FLAG_CLEARED( 451 } while (IS_FLAG_CLEARED(sr, SSP_SR_RNE)); 452 452 453 453 /* Read */ … … 473 473 lpc24xx_ssp_bus_entry *e = (lpc24xx_ssp_bus_entry *) bus; 474 474 volatile lpc24xx_ssp *ssp = e->regs; 475 volatile lpc24xx_dma_channel *receive_channel = GPDMA_CH_BASE_ADDR( 476 volatile lpc24xx_dma_channel *transmit_channel = GPDMA_CH_BASE_ADDR( 475 volatile lpc24xx_dma_channel *receive_channel = GPDMA_CH_BASE_ADDR(0); 476 volatile lpc24xx_dma_channel *transmit_channel = GPDMA_CH_BASE_ADDR(1); 477 477 uint32_t di = GPDMA_CH_CTRL_DI; 478 478 uint32_t si = GPDMA_CH_CTRL_SI; … … 484 484 /* Try to reserve DMA support for this bus */ 485 485 if (lpc24xx_ssp_dma_data.bus == NULL) { 486 rtems_interrupt_disable( 486 rtems_interrupt_disable(level); 487 487 if (lpc24xx_ssp_dma_data.bus == NULL) { 488 488 lpc24xx_ssp_dma_data.bus = e; 489 489 } 490 rtems_interrupt_enable( 490 rtems_interrupt_enable(level); 491 491 492 492 /* Try to obtain DMA channels */ 493 493 if (lpc24xx_ssp_dma_data.bus == e) { 494 bool channel_0 = lpc24xx_dma_channel_obtain(0);495 bool channel_1 = lpc24xx_dma_channel_obtain(1);496 497 if ( !channel_0 && channel_1) {498 lpc24xx_dma_channel_release( 1);499 lpc24xx_ssp_dma_data.bus = NULL;500 } else if (channel_0 && !channel_1) {501 lpc24xx_dma_channel_release( 0);502 lpc24xx_ssp_dma_data.bus = NULL;503 } else if (!channel_0 || !channel_1) {494 rtems_status_code cs0 = lpc24xx_dma_channel_obtain(0); 495 rtems_status_code cs1 = lpc24xx_dma_channel_obtain(1); 496 497 if (cs0 != RTEMS_SUCCESSFUL || cs1 != RTEMS_SUCCESSFUL) { 498 if (cs0 == RTEMS_SUCCESSFUL) { 499 lpc24xx_dma_channel_release(0); 500 } 501 if (cs1 == RTEMS_SUCCESSFUL) { 502 lpc24xx_dma_channel_release(1); 503 } 504 504 lpc24xx_ssp_dma_data.bus = NULL; 505 505 } … … 524 524 /* Receive */ 525 525 if (in != NULL) { 526 receive_channel->des t = (uint32_t) in;526 receive_channel->desc.dest = (uint32_t) in; 527 527 } else { 528 receive_channel->des t = (uint32_t) &lpc24xx_ssp_trash;528 receive_channel->desc.dest = (uint32_t) &lpc24xx_ssp_trash; 529 529 di = 0; 530 530 } 531 receive_channel-> src = (uint32_t) &ssp->dr;532 receive_channel-> lli = 0;533 receive_channel-> ctrl = SET_GPDMA_CH_CTRL_TSZ(0, n)534 | SET_GPDMA_CH_CTRL_SBSZ( 535 | SET_GPDMA_CH_CTRL_DBSZ( 536 | SET_GPDMA_CH_CTRL_SW( 537 | SET_GPDMA_CH_CTRL_DW( 531 receive_channel->desc.src = (uint32_t) &ssp->dr; 532 receive_channel->desc.lli = 0; 533 receive_channel->desc.ctrl = SET_GPDMA_CH_CTRL_TSZ(0, n) 534 | SET_GPDMA_CH_CTRL_SBSZ(0, GPDMA_CH_CTRL_BSZ_4) 535 | SET_GPDMA_CH_CTRL_DBSZ(0, GPDMA_CH_CTRL_BSZ_4) 536 | SET_GPDMA_CH_CTRL_SW(0, GPDMA_CH_CTRL_W_8) 537 | SET_GPDMA_CH_CTRL_DW(0, GPDMA_CH_CTRL_W_8) 538 538 | GPDMA_CH_CTRL_ITC 539 539 | di; 540 receive_channel->cfg = SET_GPDMA_CH_CFG_SRCPER( 541 | SET_GPDMA_CH_CFG_FLOW( 540 receive_channel->cfg = SET_GPDMA_CH_CFG_SRCPER(0, GPDMA_CH_CFG_PER_SSP1_RX) 541 | SET_GPDMA_CH_CFG_FLOW(0, GPDMA_CH_CFG_FLOW_PER_TO_MEM_DMA) 542 542 | GPDMA_CH_CFG_IE 543 543 | GPDMA_CH_CFG_ITC … … 546 546 /* Transmit */ 547 547 if (out != NULL) { 548 transmit_channel-> src = (uint32_t) out;548 transmit_channel->desc.src = (uint32_t) out; 549 549 } else { 550 transmit_channel-> src = (uint32_t) &e->idle_char;550 transmit_channel->desc.src = (uint32_t) &e->idle_char; 551 551 si = 0; 552 552 } 553 transmit_channel->des t = (uint32_t) &ssp->dr;554 transmit_channel-> lli = 0;555 transmit_channel-> ctrl = SET_GPDMA_CH_CTRL_TSZ(0, n)556 | SET_GPDMA_CH_CTRL_SBSZ( 557 | SET_GPDMA_CH_CTRL_DBSZ( 558 | SET_GPDMA_CH_CTRL_SW( 559 | SET_GPDMA_CH_CTRL_DW( 553 transmit_channel->desc.dest = (uint32_t) &ssp->dr; 554 transmit_channel->desc.lli = 0; 555 transmit_channel->desc.ctrl = SET_GPDMA_CH_CTRL_TSZ(0, n) 556 | SET_GPDMA_CH_CTRL_SBSZ(0, GPDMA_CH_CTRL_BSZ_4) 557 | SET_GPDMA_CH_CTRL_DBSZ(0, GPDMA_CH_CTRL_BSZ_4) 558 | SET_GPDMA_CH_CTRL_SW(0, GPDMA_CH_CTRL_W_8) 559 | SET_GPDMA_CH_CTRL_DW(0, GPDMA_CH_CTRL_W_8) 560 560 | GPDMA_CH_CTRL_ITC 561 561 | si; 562 transmit_channel->cfg = SET_GPDMA_CH_CFG_DESTPER( 563 | SET_GPDMA_CH_CFG_FLOW( 562 transmit_channel->cfg = SET_GPDMA_CH_CFG_DESTPER(0, GPDMA_CH_CFG_PER_SSP1_TX) 563 | SET_GPDMA_CH_CFG_FLOW(0, GPDMA_CH_CFG_FLOW_MEM_TO_PER_DMA) 564 564 | GPDMA_CH_CFG_IE 565 565 | GPDMA_CH_CFG_ITC … … 569 569 } 570 570 571 static int lpc24xx_ssp_read( 572 { 573 return lpc24xx_ssp_read_write( 571 static int lpc24xx_ssp_read(rtems_libi2c_bus_t *bus, unsigned char *in, int n) 572 { 573 return lpc24xx_ssp_read_write(bus, in, NULL, n); 574 574 } 575 575 … … 580 580 ) 581 581 { 582 return lpc24xx_ssp_read_write( 583 } 584 585 static int lpc24xx_ssp_ioctl( 582 return lpc24xx_ssp_read_write(bus, NULL, out, n); 583 } 584 585 static int lpc24xx_ssp_ioctl(rtems_libi2c_bus_t *bus, int cmd, void *arg) 586 586 { 587 587 int rv = -1; … … 593 593 switch (cmd) { 594 594 case RTEMS_LIBI2C_IOCTL_READ_WRITE: 595 rv = lpc24xx_ssp_read_write( 595 rv = lpc24xx_ssp_read_write(bus, rw->rd_buf, rw->wr_buf, rw->byte_cnt); 596 596 break; 597 597 case RTEMS_LIBI2C_IOCTL_READ_WRITE_ASYNC: … … 606 606 break; 607 607 case RTEMS_LIBI2C_IOCTL_SET_TFRMODE: 608 rv = lpc24xx_ssp_set_transfer_mode( 608 rv = lpc24xx_ssp_set_transfer_mode(bus, tm); 609 609 break; 610 610 default: … … 631 631 .bus = { 632 632 .ops = &lpc24xx_ssp_ops, 633 .size = sizeof( 633 .size = sizeof(lpc24xx_ssp_bus_entry) 634 634 }, 635 635 .regs = (volatile lpc24xx_ssp *) SSP0_BASE_ADDR, … … 640 640 .bus = { 641 641 .ops = &lpc24xx_ssp_ops, 642 .size = sizeof( 642 .size = sizeof(lpc24xx_ssp_bus_entry) 643 643 }, 644 644 .regs = (volatile lpc24xx_ssp *) SSP1_BASE_ADDR,
Note: See TracChangeset
for help on using the changeset viewer.