1 /* $Id: imxuart.c,v 1.3 2008/06/30 00:46:41 perry Exp $ */
4 #include <sys/device.h>
7 #include <arm/armreg.h>
10 #include <sys/termios.h>
13 #include <machine/bus.h>
14 #include <arm/imx/imx31var.h>
15 #include <arm/imx/imxuartreg.h>
16 #include <arm/imx/imxuartvar.h>
17 #include <evbarm/imx31/imx31lk_reg.h>
19 #define IMXUART_UNIT_MASK 0x7ffff
20 #define IMXUART_DIALOUT_MASK 0x80000
22 #define IMXUART_UNIT(dev) (minor(dev) & IMXUART_UNIT_MASK)
23 #define IMXUART_DIALOUT(dev) (minor(dev) & IMXUART_DIALOUT_MASK)
27 #define __TRACE imxuart_puts(&imxuart_softc, __func__ )
29 extern struct bus_space imx31_bs_tag
;
31 imxuart_softc_t imxuart_softc
= { { 0, }, };
33 uint32_t imxuart_snapshot_data
[32];
34 const char *imxuart_test_string
=
35 "0123456789012345678901234567890123456789\r\n";
39 static struct consdev imxuartcntab
= cons_init(imxuart
);
42 dev_type_open(imxuartopen
);
43 dev_type_close(imxuartclose
);
44 dev_type_read(imxuartread
);
45 dev_type_write(imxuartwrite
);
46 dev_type_ioctl(imxuartioctl
);
47 dev_type_stop(imxuartstop
);
48 dev_type_tty(imxuarttty
);
49 dev_type_poll(imxuartpoll
);
50 const struct cdevsw imxuart_cdevsw
= {
51 imxuartopen
, imxuartclose
, imxuartread
, imxuartwrite
,
52 imxuartioctl
, imxuartstop
, imxuarttty
, imxuartpoll
,
53 nommap
, ttykqfilter
, D_TTY
56 const struct cdevsw imxuart_cdevsw
= {
57 nullopen
, nullclose
, nullread
, nullwrite
,
58 nullioctl
, nullstop
, notty
, nullpoll
,
59 nommap
, nullkqfilter
, D_TTY
64 int imxuart_cnattach(bus_space_tag_t
, bus_addr_t
, int, int, int, tcflag_t
);
65 int imxuart_puts(imxuart_softc_t
*, const char *);
66 int imxuart_putchar(imxuart_softc_t
*, int);
67 int imxuart_getchar(imxuart_softc_t
*);
69 static int imxuart_urxd_brk(void);
70 static void imxuart_urxd_err(imxuart_softc_t
*, uint32_t);
72 static int imxuart_match(struct device
*, struct cfdata
*, void *);
73 static void imxuart_attach(struct device
*, struct device
*, void *);
75 static void imxuart_start(struct tty
*);
76 static int imxuart_param(struct tty
*, struct termios
*);
77 static void imxuart_shutdownhook(void *arg
);
79 CFATTACH_DECL(imxuart
, sizeof(struct imxuart_softc
),
80 imxuart_match
, imxuart_attach
, NULL
, NULL
);
84 * disable the specified IMX UART interrupt in softc
86 * else return previous enabled state
89 imxuart_intrspec_dis(imxuart_softc_t
*sc
, imxuart_intrix_t ix
)
91 const imxuart_intrspec_t
*spec
= &imxuart_intrspec_tab
[ix
];
94 const uint32_t syncbit
= 1 << 31;
97 if (ix
>= IMXUART_INTRSPEC_TAB_SZ
)
101 if ((sc
->sc_intrspec_enb
& v
) == 0)
103 sc
->sc_intrspec_enb
&= ~v
;
123 * enable the specified IMX UART interrupt in softc
125 * else return previous enabled state
128 imxuart_intrspec_enb(imxuart_softc_t
*sc
, imxuart_intrix_t ix
)
130 const imxuart_intrspec_t
*spec
= &imxuart_intrspec_tab
[ix
];
133 const uint32_t syncbit
= 1 << 31;
135 if (ix
>= IMXUART_INTRSPEC_TAB_SZ
)
139 if ((sc
->sc_intrspec_enb
& v
) != 0)
141 sc
->sc_intrspec_enb
|= v
;
158 * sync softc interrupt spec to UART Control regs
161 imxuart_intrspec_sync(imxuart_softc_t
*sc
)
166 const uint32_t syncbit
= 1 << 31;
167 const uint32_t mask
[4] = {
174 for (i
=0; i
< 4; i
++) {
179 r
= bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, IMX_UCRn(i
));
182 bus_space_write_4(sc
->sc_bt
, sc
->sc_bh
, IMX_UCRn(i
), r
);
189 imxuart_init(imxuart_softc_t
*sc
, uint bh
)
194 cn_tab
= &imxuartcntab
;
195 sc
->sc_bt
= &imx31_bs_tag
;
198 memset(&sc
->sc_errors
, 0, sizeof(sc
->sc_errors
));
204 imxuart_puts(imxuart_softc_t
*sc
, const char *s
)
213 err
= imxuart_putchar(sc
, c
);
219 imxuart_putchar(imxuart_softc_t
*sc
, int c
)
224 r
= bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, IMX_UTS
);
225 if ((r
& IMX_UTS_TXFUL
) == 0)
229 r
= (uint32_t)c
& IMX_UTXD_TX_DATA
;
230 bus_space_write_4(sc
->sc_bt
, sc
->sc_bh
, IMX_UTXD
, r
);
236 imxuart_getchar(imxuart_softc_t
*sc
)
242 r
= bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, IMX_URXD
);
243 if (r
& IMX_URXD_ERR
) {
244 imxuart_urxd_err(sc
, r
);
247 if (r
& IMX_URXD_CHARDY
) {
248 c
= (int)(r
& IMX_URXD_RX_DATA
);
257 imxuart_urxd_brk(void)
260 if (cn_tab
== &imxuartcntab
) {
269 imxuart_urxd_err(imxuart_softc_t
*sc
, uint32_t r
)
271 if (r
& IMX_URXD_BRK
)
272 if (imxuart_urxd_brk() == 0)
276 if (r
& IMX_URXD_BRK
)
278 if (r
& IMX_URXD_PRERR
)
279 sc
->sc_errors
.prerr
++;
280 if (r
& IMX_URXD_FRMERR
)
281 sc
->sc_errors
.frmerr
++;
282 if (r
& IMX_URXD_OVRRUN
)
283 sc
->sc_errors
.ovrrun
++;
287 imxuart_snapshot(imxuart_softc_t
*sc
, uint32_t *p
)
290 const uint r
[] = { IMX_URXD
, IMX_UTXD
, IMX_UCR1
, IMX_UCR2
,
291 IMX_UCR3
, IMX_UCR4
, IMX_UFCR
, IMX_USR1
,
292 IMX_USR2
, IMX_UESC
, IMX_UTIM
, IMX_UBIR
,
293 IMX_UBMR
, IMX_UBRC
, IMX_ONEMS
, IMX_UTS
};
295 for (i
=0; i
< ((sizeof(r
)/sizeof(r
[0]))); i
++) {
296 *p
++ = sc
->sc_bh
+ r
[i
];
297 *p
++ = bus_space_read_4(sc
->sc_bt
, sc
->sc_bh
, r
[i
]);
305 imxuart_softc_t
*sc
= &imxuart_softc
;
309 err
= imxuart_init(sc
, 1);
314 extern u_int
cpufunc_id(void);
320 err
= imxuart_snapshot(sc
, imxuart_snapshot_data
);
326 err
= imxuart_putchar(sc
, 'x');
331 err
= imxuart_puts(sc
, imxuart_test_string
);
336 err
= imxuart_snapshot(sc
, imxuart_snapshot_data
);
344 imxuart_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
346 struct aips_attach_args
* const aipsa
= aux
;
348 switch (aipsa
->aipsa_addr
) {
361 imxuart_attach(struct device
*parent
, struct device
*self
, void *aux
)
363 imxuart_softc_t
*sc
= (void *)self
;
364 struct aips_attach_args
* const aipsa
= aux
;
367 sc
->sc_bt
= aipsa
->aipsa_memt
;
368 sc
->sc_addr
= aipsa
->aipsa_addr
;
369 sc
->sc_size
= aipsa
->aipsa_size
;
370 sc
->sc_intr
= aipsa
->aipsa_intr
;
372 sc
->sc_tty
= tp
= ttymalloc();
373 tp
->t_oproc
= imxuart_start
;
374 tp
->t_param
= imxuart_param
;
377 shutdownhook_establish(imxuart_shutdownhook
, sc
);
383 imxuartcnprobe(struct consdev
*cp
)
388 major
= cdevsw_lookup_major(&imxuart_cdevsw
);
389 cp
->cn_dev
= makedev(major
, 0); /* XXX unit 0 */
390 cp
->cn_pri
= CN_REMOTE
;
394 imxuart_start(struct tty
*tp
)
400 imxuart_param(struct tty
*tp
, struct termios
*termios
)
407 imxuart_shutdownhook(void *arg
)
413 imxuartcninit(struct consdev
*cp
)
419 imxuartcngetc(dev_t dev
)
421 struct imxuart_softc
*sc
;
425 unit
= IMXUART_UNIT(dev
);
429 c
= imxuart_getchar(sc
);
434 imxuartcnputc(dev_t dev
, int c
)
436 (void)imxuart_putchar(&imxuart_softc
, c
);
440 imxuartcnpollc(dev_t dev
, int mode
)
442 /* always polled for now */
445 imxuart_cnattach(bus_space_tag_t iot
, bus_addr_t iobase
,
446 int rate
, int frequency
, int type
, tcflag_t cflag
)
448 cn_tab
= &imxuartcntab
;