xref: /minix/minix/kernel/arch/earm/bsp/ti/omap_serial.c (revision 045e0ed3)
1 #include <assert.h>
2 #include <sys/types.h>
3 #include <machine/cpu.h>
4 #include <minix/type.h>
5 #include <minix/board.h>
6 #include <io.h>
7 
8 #include "kernel/kernel.h"
9 #include "kernel/proc.h"
10 #include "kernel/vm.h"
11 #include "kernel/proto.h"
12 #include "arch_proto.h"
13 
14 #include "omap_serial.h"
15 
16 struct omap_serial
17 {
18 	vir_bytes base;
19 	vir_bytes size;
20 };
21 
22 static struct omap_serial omap_serial = {
23 	.base = 0,
24 };
25 
26 static kern_phys_map serial_phys_map;
27 
28 /*
29  * In kernel serial for the omap. The serial driver, like most other
30  * drivers, needs to be started early and even before the MMU is turned on.
31  * We start by directly accessing the hardware memory address. Later on
32  * when the MMU is turned on we still use a 1:1 mapping for these addresses.
33  *
34  * Pretty soon we are going to remap these addresses at a later stage. And this
35  * requires us to use a dynamic base address. The idea is to receive a callback
36  * from VM with the new address to use.
37  *
38  * We also try on the BeagleBone port to keep the differences between the
39  * drivers to a minimum by initializing a struct here and not using (too many)
40  * constants in the code.
41  *
42  * The serial driver also gets used in the "pre_init" stage before the kernel is loaded
43  * in high memory, so keep in mind there are two copies of this code in the kernel.
44  */
45 void
46 bsp_ser_init(void)
47 {
48 	if (BOARD_IS_BBXM(machine.board_id)) {
49 		omap_serial.base = OMAP3_DM37XX_DEBUG_UART_BASE;
50 	} else if (BOARD_IS_BB(machine.board_id)) {
51 		omap_serial.base = OMAP3_AM335X_DEBUG_UART_BASE;
52 	}
53 	omap_serial.size = 0x1000;	/* 4k */
54 
55 	kern_phys_map_ptr(omap_serial.base, omap_serial.size,
56 	    VMMF_UNCACHED | VMMF_WRITE, &serial_phys_map,
57 	    (vir_bytes) & omap_serial.base);
58 	assert(omap_serial.base);
59 }
60 
61 void
62 bsp_ser_putc(char c)
63 {
64 	int i;
65 	assert(omap_serial.base);
66 
67 	/* Wait until FIFO's empty */
68 	for (i = 0; i < 100000; i++) {
69 		if (mmio_read(omap_serial.base + OMAP3_LSR) & OMAP3_LSR_THRE) {
70 			break;
71 		}
72 	}
73 
74 	/* Write character */
75 	mmio_write(omap_serial.base + OMAP3_THR, c);
76 
77 	/* And wait again until FIFO's empty to prevent TTY from overwriting */
78 	for (i = 0; i < 100000; i++) {
79 		if (mmio_read(omap_serial.base +
80 			OMAP3_LSR) & (OMAP3_LSR_THRE | OMAP3_LSR_TEMT)) {
81 			break;
82 		}
83 	}
84 }
85