xref: /minix3/minix/kernel/arch/earm/bsp/ti/omap_serial.c (revision 9f11521a37bfb95426e4373d3586c13902e4517f)
1433d6423SLionel Sambuc #include <assert.h>
2433d6423SLionel Sambuc #include <sys/types.h>
3433d6423SLionel Sambuc #include <machine/cpu.h>
4433d6423SLionel Sambuc #include <minix/type.h>
5433d6423SLionel Sambuc #include <minix/board.h>
6433d6423SLionel Sambuc #include <io.h>
7433d6423SLionel Sambuc 
8433d6423SLionel Sambuc #include "kernel/kernel.h"
9433d6423SLionel Sambuc #include "kernel/proc.h"
10433d6423SLionel Sambuc #include "kernel/vm.h"
11433d6423SLionel Sambuc #include "kernel/proto.h"
12433d6423SLionel Sambuc #include "arch_proto.h"
13433d6423SLionel Sambuc 
14433d6423SLionel Sambuc #include "omap_serial.h"
15433d6423SLionel Sambuc 
16433d6423SLionel Sambuc struct omap_serial
17433d6423SLionel Sambuc {
18433d6423SLionel Sambuc 	vir_bytes base;
19433d6423SLionel Sambuc 	vir_bytes size;
20433d6423SLionel Sambuc };
21433d6423SLionel Sambuc 
22433d6423SLionel Sambuc static struct omap_serial omap_serial = {
23433d6423SLionel Sambuc 	.base = 0,
24433d6423SLionel Sambuc };
25433d6423SLionel Sambuc 
26433d6423SLionel Sambuc static kern_phys_map serial_phys_map;
27433d6423SLionel Sambuc 
28433d6423SLionel Sambuc /*
29*9f11521aSio12  * In kernel serial for the omap. The serial driver, like most other
30*9f11521aSio12  * drivers, needs to be started early and even before the MMU is turned on.
31433d6423SLionel Sambuc  * We start by directly accessing the hardware memory address. Later on
32*9f11521aSio12  * when the MMU is turned on we still use a 1:1 mapping for these addresses.
33433d6423SLionel Sambuc  *
34*9f11521aSio12  * Pretty soon we are going to remap these addresses at a later stage. And this
35433d6423SLionel Sambuc  * requires us to use a dynamic base address. The idea is to receive a callback
36433d6423SLionel Sambuc  * from VM with the new address to use.
37433d6423SLionel Sambuc  *
38*9f11521aSio12  * We also try on the BeagleBone port to keep the differences between the
39*9f11521aSio12  * drivers to a minimum by initializing a struct here and not using (too many)
40433d6423SLionel Sambuc  * constants in the code.
41433d6423SLionel Sambuc  *
42433d6423SLionel Sambuc  * The serial driver also gets used in the "pre_init" stage before the kernel is loaded
43*9f11521aSio12  * in high memory, so keep in mind there are two copies of this code in the kernel.
44433d6423SLionel Sambuc  */
45433d6423SLionel Sambuc void
bsp_ser_init(void)466077d1adSDr. Florian Grätz bsp_ser_init(void)
47433d6423SLionel Sambuc {
48433d6423SLionel Sambuc 	if (BOARD_IS_BBXM(machine.board_id)) {
49433d6423SLionel Sambuc 		omap_serial.base = OMAP3_DM37XX_DEBUG_UART_BASE;
50433d6423SLionel Sambuc 	} else if (BOARD_IS_BB(machine.board_id)) {
51433d6423SLionel Sambuc 		omap_serial.base = OMAP3_AM335X_DEBUG_UART_BASE;
52433d6423SLionel Sambuc 	}
53433d6423SLionel Sambuc 	omap_serial.size = 0x1000;	/* 4k */
54433d6423SLionel Sambuc 
55433d6423SLionel Sambuc 	kern_phys_map_ptr(omap_serial.base, omap_serial.size,
56433d6423SLionel Sambuc 	    VMMF_UNCACHED | VMMF_WRITE, &serial_phys_map,
57433d6423SLionel Sambuc 	    (vir_bytes) & omap_serial.base);
58433d6423SLionel Sambuc 	assert(omap_serial.base);
59433d6423SLionel Sambuc }
60433d6423SLionel Sambuc 
61433d6423SLionel Sambuc void
bsp_ser_putc(char c)62433d6423SLionel Sambuc bsp_ser_putc(char c)
63433d6423SLionel Sambuc {
64433d6423SLionel Sambuc 	int i;
65433d6423SLionel Sambuc 	assert(omap_serial.base);
66433d6423SLionel Sambuc 
67433d6423SLionel Sambuc 	/* Wait until FIFO's empty */
68433d6423SLionel Sambuc 	for (i = 0; i < 100000; i++) {
69433d6423SLionel Sambuc 		if (mmio_read(omap_serial.base + OMAP3_LSR) & OMAP3_LSR_THRE) {
70433d6423SLionel Sambuc 			break;
71433d6423SLionel Sambuc 		}
72433d6423SLionel Sambuc 	}
73433d6423SLionel Sambuc 
74433d6423SLionel Sambuc 	/* Write character */
75433d6423SLionel Sambuc 	mmio_write(omap_serial.base + OMAP3_THR, c);
76433d6423SLionel Sambuc 
77433d6423SLionel Sambuc 	/* And wait again until FIFO's empty to prevent TTY from overwriting */
78433d6423SLionel Sambuc 	for (i = 0; i < 100000; i++) {
79433d6423SLionel Sambuc 		if (mmio_read(omap_serial.base +
80433d6423SLionel Sambuc 			OMAP3_LSR) & (OMAP3_LSR_THRE | OMAP3_LSR_TEMT)) {
81433d6423SLionel Sambuc 			break;
82433d6423SLionel Sambuc 		}
83433d6423SLionel Sambuc 	}
84433d6423SLionel Sambuc }
85