![]() |
|
|||
File indexing completed on 2025-05-11 08:23:59
0001 /* SPDX-License-Identifier: BSD-2-Clause */ 0002 0003 /* 0004 * RTEMS support for tqm8xx 0005 * 0006 * This file contains the MPC8xx SPI driver. 0007 */ 0008 0009 /* 0010 * Copyright (c) 2009 embedded brains GmbH & Co. KG 0011 * 0012 * Redistribution and use in source and binary forms, with or without 0013 * modification, are permitted provided that the following conditions 0014 * are met: 0015 * 1. Redistributions of source code must retain the above copyright 0016 * notice, this list of conditions and the following disclaimer. 0017 * 2. Redistributions in binary form must reproduce the above copyright 0018 * notice, this list of conditions and the following disclaimer in the 0019 * documentation and/or other materials provided with the distribution. 0020 * 0021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 0022 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 0023 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 0024 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 0025 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 0026 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 0027 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 0028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 0029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 0030 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 0031 * POSSIBILITY OF SUCH DAMAGE. 0032 */ 0033 0034 #include <stdlib.h> 0035 #include <bsp.h> 0036 #include <mpc8xx.h> 0037 #include <bsp/spi.h> 0038 #include <libchip/disp_hcms29xx.h> 0039 #include <rtems/error.h> 0040 #include <rtems/bspIo.h> 0041 #include <errno.h> 0042 #include <rtems/libi2c.h> 0043 #include <bsp/irq.h> 0044 0045 #define M8xx_PB_SPI_MISO_MSK (1<<(31-28)) 0046 #define M8xx_PB_SPI_MOSI_MSK (1<<(31-29)) 0047 #define M8xx_PB_SPI_CLK_MSK (1<<(31-30)) 0048 0049 #undef DEBUG 0050 0051 /* 0052 * this is a dummy receive buffer for sequences, 0053 * where only send data are available 0054 */ 0055 uint8_t m8xx_spi_dummy_rxbuf[2]; 0056 /*=========================================================================*\ 0057 | Function: | 0058 \*-------------------------------------------------------------------------*/ 0059 static rtems_status_code m8xx_spi_baud_to_mode 0060 ( 0061 /*-------------------------------------------------------------------------*\ 0062 | Purpose: | 0063 | determine proper divider value | 0064 +---------------------------------------------------------------------------+ 0065 | Input Parameters: | 0066 \*-------------------------------------------------------------------------*/ 0067 uint32_t baudrate, /* desired baudrate */ 0068 uint32_t *spimode /* result value */ 0069 ) 0070 /*-------------------------------------------------------------------------*\ 0071 | Return Value: | 0072 | o = ok or error code | 0073 \*=========================================================================*/ 0074 { 0075 uint32_t divider; 0076 uint16_t tmpmode = 0; 0077 /* 0078 * determine clock divider and DIV16 bit 0079 */ 0080 divider = BSP_bus_frequency/baudrate; 0081 if (divider > 64) { 0082 tmpmode = M8xx_SPMODE_DIV16; 0083 divider /= 16; 0084 } 0085 if ((divider < 1) || 0086 (divider > 64)) { 0087 return RTEMS_INVALID_NUMBER; 0088 } 0089 else { 0090 tmpmode |= M8xx_SPMODE_PM(divider/4-1); 0091 } 0092 *spimode = tmpmode; 0093 return RTEMS_SUCCESSFUL; 0094 } 0095 0096 /*=========================================================================*\ 0097 | Function: | 0098 \*-------------------------------------------------------------------------*/ 0099 static rtems_status_code m8xx_spi_char_mode 0100 ( 0101 /*-------------------------------------------------------------------------*\ 0102 | Purpose: | 0103 | determine proper value for character size | 0104 +---------------------------------------------------------------------------+ 0105 | Input Parameters: | 0106 \*-------------------------------------------------------------------------*/ 0107 m8xx_spi_softc_t *softc_ptr, /* handle */ 0108 uint32_t bits_per_char, /* bits per character */ 0109 bool lsb_first, /* TRUE: send LSB first */ 0110 uint16_t *spimode /* result value */ 0111 ) 0112 /*-------------------------------------------------------------------------*\ 0113 | Return Value: | 0114 | o = ok or error code | 0115 \*=========================================================================*/ 0116 { 0117 uint16_t tmpmode; 0118 0119 /* 0120 * calculate data format 0121 */ 0122 if ((bits_per_char >= 4) && 0123 (bits_per_char <= 16)) { 0124 tmpmode = M8xx_SPMODE_CLEN( bits_per_char-1); 0125 } 0126 else { 0127 return RTEMS_INVALID_NUMBER; 0128 } 0129 0130 *spimode = tmpmode; 0131 return 0; 0132 } 0133 0134 /*=========================================================================*\ 0135 | Function: | 0136 \*-------------------------------------------------------------------------*/ 0137 static int m8xx_spi_wait 0138 ( 0139 /*-------------------------------------------------------------------------*\ 0140 | Purpose: | 0141 | wait for spi to become idle | 0142 +---------------------------------------------------------------------------+ 0143 | Input Parameters: | 0144 \*-------------------------------------------------------------------------*/ 0145 m8xx_spi_softc_t *softc_ptr /* handle */ 0146 ) 0147 /*-------------------------------------------------------------------------*\ 0148 | Return Value: | 0149 | o = ok or error code | 0150 \*=========================================================================*/ 0151 { 0152 uint16_t act_status; 0153 rtems_status_code rc; 0154 uint32_t tout; 0155 0156 #if defined(DEBUG) 0157 printk("m8xx_spi_wait called... "); 0158 #endif 0159 if (softc_ptr->initialized) { 0160 /* 0161 * allow interrupts, when receiver is not empty 0162 */ 0163 m8xx.spim = (M8xx_SPIE_TXE | M8xx_SPIE_TXB | 0164 M8xx_SPIE_BSY | M8xx_SPIE_MME); 0165 0166 rc = rtems_semaphore_obtain(softc_ptr->irq_sema_id, 0167 RTEMS_WAIT, 0168 RTEMS_NO_TIMEOUT); 0169 if (rc != RTEMS_SUCCESSFUL) { 0170 return rc; 0171 } 0172 } 0173 else { 0174 tout = 0; 0175 do { 0176 if (tout++ > 1000000) { 0177 #if defined(DEBUG) 0178 printk("... exit with RTEMS_TIMEOUT\r\n"); 0179 #endif 0180 return RTEMS_TIMEOUT; 0181 } 0182 /* 0183 * wait for SPI to terminate 0184 */ 0185 } while (!(m8xx.spie & M8xx_SPIE_TXB)); 0186 } 0187 0188 act_status = m8xx.spie; 0189 if ((act_status & (M8xx_SPIE_TXE | M8xx_SPIE_TXB | 0190 M8xx_SPIE_BSY | M8xx_SPIE_MME))!= M8xx_SPIE_TXB) { 0191 #if defined(DEBUG) 0192 printk("... exit with RTEMS_IO_ERROR," 0193 "act_status=0x%04x,mask=0x%04x,desired_status=0x%04x\r\n", 0194 act_status,status_mask,desired_status); 0195 #endif 0196 return RTEMS_IO_ERROR; 0197 } 0198 #if defined(DEBUG) 0199 printk("... exit OK\r\n"); 0200 #endif 0201 return RTEMS_SUCCESSFUL; 0202 } 0203 0204 /*=========================================================================*\ 0205 | Function: | 0206 \*-------------------------------------------------------------------------*/ 0207 static rtems_isr m8xx_spi_irq_handler 0208 ( 0209 /*-------------------------------------------------------------------------*\ 0210 | Purpose: | 0211 | handle interrupts | 0212 +---------------------------------------------------------------------------+ 0213 | Input Parameters: | 0214 \*-------------------------------------------------------------------------*/ 0215 void *arg 0216 ) 0217 /*-------------------------------------------------------------------------*\ 0218 | Return Value: | 0219 | <none> | 0220 \*=========================================================================*/ 0221 { 0222 m8xx_spi_softc_t *softc_ptr = arg; 0223 0224 /* 0225 * disable interrupt mask 0226 */ 0227 m8xx.spim = 0; 0228 if (softc_ptr->initialized) { 0229 rtems_semaphore_release(softc_ptr->irq_sema_id); 0230 } 0231 } 0232 0233 static void 0234 mpc8xx_spi_irq_on(const rtems_irq_connect_data *irq) 0235 { 0236 } 0237 0238 static void 0239 mpc8xx_spi_irq_off(const rtems_irq_connect_data *irq) 0240 { 0241 } 0242 0243 static int 0244 mpc8xx_spi_irq_isOn(const rtems_irq_connect_data *irq) 0245 { 0246 return 1; 0247 } 0248 0249 /*=========================================================================*\ 0250 | Function: | 0251 \*-------------------------------------------------------------------------*/ 0252 static void m8xx_spi_install_irq_handler 0253 ( 0254 /*-------------------------------------------------------------------------*\ 0255 | Purpose: | 0256 | install the interrupt handler | 0257 +---------------------------------------------------------------------------+ 0258 | Input Parameters: | 0259 \*-------------------------------------------------------------------------*/ 0260 m8xx_spi_softc_t *softc_ptr, /* ptr to control structure */ 0261 int install /* TRUE: install, FALSE: remove */ 0262 ) 0263 /*-------------------------------------------------------------------------*\ 0264 | Return Value: | 0265 | <none> | 0266 \*=========================================================================*/ 0267 { 0268 rtems_status_code rc = RTEMS_SUCCESSFUL; 0269 0270 /* 0271 * install handler for SPI device 0272 */ 0273 /* 0274 * create semaphore for IRQ synchronization 0275 */ 0276 rc = rtems_semaphore_create(rtems_build_name('s','p','i','s'), 0277 0, 0278 RTEMS_FIFO 0279 | RTEMS_SIMPLE_BINARY_SEMAPHORE, 0280 0, 0281 &softc_ptr->irq_sema_id); 0282 if (rc != RTEMS_SUCCESSFUL) { 0283 rtems_panic("SPI: cannot create semaphore"); 0284 } 0285 if (rc == RTEMS_SUCCESSFUL) { 0286 rtems_irq_connect_data irq_conn_data = { 0287 BSP_CPM_IRQ_SPI, 0288 m8xx_spi_irq_handler, /* rtems_irq_hdl */ 0289 (rtems_irq_hdl_param)softc_ptr, /* (rtems_irq_hdl_param) */ 0290 mpc8xx_spi_irq_on, /* (rtems_irq_enable) */ 0291 mpc8xx_spi_irq_off, /* (rtems_irq_disable) */ 0292 mpc8xx_spi_irq_isOn /* (rtems_irq_is_enabled) */ 0293 }; 0294 if (!BSP_install_rtems_irq_handler (&irq_conn_data)) { 0295 rtems_panic("SPI: cannot install IRQ handler"); 0296 } 0297 } 0298 } 0299 0300 /*=========================================================================*\ 0301 | Function: | 0302 \*-------------------------------------------------------------------------*/ 0303 rtems_status_code m8xx_spi_init 0304 ( 0305 /*-------------------------------------------------------------------------*\ 0306 | Purpose: | 0307 | initialize the driver | 0308 +---------------------------------------------------------------------------+ 0309 | Input Parameters: | 0310 \*-------------------------------------------------------------------------*/ 0311 rtems_libi2c_bus_t *bh /* bus specifier structure */ 0312 ) 0313 /*-------------------------------------------------------------------------*\ 0314 | Return Value: | 0315 | o = ok or error code | 0316 \*=========================================================================*/ 0317 { 0318 m8xx_spi_softc_t *softc_ptr = &(((m8xx_spi_desc_t *)(bh))->softc); 0319 rtems_status_code rc = RTEMS_SUCCESSFUL; 0320 0321 #if defined(DEBUG) 0322 printk("m8xx_spi_init called... "); 0323 #endif 0324 /* 0325 * init HW registers: 0326 */ 0327 /* 0328 * FIXME: set default mode in SPMODE 0329 */ 0330 0331 /* 0332 * allocate BDs (1x RX, 1x TX) 0333 */ 0334 if (rc == RTEMS_SUCCESSFUL) { 0335 softc_ptr->rx_bd = m8xx_bd_allocate (1); 0336 softc_ptr->tx_bd = m8xx_bd_allocate (1); 0337 if ((softc_ptr->rx_bd == NULL) || 0338 (softc_ptr->tx_bd == NULL)) { 0339 rc = RTEMS_NO_MEMORY; 0340 } 0341 } 0342 /* 0343 * set parameter RAM 0344 */ 0345 m8xx.spip.rbase = (char *)softc_ptr->rx_bd - (char *)&m8xx; 0346 m8xx.spip.tbase = (char *)softc_ptr->tx_bd - (char *)&m8xx; 0347 m8xx.spip.rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0); 0348 m8xx.spip.tfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0); 0349 m8xx.spip.mrblr = 2; 0350 0351 /* 0352 * issue "InitRxTx" Command to CP 0353 */ 0354 m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SPI); 0355 0356 /* 0357 * init interrupt stuff 0358 */ 0359 if (rc == RTEMS_SUCCESSFUL) { 0360 m8xx_spi_install_irq_handler(softc_ptr,TRUE); 0361 } 0362 if (rc == RTEMS_SUCCESSFUL) { 0363 /* 0364 * set up ports 0365 * LINE PAR DIR DAT 0366 * ----------------------- 0367 * MOSI 1 1 x 0368 * MISO 1 1 x 0369 * CLK 1 1 x 0370 */ 0371 0372 /* set Port B Pin Assignment Register... */ 0373 m8xx.pbpar = 0374 m8xx.pbpar 0375 | M8xx_PB_SPI_MISO_MSK 0376 | M8xx_PB_SPI_MOSI_MSK 0377 | M8xx_PB_SPI_CLK_MSK; 0378 0379 /* set Port B Data Direction Register... */ 0380 m8xx.pbdir = 0381 m8xx.pbdir 0382 | M8xx_PB_SPI_MISO_MSK 0383 | M8xx_PB_SPI_MOSI_MSK 0384 | M8xx_PB_SPI_CLK_MSK; 0385 } 0386 /* 0387 * mark, that we have initialized 0388 */ 0389 if (rc == RTEMS_SUCCESSFUL) { 0390 softc_ptr->initialized = TRUE; 0391 } 0392 #if defined(DEBUG) 0393 printk("... exit OK\r\n"); 0394 #endif 0395 return rc; 0396 } 0397 0398 0399 /*=========================================================================*\ 0400 | Function: | 0401 \*-------------------------------------------------------------------------*/ 0402 static int m8xx_spi_read_write_bytes 0403 ( 0404 /*-------------------------------------------------------------------------*\ 0405 | Purpose: | 0406 | transmit/receive some bytes from SPI device | 0407 +---------------------------------------------------------------------------+ 0408 | Input Parameters: | 0409 \*-------------------------------------------------------------------------*/ 0410 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0411 unsigned char *rbuf, /* buffer to store bytes */ 0412 const unsigned char *tbuf, /* buffer to send bytes */ 0413 int len /* number of bytes to transceive */ 0414 ) 0415 /*-------------------------------------------------------------------------*\ 0416 | Return Value: | 0417 | number of bytes received or (negative) error code | 0418 \*=========================================================================*/ 0419 { 0420 m8xx_spi_softc_t *softc_ptr = &(((m8xx_spi_desc_t *)(bh))->softc); 0421 rtems_status_code rc = RTEMS_SUCCESSFUL; 0422 int bc = 0; 0423 0424 #if defined(DEBUG) 0425 printk("m8xx_spi_read_write_bytes called... "); 0426 #endif 0427 0428 /* 0429 * prepare RxBD 0430 */ 0431 if (rc == RTEMS_SUCCESSFUL) { 0432 if (rbuf == NULL) { 0433 /* 0434 * no Tx buffer: receive to dummy buffer 0435 */ 0436 m8xx.spip.mrblr = sizeof(m8xx_spi_dummy_rxbuf); 0437 softc_ptr->rx_bd->buffer = m8xx_spi_dummy_rxbuf; 0438 softc_ptr->rx_bd->length = 0; 0439 softc_ptr->rx_bd->status = (M8xx_BD_EMPTY | M8xx_BD_WRAP | 0440 M8xx_BD_CONTINUOUS); 0441 } 0442 else { 0443 m8xx.spip.mrblr = len; 0444 softc_ptr->rx_bd->buffer = rbuf; 0445 softc_ptr->rx_bd->length = 0; 0446 softc_ptr->rx_bd->status = (M8xx_BD_EMPTY | M8xx_BD_WRAP); 0447 } 0448 } 0449 /* 0450 * prepare TxBD 0451 */ 0452 if (rc == RTEMS_SUCCESSFUL) { 0453 if (tbuf == NULL) { 0454 /* 0455 * no Tx buffer: transmit from dummy buffer 0456 */ 0457 softc_ptr->tx_bd->buffer = m8xx_spi_dummy_rxbuf; 0458 softc_ptr->tx_bd->length = len; 0459 softc_ptr->tx_bd->status = (M8xx_BD_READY | M8xx_BD_WRAP | 0460 M8xx_BD_CONTINUOUS); 0461 } 0462 else { 0463 softc_ptr->tx_bd->buffer = (char *)tbuf; 0464 softc_ptr->tx_bd->length = len; 0465 softc_ptr->tx_bd->status = (M8xx_BD_READY | M8xx_BD_WRAP); 0466 } 0467 } 0468 0469 if (rc == RTEMS_SUCCESSFUL) { 0470 /* 0471 * set START command 0472 */ 0473 m8xx.spcom = M8xx_SPCOM_STR; 0474 /* 0475 * wait for SPI to finish 0476 */ 0477 rc = m8xx_spi_wait(softc_ptr); 0478 } 0479 #if defined(DEBUG) 0480 printk("... exit OK, rc=%d\r\n",bc); 0481 #endif 0482 return (rc == RTEMS_SUCCESSFUL) ? bc : -rc; 0483 } 0484 0485 /*=========================================================================*\ 0486 | Function: | 0487 \*-------------------------------------------------------------------------*/ 0488 int m8xx_spi_read_bytes 0489 ( 0490 /*-------------------------------------------------------------------------*\ 0491 | Purpose: | 0492 | receive some bytes from SPI device | 0493 +---------------------------------------------------------------------------+ 0494 | Input Parameters: | 0495 \*-------------------------------------------------------------------------*/ 0496 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0497 unsigned char *buf, /* buffer to store bytes */ 0498 int len /* number of bytes to receive */ 0499 ) 0500 /*-------------------------------------------------------------------------*\ 0501 | Return Value: | 0502 | number of bytes received or (negative) error code | 0503 \*=========================================================================*/ 0504 { 0505 return m8xx_spi_read_write_bytes(bh,buf,NULL,len); 0506 } 0507 0508 /*=========================================================================*\ 0509 | Function: | 0510 \*-------------------------------------------------------------------------*/ 0511 int m8xx_spi_write_bytes 0512 ( 0513 /*-------------------------------------------------------------------------*\ 0514 | Purpose: | 0515 | send some bytes to SPI device | 0516 +---------------------------------------------------------------------------+ 0517 | Input Parameters: | 0518 \*-------------------------------------------------------------------------*/ 0519 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0520 unsigned char *buf, /* buffer to send */ 0521 int len /* number of bytes to send */ 0522 0523 ) 0524 /*-------------------------------------------------------------------------*\ 0525 | Return Value: | 0526 | number of bytes sent or (negative) error code | 0527 \*=========================================================================*/ 0528 { 0529 return m8xx_spi_read_write_bytes(bh,NULL,buf,len); 0530 } 0531 0532 /*=========================================================================*\ 0533 | Function: | 0534 \*-------------------------------------------------------------------------*/ 0535 rtems_status_code m8xx_spi_set_tfr_mode 0536 ( 0537 /*-------------------------------------------------------------------------*\ 0538 | Purpose: | 0539 | set SPI to desired baudrate/clock mode/character mode | 0540 +---------------------------------------------------------------------------+ 0541 | Input Parameters: | 0542 \*-------------------------------------------------------------------------*/ 0543 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0544 const rtems_libi2c_tfr_mode_t *tfr_mode /* transfer mode info */ 0545 ) 0546 /*-------------------------------------------------------------------------*\ 0547 | Return Value: | 0548 | rtems_status_code | 0549 \*=========================================================================*/ 0550 { 0551 m8xx_spi_softc_t *softc_ptr = &(((m8xx_spi_desc_t *)(bh))->softc); 0552 uint32_t spimode_baud; 0553 uint16_t spimode; 0554 rtems_status_code rc = RTEMS_SUCCESSFUL; 0555 /* 0556 * FIXME: set proper mode 0557 */ 0558 if (rc == RTEMS_SUCCESSFUL) { 0559 rc = m8xx_spi_baud_to_mode(tfr_mode->baudrate,&spimode_baud); 0560 } 0561 if (rc == RTEMS_SUCCESSFUL) { 0562 rc = m8xx_spi_char_mode(softc_ptr, 0563 tfr_mode->bits_per_char, 0564 tfr_mode->lsb_first, 0565 &spimode); 0566 } 0567 if (rc == RTEMS_SUCCESSFUL) { 0568 spimode |= spimode_baud; 0569 spimode |= M8xx_SPMODE_MASTER; /* set master mode */ 0570 if (!tfr_mode->lsb_first) { 0571 spimode |= M8xx_SPMODE_REV; 0572 } 0573 if (tfr_mode->clock_inv) { 0574 spimode |= M8xx_SPMODE_CI; 0575 } 0576 if (tfr_mode->clock_phs) { 0577 spimode |= M8xx_SPMODE_CP; 0578 } 0579 } 0580 0581 if (rc == RTEMS_SUCCESSFUL) { 0582 /* 0583 * disable SPI 0584 */ 0585 m8xx.spmode &= ~M8xx_SPMODE_EN; 0586 /* 0587 * set new mode and reenable SPI 0588 */ 0589 m8xx.spmode = spimode | M8xx_SPMODE_EN; 0590 } 0591 return rc; 0592 } 0593 0594 0595 /*=========================================================================*\ 0596 | Function: | 0597 \*-------------------------------------------------------------------------*/ 0598 int m8xx_spi_ioctl 0599 ( 0600 /*-------------------------------------------------------------------------*\ 0601 | Purpose: | 0602 | perform selected ioctl function for SPI | 0603 +---------------------------------------------------------------------------+ 0604 | Input Parameters: | 0605 \*-------------------------------------------------------------------------*/ 0606 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0607 int cmd, /* ioctl command code */ 0608 void *arg /* additional argument array */ 0609 ) 0610 /*-------------------------------------------------------------------------*\ 0611 | Return Value: | 0612 | rtems_status_code | 0613 \*=========================================================================*/ 0614 { 0615 int ret_val = -1; 0616 0617 switch(cmd) { 0618 case RTEMS_LIBI2C_IOCTL_SET_TFRMODE: 0619 ret_val = 0620 -m8xx_spi_set_tfr_mode(bh, 0621 (const rtems_libi2c_tfr_mode_t *)arg); 0622 break; 0623 case RTEMS_LIBI2C_IOCTL_READ_WRITE: 0624 ret_val = 0625 m8xx_spi_read_write_bytes(bh, 0626 ((rtems_libi2c_read_write_t *)arg)->rd_buf, 0627 ((rtems_libi2c_read_write_t *)arg)->wr_buf, 0628 ((rtems_libi2c_read_write_t *)arg)->byte_cnt); 0629 break; 0630 default: 0631 ret_val = -RTEMS_NOT_DEFINED; 0632 break; 0633 } 0634 return ret_val; 0635 } 0636 0637 /*=========================================================================*\ 0638 | Board-specific adaptation functions | 0639 \*=========================================================================*/ 0640 0641 /*=========================================================================*\ 0642 | Function: | 0643 \*-------------------------------------------------------------------------*/ 0644 static rtems_status_code bsp_spi_send_start 0645 ( 0646 /*-------------------------------------------------------------------------*\ 0647 | Purpose: | 0648 | dummy function, SPI has no start condition | 0649 +---------------------------------------------------------------------------+ 0650 | Input Parameters: | 0651 \*-------------------------------------------------------------------------*/ 0652 rtems_libi2c_bus_t *bh /* bus specifier structure */ 0653 ) 0654 /*-------------------------------------------------------------------------*\ 0655 | Return Value: | 0656 | o = ok or error code | 0657 \*=========================================================================*/ 0658 { 0659 return RTEMS_SUCCESSFUL; 0660 } 0661 0662 /*=========================================================================*\ 0663 | Function: | 0664 \*-------------------------------------------------------------------------*/ 0665 static rtems_status_code bsp_spi_sel_addr 0666 ( 0667 /*-------------------------------------------------------------------------*\ 0668 | Purpose: | 0669 | address a slave device on the bus | 0670 +---------------------------------------------------------------------------+ 0671 | Input Parameters: | 0672 \*-------------------------------------------------------------------------*/ 0673 rtems_libi2c_bus_t *bh, /* bus specifier structure */ 0674 uint32_t addr, /* address to send on bus */ 0675 int rw /* 0=write,1=read */ 0676 ) 0677 /*-------------------------------------------------------------------------*\ 0678 | Return Value: | 0679 | rtems_status_code | 0680 \*=========================================================================*/ 0681 { 0682 #if defined(PGHPLUS) 0683 pbdat_val = m8xx.pbdat | (PGHPLUS_SPI_PB_DISP4_RS_MSK | 0684 PGHPLUS_SPI_PB_DISP4_CE_MSK | 0685 PGHPLUS_SPI_PB_EEP_CE_MSK); 0686 /* 0687 * select given device 0688 */ 0689 switch(addr) { 0690 case PGHPLUS_SPI_ADDR_EEPROM: 0691 pbdat_val &= ~PGHPLUS_SPI_PB_EEP_CE_MSK; 0692 break; 0693 case PGHPLUS_SPI_ADDR_DISP4_DATA: 0694 pbdat_val = (m8xx.pbdat 0695 & ~(PGHPLUS_PB_SPI_DISP4_CE_MSK | 0696 PGHPLUS_PB_SPI_DISP4_RS_MSK)); 0697 break; 0698 case PGHPLUS_SPI_ADDR_DISP4_CTRL: 0699 pbdat_val = (m8xx.pbdat 0700 & ~(PGHPLUS_PB_SPI_DISP4_CE_MSK) 0701 | PGHPLUS_PB_SPI_DISP4_RS_MSK); 0702 break; 0703 default: 0704 return RTEMS_INVALID_NUMBER; 0705 } 0706 m8xx_pbdat = pbdat_val 0707 #endif /* PGHPLUS */ 0708 return RTEMS_SUCCESSFUL; 0709 } 0710 0711 /*=========================================================================*\ 0712 | Function: | 0713 \*-------------------------------------------------------------------------*/ 0714 static rtems_status_code bsp_spi_send_stop 0715 ( 0716 /*-------------------------------------------------------------------------*\ 0717 | Purpose: | 0718 | deselect SPI | 0719 +---------------------------------------------------------------------------+ 0720 | Input Parameters: | 0721 \*-------------------------------------------------------------------------*/ 0722 rtems_libi2c_bus_t *bh /* bus specifier structure */ 0723 ) 0724 /*-------------------------------------------------------------------------*\ 0725 | Return Value: | 0726 | o = ok or error code | 0727 \*=========================================================================*/ 0728 { 0729 #if defined(DEBUG) 0730 printk("bsp_spi_send_stop called... "); 0731 #endif 0732 m8xx.pbdat = (m8xx.pbdat 0733 | PGHPLUS_PB_SPI_DISP4_CE_MSK 0734 | PGHPLUS_PB_SPI_EEP_CE_MSK); 0735 #if defined(DEBUG) 0736 printk("... exit OK\r\n"); 0737 #endif 0738 return RTEMS_SUCCESSFUL; 0739 } 0740 0741 /*=========================================================================*\ 0742 | Function: | 0743 \*-------------------------------------------------------------------------*/ 0744 static rtems_status_code bsp_spi_init 0745 ( 0746 /*-------------------------------------------------------------------------*\ 0747 | Purpose: | 0748 | do board specific init: | 0749 | - initialize pins for addressing | 0750 | - register further drivers | 0751 +---------------------------------------------------------------------------+ 0752 | Input Parameters: | 0753 \*-------------------------------------------------------------------------*/ 0754 int spi_busno 0755 ) 0756 /*-------------------------------------------------------------------------*\ 0757 | Return Value: | 0758 | o = ok or error code | 0759 \*=========================================================================*/ 0760 { 0761 int ret_code; 0762 0763 #if defined(DEBUG) 0764 printk("bsp_spi_init called... "); 0765 #endif 0766 0767 /* 0768 * init port pins used to address/select SPI devices 0769 */ 0770 0771 /* 0772 * set up ports 0773 * LINE PAR DIR DAT 0774 * ----------------------- 0775 * EEP_CE 0 1 act-high 0776 * DISP4_CS 0 1 act-high 0777 * DISP4_RS 0 1 active 0778 */ 0779 0780 /* set Port B Pin Assignment Register... */ 0781 m8xx.pbpar = 0782 (m8xx.pbpar 0783 & ~(PGHPLUS_PB_SPI_EEP_CE_MSK 0784 | PGHPLUS_PB_SPI_DISP4_CE_MSK 0785 | PGHPLUS_PB_SPI_DISP4_RS_MSK)); 0786 0787 /* set Port B Data Direction Register... */ 0788 m8xx.pbdir = 0789 m8xx.pbdir 0790 | PGHPLUS_PB_SPI_EEP_CE_MSK 0791 | PGHPLUS_PB_SPI_DISP4_CE_MSK 0792 | PGHPLUS_PB_SPI_DISP4_RS_MSK; 0793 0794 /* set Port B Data Register to inactive CE state */ 0795 m8xx.pbdat = 0796 m8xx.pbdat 0797 | PGHPLUS_PB_SPI_DISP4_CE_MSK 0798 | PGHPLUS_PB_SPI_DISP4_RS_MSK; 0799 0800 /* 0801 * register devices 0802 */ 0803 ret_code = rtems_libi2c_register_drv("disp", 0804 disp_hcms29xx_driver_descriptor, 0805 spi_busno,PGHPLUS_SPI_ADDR_DISP4); 0806 if (ret_code < 0) { 0807 return -ret_code; 0808 } 0809 0810 #if defined(DEBUG) 0811 printk("... exit OK\r\n"); 0812 #endif 0813 return RTEMS_SUCCESSFUL; 0814 } 0815 0816 /*=========================================================================*\ 0817 | list of handlers | 0818 \*=========================================================================*/ 0819 0820 rtems_libi2c_bus_ops_t bsp_spi_ops = { 0821 init: m8xx_spi_init, 0822 send_start: bsp_spi_send_start, 0823 send_stop: bsp_spi_send_stop, 0824 send_addr: bsp_spi_sel_addr, 0825 read_bytes: m8xx_spi_read_bytes, 0826 write_bytes: m8xx_spi_write_bytes, 0827 ioctl: m8xx_spi_ioctl 0828 }; 0829 0830 static m8xx_spi_desc_t bsp_spi_bus_desc = { 0831 {/* public fields */ 0832 ops: &bsp_spi_ops, 0833 size: sizeof(bsp_spi_bus_desc) 0834 }, 0835 { /* our private fields */ 0836 initialized: FALSE 0837 } 0838 }; 0839 0840 /*=========================================================================*\ 0841 | initialization | 0842 \*=========================================================================*/ 0843 0844 /*=========================================================================*\ 0845 | Function: | 0846 \*-------------------------------------------------------------------------*/ 0847 rtems_status_code bsp_register_spi 0848 ( 0849 /*-------------------------------------------------------------------------*\ 0850 | Purpose: | 0851 | register SPI bus and devices | 0852 +---------------------------------------------------------------------------+ 0853 | Input Parameters: | 0854 \*-------------------------------------------------------------------------*/ 0855 void /* <none> */ 0856 ) 0857 /*-------------------------------------------------------------------------*\ 0858 | Return Value: | 0859 | 0 or error code | 0860 \*=========================================================================*/ 0861 { 0862 int ret_code; 0863 int spi_busno; 0864 0865 /* 0866 * init I2C library (if not already done) 0867 */ 0868 rtems_libi2c_initialize (); 0869 0870 0871 /* 0872 * register SPI bus 0873 */ 0874 ret_code = rtems_libi2c_register_bus("/dev/spi", 0875 &(bsp_spi_bus_desc.bus_desc)); 0876 if (ret_code < 0) { 0877 return -ret_code; 0878 } 0879 spi_busno = ret_code; 0880 0881 bsp_spi_init(spi_busno); 0882 /* 0883 * FIXME: further drivers, when available 0884 */ 0885 return RTEMS_SUCCESSFUL; 0886 } 0887 0888
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |