Add Raspberry PI's mini-UART
This commit is contained in:
		| @@ -5,7 +5,8 @@ include $(BASEDIR)/header.mk | |||||||
|  |  | ||||||
| OBJS_$(d) := $(d)/pl011.o \ | OBJS_$(d) := $(d)/pl011.o \ | ||||||
| 	$(d)/pl110.o \ | 	$(d)/pl110.o \ | ||||||
| 	$(d)/pl111.o | 	$(d)/pl111.o \ | ||||||
|  | 	$(d)/pi_mini_uart.o | ||||||
|  |  | ||||||
| KOBJS += $(OBJS_$(d)) | KOBJS += $(OBJS_$(d)) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										105
									
								
								devices/pi_mini_uart.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								devices/pi_mini_uart.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | |||||||
|  | /* | ||||||
|  |     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 <types.h> | ||||||
|  |  | ||||||
|  | #define VC_MMU_IO_OFFSET(addr) (addr - 0x7E000000 + 0x20000000) | ||||||
|  |  | ||||||
|  | /* Auxiliary IO registers (includes both mini-UART and SPI) */ | ||||||
|  | #define AUX_IRQ VC_MMU_IO_OFFSET(0x7E215000) | ||||||
|  | #define AUX_ENABLES VC_MMU_IO_OFFSET(0x7E215004) | ||||||
|  | #define AUX_MU_IO_REG VC_MMU_IO_OFFSET(0x7E215040) | ||||||
|  | #define AUX_MU_IER_REG VC_MMU_IO_OFFSET(0x7E215044) | ||||||
|  | #define AUX_MU_IIR_REG VC_MMU_IO_OFFSET(0x7E215048) | ||||||
|  | #define AUX_MU_LCR_REG VC_MMU_IO_OFFSET(0x7E21504C) | ||||||
|  | #define AUX_MU_MCR_REG VC_MMU_IO_OFFSET(0x7E215050) | ||||||
|  | #define AUX_MU_LSR_REG VC_MMU_IO_OFFSET(0x7E215054) | ||||||
|  | #define AUX_MU_MSR_REG VC_MMU_IO_OFFSET(0x7E215058) | ||||||
|  | #define AUX_MU_SCRATCH VC_MMU_IO_OFFSET(0x7E21505C) | ||||||
|  | #define AUX_MU_CNTL_REG VC_MMU_IO_OFFSET(0x7E215060) | ||||||
|  | #define AUX_MU_STAT_REG VC_MMU_IO_OFFSET(0x7E215064) | ||||||
|  | #define AUX_MU_BAUD_REG VC_MMU_IO_OFFSET(0x7E215068) | ||||||
|  | #define AUX_SPI0_CNTL0_REG VC_MMU_IO_OFFSET(0x7E215080) | ||||||
|  | #define AUX_SPI0_CNTL1_REG VC_MMU_IO_OFFSET(0x7E215084) | ||||||
|  | #define AUX_SPI0_STAT_REG VC_MMU_IO_OFFSET(0x7E215088) | ||||||
|  | #define AUX_SPI0_IO_REG VC_MMU_IO_OFFSET(0x7E215090) | ||||||
|  | #define AUX_SPI0_PEEK_REG VC_MMU_IO_OFFSET(0x7E215094) | ||||||
|  | #define AUX_SPI1_CNTL0_REG VC_MMU_IO_OFFSET(0x7E2150C0) | ||||||
|  | #define AUX_SPI1_CNTL1_REG VC_MMU_IO_OFFSET(0x7E2150C4) | ||||||
|  | #define AUX_SPI1_STAT_REG VC_MMU_IO_OFFSET(0x7E2150C8) | ||||||
|  | #define AUX_SPI1_IO_REG VC_MMU_IO_OFFSET(0x7E2150D0) | ||||||
|  | #define AUX_SPI1_PEEK_REG VC_MMU_IO_OFFSET(0x7E2150D4) | ||||||
|  |  | ||||||
|  | /* Constants for mini-UART operation */ | ||||||
|  | #define MINI_UART_TX_EMPTY 0x20 | ||||||
|  |  | ||||||
|  | /* General GPIO pin registers */ | ||||||
|  | #define GPFSEL1 VC_MMU_IO_OFFSET(0x7E200004) | ||||||
|  | #define GPSET0 VC_MMU_IO_OFFSET(0x7E20001C) | ||||||
|  | #define GPCLR0 VC_MMU_IO_OFFSET(0x7E200028) | ||||||
|  | #define GPPUD VC_MMU_IO_OFFSET(0x7E200094) | ||||||
|  | #define GPPUDCLK0 VC_MMU_IO_OFFSET(0x7E200098) | ||||||
|  |  | ||||||
|  | void mini_uart_init() { | ||||||
|  | 	uint32 aux_enables; | ||||||
|  | 	uint32 gpfsel1; | ||||||
|  | 	unsigned int i; | ||||||
|  |  | ||||||
|  | 	/* Enable the mini-UART */ | ||||||
|  | 	aux_enables = (*(uint32 *)AUX_ENABLES) & 0x7; | ||||||
|  | 	*(uint32 *)AUX_ENABLES = aux_enables | 0x1; | ||||||
|  |  | ||||||
|  | 	//TODO are these all necessary? | ||||||
|  | 	*(uint32 *)AUX_MU_IER_REG = 0; //disable interrupts | ||||||
|  | 	*(uint32 *)AUX_MU_CNTL_REG = 0; //disable RX and TX | ||||||
|  | 	*(uint32 *)AUX_MU_LCR_REG = 3; //set to 8-bit mode (though this only takes setting bit 0, no clue why bit 1 is set too) | ||||||
|  | 	*(uint32 *)AUX_MU_MCR_REG = 0; //"If clear the UART1_RTS line is high If set the UART1_RTS line is low" | ||||||
|  | 	*(uint32 *)AUX_MU_IER_REG = 0; //disable interrupts again? | ||||||
|  | 	*(uint32 *)AUX_MU_IIR_REG = 0xC6; //why are we setting the interrupt status - this looks like a read-only register? | ||||||
|  | 					//also, the manual says setting bits 2&3 simultaneously shouldn't be possible... | ||||||
|  |  | ||||||
|  | 	// baudrate = system_clock_freq / ( 8 * (baudrate_reg + 1)) | ||||||
|  | 	// baudrate_reg = system_clock_freq / baudrate / 8 - 1 | ||||||
|  | 	// baudrate_reg = 250000000 / 115200 / 8 - 1 = 270 | ||||||
|  | 	*(uint32 *)AUX_MU_BAUD_REG = 270; | ||||||
|  |  | ||||||
|  | 	//set the GPIO pin to the alternate function for this UART | ||||||
|  | 	gpfsel1 = (*(uint32 *)GPFSEL1) & ~(7<<12); //get the GPIO Function Select 1 register, and keep all the bits except those that are for GPIO pin 14 | ||||||
|  | 	gpfsel1 |= 2<<12; // set to 010 (GPIO Pin 14 takes alternate function 5) | ||||||
|  | 	*(uint32 *)GPFSEL1 = gpfsel1; | ||||||
|  |  | ||||||
|  | 	//Follow the procedure for change pull-up/pull-down status (see page 101 of the BCM2835 ARM Peripherals datasheet) | ||||||
|  | 	*(uint32 *)GPPUD = 0; //disable pull-up/pull-down for those pins which receive a write to their bit in GPPUDCLK0/1 | ||||||
|  | 	for(i = 0; i < 150; i++) asm(""); //wait at least 150 cycles | ||||||
|  | 	*(uint32 *)GPPUDCLK0 = 1<<14; //"Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to modify" (in our case, this is 14) | ||||||
|  | 	for(i = 0; i < 150; i++) asm(""); //wait at least 150 cycles | ||||||
|  | //	*(uint32 *)GPPUD = 0; //remove the signal (shouldn't really be necessary since it was 0 anyway in our case) | ||||||
|  | 	*(uint32 *)GPPUDCLK0 = 0; //clear the clock | ||||||
|  |  | ||||||
|  | 	*(uint32 *)AUX_MU_CNTL_REG = 2; //enable TX | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void 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; | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								include/devices/pi_mini_uart.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								include/devices/pi_mini_uart.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | /* | ||||||
|  |     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. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef PI_MINI_UART_H | ||||||
|  | #define PI_MINI_UART_H | ||||||
|  |  | ||||||
|  | void mini_uart_init(); | ||||||
|  | void mini_uart_putc(char c); | ||||||
|  |  | ||||||
|  | #endif /* PI_MINI_UART_H */ | ||||||
		Reference in New Issue
	
	Block a user