source: rtems/bsps/m68k/gen68360/spi/m360_spi.c @ 276afd2b

5
Last change on this file since 276afd2b was 276afd2b, checked in by Sebastian Huber <sebastian.huber@…>, on 04/23/18 at 07:48:52

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