devices -> drivers
This commit is contained in:
		
							
								
								
									
										69
									
								
								drivers/bcm2835_mailbox.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								drivers/bcm2835_mailbox.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| /* | ||||
|     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> | ||||
|  | ||||
| /* Mailbox Memory-Mapped Registers */ | ||||
| #define VC_MMU_IO_OFFSET(addr) (addr - 0x7E000000 + 0x20000000) | ||||
|  | ||||
| #define MBOX0_READ	VC_MMU_IO_OFFSET(0x7E00B880) | ||||
| /*	MBOX0_READ layout: | ||||
| 	31-4	data	The 28 bits of data sent to the CPU | ||||
| 	3-0	channel	The mailbox channel number from which the data originated */ | ||||
| #define MBOX0_PEEK	VC_MMU_IO_OFFSET(0x7E00B890)	//Read from the mailbox without removing data from it. | ||||
| #define MBOX0_SENDER	VC_MMU_IO_OFFSET(0x7E00B894)	//Sender ID (bottom 2 bits only) | ||||
| #define MBOX0_STATUS	VC_MMU_IO_OFFSET(0x7E00B898) | ||||
| /*	MBOX0_STATUS layout: | ||||
| 	31	full	Set if the mailbox is full, and thus no more data can be written to it. | ||||
| 	30	empty	Set if the mailbox is empty, and thus no more data is available to be read from it. | ||||
| 	29-0		unused? */ | ||||
| #define MBOX0_CONFIG	VC_MMU_IO_OFFSET(0x7E00B89C) | ||||
| #define MBOX0_WRITE	VC_MMU_IO_OFFSET(0x7E00B8A0)	//also MBOX1_READ? | ||||
| /*	MBOX0_WRITE layout: | ||||
| 	31-4	data	The 28 bits of data to be sent | ||||
| 	3-0	channel	The mailbox channel to send data to */ | ||||
|  | ||||
| #define MBOX0_STATUS_FULL	0x80000000 | ||||
| #define MBOX0_STATUS_EMPTY	0x40000000 | ||||
|  | ||||
|  | ||||
| uint32 mailbox_read(uint32 channel) { | ||||
| 	uint32 mbox_msg; | ||||
| 	while (1) { | ||||
| 		int i; | ||||
| 		for (i = 0; *(volatile uint32 *)MBOX0_STATUS & MBOX0_STATUS_EMPTY; i++) { | ||||
| 			if (i >= 1<<20) | ||||
| 				return 0xFFFFFFFF; | ||||
| 		} | ||||
|  | ||||
| 		mbox_msg = *(volatile uint32 *)MBOX0_READ; | ||||
| 		if ((mbox_msg & 0xf) == channel) | ||||
| 			return mbox_msg & ~0xf; | ||||
| 	} | ||||
| }  | ||||
|  | ||||
| void mailbox_write(uint32 channel, uint32 data) { | ||||
| 	channel &= 0xf; | ||||
| 	data &= ~0xf; | ||||
|  | ||||
| 	while (*(volatile uint32 *)MBOX0_STATUS & MBOX0_STATUS_FULL); | ||||
|  | ||||
| 	*(volatile uint32 *)MBOX0_WRITE = channel | data; | ||||
| } | ||||
							
								
								
									
										94
									
								
								drivers/bcm2835_videocore.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								drivers/bcm2835_videocore.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /* | ||||
|     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> | ||||
| #include <framebuffer.h> | ||||
| #include <kmalloc.h> | ||||
| #include <print.h> | ||||
| #include <drivers/bcm2835_mailbox.h> | ||||
|  | ||||
| struct bcm2835_config { | ||||
| 	uint32 width; | ||||
| 	uint32 height; | ||||
| 	uint32 vwidth; | ||||
| 	uint32 vheight; | ||||
| 	uint32 pitch; | ||||
| 	uint32 color_depth; | ||||
| 	uint32 xoffset; | ||||
| 	uint32 yoffset; | ||||
| 	uint32 fb_base_addr; | ||||
| 	uint32 size; | ||||
| }; | ||||
|  | ||||
| #define MAILBOX_BUFFER_SIZE (32*4*2) | ||||
| #define FB_WIDTH 1024 | ||||
| #define FB_HEIGHT 768 | ||||
|  | ||||
| struct fbdev bcm2835_fb_device; | ||||
|  | ||||
| int bcm2835_videocore_init(struct fb *f, unsigned int color_depth) { | ||||
| 	struct bcm2835_config *cfg; | ||||
| 	uint32 result; | ||||
| 	void *mailbox_buffer_orig, *mailbox_buffer; | ||||
|  | ||||
| 	if (!(mailbox_buffer_orig = kmalloc(MAILBOX_BUFFER_SIZE))) { | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	/* Round mailbox buffer to multiple of 0x10 because the low 4 bits of | ||||
| 	the mailbox are used to send the channel, and therefore can't hold the low 4 | ||||
| 	bits of the address */ | ||||
| 	if ((uint32)mailbox_buffer_orig & 0xf) | ||||
| 		mailbox_buffer = (void *)((uint32)mailbox_buffer_orig & ~0xf) + 0x10; | ||||
| 	else | ||||
| 		mailbox_buffer = mailbox_buffer_orig; | ||||
|  | ||||
| 	cfg = (struct bcm2835_config *)mailbox_buffer; | ||||
| 	cfg->width = FB_WIDTH; | ||||
| 	cfg->height = FB_HEIGHT; | ||||
| 	cfg->vwidth = FB_WIDTH; | ||||
| 	cfg->vheight = FB_HEIGHT; | ||||
| 	cfg->pitch = 0; | ||||
| 	cfg->color_depth = color_depth; | ||||
| 	cfg->xoffset = 0; | ||||
| 	cfg->yoffset = 0; | ||||
| 	cfg->fb_base_addr = 0; | ||||
| 	cfg->size = 0; | ||||
|  | ||||
| 	mailbox_write(MBOX_FB, (uint32)cfg); | ||||
| 	result = mailbox_read(MBOX_FB); | ||||
|  | ||||
| 	if (result || !cfg->fb_base_addr) { | ||||
| 		print("Error: did not request a proper framebuffer\n"); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	f->device = &bcm2835_fb_device; | ||||
| 	f->device->fbaddr = (void*)cfg->fb_base_addr; | ||||
| 	f->width = cfg->width; | ||||
| 	f->device->pixelwidth = cfg->width; | ||||
| 	f->height = cfg->height; | ||||
| 	f->device->pixelheight = cfg->height; | ||||
|  | ||||
| 	f->color_depth = color_depth; | ||||
| 	f->device->color_depth = color_depth; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										20
									
								
								drivers/kernel.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								drivers/kernel.mk
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| DIRNAME := drivers | ||||
| SUBDIRS := | ||||
|  | ||||
| include $(BASEDIR)/header.mk | ||||
|  | ||||
| OBJS_$(d)_$(CONFIG_VEXPRESS_A9) := \ | ||||
| 	$(d)/pl011.o \ | ||||
| 	$(d)/pl111.o | ||||
|  | ||||
| OBJS_$(d)_$(CONFIG_INTEGRATOR_CP) := \ | ||||
| 	$(d)/pl110.o \ | ||||
|  | ||||
| OBJS_$(d)_$(CONFIG_RPI) := \ | ||||
| 	$(d)/pi_mini_uart.o \ | ||||
| 	$(d)/bcm2835_mailbox.o \ | ||||
| 	$(d)/bcm2835_videocore.o | ||||
|  | ||||
| KOBJS += $(OBJS_$(d)_y) | ||||
|  | ||||
| include $(BASEDIR)/footer.mk | ||||
							
								
								
									
										105
									
								
								drivers/pi_mini_uart.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								drivers/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; | ||||
| } | ||||
							
								
								
									
										34
									
								
								drivers/pl011.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								drivers/pl011.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| /* | ||||
|     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 PL011_SERIAL_BASE 0x10009000 | ||||
| #define PL011_SERIAL_FLAG_REGISTER 0x18 | ||||
| #define PL011_SERIAL_BUFFER_FULL (1 << 5) | ||||
|  | ||||
| void 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; | ||||
| } | ||||
							
								
								
									
										90
									
								
								drivers/pl110.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								drivers/pl110.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| /* | ||||
|     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> | ||||
| #include <framebuffer.h> | ||||
| #include <mm.h> | ||||
| #include <math.h> | ||||
|  | ||||
| #define PL110_CR_EN		0x001 | ||||
| #define PL110_CR_PWR		0x800 | ||||
| #define PL110_IOBASE		0xc0000000 | ||||
| #define PL110_PALBASE		(PL110_IOBASE + 0x200) | ||||
|  | ||||
| struct pl110_control { | ||||
| 	uint32	volatile timing0;	//0 | ||||
| 	uint32	volatile timing1;	//4 | ||||
| 	uint32	volatile timing2;	//8 | ||||
| 	uint32	volatile timing3;	//c | ||||
| 	uint32	volatile upbase;	//10 | ||||
| 	uint32	volatile lpbase;	//14 | ||||
| 	uint32	volatile intrenable;	//18 | ||||
| 	uint32	volatile control;	//1c | ||||
| }; | ||||
|  | ||||
| struct fbdev pl110_fb_device; | ||||
|  | ||||
| int pl110_init(struct fb *f, unsigned int color_depth) { | ||||
| 	unsigned int width, height; | ||||
| 	unsigned int fb_size, power; | ||||
| 	struct pl110_control *plio = (struct pl110_control*)PL110_IOBASE; | ||||
| 	struct page *p; | ||||
|  | ||||
| 	/* 640x480 pixels */ | ||||
| 	width = 640; | ||||
| 	height = 480; | ||||
| 	plio->timing0 = 0x3f1f3f9c; | ||||
| 	plio->timing1 = 0x080b61df; | ||||
|  | ||||
| 	/* Allocate memory for framebuffer */ | ||||
| 	fb_size = width * height * (color_depth / 8); | ||||
| 	power = log(fb_size) - log(MM_PAGE_SIZE); | ||||
| 	if ((unsigned int)1<<power < fb_size) | ||||
| 		power++; | ||||
| 	p = mm_get_free_pages(power); | ||||
| 	if (!p) | ||||
| 		return -1; | ||||
|  | ||||
| 	plio->upbase = (uint32)p->address; | ||||
|  | ||||
| 	if (color_depth == FB_COLOR_DEPTH_8) { | ||||
| 		plio->control = 0x1827; | ||||
| 	} else if (color_depth == FB_COLOR_DEPTH_16) { | ||||
| 		plio->control = 0x1829; | ||||
| 	} else if (color_depth == FB_COLOR_DEPTH_24) { | ||||
| 		plio->control = 0x182B; | ||||
| 	} else { | ||||
| 		//assume 16 if nothing else fit | ||||
| 		color_depth = 16; | ||||
| 		plio->control = 0x1829; | ||||
| 	} | ||||
|  | ||||
| 	f->device = &pl110_fb_device; | ||||
| 	f->device->fbaddr = (void*)plio->upbase; | ||||
| 	f->width = width; | ||||
| 	f->device->pixelwidth = width; | ||||
| 	f->height = height; | ||||
| 	f->device->pixelheight = height; | ||||
|  | ||||
| 	f->color_depth = color_depth; | ||||
| 	f->device->color_depth = color_depth; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										89
									
								
								drivers/pl111.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								drivers/pl111.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| /* | ||||
|     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> | ||||
| #include <framebuffer.h> | ||||
| #include <mm.h> | ||||
| #include <math.h> | ||||
|  | ||||
| #define PL111_CR_EN		0x001 | ||||
| #define PL111_CR_PWR		0x800 | ||||
| #define PL111_IOBASE		0x10020000 | ||||
| #define PL111_PALBASE		(PL111_IOBASE + 0x200) | ||||
|  | ||||
| struct pl111_control { | ||||
| 	uint32	volatile timing0;	//0 | ||||
| 	uint32	volatile timing1;	//4 | ||||
| 	uint32	volatile timing2;	//8 | ||||
| 	uint32	volatile timing3;	//c | ||||
| 	uint32	volatile upbase;	//10 | ||||
| 	uint32	volatile lpbase;	//14 | ||||
| 	uint32	volatile control;	//18 | ||||
| }; | ||||
|  | ||||
| struct fbdev pl111_fb_device; | ||||
|  | ||||
| int pl111_init(struct fb *f, unsigned int color_depth) { | ||||
| 	unsigned int width, height; | ||||
| 	unsigned int fb_size, power; | ||||
| 	struct pl111_control *plio = (struct pl111_control*)PL111_IOBASE; | ||||
| 	struct page *p; | ||||
|  | ||||
| 	/* 640x480 pixels */ | ||||
| 	width = 640; | ||||
| 	height = 480; | ||||
| 	plio->timing0 = 0x3f1f3f9c; | ||||
| 	plio->timing1 = 0x080b61df; | ||||
|  | ||||
| 	/* Allocate memory for framebuffer */ | ||||
| 	fb_size = width * height * (color_depth / 8); | ||||
| 	power = log(fb_size) - log(MM_PAGE_SIZE); | ||||
| 	if ((unsigned int)1<<power < fb_size) | ||||
| 		power++; | ||||
| 	p = mm_get_free_pages(power); | ||||
| 	if (!p) | ||||
| 		return -1; | ||||
|  | ||||
| 	plio->upbase = (uint32)p->address; | ||||
|  | ||||
| 	if (color_depth == FB_COLOR_DEPTH_8) { | ||||
| 		plio->control = 0x1827; | ||||
| 	} else if (color_depth == FB_COLOR_DEPTH_16) { | ||||
| 		plio->control = 0x1829; | ||||
| 	} else if (color_depth == FB_COLOR_DEPTH_24) { | ||||
| 		plio->control = 0x182B; | ||||
| 	} else { | ||||
| 		//assume 16 if nothing else fit | ||||
| 		color_depth = 16; | ||||
| 		plio->control = 0x1829; | ||||
| 	} | ||||
|  | ||||
| 	f->device = &pl111_fb_device; | ||||
| 	f->device->fbaddr = (void*)plio->upbase; | ||||
| 	f->width = width; | ||||
| 	f->device->pixelwidth = width; | ||||
| 	f->height = height; | ||||
| 	f->device->pixelheight = height; | ||||
|  | ||||
| 	f->color_depth = color_depth; | ||||
| 	f->device->color_depth = color_depth; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user