initcalls: Add initial implementation
Create simple serial subsystem which makes use of initcalls, and convert existing serial drivers to its use.
This commit is contained in:
		| @@ -3,6 +3,9 @@ SUBDIRS := | ||||
|  | ||||
| include $(BASEDIR)/header.mk | ||||
|  | ||||
| OBJS_$(d) := \ | ||||
| 	$(d)/serial.o | ||||
|  | ||||
| OBJS_$(d)_$(CONFIG_VEXPRESS_A9) := \ | ||||
| 	$(d)/pl011.o \ | ||||
| 	$(d)/pl111.o | ||||
| @@ -15,6 +18,6 @@ OBJS_$(d)_$(CONFIG_RPI) := \ | ||||
| 	$(d)/bcm2835_mailbox.o \ | ||||
| 	$(d)/bcm2835_videocore.o | ||||
|  | ||||
| KOBJS += $(OBJS_$(d)_y) | ||||
| KOBJS += $(OBJS_$(d)) $(OBJS_$(d)_y) | ||||
|  | ||||
| include $(BASEDIR)/footer.mk | ||||
|   | ||||
| @@ -18,8 +18,11 @@ | ||||
|     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  */ | ||||
|  | ||||
| #include <init.h> | ||||
| #include <types.h> | ||||
|  | ||||
| #include <drivers/serial.h> | ||||
|  | ||||
| #define VC_MMU_IO_OFFSET(addr) (addr - 0x7E000000 + 0x20000000) | ||||
|  | ||||
| /* Auxiliary IO registers (includes both mini-UART and SPI) */ | ||||
| @@ -57,7 +60,7 @@ | ||||
| #define GPPUD VC_MMU_IO_OFFSET(0x7E200094) | ||||
| #define GPPUDCLK0 VC_MMU_IO_OFFSET(0x7E200098) | ||||
|  | ||||
| void mini_uart_init() { | ||||
| void mini_uart_device_init() { | ||||
| 	uint32 aux_enables; | ||||
| 	uint32 gpfsel1; | ||||
| 	unsigned int i; | ||||
| @@ -96,10 +99,23 @@ void mini_uart_init() { | ||||
| 	*(uint32 *)AUX_MU_CNTL_REG = 2; //enable TX | ||||
| } | ||||
|  | ||||
| void mini_uart_putc(char c) { | ||||
| int mini_uart_putc(char c) { | ||||
| 	/* Wait until the serial buffer is empty */ | ||||
| 	while (!(*(volatile uint32*)AUX_MU_LSR_REG & MINI_UART_TX_EMPTY)); | ||||
|  | ||||
| 	/* When it's empty, write our character */ | ||||
| 	*(volatile uint32*)AUX_MU_IO_REG = c; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct serial_dev mini_uart_dev = { | ||||
| 	.putc = &mini_uart_putc | ||||
| }; | ||||
|  | ||||
| void mini_uart_init() { | ||||
| 	mini_uart_device_init(); | ||||
| 	serial_register_device(&mini_uart_dev); | ||||
| } | ||||
|  | ||||
| early_initcall(mini_uart_init); | ||||
|   | ||||
| @@ -18,17 +18,31 @@ | ||||
|     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  */ | ||||
|  | ||||
| #include <init.h> | ||||
| #include <drivers/serial.h> | ||||
| #include <types.h> | ||||
|  | ||||
| #define PL011_SERIAL_BASE 0x10009000 | ||||
| #define PL011_SERIAL_FLAG_REGISTER 0x18 | ||||
| #define PL011_SERIAL_BUFFER_FULL (1 << 5) | ||||
|  | ||||
| void pl011_putc(char c) | ||||
| int pl011_putc(char c) | ||||
| { | ||||
| 	/* Wait until the serial buffer is empty */ | ||||
| 	while (*(volatile uint32*)(PL011_SERIAL_BASE + PL011_SERIAL_FLAG_REGISTER) & (PL011_SERIAL_BUFFER_FULL)); | ||||
|  | ||||
| 	/* When it's empty, put our character at the base */ | ||||
| 	*(volatile uint32*)PL011_SERIAL_BASE = c; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct serial_dev pl011_dev = { | ||||
| 	.putc = &pl011_putc | ||||
| }; | ||||
|  | ||||
| void pl011_init() { | ||||
| 	serial_register_device(&pl011_dev); | ||||
| } | ||||
|  | ||||
| early_initcall(pl011_init); | ||||
|   | ||||
							
								
								
									
										40
									
								
								drivers/serial.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								drivers/serial.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
|     Copyright (C) 2012, Aaron Lindsay <aaron@aclindsay.com> | ||||
|  | ||||
|     This file is part of Aedrix. | ||||
|  | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
|  | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU General Public License along | ||||
|     with this program; if not, write to the Free Software Foundation, Inc., | ||||
|     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||
|  */ | ||||
|  | ||||
| #include <init.h> | ||||
| #include <drivers/serial.h> | ||||
|  | ||||
| struct serial_dev *first_serial_dev; | ||||
|  | ||||
| int serial_register_device(struct serial_dev *sdev) { | ||||
| 	if (!first_serial_dev) | ||||
| 		first_serial_dev = sdev; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| struct serial_dev *serial_first_device() { | ||||
| 	return first_serial_dev; | ||||
| } | ||||
|  | ||||
| void serial_init() { | ||||
| 	first_serial_dev = 0; | ||||
| } | ||||
|  | ||||
| driversubsys_initcall(serial_init); | ||||
		Reference in New Issue
	
	Block a user