source: rtems/c/src/lib/libbsp/i386/pc386/console/exar17d15x.c @ 22bbb9f1

5
Last change on this file since 22bbb9f1 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/**
2 * @file
3 *
4 * @brief Driver for Exar XR17D15x Multiport UARTs
5 *
6 * This driver supports 2, 4 or 8 port Exar parts which are NS16550
7 * compatible.
8 */
9
10/*
11 *  COPYRIGHT (c) 1989-2012.
12 *  On-Line Applications Research Corporation (OAR).
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19#include <bsp.h>
20#include <termios.h>
21#include <stdio.h>
22#include <stdlib.h>
23
24#include <rtems/termiostypes.h>
25#include <libchip/serial.h>
26#include <libchip/ns16550.h>
27#include <rtems/bspIo.h>
28#include <rtems/pci.h>
29#include <bsp/exar17d15x.h>
30#include "../../../shared/console_private.h"
31
32#define MAX_BOARDS 4
33
34/*
35 *  This is the rate for the clock internal to the parts.
36 */
37#define EXAR_CLOCK_RATE  (921600*16)
38
39/*
40 *  Supported PCI Ids
41 */
42#define PCI_VENDOR_ID_EXAR 0x13A8
43#define PCI_VENDOR_ID_EXAR_XR17D158 0x0158
44#define PCI_VENDOR_ID_EXAR_XR17D154 0x0154
45#define PCI_VENDOR_ID_EXAR_XR17D152 0x0152
46
47/*
48 * Structure to manage each instance found.
49 */
50typedef struct {
51  uint16_t  vendor;
52  uint16_t  device;
53  uint8_t   ports;
54} exar_parts_t;
55
56static exar_parts_t Supported[] = {
57  { PCI_VENDOR_ID_EXAR, PCI_VENDOR_ID_EXAR_XR17D158, 8 },
58  { PCI_VENDOR_ID_EXAR, PCI_VENDOR_ID_EXAR_XR17D154, 4 },
59  { PCI_VENDOR_ID_EXAR, PCI_VENDOR_ID_EXAR_XR17D152, 2 },
60  { 0, 0, 0 }
61};
62
63/*
64 * Information saved from PCI scan
65 */
66typedef struct {
67  bool      found;
68  uint32_t  base;
69  uint8_t   irq;
70  uint8_t   bus;
71  uint8_t   slot;
72  uint8_t   ports;
73} exar17d15x_conf_t;
74
75/*
76 *  Register Access Routines
77 */
78static uint8_t xr17d15x_get_register(uint32_t addr, uint8_t i)
79{
80  uint8_t          val = 0;
81  volatile uint8_t *reg = (volatile uint8_t *)(addr + i);
82
83  val = *reg;
84  // printk( "RD %p -> 0x%02x\n", reg, val );
85  return val;
86}
87
88static void xr17d15x_set_register(uint32_t addr, uint8_t i, uint8_t val)
89{
90  volatile uint8_t *reg = (volatile uint8_t *)(addr + i);
91
92  // printk( "WR %p <- 0x%02x\n", reg, val );
93  *reg = val;
94}
95
96rtems_device_driver exar17d15x_initialize(
97  rtems_device_major_number  major,
98  rtems_device_minor_number  minor_arg,
99  void                      *arg
100)
101{
102  // int  pbus, pdev, pfun;
103  exar17d15x_conf_t  conf[MAX_BOARDS];
104  int              boards = 0;
105  int              b = 0;
106  int              p;
107  console_tbl     *ports;
108  console_tbl     *port_p;
109  int              pbus;
110  int              pdev;
111  int              pfun;
112  int              status;
113  int              instance;
114  int              i;
115  int              total_ports = 0;
116
117  for ( b=0 ; b<MAX_BOARDS ; b++ ) {
118    conf[b].found = false;
119  }
120
121  /*
122   *  Scan for Serial port boards
123   *
124   *  NOTE: There appear to be Exar parts with 2 and 4 ports which would
125   *        be easy to support.  Just change the hard-coded 8 ports per
126   *        board to variable and adjust.
127   *
128   *  NOTE: There are likely other board vendors which could be supported
129   *        by this.
130   */
131  for ( instance=0 ; instance < MAX_BOARDS ; instance++ ) {
132
133    for ( i=0 ; Supported[i].ports != 0 ; i++ ) {
134      status = pci_find_device(
135        Supported[i].vendor,
136        Supported[i].device,
137        instance,
138        &pbus,
139        &pdev,
140        &pfun
141      );
142      if ( status == PCIB_ERR_SUCCESS ) {
143        boards++;
144        conf[instance].found = true;
145        conf[instance].ports = Supported[i].ports;
146        total_ports += conf[instance].ports;
147        break;
148      }
149    }
150
151    if ( status != PCIB_ERR_SUCCESS )
152      continue;
153
154    pci_read_config_byte(
155      pbus,
156      pdev,
157      pfun,
158      PCI_INTERRUPT_LINE,
159      &conf[instance].irq
160    );
161    pci_read_config_dword(
162      pbus,
163      pdev,
164      pfun,
165      PCI_BASE_ADDRESS_0,
166      &conf[instance].base
167    );
168    printk(
169      "Found Exar 17D15x %d at 0x%08x IRQ %d with %d ports\n",
170      instance,
171      conf[instance].base,
172      conf[instance].irq,
173      conf[instance].ports
174    );
175  }
176
177  /*
178   *  Now allocate array of device structures and fill them in
179   */
180  ports = calloc( total_ports, sizeof( console_tbl ) );
181  port_p = ports;
182  for ( b=0 ; b<MAX_BOARDS ; b++ ) {
183    if ( conf[b].found == false )
184      continue;
185    for ( p=0 ; p<conf[b].ports ; p++ ) {
186      char name[32];
187
188      sprintf( name, "/dev/exar17d15x_%d_%d", b, p );
189      //printk("Found %s\n", name );
190      port_p->sDeviceName   = strdup( name );
191      port_p->deviceType    = SERIAL_NS16550;
192      #if 1
193        port_p->pDeviceFns    = &ns16550_fns_polled;
194      #else
195        port_p->pDeviceFns    = &ns16550_fns;
196      #endif
197
198      port_p->deviceProbe   = NULL;
199      port_p->pDeviceFlow   = NULL;
200      port_p->ulMargin      = 16;
201      port_p->ulHysteresis  = 8;
202      port_p->pDeviceParams = (void *) 9600;
203      port_p->ulCtrlPort1   = conf[b].base + (p * 0x0200);
204      port_p->ulCtrlPort2   = 0;                   /* NA */
205      port_p->ulDataPort    = 0;                   /* NA */
206      port_p->getRegister   = xr17d15x_get_register;
207      port_p->setRegister   = xr17d15x_set_register;
208      port_p->getData       = NULL;                /* NA */
209      port_p->setData       = NULL;                /* NA */
210      port_p->ulClock       = EXAR_CLOCK_RATE;
211      port_p->ulIntVector   = conf[b].irq;
212
213      port_p++;
214    }  /* end ports */
215  }    /* end boards */
216
217  /*
218   *  Register the devices
219   */
220  if ( boards )
221    console_register_devices( ports, total_ports );
222
223  return RTEMS_SUCCESSFUL;
224}
Note: See TracBrowser for help on using the repository browser.