source: rtems/bsps/powerpc/tqm8xx/spi/spi.c @ 276afd2b

5
Last change on this file since 276afd2b was 276afd2b, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 23, 2018 at 7:48:52 AM

bsps: Move SPI drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 32.6 KB
Line 
1/*===============================================================*\
2| Project: RTEMS support for tqm8xx                               |
3+-----------------------------------------------------------------+
4|                    Copyright (c) 2009                           |
5|                    Embedded Brains GmbH                         |
6|                    Obere Lagerstr. 30                           |
7|                    D-82178 Puchheim                             |
8|                    Germany                                      |
9|                    rtems@embedded-brains.de                     |
10+-----------------------------------------------------------------+
11| The license and distribution terms for this file may be         |
12| found in the file LICENSE in this distribution or at            |
13|                                                                 |
14| http://www.rtems.org/license/LICENSE.                           |
15|                                                                 |
16+-----------------------------------------------------------------+
17| this file contains the MPC8xx SPI driver                        |
18\*===============================================================*/
19#include <stdlib.h>
20#include <bsp.h>
21#include <mpc8xx.h>
22#include <bsp/spi.h>
23#include <libchip/disp_hcms29xx.h>
24#include <rtems/error.h>
25#include <rtems/bspIo.h>
26#include <errno.h>
27#include <rtems/libi2c.h>
28#include <bsp/irq.h>
29
30#define M8xx_PB_SPI_MISO_MSK       (1<<(31-28))
31#define M8xx_PB_SPI_MOSI_MSK       (1<<(31-29))
32#define M8xx_PB_SPI_CLK_MSK        (1<<(31-30))
33
34#undef DEBUG
35
36/*
37 * this is a dummy receive buffer for sequences,
38 * where only send data are available
39 */
40uint8_t m8xx_spi_dummy_rxbuf[2];
41/*=========================================================================*\
42| Function:                                                                 |
43\*-------------------------------------------------------------------------*/
44static rtems_status_code m8xx_spi_baud_to_mode
45(
46/*-------------------------------------------------------------------------*\
47| Purpose:                                                                  |
48|   determine proper divider value                                          |
49+---------------------------------------------------------------------------+
50| Input Parameters:                                                         |
51\*-------------------------------------------------------------------------*/
52 uint32_t baudrate,                      /* desired baudrate               */
53 uint32_t *spimode                       /* result value                   */
54)
55/*-------------------------------------------------------------------------*\
56| Return Value:                                                             |
57|    o = ok or error code                                                   |
58\*=========================================================================*/
59{
60  uint32_t divider;
61  uint16_t tmpmode = 0;
62  /*
63   * determine clock divider and DIV16 bit
64   */
65  divider = BSP_bus_frequency/baudrate;
66  if (divider > 64) {
67    tmpmode = M8xx_SPMODE_DIV16;
68    divider /= 16;
69  }
70  if ((divider <  1) ||
71      (divider > 64)) {
72    return RTEMS_INVALID_NUMBER;
73  }
74  else {
75    tmpmode |= M8xx_SPMODE_PM(divider/4-1);
76  }
77  *spimode = tmpmode;
78  return RTEMS_SUCCESSFUL;
79}
80
81/*=========================================================================*\
82| Function:                                                                 |
83\*-------------------------------------------------------------------------*/
84static rtems_status_code m8xx_spi_char_mode
85(
86/*-------------------------------------------------------------------------*\
87| Purpose:                                                                  |
88|   determine proper value for character size                               |
89+---------------------------------------------------------------------------+
90| Input Parameters:                                                         |
91\*-------------------------------------------------------------------------*/
92 m8xx_spi_softc_t *softc_ptr,            /* handle                         */
93 uint32_t bits_per_char,                 /* bits per character             */
94 bool     lsb_first,                     /* TRUE: send LSB first           */
95 uint16_t *spimode                       /* result value                   */
96)
97/*-------------------------------------------------------------------------*\
98| Return Value:                                                             |
99|    o = ok or error code                                                   |
100\*=========================================================================*/
101{
102  uint16_t tmpmode;
103
104  /*
105   * calculate data format
106   */
107  if ((bits_per_char >= 4) &&
108      (bits_per_char <= 16)) {
109    tmpmode = M8xx_SPMODE_CLEN( bits_per_char-1);
110  }
111  else {
112    return RTEMS_INVALID_NUMBER;
113  }
114
115  *spimode = tmpmode;
116  return 0;
117}
118
119/*=========================================================================*\
120| Function:                                                                 |
121\*-------------------------------------------------------------------------*/
122static int m8xx_spi_wait
123(
124/*-------------------------------------------------------------------------*\
125| Purpose:                                                                  |
126|   wait for spi to become idle                                             |
127+---------------------------------------------------------------------------+
128| Input Parameters:                                                         |
129\*-------------------------------------------------------------------------*/
130 m8xx_spi_softc_t    *softc_ptr           /* handle              */
131)
132/*-------------------------------------------------------------------------*\
133| Return Value:                                                             |
134|    o = ok or error code                                                   |
135\*=========================================================================*/
136{
137  uint16_t act_status;
138  rtems_status_code rc;
139  uint32_t tout;
140
141#if defined(DEBUG)
142  printk("m8xx_spi_wait called... ");
143#endif
144  if (softc_ptr->initialized) {
145    /*
146     * allow interrupts, when receiver is not empty
147     */
148    m8xx.spim = (M8xx_SPIE_TXE | M8xx_SPIE_TXB |
149                 M8xx_SPIE_BSY | M8xx_SPIE_MME);
150
151    rc = rtems_semaphore_obtain(softc_ptr->irq_sema_id,
152                                RTEMS_WAIT,
153                                RTEMS_NO_TIMEOUT);
154    if (rc != RTEMS_SUCCESSFUL) {
155      return rc;
156    }
157  }
158  else {
159    tout = 0;
160    do {
161      if (tout++ > 1000000) {
162#if defined(DEBUG)
163        printk("... exit with RTEMS_TIMEOUT\r\n");
164#endif
165        return RTEMS_TIMEOUT;
166      }
167      /*
168       * wait for SPI to terminate
169       */
170    } while (!(m8xx.spie & M8xx_SPIE_TXB));
171  }
172
173  act_status = m8xx.spie;
174  if ((act_status  & (M8xx_SPIE_TXE | M8xx_SPIE_TXB |
175                      M8xx_SPIE_BSY | M8xx_SPIE_MME))!= M8xx_SPIE_TXB) {
176#if defined(DEBUG)
177    printk("... exit with RTEMS_IO_ERROR,"
178           "act_status=0x%04x,mask=0x%04x,desired_status=0x%04x\r\n",
179           act_status,status_mask,desired_status);
180#endif
181    return RTEMS_IO_ERROR;
182  }
183#if defined(DEBUG)
184        printk("... exit OK\r\n");
185#endif
186  return RTEMS_SUCCESSFUL;
187}
188
189/*=========================================================================*\
190| Function:                                                                 |
191\*-------------------------------------------------------------------------*/
192static rtems_isr m8xx_spi_irq_handler
193(
194/*-------------------------------------------------------------------------*\
195| Purpose:                                                                  |
196|   handle interrupts                                                       |
197+---------------------------------------------------------------------------+
198| Input Parameters:                                                         |
199\*-------------------------------------------------------------------------*/
200 void *arg
201)
202/*-------------------------------------------------------------------------*\
203| Return Value:                                                             |
204|    <none>                                                                 |
205\*=========================================================================*/
206{
207  m8xx_spi_softc_t *softc_ptr = arg;
208
209  /*
210   * disable interrupt mask
211   */
212  m8xx.spim = 0;
213  if (softc_ptr->initialized) {
214    rtems_semaphore_release(softc_ptr->irq_sema_id);
215  }
216}
217
218static void
219mpc8xx_spi_irq_on(const rtems_irq_connect_data *irq)
220{
221}
222
223static void
224mpc8xx_spi_irq_off(const rtems_irq_connect_data *irq)
225{
226}
227
228static int
229mpc8xx_spi_irq_isOn(const rtems_irq_connect_data *irq)
230{
231  return 1;
232}
233
234/*=========================================================================*\
235| Function:                                                                 |
236\*-------------------------------------------------------------------------*/
237static void m8xx_spi_install_irq_handler
238(
239/*-------------------------------------------------------------------------*\
240| Purpose:                                                                  |
241|   install the interrupt handler                                           |
242+---------------------------------------------------------------------------+
243| Input Parameters:                                                         |
244\*-------------------------------------------------------------------------*/
245 m8xx_spi_softc_t *softc_ptr,           /* ptr to control structure        */
246 int install                            /* TRUE: install, FALSE: remove    */
247)
248/*-------------------------------------------------------------------------*\
249| Return Value:                                                             |
250|    <none>                                                                 |
251\*=========================================================================*/
252{
253  rtems_status_code rc = RTEMS_SUCCESSFUL;
254
255  /*
256   * install handler for SPI device
257   */
258  /*
259   * create semaphore for IRQ synchronization
260   */
261  rc = rtems_semaphore_create(rtems_build_name('s','p','i','s'),
262                              0,
263                              RTEMS_FIFO
264                              | RTEMS_SIMPLE_BINARY_SEMAPHORE,
265                              0,
266                              &softc_ptr->irq_sema_id);
267  if (rc != RTEMS_SUCCESSFUL) {
268    rtems_panic("SPI: cannot create semaphore");
269  }
270  if (rc == RTEMS_SUCCESSFUL) {
271    rtems_irq_connect_data irq_conn_data = {
272      BSP_CPM_IRQ_SPI,
273      m8xx_spi_irq_handler,            /* rtems_irq_hdl           */
274      (rtems_irq_hdl_param)softc_ptr,  /* (rtems_irq_hdl_param)   */
275      mpc8xx_spi_irq_on,               /* (rtems_irq_enable)      */
276      mpc8xx_spi_irq_off,              /* (rtems_irq_disable)     */
277      mpc8xx_spi_irq_isOn              /* (rtems_irq_is_enabled)  */
278    };
279    if (!BSP_install_rtems_irq_handler (&irq_conn_data)) {
280      rtems_panic("SPI: cannot install IRQ handler");
281    }
282  }
283}
284
285/*=========================================================================*\
286| Function:                                                                 |
287\*-------------------------------------------------------------------------*/
288rtems_status_code m8xx_spi_init
289(
290/*-------------------------------------------------------------------------*\
291| Purpose:                                                                  |
292|   initialize the driver                                                   |
293+---------------------------------------------------------------------------+
294| Input Parameters:                                                         |
295\*-------------------------------------------------------------------------*/
296 rtems_libi2c_bus_t *bh                  /* bus specifier structure        */
297)
298/*-------------------------------------------------------------------------*\
299| Return Value:                                                             |
300|    o = ok or error code                                                   |
301\*=========================================================================*/
302{
303  m8xx_spi_softc_t *softc_ptr = &(((m8xx_spi_desc_t *)(bh))->softc);
304  rtems_status_code rc = RTEMS_SUCCESSFUL;
305
306#if defined(DEBUG)
307  printk("m8xx_spi_init called... ");
308#endif
309  /*
310   * init HW registers:
311   */
312  /*
313   * FIXME: set default mode in SPMODE
314   */
315
316  /*
317   * allocate BDs (1x RX, 1x TX)
318   */
319  if (rc == RTEMS_SUCCESSFUL) {
320    softc_ptr->rx_bd = m8xx_bd_allocate (1);
321    softc_ptr->tx_bd = m8xx_bd_allocate (1);
322    if ((softc_ptr->rx_bd == NULL) ||
323        (softc_ptr->tx_bd == NULL)) {
324      rc = RTEMS_NO_MEMORY;
325    }
326  }
327  /*
328   * set parameter RAM
329   */
330  m8xx.spip.rbase = (char *)softc_ptr->rx_bd - (char *)&m8xx;
331  m8xx.spip.tbase = (char *)softc_ptr->tx_bd - (char *)&m8xx;
332  m8xx.spip.rfcr  = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0);
333  m8xx.spip.tfcr  = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0);
334  m8xx.spip.mrblr = 2;
335
336  /*
337   * issue "InitRxTx" Command to CP
338   */
339  m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SPI);
340
341  /*
342   * init interrupt stuff
343   */
344  if (rc == RTEMS_SUCCESSFUL) {
345    m8xx_spi_install_irq_handler(softc_ptr,TRUE);
346  }
347  if (rc == RTEMS_SUCCESSFUL) {
348    /*
349     * set up ports
350     * LINE      PAR  DIR  DAT
351     * -----------------------
352     * MOSI       1    1    x
353     * MISO       1    1    x
354     * CLK        1    1    x
355     */
356
357    /* set Port B Pin Assignment Register... */
358    m8xx.pbpar =
359      m8xx.pbpar
360      | M8xx_PB_SPI_MISO_MSK
361      | M8xx_PB_SPI_MOSI_MSK
362      | M8xx_PB_SPI_CLK_MSK;
363
364    /* set Port B Data Direction Register... */
365    m8xx.pbdir =
366      m8xx.pbdir
367      | M8xx_PB_SPI_MISO_MSK
368      | M8xx_PB_SPI_MOSI_MSK
369      | M8xx_PB_SPI_CLK_MSK;
370  }
371  /*
372   * mark, that we have initialized
373   */
374  if (rc == RTEMS_SUCCESSFUL) {
375    softc_ptr->initialized = TRUE;
376  }
377#if defined(DEBUG)
378  printk("... exit OK\r\n");
379#endif
380  return rc;
381}
382
383
384/*=========================================================================*\
385| Function:                                                                 |
386\*-------------------------------------------------------------------------*/
387static int m8xx_spi_read_write_bytes
388(
389/*-------------------------------------------------------------------------*\
390| Purpose:                                                                  |
391|   transmit/receive some bytes from SPI device                             |
392+---------------------------------------------------------------------------+
393| Input Parameters:                                                         |
394\*-------------------------------------------------------------------------*/
395 rtems_libi2c_bus_t *bh,                 /* bus specifier structure        */
396 unsigned char *rbuf,                    /* buffer to store bytes          */
397 const unsigned char *tbuf,              /* buffer to send  bytes          */
398 int len                                 /* number of bytes to transceive  */
399)
400/*-------------------------------------------------------------------------*\
401| Return Value:                                                             |
402|    number of bytes received or (negative) error code                      |
403\*=========================================================================*/
404{
405  m8xx_spi_softc_t *softc_ptr = &(((m8xx_spi_desc_t *)(bh))->softc);
406  rtems_status_code rc = RTEMS_SUCCESSFUL;
407  int bc = 0;
408
409#if defined(DEBUG)
410  printk("m8xx_spi_read_write_bytes called... ");
411#endif
412
413  /*
414   * prepare RxBD
415   */
416  if (rc == RTEMS_SUCCESSFUL) {
417    if (rbuf == NULL) {
418      /*
419       * no Tx buffer: receive to dummy buffer
420       */
421      m8xx.spip.mrblr          = sizeof(m8xx_spi_dummy_rxbuf);
422      softc_ptr->rx_bd->buffer = m8xx_spi_dummy_rxbuf;
423      softc_ptr->rx_bd->length = 0;
424      softc_ptr->rx_bd->status = (M8xx_BD_EMPTY | M8xx_BD_WRAP |
425                                  M8xx_BD_CONTINUOUS);
426    }
427    else {
428      m8xx.spip.mrblr          = len;
429      softc_ptr->rx_bd->buffer = rbuf;
430      softc_ptr->rx_bd->length = 0;
431      softc_ptr->rx_bd->status = (M8xx_BD_EMPTY | M8xx_BD_WRAP);
432    }
433  }
434  /*
435   * prepare TxBD
436   */
437  if (rc == RTEMS_SUCCESSFUL) {
438    if (tbuf == NULL) {
439      /*
440       * no Tx buffer: transmit from dummy buffer
441       */
442      softc_ptr->tx_bd->buffer = m8xx_spi_dummy_rxbuf;
443      softc_ptr->tx_bd->length = len;
444      softc_ptr->tx_bd->status = (M8xx_BD_READY | M8xx_BD_WRAP |
445                                  M8xx_BD_CONTINUOUS);
446    }
447    else {
448      softc_ptr->tx_bd->buffer = (char *)tbuf;
449      softc_ptr->tx_bd->length = len;
450      softc_ptr->tx_bd->status = (M8xx_BD_READY | M8xx_BD_WRAP);
451    }
452  }
453
454  if (rc == RTEMS_SUCCESSFUL) {
455    /*
456     * set START command
457     */
458    m8xx.spcom = M8xx_SPCOM_STR;
459    /*
460     * wait for SPI to finish
461     */
462    rc = m8xx_spi_wait(softc_ptr);
463  }
464#if defined(DEBUG)
465  printk("... exit OK, rc=%d\r\n",bc);
466#endif
467  return (rc == RTEMS_SUCCESSFUL) ? bc : -rc;
468}
469
470/*=========================================================================*\
471| Function:                                                                 |
472\*-------------------------------------------------------------------------*/
473int m8xx_spi_read_bytes
474(
475/*-------------------------------------------------------------------------*\
476| Purpose:                                                                  |
477|   receive some bytes from SPI device                                      |
478+---------------------------------------------------------------------------+
479| Input Parameters:                                                         |
480\*-------------------------------------------------------------------------*/
481 rtems_libi2c_bus_t *bh,                 /* bus specifier structure        */
482 unsigned char *buf,                     /* buffer to store bytes          */
483 int len                                 /* number of bytes to receive     */
484)
485/*-------------------------------------------------------------------------*\
486| Return Value:                                                             |
487|    number of bytes received or (negative) error code                      |
488\*=========================================================================*/
489{
490  return m8xx_spi_read_write_bytes(bh,buf,NULL,len);
491}
492
493/*=========================================================================*\
494| Function:                                                                 |
495\*-------------------------------------------------------------------------*/
496int m8xx_spi_write_bytes
497(
498/*-------------------------------------------------------------------------*\
499| Purpose:                                                                  |
500|   send some bytes to SPI device                                           |
501+---------------------------------------------------------------------------+
502| Input Parameters:                                                         |
503\*-------------------------------------------------------------------------*/
504 rtems_libi2c_bus_t *bh,                 /* bus specifier structure        */
505 unsigned char *buf,                     /* buffer to send                 */
506 int len                                 /* number of bytes to send        */
507
508)
509/*-------------------------------------------------------------------------*\
510| Return Value:                                                             |
511|    number of bytes sent or (negative) error code                          |
512\*=========================================================================*/
513{
514  return m8xx_spi_read_write_bytes(bh,NULL,buf,len);
515}
516
517/*=========================================================================*\
518| Function:                                                                 |
519\*-------------------------------------------------------------------------*/
520rtems_status_code m8xx_spi_set_tfr_mode
521(
522/*-------------------------------------------------------------------------*\
523| Purpose:                                                                  |
524|   set SPI to desired baudrate/clock mode/character mode                   |
525+---------------------------------------------------------------------------+
526| Input Parameters:                                                         |
527\*-------------------------------------------------------------------------*/
528 rtems_libi2c_bus_t *bh,                 /* bus specifier structure        */
529 const rtems_libi2c_tfr_mode_t *tfr_mode /* transfer mode info             */
530)
531/*-------------------------------------------------------------------------*\
532| Return Value:                                                             |
533|    rtems_status_code                                                      |
534\*=========================================================================*/
535{
536  m8xx_spi_softc_t *softc_ptr = &(((m8xx_spi_desc_t *)(bh))->softc);
537  uint32_t spimode_baud;
538  uint16_t spimode;
539  rtems_status_code rc = RTEMS_SUCCESSFUL;
540  /*
541   * FIXME: set proper mode
542   */
543  if (rc == RTEMS_SUCCESSFUL) {
544    rc = m8xx_spi_baud_to_mode(tfr_mode->baudrate,&spimode_baud);
545  }
546  if (rc == RTEMS_SUCCESSFUL) {
547    rc = m8xx_spi_char_mode(softc_ptr,
548                               tfr_mode->bits_per_char,
549                               tfr_mode->lsb_first,
550                               &spimode);
551  }
552  if (rc == RTEMS_SUCCESSFUL) {
553    spimode |= spimode_baud;
554    spimode |= M8xx_SPMODE_MASTER; /* set master mode */
555    if (!tfr_mode->lsb_first) {
556      spimode |= M8xx_SPMODE_REV;
557    }
558    if (tfr_mode->clock_inv) {
559      spimode |= M8xx_SPMODE_CI;
560    }
561    if (tfr_mode->clock_phs) {
562      spimode |= M8xx_SPMODE_CP;
563    }
564  }
565
566  if (rc == RTEMS_SUCCESSFUL) {
567    /*
568     * disable SPI
569     */
570    m8xx.spmode &= ~M8xx_SPMODE_EN;
571    /*
572     * set new mode and reenable SPI
573     */
574    m8xx.spmode = spimode | M8xx_SPMODE_EN;
575  }
576  return rc;
577}
578
579
580/*=========================================================================*\
581| Function:                                                                 |
582\*-------------------------------------------------------------------------*/
583int m8xx_spi_ioctl
584(
585/*-------------------------------------------------------------------------*\
586| Purpose:                                                                  |
587|   perform selected ioctl function for SPI                                 |
588+---------------------------------------------------------------------------+
589| Input Parameters:                                                         |
590\*-------------------------------------------------------------------------*/
591 rtems_libi2c_bus_t *bh,                 /* bus specifier structure        */
592 int                 cmd,                /* ioctl command code             */
593 void               *arg                 /* additional argument array      */
594)
595/*-------------------------------------------------------------------------*\
596| Return Value:                                                             |
597|    rtems_status_code                                                      |
598\*=========================================================================*/
599{
600  int ret_val = -1;
601
602  switch(cmd) {
603  case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
604    ret_val =
605      -m8xx_spi_set_tfr_mode(bh,
606                                (const rtems_libi2c_tfr_mode_t *)arg);
607    break;
608  case RTEMS_LIBI2C_IOCTL_READ_WRITE:
609    ret_val =
610      m8xx_spi_read_write_bytes(bh,
611                                ((rtems_libi2c_read_write_t *)arg)->rd_buf,
612                                ((rtems_libi2c_read_write_t *)arg)->wr_buf,
613                                ((rtems_libi2c_read_write_t *)arg)->byte_cnt);
614    break;
615  default:
616    ret_val = -RTEMS_NOT_DEFINED;
617    break;
618  }
619  return ret_val;
620}
621
622/*=========================================================================*\
623| Board-specific adaptation functions                                       |
624\*=========================================================================*/
625
626/*=========================================================================*\
627| Function:                                                                 |
628\*-------------------------------------------------------------------------*/
629static rtems_status_code bsp_spi_send_start
630(
631/*-------------------------------------------------------------------------*\
632| Purpose:                                                                  |
633|   dummy function, SPI has no start condition                              |
634+---------------------------------------------------------------------------+
635| Input Parameters:                                                         |
636\*-------------------------------------------------------------------------*/
637 rtems_libi2c_bus_t *bh                  /* bus specifier structure        */
638)
639/*-------------------------------------------------------------------------*\
640| Return Value:                                                             |
641|    o = ok or error code                                                   |
642\*=========================================================================*/
643{
644  return RTEMS_SUCCESSFUL;
645}
646
647/*=========================================================================*\
648| Function:                                                                 |
649\*-------------------------------------------------------------------------*/
650static rtems_status_code bsp_spi_sel_addr
651(
652/*-------------------------------------------------------------------------*\
653| Purpose:                                                                  |
654|   address a slave device on the bus                                       |
655+---------------------------------------------------------------------------+
656| Input Parameters:                                                         |
657\*-------------------------------------------------------------------------*/
658 rtems_libi2c_bus_t *bh,                 /* bus specifier structure        */
659 uint32_t addr,                          /* address to send on bus         */
660 int rw                                  /* 0=write,1=read                 */
661)
662/*-------------------------------------------------------------------------*\
663| Return Value:                                                             |
664|    rtems_status_code                                                      |
665\*=========================================================================*/
666{                           
667#if defined(PGHPLUS)
668  pbdat_val = m8xx.pbdat | (PGHPLUS_SPI_PB_DISP4_RS_MSK |
669                            PGHPLUS_SPI_PB_DISP4_CE_MSK |
670                            PGHPLUS_SPI_PB_EEP_CE_MSK);
671  /*
672   * select given device
673   */
674  switch(addr) {
675  case PGHPLUS_SPI_ADDR_EEPROM:
676    pbdat_val &= ~PGHPLUS_SPI_PB_EEP_CE_MSK;
677    break;
678  case PGHPLUS_SPI_ADDR_DISP4_DATA:
679    pbdat_val = (m8xx.pbdat
680                  & ~(PGHPLUS_PB_SPI_DISP4_CE_MSK |
681                      PGHPLUS_PB_SPI_DISP4_RS_MSK));
682    break;
683  case PGHPLUS_SPI_ADDR_DISP4_CTRL:
684    pbdat_val = (m8xx.pbdat
685                  & ~(PGHPLUS_PB_SPI_DISP4_CE_MSK)
686                  |   PGHPLUS_PB_SPI_DISP4_RS_MSK);
687    break;
688  default:
689    return RTEMS_INVALID_NUMBER;
690  }
691  m8xx_pbdat = pbdat_val
692#endif /* PGHPLUS */
693  return  RTEMS_SUCCESSFUL;
694}
695
696/*=========================================================================*\
697| Function:                                                                 |
698\*-------------------------------------------------------------------------*/
699static rtems_status_code bsp_spi_send_stop
700(
701/*-------------------------------------------------------------------------*\
702| Purpose:                                                                  |
703|   deselect SPI                                                            |
704+---------------------------------------------------------------------------+
705| Input Parameters:                                                         |
706\*-------------------------------------------------------------------------*/
707 rtems_libi2c_bus_t *bh                  /* bus specifier structure        */
708)
709/*-------------------------------------------------------------------------*\
710| Return Value:                                                             |
711|    o = ok or error code                                                   |
712\*=========================================================================*/
713{
714#if defined(DEBUG)
715  printk("bsp_spi_send_stop called... ");
716#endif
717    m8xx.pbdat = (m8xx.pbdat
718                  | PGHPLUS_PB_SPI_DISP4_CE_MSK
719                  | PGHPLUS_PB_SPI_EEP_CE_MSK);
720#if defined(DEBUG)
721  printk("... exit OK\r\n");
722#endif
723  return RTEMS_SUCCESSFUL;
724}
725
726/*=========================================================================*\
727| Function:                                                                 |
728\*-------------------------------------------------------------------------*/
729static rtems_status_code bsp_spi_init
730(
731/*-------------------------------------------------------------------------*\
732| Purpose:                                                                  |
733|   do board specific init:                                                 |
734|   - initialize pins for addressing                                        |
735|   - register further drivers                                              |
736+---------------------------------------------------------------------------+
737| Input Parameters:                                                         |
738\*-------------------------------------------------------------------------*/
739 int spi_busno
740)
741/*-------------------------------------------------------------------------*\
742| Return Value:                                                             |
743|    o = ok or error code                                                   |
744\*=========================================================================*/
745{
746  int ret_code;
747
748#if defined(DEBUG)
749  printk("bsp_spi_init called... ");
750#endif
751
752  /*
753   * init port pins used to address/select SPI devices
754   */
755
756  /*
757   * set up ports
758   * LINE      PAR  DIR  DAT
759   * -----------------------
760   * EEP_CE     0    1 act-high
761   * DISP4_CS   0    1 act-high
762   * DISP4_RS   0    1 active
763   */
764
765  /* set Port B Pin Assignment Register... */
766  m8xx.pbpar =
767    (m8xx.pbpar
768     & ~(PGHPLUS_PB_SPI_EEP_CE_MSK
769         | PGHPLUS_PB_SPI_DISP4_CE_MSK
770         | PGHPLUS_PB_SPI_DISP4_RS_MSK));
771
772    /* set Port B Data Direction Register... */
773  m8xx.pbdir =
774    m8xx.pbdir
775    | PGHPLUS_PB_SPI_EEP_CE_MSK
776    | PGHPLUS_PB_SPI_DISP4_CE_MSK
777    | PGHPLUS_PB_SPI_DISP4_RS_MSK;
778
779  /* set Port B Data Register to inactive CE state */
780  m8xx.pbdat =
781    m8xx.pbdat
782    | PGHPLUS_PB_SPI_DISP4_CE_MSK
783    | PGHPLUS_PB_SPI_DISP4_RS_MSK;
784
785  /*
786   * register devices
787   */
788  ret_code = rtems_libi2c_register_drv("disp",
789                                       disp_hcms29xx_driver_descriptor,
790                                       spi_busno,PGHPLUS_SPI_ADDR_DISP4);
791  if (ret_code < 0) {
792    return -ret_code;
793  }
794
795#if defined(DEBUG)
796  printk("... exit OK\r\n");
797#endif
798  return RTEMS_SUCCESSFUL;
799}
800
801/*=========================================================================*\
802| list of handlers                                                          |
803\*=========================================================================*/
804
805rtems_libi2c_bus_ops_t bsp_spi_ops = {
806  init:             m8xx_spi_init,
807  send_start:       bsp_spi_send_start,
808  send_stop:        bsp_spi_send_stop,
809  send_addr:        bsp_spi_sel_addr,
810  read_bytes:       m8xx_spi_read_bytes,
811  write_bytes:      m8xx_spi_write_bytes,
812  ioctl:            m8xx_spi_ioctl
813};
814
815static m8xx_spi_desc_t bsp_spi_bus_desc = {
816  {/* public fields */
817    ops:        &bsp_spi_ops,
818    size:       sizeof(bsp_spi_bus_desc)
819  },
820  { /* our private fields */
821    initialized: FALSE
822  }
823};
824
825/*=========================================================================*\
826| initialization                                                            |
827\*=========================================================================*/
828
829/*=========================================================================*\
830| Function:                                                                 |
831\*-------------------------------------------------------------------------*/
832rtems_status_code bsp_register_spi
833(
834/*-------------------------------------------------------------------------*\
835| Purpose:                                                                  |
836|   register SPI bus and devices                                            |
837+---------------------------------------------------------------------------+
838| Input Parameters:                                                         |
839\*-------------------------------------------------------------------------*/
840 void                                    /* <none>                         */
841)
842/*-------------------------------------------------------------------------*\
843| Return Value:                                                             |
844|    0 or error code                                                        |
845\*=========================================================================*/
846{
847  int ret_code;
848  int spi_busno;
849
850  /*
851   * init I2C library (if not already done)
852   */
853  rtems_libi2c_initialize ();
854
855
856  /*
857   * register SPI bus
858   */
859  ret_code = rtems_libi2c_register_bus("/dev/spi",
860                                       &(bsp_spi_bus_desc.bus_desc));
861  if (ret_code < 0) {
862    return -ret_code;
863  }
864  spi_busno = ret_code;
865
866  bsp_spi_init(spi_busno);
867  /*
868   * FIXME: further drivers, when available
869   */
870  return RTEMS_SUCCESSFUL;
871}
872
873
Note: See TracBrowser for help on using the repository browser.