Xenomai  3.1
16550A_io.h
1 /*
2  * Copyright (C) 2007 Jan Kiszka <jan.kiszka@web.de>.
3  *
4  * Xenomai is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * Xenomai is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Xenomai; if not, write to the Free Software Foundation,
16  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 /* Manages the I/O access method of the driver. */
20 
21 typedef enum { MODE_PIO, MODE_MMIO } io_mode_t;
22 
23 #if defined(CONFIG_XENO_DRIVERS_16550A_PIO) || \
24  defined(CONFIG_XENO_DRIVERS_16550A_ANY)
25 static unsigned long io[MAX_DEVICES];
26 module_param_array(io, ulong, NULL, 0400);
27 MODULE_PARM_DESC(io, "I/O port addresses of the serial devices");
28 #endif /* CONFIG_XENO_DRIVERS_16550A_PIO || CONFIG_XENO_DRIVERS_16550A_ANY */
29 
30 #if defined(CONFIG_XENO_DRIVERS_16550A_MMIO) || \
31  defined(CONFIG_XENO_DRIVERS_16550A_ANY)
32 static unsigned long mem[MAX_DEVICES];
33 static void *mapped_io[MAX_DEVICES];
34 module_param_array(mem, ulong, NULL, 0400);
35 MODULE_PARM_DESC(mem, "I/O memory addresses of the serial devices");
36 #endif /* CONFIG_XENO_DRIVERS_16550A_MMIO || CONFIG_XENO_DRIVERS_16550A_ANY */
37 
38 #ifdef CONFIG_XENO_DRIVERS_16550A_PIO
39 
40 #define RT_16550_IO_INLINE inline
41 
42 extern void *mapped_io[]; /* dummy */
43 
44 static inline unsigned long rt_16550_addr_param(int dev_id)
45 {
46  return io[dev_id];
47 }
48 
49 static inline int rt_16550_addr_param_valid(int dev_id)
50 {
51  return 1;
52 }
53 
54 static inline unsigned long rt_16550_base_addr(int dev_id)
55 {
56  return io[dev_id];
57 }
58 
59 static inline io_mode_t rt_16550_io_mode(int dev_id)
60 {
61  return MODE_PIO;
62 }
63 
64 static inline io_mode_t
65 rt_16550_io_mode_from_ctx(struct rt_16550_context *ctx)
66 {
67  return MODE_PIO;
68 }
69 
70 static inline void
71 rt_16550_init_io_ctx(int dev_id, struct rt_16550_context *ctx)
72 {
73  ctx->base_addr = io[dev_id];
74 }
75 
76 #elif defined(CONFIG_XENO_DRIVERS_16550A_MMIO)
77 
78 #define RT_16550_IO_INLINE inline
79 
80 extern unsigned long io[]; /* dummy */
81 
82 static inline unsigned long rt_16550_addr_param(int dev_id)
83 {
84  return mem[dev_id];
85 }
86 
87 static inline int rt_16550_addr_param_valid(int dev_id)
88 {
89  return 1;
90 }
91 
92 static inline unsigned long rt_16550_base_addr(int dev_id)
93 {
94  return (unsigned long)mapped_io[dev_id];
95 }
96 
97 static inline io_mode_t rt_16550_io_mode(int dev_id)
98 {
99  return MODE_MMIO;
100 }
101 
102 static inline io_mode_t
103 rt_16550_io_mode_from_ctx(struct rt_16550_context *ctx)
104 {
105  return MODE_MMIO;
106 }
107 
108 static inline void
109 rt_16550_init_io_ctx(int dev_id, struct rt_16550_context *ctx)
110 {
111  ctx->base_addr = (unsigned long)mapped_io[dev_id];
112 }
113 
114 #elif defined(CONFIG_XENO_DRIVERS_16550A_ANY)
115 
116 #define RT_16550_IO_INLINE /* uninline */
117 
118 static inline unsigned long rt_16550_addr_param(int dev_id)
119 {
120  return (io[dev_id]) ? io[dev_id] : mem[dev_id];
121 }
122 
123 static inline int rt_16550_addr_param_valid(int dev_id)
124 {
125  return !(io[dev_id] && mem[dev_id]);
126 }
127 
128 static inline unsigned long rt_16550_base_addr(int dev_id)
129 {
130  return (io[dev_id]) ? io[dev_id] : (unsigned long)mapped_io[dev_id];
131 }
132 
133 static inline io_mode_t rt_16550_io_mode(int dev_id)
134 {
135  return (io[dev_id]) ? MODE_PIO : MODE_MMIO;
136 }
137 
138 static inline io_mode_t
139 rt_16550_io_mode_from_ctx(struct rt_16550_context *ctx)
140 {
141  return ctx->io_mode;
142 }
143 
144 static inline void
145 rt_16550_init_io_ctx(int dev_id, struct rt_16550_context *ctx)
146 {
147  if (io[dev_id]) {
148  ctx->base_addr = io[dev_id];
149  ctx->io_mode = MODE_PIO;
150  } else {
151  ctx->base_addr = (unsigned long)mapped_io[dev_id];
152  ctx->io_mode = MODE_MMIO;
153  }
154 }
155 
156 #else
157 # error Unsupported I/O access method
158 #endif
159 
160 static RT_16550_IO_INLINE u8
161 rt_16550_reg_in(io_mode_t io_mode, unsigned long base, int off)
162 {
163  switch (io_mode) {
164  case MODE_PIO:
165  return inb(base + off);
166  default: /* MODE_MMIO */
167  return readb((void *)base + off);
168  }
169 }
170 
171 static RT_16550_IO_INLINE void
172 rt_16550_reg_out(io_mode_t io_mode, unsigned long base, int off, u8 val)
173 {
174  switch (io_mode) {
175  case MODE_PIO:
176  outb(val, base + off);
177  break;
178  case MODE_MMIO:
179  writeb(val, (void *)base + off);
180  break;
181  }
182 }
183 
184 static int rt_16550_init_io(int dev_id, char* name)
185 {
186  switch (rt_16550_io_mode(dev_id)) {
187  case MODE_PIO:
188  if (!request_region(rt_16550_addr_param(dev_id), 8, name))
189  return -EBUSY;
190  break;
191  case MODE_MMIO:
192  mapped_io[dev_id] = ioremap(rt_16550_addr_param(dev_id), 8);
193  if (!mapped_io[dev_id])
194  return -EBUSY;
195  break;
196  }
197  return 0;
198 }
199 
200 static void rt_16550_release_io(int dev_id)
201 {
202  switch (rt_16550_io_mode(dev_id)) {
203  case MODE_PIO:
204  release_region(io[dev_id], 8);
205  break;
206  case MODE_MMIO:
207  iounmap(mapped_io[dev_id]);
208  break;
209  }
210 }