![]() |
|
|||
File indexing completed on 2025-05-11 08:23:45
0001 /* 0002 * This file contains the M360 SPI driver 0003 */ 0004 0005 /* 0006 * Copyright (c) 2008 Embedded Brains GmbH. All rights reserved. 0007 * 0008 * 0009 * The license and distribution terms for this file may be 0010 * found in the file LICENSE in this distribution or at 0011 * http://www.rtems.org/license/LICENSE. 0012 */ 0013 0014 #include <stdlib.h> 0015 #include <bsp.h> 0016 #include <rtems/m68k/m68360.h> 0017 #include <rtems/m68k/m360_spi.h> 0018 #include <rtems/error.h> 0019 #include <rtems/bspIo.h> 0020 #include <errno.h> 0021 #include <rtems/libi2c.h> 0022 0023 #undef DEBUG 0024 static m360_spi_softc_t *m360_spi_softc_ptr; 0025 /* 0026 * this is a dummy receive buffer for sequences, 0027 * where only send data are available 0028 */ 0029 uint8_t m360_spi_dummy_rxbuf[2]; 0030 /*=========================================================================*\ 0031 | Function: | 0032 \*-------------------------------------------------------------------------*/ 0033 static rtems_status_code m360_spi_baud_to_mode 0034 ( 0035 /*-------------------------------------------------------------------------*\ 0036 | Purpose: | 0037 | determine proper divider value | 0038 +---------------------------------------------------------------------------+ 0039 | Input Parameters: | 0040 \*-------------------------------------------------------------------------*/ 0041 uint32_t baudrate, /* desired baudrate */ 0042 uint32_t *spimode /* result value */ 0043 ) 0044 /*-------------------------------------------------------------------------*\ 0045 | Return Value: | 0046 | o = ok or error code | 0047 \*=========================================================================*/ 0048 { 0049 uint32_t divider; 0050 uint16_t tmpmode = 0; 0051 /* 0052 * determine clock divider and DIV16 bit 0053 */ 0054 divider = m360_clock_rate/baudrate; 0055 if (divider > 64) { 0056 tmpmode = M360_SPMODE_DIV16; 0057 divider /= 16; 0058 } 0059 if ((divider < 1) || 0060 (divider > 64)) { 0061 return RTEMS_INVALID_NUMBER; 0062 } 0063 else { 0064 tmpmode |= M360_SPMODE_PM(divider/4-1); 0065 } 0066 *spimode = tmpmode; 0067 return RTEMS_SUCCESSFUL; 0068 } 0069 0070 /*=========================================================================*\ 0071 | Function: | 0072 \*-------------------------------------------------------------------------*/ 0073 static rtems_status_code m360_spi_char_mode 0074 ( 0075 /*-------------------------------------------------------------------------*\ 0076 | Purpose: | 0077 | determine proper value for character size | 0078 +---------------------------------------------------------------------------+ 0079 | Input Parameters: | 0080 \*-------------------------------------------------------------------------*/ 0081 m360_spi_softc_t *softc_ptr, /* handle */ 0082 uint32_t bits_per_char, /* bits per character */ 0083 bool lsb_first, /* TRUE: send LSB first */ 0084 uint16_t *spimode /* result value */ 0085 ) 0086 /*-------------------------------------------------------------------------*\ 0087 | Return Value: | 0088 | o = ok or error code | 0089 \*=========================================================================*/ 0090 { 0091 uint16_t tmpmode; 0092 0093 /* 0094 * calculate data format 0095 */ 0096 if ((bits_per_char >= 4) && 0097 (bits_per_char <= 16)) { 0098 tmpmode = M360_SPMODE_CLEN( bits_per_char-1); 0099 } 0100 else { 0101 return RTEMS_INVALID_NUMBER; 0102 } 0103 0104 *spimode = tmpmode; 0105 return 0; 0106 } 0107 0108 /*=========================================================================*\ 0109 | Function: | 0110 \*-------------------------------------------------------------------------*/ 0111 static int m360_spi_wait 0112 ( 0113 /*-------------------------------------------------------------------------*\ 0114 | Purpose: | 0115 | wait for spi to become idle | 0116 +---------------------------------------------------------------------------+ 0117 | Input Parameters: | 0118 \*-------------------------------------------------------------------------*/ 0119 m360_spi_softc_t *softc_ptr /* handle */ 0120 ) 0121 /*-------------------------------------------------------------------------*\ 0122 | Return Value: | 0123 | o = ok or error code | 0124 \*=========================================================================*/ 0125 { 0126 uint16_t act_status; 0127 rtems_status_code rc; 0128 uint32_t tout; 0129 0130 #if defined(DEBUG) 0131 printk("m360_spi_wait called... "); 0132 #endif 0133 if (softc_ptr->initialized) { 0134 /* 0135 * allow interrupts, when receiver is not empty 0136 */ 0137 m360.spim = (M360_SPIE_TXE | M360_SPIE_TXB | 0138 M360_SPIE_BSY | M360_SPIE_MME); 0139 0140 rc = rtems_semaphore_obtain(softc_ptr->irq_sema_id, 0141 RTEMS_WAIT, 0142 RTEMS_NO_TIMEOUT); 0143 if (rc != RTEMS_SUCCESSFUL) { 0144 return rc; 0145 } 0146 } 0147 else { 0148 tout = 0; 0149 do { 0150 if (tout++ > 1000000) { 0151 #if defined(DEBUG) 0152 printk("... exit with RTEMS_TIMEOUT\r\n"); 0153 #endif 0154 return RTEMS_TIMEOUT; 0155 } 0156 /* 0157 * wait for SPI to terminate 0158 */ 0159 } while (!(m360.spie & M360_SPIE_TXB)); 0160 } 0161 0162 act_status = m360.spie; 0163 if ((act_status & (M360_SPIE_TXE | M360_SPIE_TXB | 0164 M360_SPIE_BSY | M360_SPIE_MME))!= M360_SPIE_TXB) { 0165 #if defined(DEBUG) 0166 printk("... exit with RTEMS_IO_ERROR," 0167 "act_status=0x%04x,mask=0x%04x,desired_status=0x%04x\r\n", 0168 act_status,status_mask,desired_status); 0169 #endif 0170 return RTEMS_IO_ERROR; 0171 } 0172 #if defined(DEBUG) 0173 printk("... exit OK\r\n"); 0174 #endif 0175 return RTEMS_SUCCESSFUL; 0176 } 0177 0178 /*=========================================================================*\ 0179 | Function: | 0180 \*-------------------------------------------------------------------------*/ 0181 static rtems_isr m360_spi_irq_handler 0182 ( 0183 /*-------------------------------------------------------------------------*\ 0184 | Purpose: | 0185 | handle interrupts | 0186 +---------------------------------------------------------------------------+ 0187 | Input Parameters: | 0188 \*-------------------------------------------------------------------------*/ 0189 rtems_vector_number v /* vector number */ 0190 ) 0191 /*-------------------------------------------------------------------------*\ 0192 | Return Value: | 0193 | <none> | 0194 \*=========================================================================*/ 0195 { 0196 m360_spi_softc_t *softc_ptr = m360_spi_softc_ptr; 0197 0198 /* 0199 * disable interrupt mask 0200 */ 0201 m360.spim = 0; 0202 if (softc_ptr->initialized) { 0203 rtems_semaphore_release(softc_ptr->irq_sema_id); 0204 } 0205 } 0206 0207 /*=========================================================================*\ 0208 | Function: | 0209 \*-------------------------------------------------------------------------*/ 0210 static void m360_spi_install_irq_handler 0211 ( 0212 /*-------------------------------------------------------------------------*\ 0213 | Purpose: | 0214 | (un-)install the interrupt handler | 0215 +---------------------------------------------------------------------------+ 0216 | Input Parameters: | 0217 \*-------------------------------------------------------------------------*/ 0218 m360_spi_softc_t *softc_ptr, /* ptr to control structure */ 0219 int install /* TRUE: install, FALSE: remove */ 0220 ) 0221 /*-------------------------------------------------------------------------*\ 0222 | Return Value: | 0223 | <none> | 0224 \*=========================================================================*/ 0225 { 0226 rtems_status_code rc = RTEMS_SUCCESSFUL; 0227 0228 /* 0229 * (un-)install handler for SPI device 0230 */ 0231 if (install) { 0232 /* 0233 * create semaphore for IRQ synchronization 0234 */ 0235 rc = rtems_semaphore_create(rtems_build_name('s','p','i','s'), 0236 0, 0237 RTEMS_FIFO 0238 | RTEMS_SIMPLE_BINARY_SEMAPHORE, 0239 0, 0240 &softc_ptr->irq_sema_id); 0241 if (rc != RTEMS_SUCCESSFUL) { 0242 rtems_panic("SPI: cannot create semaphore"); 0243 } 0244 if (rc == RTEMS_SUCCESSFUL) { 0245 rc = rtems_interrupt_catch (m360_spi_irq_handler, 0246 (m360.cicr & 0xE0) | 0x05, 0247 &softc_ptr->old_handler); 0248 if (rc != RTEMS_SUCCESSFUL) { 0249 rtems_panic("SPI: cannot install IRQ handler"); 0250 } 0251 } 0252 /* 0253 * enable IRQ in CPIC 0254 */ 0255 if (rc == RTEMS_SUCCESSFUL) { 0256 m360.cimr |= (1 << 5); 0257 } 0258 } 0259 else { 0260 rtems_isr_entry old_handler; 0261 /* 0262 * disable IRQ in CPIC 0263 */ 0264 if (rc == RTEMS_SUCCESSFUL) { 0265 m360.cimr &= ~(1 << 5); 0266 } 0267 rc = rtems_interrupt_catch (softc_ptr->old_handler, 0268 (m360.cicr & 0xE0) | 0x05, 0269 &old_handler); 0270 if (rc != RTEMS_SUCCESSFUL) { 0271 rtems_panic("SPI: cannot uninstall IRQ handler"); 0272 } 0273 /* 0274 * delete sync semaphore 0275 */ 0276 if (softc_ptr->irq_sema_id != 0) { 0277 rc = rtems_semaphore_delete(softc_ptr->irq_sema_id); 0278 if (rc != RTEMS_SUCCESSFUL) { 0279 rtems_panic("SPI: cannot delete semaphore"); 0280 } 0281 } 0282 } 0283 } 0284 0285 /*=========================================================================*\ 0286 | Function: | 0287 \*-------------------------------------------------------------------------*/ 0288 rtems_status_code m360_spi_init 0289 ( 0290 /*-------------------------------------------------------------------------*\ 0291 | Purpose: | 0292 | initialize the driver | 0293 +---------------------------------------------------------------------------+ 0294 | Input Parameters: | 0295 \*-------------------------------------------------------------------------*/ 0296 rtems_libi2c_bus_t *bh /* bus specifier structure */ 0297 ) 0298 /*-------------------------------------------------------------------------*\ 0299 | Return Value: | 0300 | o = ok or error code | 0301 \*=========================================================================*/ 0302 { 0303 m360_spi_softc_t *softc_ptr = &(((m360_spi_desc_t *)(bh))->softc); 0304 rtems_status_code rc = RTEMS_SUCCESSFUL; 0305 0306 #if defined(DEBUG) 0307 printk("m360_spi_init called... "); 0308 #endif 0309 /* 0310 * init HW registers: 0311 */ 0312 /* 0313 * FIXME: set default mode in SPMODE 0314 */ 0315 0316 /* 0317 * allocate BDs (1x RX, 1x TX) 0318 */ 0319 if (rc == RTEMS_SUCCESSFUL) { 0320 softc_ptr->rx_bd = M360AllocateBufferDescriptors (1); 0321 softc_ptr->tx_bd = M360AllocateBufferDescriptors (1); 0322 if ((softc_ptr->rx_bd == NULL) || 0323 (softc_ptr->tx_bd == NULL)) { 0324 rc = RTEMS_NO_MEMORY; 0325 } 0326 } 0327 /* 0328 * set parameter RAM 0329 */ 0330 m360.spip.rbase = (char *)softc_ptr->rx_bd - (char *)&m360; 0331 m360.spip.tbase = (char *)softc_ptr->tx_bd - (char *)&m360; 0332 m360.spip.rfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE; 0333 m360.spip.tfcr = M360_RFCR_MOT | M360_RFCR_DMA_SPACE; 0334 m360.spip.mrblr = 2; 0335 0336 /* 0337 * issue "InitRxTx" Command to CP 0338 */ 0339 M360ExecuteRISC (M360_CR_OP_INIT_RX_TX | M360_CR_CHAN_SPI); 0340 0341 /* 0342 * init interrupt stuff 0343 */ 0344 if (rc == RTEMS_SUCCESSFUL) { 0345 m360_spi_install_irq_handler(softc_ptr,TRUE); 0346 } 0347 if (rc == RTEMS_SUCCESSFUL) { 0348 /* 0349 * set up ports 0350 * LINE PAR DIR DAT 0351 * ----------------------- 0352 * MOSI 1 1 x 0353 * MISO 1 1 x 0354 * CLK 1 1 x 0355 */ 0356 0357 /* set Port B Pin Assignment Register... */ 0358 m360.pbpar = 0359 m360.pbpar 0360 | M360_PB_SPI_MISO_MSK 0361 | M360_PB_SPI_MOSI_MSK 0362 | M360_PB_SPI_CLK_MSK; 0363 0364 /* set Port B Data Direction Register... */ 0365 m360.pbdir = 0366 m360.pbdir 0367 | M360_PB_SPI_MISO_MSK 0368 | M360_PB_SPI_MOSI_MSK 0369 | M360_PB_SPI_CLK_MSK; 0370 } 0371 /* 0372 * mark, that we have initialized 0373 */ 0374 if (rc == RTEMS_SUCCESSFUL) { 0375 softc_ptr->initialized = TRUE; 0376 } 0377 #if defined(DEBUG) 0378 printk("... exit OK\r\n"); 0379 #endif 0380 return rc; 0381 } 0382 0383 0384 /*=========================================================================*\ 0385 | Function: | 0386 \*-------------------------------------------------------------------------*/ 0387 static int m360_spi_read_write_bytes 0388 ( 0389 /*-------------------------------------------------------------------------*\ 0390 | Purpose: | 0391 | transmit/receive some bytes from SPI device | 0392 +---------------------------------------------------------------------------+ 0393 | Input Parameters: | 0394 \*-------------------------------------------------------------------------*/ 0395 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0396 unsigned char *rbuf, /* buffer to store bytes */ 0397 const unsigned char *tbuf, /* buffer to send bytes */ 0398 int len /* number of bytes to transceive */ 0399 ) 0400 /*-------------------------------------------------------------------------*\ 0401 | Return Value: | 0402 | number of bytes received or (negative) error code | 0403 \*=========================================================================*/ 0404 { 0405 m360_spi_softc_t *softc_ptr = &(((m360_spi_desc_t *)(bh))->softc); 0406 rtems_status_code rc = RTEMS_SUCCESSFUL; 0407 int bc = 0; 0408 0409 #if defined(DEBUG) 0410 printk("m360_spi_read_write_bytes called... "); 0411 #endif 0412 0413 /* 0414 * prepare RxBD 0415 */ 0416 if (rc == RTEMS_SUCCESSFUL) { 0417 if (rbuf == NULL) { 0418 /* 0419 * no Tx buffer: receive to dummy buffer 0420 */ 0421 m360.spip.mrblr = sizeof(m360_spi_dummy_rxbuf); 0422 softc_ptr->rx_bd->buffer = m360_spi_dummy_rxbuf; 0423 softc_ptr->rx_bd->length = 0; 0424 softc_ptr->rx_bd->status = (M360_BD_EMPTY | M360_BD_WRAP | 0425 M360_BD_CONTINUOUS); 0426 } 0427 else { 0428 m360.spip.mrblr = len; 0429 softc_ptr->rx_bd->buffer = rbuf; 0430 softc_ptr->rx_bd->length = 0; 0431 softc_ptr->rx_bd->status = (M360_BD_EMPTY | M360_BD_WRAP); 0432 } 0433 } 0434 /* 0435 * prepare TxBD 0436 */ 0437 if (rc == RTEMS_SUCCESSFUL) { 0438 if (tbuf == NULL) { 0439 /* 0440 * FIXME: no Tx buffer: transmit from dummy buffer 0441 */ 0442 softc_ptr->tx_bd->buffer = m360_spi_dummy_rxbuf; 0443 softc_ptr->tx_bd->length = len; 0444 softc_ptr->tx_bd->status = (M360_BD_READY | M360_BD_WRAP | 0445 M360_BD_CONTINUOUS); 0446 } 0447 else { 0448 softc_ptr->tx_bd->buffer = tbuf; 0449 softc_ptr->tx_bd->length = len; 0450 softc_ptr->tx_bd->status = (M360_BD_READY | M360_BD_WRAP); 0451 } 0452 } 0453 0454 if (rc == RTEMS_SUCCESSFUL) { 0455 /* 0456 * set START command 0457 */ 0458 m360.spcom = M360_SPCOM_STR; 0459 /* 0460 * wait for SPI to finish 0461 */ 0462 rc = m360_spi_wait(softc_ptr); 0463 } 0464 #if defined(DEBUG) 0465 printk("... exit OK, rc=%d\r\n",bc); 0466 #endif 0467 return (rc == RTEMS_SUCCESSFUL) ? bc : -rc; 0468 } 0469 0470 /*=========================================================================*\ 0471 | Function: | 0472 \*-------------------------------------------------------------------------*/ 0473 int m360_spi_read_bytes 0474 ( 0475 /*-------------------------------------------------------------------------*\ 0476 | Purpose: | 0477 | receive some bytes from SPI device | 0478 +---------------------------------------------------------------------------+ 0479 | Input Parameters: | 0480 \*-------------------------------------------------------------------------*/ 0481 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0482 unsigned char *buf, /* buffer to store bytes */ 0483 int len /* number of bytes to receive */ 0484 ) 0485 /*-------------------------------------------------------------------------*\ 0486 | Return Value: | 0487 | number of bytes received or (negative) error code | 0488 \*=========================================================================*/ 0489 { 0490 return m360_spi_read_write_bytes(bh,buf,NULL,len); 0491 } 0492 0493 /*=========================================================================*\ 0494 | Function: | 0495 \*-------------------------------------------------------------------------*/ 0496 int m360_spi_write_bytes 0497 ( 0498 /*-------------------------------------------------------------------------*\ 0499 | Purpose: | 0500 | send some bytes to SPI device | 0501 +---------------------------------------------------------------------------+ 0502 | Input Parameters: | 0503 \*-------------------------------------------------------------------------*/ 0504 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0505 unsigned char *buf, /* buffer to send */ 0506 int len /* number of bytes to send */ 0507 0508 ) 0509 /*-------------------------------------------------------------------------*\ 0510 | Return Value: | 0511 | number of bytes sent or (negative) error code | 0512 \*=========================================================================*/ 0513 { 0514 return m360_spi_read_write_bytes(bh,NULL,buf,len); 0515 } 0516 0517 /*=========================================================================*\ 0518 | Function: | 0519 \*-------------------------------------------------------------------------*/ 0520 rtems_status_code m360_spi_set_tfr_mode 0521 ( 0522 /*-------------------------------------------------------------------------*\ 0523 | Purpose: | 0524 | set SPI to desired baudrate/clock mode/character mode | 0525 +---------------------------------------------------------------------------+ 0526 | Input Parameters: | 0527 \*-------------------------------------------------------------------------*/ 0528 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0529 const rtems_libi2c_tfr_mode_t *tfr_mode /* transfer mode info */ 0530 ) 0531 /*-------------------------------------------------------------------------*\ 0532 | Return Value: | 0533 | rtems_status_code | 0534 \*=========================================================================*/ 0535 { 0536 m360_spi_softc_t *softc_ptr = &(((m360_spi_desc_t *)(bh))->softc); 0537 uint32_t spimode_baud,spimode; 0538 rtems_status_code rc = RTEMS_SUCCESSFUL; 0539 /* 0540 * FIXME: set proper mode 0541 */ 0542 if (rc == RTEMS_SUCCESSFUL) { 0543 rc = m360_spi_baud_to_mode(tfr_mode->baudrate,&spimode_baud); 0544 } 0545 if (rc == RTEMS_SUCCESSFUL) { 0546 rc = m360_spi_char_mode(softc_ptr, 0547 tfr_mode->bits_per_char, 0548 tfr_mode->lsb_first, 0549 &spimode); 0550 } 0551 if (rc == RTEMS_SUCCESSFUL) { 0552 spimode |= spimode_baud; 0553 spimode |= M360_SPMODE_MASTER; /* set master mode */ 0554 if (!tfr_mode->lsb_first) { 0555 spimode |= M360_SPMODE_REV; 0556 } 0557 if (tfr_mode->clock_inv) { 0558 spimode |= M360_SPMODE_CI; 0559 } 0560 if (tfr_mode->clock_phs) { 0561 spimode |= M360_SPMODE_CP; 0562 } 0563 } 0564 0565 if (rc == RTEMS_SUCCESSFUL) { 0566 /* 0567 * disable SPI 0568 */ 0569 m360.spmode &= ~M360_SPMODE_EN; 0570 /* 0571 * set new mode and reenable SPI 0572 */ 0573 m360.spmode = spimode | M360_SPMODE_EN; 0574 } 0575 return rc; 0576 } 0577 0578 0579 /*=========================================================================*\ 0580 | Function: | 0581 \*-------------------------------------------------------------------------*/ 0582 int m360_spi_ioctl 0583 ( 0584 /*-------------------------------------------------------------------------*\ 0585 | Purpose: | 0586 | perform selected ioctl function for SPI | 0587 +---------------------------------------------------------------------------+ 0588 | Input Parameters: | 0589 \*-------------------------------------------------------------------------*/ 0590 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0591 int cmd, /* ioctl command code */ 0592 void *arg /* additional argument array */ 0593 ) 0594 /*-------------------------------------------------------------------------*\ 0595 | Return Value: | 0596 | rtems_status_code | 0597 \*=========================================================================*/ 0598 { 0599 int ret_val = -1; 0600 0601 switch(cmd) { 0602 case RTEMS_LIBI2C_IOCTL_SET_TFRMODE: 0603 ret_val = 0604 -m360_spi_set_tfr_mode(bh, 0605 (const rtems_libi2c_tfr_mode_t *)arg); 0606 break; 0607 case RTEMS_LIBI2C_IOCTL_READ_WRITE: 0608 ret_val = 0609 m360_spi_read_write_bytes(bh, 0610 ((rtems_libi2c_read_write_t *)arg)->rd_buf, 0611 ((rtems_libi2c_read_write_t *)arg)->wr_buf, 0612 ((rtems_libi2c_read_write_t *)arg)->byte_cnt); 0613 break; 0614 default: 0615 ret_val = -RTEMS_NOT_DEFINED; 0616 break; 0617 } 0618 return ret_val; 0619 } 0620 0621 /*=========================================================================*\ 0622 | Board-specific adaptation functions | 0623 \*=========================================================================*/ 0624 0625 /*=========================================================================*\ 0626 | Function: | 0627 \*-------------------------------------------------------------------------*/ 0628 static rtems_status_code bsp_spi_sel_addr 0629 ( 0630 /*-------------------------------------------------------------------------*\ 0631 | Purpose: | 0632 | address a slave device on the bus | 0633 +---------------------------------------------------------------------------+ 0634 | Input Parameters: | 0635 \*-------------------------------------------------------------------------*/ 0636 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0637 uint32_t addr, /* address to send on bus */ 0638 int rw /* 0=write,1=read */ 0639 ) 0640 /*-------------------------------------------------------------------------*\ 0641 | Return Value: | 0642 | o = ok or error code | 0643 \*=========================================================================*/ 0644 { 0645 #if defined(PGH360) 0646 /* 0647 * select given device 0648 */ 0649 /* 0650 * GPIO1[24] is SPI_A0 0651 * GPIO1[25] is SPI_A1 0652 * GPIO1[26] is SPI_A2 0653 * set pins to address 0654 */ 0655 switch(addr) { 0656 case PGH360_SPI_ADDR_EEPROM: 0657 m360.pbdat &= ~PGH360_PB_SPI_EEP_CE_MSK; 0658 break; 0659 case PGH360_SPI_ADDR_DISP4_DATA: 0660 m360.pbdat = (m360.pbdat 0661 & ~(PGH360_PB_SPI_DISP4_CE_MSK | 0662 PGH360_PB_SPI_DISP4_RS_MSK)); 0663 break; 0664 case PGH360_SPI_ADDR_DISP4_CTRL: 0665 m360.pbdat = (m360.pbdat 0666 & ~(PGH360_PB_SPI_DISP4_CE_MSK) 0667 | PGH360_PB_SPI_DISP4_RS_MSK); 0668 break; 0669 default: 0670 return RTEMS_INVALID_NUMBER; 0671 } 0672 #endif /* PGH360 */ 0673 return RTEMS_SUCCESSFUL; 0674 } 0675 0676 /*=========================================================================*\ 0677 | Function: | 0678 \*-------------------------------------------------------------------------*/ 0679 static rtems_status_code bsp_spi_send_start_dummy 0680 ( 0681 /*-------------------------------------------------------------------------*\ 0682 | Purpose: | 0683 | dummy function, SPI has no start condition | 0684 +---------------------------------------------------------------------------+ 0685 | Input Parameters: | 0686 \*-------------------------------------------------------------------------*/ 0687 rtems_libi2c_bus_t *bh /* bus specifier structure */ 0688 ) 0689 /*-------------------------------------------------------------------------*\ 0690 | Return Value: | 0691 | o = ok or error code | 0692 \*=========================================================================*/ 0693 { 0694 return 0; 0695 } 0696 0697 /*=========================================================================*\ 0698 | Function: | 0699 \*-------------------------------------------------------------------------*/ 0700 static rtems_status_code bsp_spi_send_stop 0701 ( 0702 /*-------------------------------------------------------------------------*\ 0703 | Purpose: | 0704 | deselect SPI | 0705 +---------------------------------------------------------------------------+ 0706 | Input Parameters: | 0707 \*-------------------------------------------------------------------------*/ 0708 rtems_libi2c_bus_t *bh /* bus specifier structure */ 0709 ) 0710 /*-------------------------------------------------------------------------*\ 0711 | Return Value: | 0712 | o = ok or error code | 0713 \*=========================================================================*/ 0714 { 0715 #if defined(DEBUG) 0716 printk("bsp_spi_send_stop called... "); 0717 #endif 0718 #if defined(PGH360) 0719 m360.pbdat = (m360.pbdat 0720 | PGH360_PB_SPI_DISP4_CE_MSK 0721 | PGH360_PB_SPI_EEP_CE_MSK); 0722 #endif 0723 #if defined(DEBUG) 0724 printk("... exit OK\r\n"); 0725 #endif 0726 return 0; 0727 } 0728 0729 /*=========================================================================*\ 0730 | list of handlers | 0731 \*=========================================================================*/ 0732 0733 rtems_libi2c_bus_ops_t bsp_spi_ops = { 0734 init: m360_spi_init, 0735 send_start: bsp_spi_send_start_dummy, 0736 send_stop: bsp_spi_send_stop, 0737 send_addr: bsp_spi_sel_addr, 0738 read_bytes: m360_spi_read_bytes, 0739 write_bytes: m360_spi_write_bytes, 0740 ioctl: m360_spi_ioctl 0741 }; 0742 0743 static m360_spi_desc_t bsp_spi_bus_desc = { 0744 {/* public fields */ 0745 ops: &bsp_spi_ops, 0746 size: sizeof(bsp_spi_bus_desc) 0747 }, 0748 { /* our private fields */ 0749 initialized: FALSE 0750 } 0751 }; 0752 0753 /*=========================================================================*\ 0754 | initialization | 0755 \*=========================================================================*/ 0756 0757 /*=========================================================================*\ 0758 | Function: | 0759 \*-------------------------------------------------------------------------*/ 0760 rtems_status_code bsp_register_spi 0761 ( 0762 /*-------------------------------------------------------------------------*\ 0763 | Purpose: | 0764 | register SPI bus and devices | 0765 +---------------------------------------------------------------------------+ 0766 | Input Parameters: | 0767 \*-------------------------------------------------------------------------*/ 0768 void /* <none> */ 0769 ) 0770 /*-------------------------------------------------------------------------*\ 0771 | Return Value: | 0772 | 0 or error code | 0773 \*=========================================================================*/ 0774 { 0775 int ret_code; 0776 int spi_busno; 0777 0778 /* 0779 * init I2C library (if not already done) 0780 */ 0781 rtems_libi2c_initialize (); 0782 0783 /* 0784 * init port pins used to address/select SPI devices 0785 */ 0786 0787 #if defined(PGH360) 0788 0789 /* 0790 * set up ports 0791 * LINE PAR DIR DAT 0792 * ----------------------- 0793 * EEP_CE 0 1 act-high 0794 * DISP4_CS 0 1 act-high 0795 * DISP4_RS 0 1 active 0796 */ 0797 0798 /* set Port B Pin Assignment Register... */ 0799 m360.pbpar = 0800 (m360.pbpar 0801 & ~(PGH360_PB_SPI_EEP_CE_MSK 0802 | PGH360_PB_SPI_DISP4_CE_MSK 0803 | PGH360_PB_SPI_DISP4_RS_MSK)); 0804 0805 /* set Port B Data Direction Register... */ 0806 m360.pbdir = 0807 m360.pbdir 0808 | PGH360_PB_SPI_EEP_CE_MSK 0809 | PGH360_PB_SPI_DISP4_CE_MSK 0810 | PGH360_PB_SPI_DISP4_RS_MSK; 0811 0812 /* set Port B Data Register to inactive CE state */ 0813 m360.pbdat = 0814 m360.pbdat 0815 | PGH360_PB_SPI_DISP4_CE_MSK 0816 | PGH360_PB_SPI_DISP4_RS_MSK; 0817 #endif 0818 0819 /* 0820 * register SPI bus 0821 */ 0822 ret_code = rtems_libi2c_register_bus("/dev/spi", 0823 &(bsp_spi_bus_desc.bus_desc)); 0824 if (ret_code < 0) { 0825 return -ret_code; 0826 } 0827 spi_busno = ret_code; 0828 #if defined(PGH360) 0829 /* 0830 * register devices 0831 */ 0832 #if 0 0833 ret_code = rtems_libi2c_register_drv(RTEMS_BSP_SPI_FLASH_DEVICE_NAME, 0834 spi_flash_m25p40_rw_driver_descriptor, 0835 spi_busno,0x00); 0836 if (ret_code < 0) { 0837 return -ret_code; 0838 } 0839 #endif 0840 #endif /* defined(PGH360) */ 0841 /* 0842 * FIXME: further drivers, when available 0843 */ 0844 return 0; 0845 } 0846 0847
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |