# HG changeset patch # User Paul Boddie # Date 1456326826 -3600 # Node ID 62866e8d0f3b79c5219ff577c826541c278fbafb # Parent 62ee61016b7554bf7cfffe43718f9e96e3557c70# Parent 24d8d5589ab5f93269f41685e0800b9b844e6c7e Merged changes from the branch upon reverting to position-independent code. diff -r 62ee61016b75 -r 62866e8d0f3b README.txt --- a/README.txt Sat Jun 13 00:06:18 2015 +0200 +++ b/README.txt Wed Feb 24 16:13:46 2016 +0100 @@ -8,19 +8,45 @@ routines for "bare metal" software usage in order to illustrate the initialisation requirements and to make it possible to deploy other software. +An attempt has been made to also generate payloads for the jz4730-based +MiniPC/Mipsbook/Minibook device. This device does not appear to support USB +boot mode, and thus any payloads will need to be deployed by other means, such +as through the use of SD/MMC media. + +Deployment over USB +------------------- + The payloads can be deployed on the Ben NanoNote using the USB boot mode as described on the Qi-Hardware site: http://en.qi-hardware.com/wiki/USB_BOOT_mode -A suitable command can be issued on a USB host machine as follows (given +The provided script can be issued on a USB host machine as follows (given sufficient privileges): -usbboot -c 'boot' -1 stage1/stage1.bin -2 stage2/stage2.bin +./boot_usb + +This employs the xbboot program which is available in the xburst-tools +package: + +http://en.qi-hardware.com/wiki/Xburst-tools + +The different MiniPC products do not appear to support USB boot. + +Deployment using microSD/SD/MMC Media +------------------------------------- -An attempt has been made to also generate payloads for the jz4730-based -MiniPC/Mipsbook/Minibook device. This device does not appear to support USB -boot mode, and thus any payloads will need to be deployed by other means. +The stage 2 payload can be written to a suitable media card as a uImage file +which can then be loaded and invoked by a U-Boot bootloader already installed +on the Ben NanoNote or MiniPC product. + +Typically, U-Boot on the Ben NanoNote will look for such a file located at +/boot/uImage within the first partition of a microSD card. On the MiniPC, +U-Boot will look for a file located at /uImage (in other words, a file called +uImage in the top-level directory) within the first partition of an SD card. + +Since U-Boot should have initialised the RAM and clocks, the stage 1 payload +is superfluous, and only the stage 2 payload is needed in this situation. Related U-Boot Resources ------------------------ diff -r 62ee61016b75 -r 62866e8d0f3b boot_usb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/boot_usb Wed Feb 24 16:13:46 2016 +0100 @@ -0,0 +1,31 @@ +#!/bin/sh + +# To use the installed stage1 payload... + +if [ "$1" = '--default1' ]; then + if xbboot -u 0x81c00000 stage2/stage2.bin ; then + exit 0 + else + exit 1 + fi + +# To use usbboot, which is less elegant but sometimes more reliable... + +elif [ "$1" = '--usbboot' ]; then + if usbboot -c 'boot' -1 stage1/stage1.bin -2 stage2/stage2.bin ; then + exit 0 + else + exit 1 + fi +fi + +# Otherwise, use the generated payloads with xbboot. + +xbboot set_addr 0x80002000 +xbboot bulk_write stage1/stage1.bin +xbboot start1 0x80002000 +xbboot get_info +xbboot set_addr 0x81c00000 +xbboot bulk_write stage2/stage2.bin +xbboot flush_cache +xbboot start2 0x81c00000 diff -r 62ee61016b75 -r 62866e8d0f3b include/jz4730.h --- a/include/jz4730.h Sat Jun 13 00:06:18 2015 +0200 +++ b/include/jz4730.h Wed Feb 24 16:13:46 2016 +0100 @@ -2,7 +2,7 @@ * Include file for Ingenic Semiconductor's JZ4730 CPU. * * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. - * Copyright (C) 2009 Qi Hardware Inc., + * Copyright (C) 2009 Qi Hardware Inc. * Author: Xiangfu Liu * Copyright (C) 2015 Paul Boddie * diff -r 62ee61016b75 -r 62866e8d0f3b include/jz4730_compat.h --- a/include/jz4730_compat.h Sat Jun 13 00:06:18 2015 +0200 +++ b/include/jz4730_compat.h Wed Feb 24 16:13:46 2016 +0100 @@ -1,12 +1,12 @@ /* - * Compatibility definitions for using jz4740 code with the jz4730 + * Compatibility definitions for using jz4740 code with the jz4730. * * Copyright (C) 2015 Paul Boddie * - * 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 - * 3 of the License, or (at your option) any later version. + * 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 3 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 @@ -14,9 +14,7 @@ * 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 + * along with this program. If not, see . */ #ifndef __JZ4730_COMPAT_H__ @@ -25,6 +23,7 @@ #define REG_CPM_CPCCR REG_CPM_CFCR #define REG_CPM_CPPCR REG_CPM_PLCR1 +#define CPM_CPCCR_CE CPM_CFCR_UPE #define CPM_CPCCR_CDIV_BIT CPM_CFCR_IFR_BIT #define CPM_CPCCR_HDIV_BIT CPM_CFCR_SFR_BIT #define CPM_CPCCR_PDIV_BIT CPM_CFCR_PFR_BIT @@ -37,4 +36,6 @@ #define CPM_CPPCR_PLLST_BIT CPM_PLCR1_PLL1ST_BIT #define CPM_CPPCR_PLLEN CPM_PLCR1_PLL1EN +#define __cpm_set_ldiv __cpm_set_lcdclk_div + #endif /* __JZ4730_COMPAT_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b include/jz4740.h --- a/include/jz4740.h Sat Jun 13 00:06:18 2015 +0200 +++ b/include/jz4740.h Wed Feb 24 16:13:46 2016 +0100 @@ -2,7 +2,7 @@ * Include file for Ingenic Semiconductor's JZ4740 CPU. * * Copyright (C) 2006 - 2007 Ingenic Semiconductor Inc. - * Copyright (C) 2009 Qi Hardware Inc., + * Copyright (C) 2009 Qi Hardware Inc. * Author: Xiangfu Liu * Copyright (C) 2015 Paul Boddie * @@ -803,7 +803,7 @@ #define GPIO_PXTRGS(n) (GPIO_BASE + (0x74 + (n)*0x100)) /* Trigger Set Register */ #define GPIO_PXTRGC(n) (GPIO_BASE + (0x78 + (n)*0x100)) /* Trigger Set Register */ #define GPIO_PXFLG(n) (GPIO_BASE + (0x80 + (n)*0x100)) /* Port Flag Register */ -#define GPIO_PXFLGC(n) (GPIO_BASE + (0x14 + (n)*0x100)) /* Port Flag clear Register */ +#define GPIO_PXFLGC(n) (GPIO_BASE + (0x84 + (n)*0x100)) /* Port Flag clear Register */ #define REG_GPIO_PXPIN(n) REG32(GPIO_PXPIN((n))) /* PIN level */ #define REG_GPIO_PXDAT(n) REG32(GPIO_PXDAT((n))) /* 1: interrupt pending */ diff -r 62ee61016b75 -r 62866e8d0f3b include/minipc.h --- a/include/minipc.h Sat Jun 13 00:06:18 2015 +0200 +++ b/include/minipc.h Wed Feb 24 16:13:46 2016 +0100 @@ -1,14 +1,14 @@ /* - * MiniPC configuration parameters + * MiniPC configuration parameters. * * Copyright (C) 2009 Qi Hardware Inc. * Authors: Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * - * 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 - * 3 of the License, or (at your option) any later version. + * 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 3 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 @@ -16,23 +16,18 @@ * 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 + * along with this program. If not, see . */ #ifndef __MINIPC_H__ #define __MINIPC_H__ /* - * Display configuration - */ -#define LCD_BPP LCD_COLOR32 - -/* * GPIO definition */ #define GPIO_LED_EN 92 #define GPIO_DISP_OFF_N 93 +#define GPIO_PWM0 94 +#define GPIO_POWER 97 #endif /* __MINIPC_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b include/nanonote.h --- a/include/nanonote.h Sat Jun 13 00:06:18 2015 +0200 +++ b/include/nanonote.h Wed Feb 24 16:13:46 2016 +0100 @@ -1,14 +1,14 @@ /* - * Ben NanoNote configuration parameters + * Ben NanoNote configuration parameters. * * Copyright (C) 2009 Qi Hardware Inc. * Authors: Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * - * 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 - * 3 of the License, or (at your option) any later version. + * 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 3 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 @@ -16,20 +16,13 @@ * 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 + * along with this program. If not, see . */ #ifndef __NANONOTE_H__ #define __NANONOTE_H__ /* - * Display configuration - */ -#define LCD_BPP LCD_COLOR32 - -/* * GPIO definition * See: http://en.qi-hardware.com/wiki/Hardware_basics */ @@ -49,6 +42,8 @@ #define GPIO_KEYIN_BASE (3 * 32 + 18) #define GPIO_KEYIN_8 (3 * 32 + 26) +#define GPIO_POWER (3 * 32 + 29) + #define GPIO_SD_CD_N GPIO_SD_DETECT /* SD Card insert detect */ #define GPIO_SD_VCC_EN_N GPIO_SDPW_EN /* SD Card Power Enable */ diff -r 62ee61016b75 -r 62866e8d0f3b include/sdram.h --- a/include/sdram.h Sat Jun 13 00:06:18 2015 +0200 +++ b/include/sdram.h Wed Feb 24 16:13:46 2016 +0100 @@ -1,14 +1,17 @@ /* - * Common SDRAM configuration + * Common SDRAM configuration. + * + * Copyright (C) 1996, 1997 by Ralf Baechle * * Copyright (C) 2009 Qi Hardware Inc. * Authors: Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * + * Copyright (C) 2015, 2016 Paul Boddie * - * 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 - * 3 of the License, or (at your option) any later version. + * 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 3 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 @@ -16,19 +19,12 @@ * 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 + * along with this program. If not, see . */ #ifndef __SDRAM_H__ #define __SDRAM_H__ -/* virt_to_phys() from u-boot/arch/mips/include/asm/addrspace.h - via u-boot/arch/mips/include/asm/io.h */ -/* #define virt_to_phys(n) (((int) n) & 0x1fffffff) */ -#define virt_to_phys(n) ((int) n) - /* * RAM configuration */ @@ -69,6 +65,15 @@ #define CONFIG_SYS_ICACHE_SIZE 16384 #define CONFIG_SYS_CACHELINE_SIZE 32 +#define Index_Invalidate_I 0x00 +#define Index_Writeback_Inv_D 0x01 +#define Index_Store_Tag_I 0x08 +#define Index_Store_Tag_D 0x09 +#define Hit_Writeback_Inv_D 0x15 + +#define CONFIG_CM_UNCACHED 2 +#define CONFIG_CM_CACHABLE_NONCOHERENT 3 + /* * Memory configuration */ diff -r 62ee61016b75 -r 62866e8d0f3b include/usb_boot_defines.h --- a/include/usb_boot_defines.h Sat Jun 13 00:06:18 2015 +0200 +++ b/include/usb_boot_defines.h Wed Feb 24 16:13:46 2016 +0100 @@ -1,5 +1,7 @@ /* - * Copyright(C) 2009 Qi Hardware Inc., + * USB boot definitions. + * + * Copyright (C) 2009 Qi Hardware Inc. * Authors: Marek Lindner * Xiangfu Liu * diff -r 62ee61016b75 -r 62866e8d0f3b include/xburst_types.h --- a/include/xburst_types.h Sat Jun 13 00:06:18 2015 +0200 +++ b/include/xburst_types.h Wed Feb 24 16:13:46 2016 +0100 @@ -1,11 +1,13 @@ /* - * Copyright 2009 (C) Qi Hardware Inc., + * Ingenic XBurst type definitions. + * + * Copyright 2009 (C) Qi Hardware Inc. * Author: Xiangfu Liu * - * 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 - * 3 of the License, or (at your option) any later version. + * 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 3 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 @@ -13,9 +15,7 @@ * 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 + * along with this program. If not, see . */ #ifndef __XBURST_TYPES_H__ diff -r 62ee61016b75 -r 62866e8d0f3b stage1/Makefile --- a/stage1/Makefile Sat Jun 13 00:06:18 2015 +0200 +++ b/stage1/Makefile Wed Feb 24 16:13:46 2016 +0100 @@ -3,18 +3,18 @@ # Copyright (C) 2015 Paul Boddie # Copyright (C) Xiangfu Liu # -# 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 3 of the License, or (at your option) any later -# version. +# 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 3 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. +# 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, see . +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . ARCH = mipsel-linux-gnu CC = $(ARCH)-gcc diff -r 62ee61016b75 -r 62866e8d0f3b stage1/board.c --- a/stage1/board.c Sat Jun 13 00:06:18 2015 +0200 +++ b/stage1/board.c Wed Feb 24 16:13:46 2016 +0100 @@ -7,18 +7,18 @@ * Copyright (C) Xiangfu Liu * Copyright (C) 2015 Paul Boddie * - * 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 3 of the License, or (at your option) any later - * version. + * 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 3 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. + * 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, see . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #ifdef CONFIG_CPU_JZ4730 @@ -49,10 +49,13 @@ fw_args = (struct fw_args *)0x80002008; FW_CPU_ID = fw_args->cpu_id ; - FW_SDRAM_BW16 = fw_args->bus_width; - FW_SDRAM_BANK4 = fw_args->bank_num; - FW_SDRAM_ROW = fw_args->row_addr; - FW_SDRAM_COL = fw_args->col_addr; + + /* Where the arguments have not been initialised, use the defaults. */ + + FW_SDRAM_BW16 = FW_CPU_ID ? fw_args->bus_width : SDRAM_BW16; + FW_SDRAM_BANK4 = FW_CPU_ID ? fw_args->bank_num : SDRAM_BANK4; + FW_SDRAM_ROW = FW_CPU_ID ? fw_args->row_addr : SDRAM_ROW; + FW_SDRAM_COL = FW_CPU_ID ? fw_args->col_addr : SDRAM_COL; FW_CONFIG_MOBILE_SDRAM = fw_args->is_mobile; FW_IS_SHARE = fw_args->is_busshare; } diff -r 62ee61016b75 -r 62866e8d0f3b stage1/head1.S --- a/stage1/head1.S Sat Jun 13 00:06:18 2015 +0200 +++ b/stage1/head1.S Wed Feb 24 16:13:46 2016 +0100 @@ -1,15 +1,15 @@ /* - * Entry point of the firmware. - * The firmware code is executed in the ICache. + * Initialisation for the stage 1 payload with support for boot parameters. + * + * Copyright (C) 2009 Qi Hardware Inc. + * Author: Wolfgang Spraul * - * Copyright 2009 (C) Qi Hardware Inc., - * Author: Xiangfu Liu + * Copyright (C) 2015, 2016 Paul Boddie * - * Copyright (C) 2015 Paul Boddie - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 3 as published by the Free Software Foundation. + * 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 3 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 @@ -17,36 +17,48 @@ * 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 + * along with this program. If not, see . */ - .text +.text +.extern c_main +.globl _start +.set noreorder - .extern c_main +#define CP0_STATUS $12 +#define CP0_CAUSE $13 - .globl _start - .set noreorder _start: - b real_start - nop - .word 0x0 /* address: 0x80002008 */ - .word 0x0 - .word 0x0 - .word 0x0 - .word 0x0 - .word 0x0 - .word 0x0 - .word 0x0 - /* reserve 8 words for args sizeof(struct fw_args) - */ -real_start: - /* - * setup stack, jump to C code - */ - la $29, 0x80004000 /* sp */ - j c_main + b real_start nop - .set reorder + /* 8 words for firmware parameters (0x80002008), struct fw_args */ + + .word 0x0 + .word 0x0 + .word 0x0 + .word 0x0 + .word 0x0 + .word 0x0 + .word 0x0 + .word 0x0 + +real_start: + /* + Reset various registers. Otherwise, interrupts do not apparently get + re-enabled properly later when requested. + */ + + li $t0, 0x0040fc04 /* BEV=1, interrupts enabled, ERL=1 */ + mtc0 $t0, CP0_STATUS + + li $t0, 0x00800000 /* IV=1 */ + mtc0 $t0, CP0_CAUSE + + /* Setup stack, jump to C code. */ + + la $sp, 0x80004000 + j c_main + nop + +.set reorder diff -r 62ee61016b75 -r 62866e8d0f3b stage1/stage1.c --- a/stage1/stage1.c Sat Jun 13 00:06:18 2015 +0200 +++ b/stage1/stage1.c Wed Feb 24 16:13:46 2016 +0100 @@ -4,18 +4,18 @@ * Copyright (C) 2015 Paul Boddie * Copyright (C) Wolfgang Spraul * - * 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 3 of the License, or (at your option) any later - * version. + * 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 3 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. + * 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, see . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #include "board.h" diff -r 62ee61016b75 -r 62866e8d0f3b stage2/Makefile --- a/stage2/Makefile Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/Makefile Wed Feb 24 16:13:46 2016 +0100 @@ -1,20 +1,20 @@ # Makefile - Build the NanoNote payload # -# Copyright (C) 2015 Paul Boddie +# Copyright (C) 2015, 2016 Paul Boddie # Copyright (C) Xiangfu Liu # -# 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 3 of the License, or (at your option) any later -# version. +# 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 3 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. +# 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, see . +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . ARCH = mipsel-linux-gnu CC = $(ARCH)-gcc @@ -30,10 +30,10 @@ CFLAGS = -O2 -Wall \ -fno-unit-at-a-time -fno-zero-initialized-in-bss \ - -ffreestanding -fno-hosted -fno-builtin \ - -march=mips32 -fPIC \ + -ffreestanding -fno-hosted -fno-builtin -fPIC \ + -march=mips32 \ -I../include -LDFLAGS = -nostdlib -EL -pie +LDFLAGS = -nostdlib -EL UIMAGE = uImage PAYLOAD = stage2.bin @@ -62,8 +62,8 @@ # Ordering of objects is important and cannot be left to replacement rules. -SRC = head2.S stage2.c lcd.c jzlcd.c board.c $(BOARD_SRC) -OBJ = head2.o stage2.o lcd.o jzlcd.o board.o $(BOARD_OBJ) +SRC = head2.S entry.S handlers.S stage2.c cpu.c lcd.c jzlcd.c board.c irq.c $(BOARD_SRC) +OBJ = head2.o entry.o handlers.o stage2.o cpu.o lcd.o jzlcd.o board.o irq.o $(BOARD_OBJ) .PHONY: all clean distclean @@ -76,7 +76,7 @@ echo "Nothing else to clean." $(UIMAGE): $(PAYLOAD) - $(MKIMAGE) -A mips -O u-boot -T standalone -C none -a 0x80000000 -e 0x80000000 -n NanoPayload -d $(PAYLOAD) $(UIMAGE) + $(MKIMAGE) -A mips -O linux -T kernel -C none -a 0x81c00000 -e 0x81c00000 -n NanoPayload -d $(PAYLOAD) $(UIMAGE) $(PAYLOAD): $(TARGET) $(OBJCOPY) -O binary $(@:.bin=.elf) $@+ diff -r 62ee61016b75 -r 62866e8d0f3b stage2/board-minipc.c --- a/stage2/board-minipc.c Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/board-minipc.c Wed Feb 24 16:13:46 2016 +0100 @@ -6,18 +6,18 @@ * Copyright (C) Xiangfu Liu * Copyright (C) 2015 Paul Boddie * - * 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 3 of the License, or (at your option) any later - * version. + * 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 3 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. + * 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, see . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #include "board.h" @@ -62,7 +62,7 @@ unsigned long lastdec; /* - * timer without interrupts + * Timer without interrupts. */ int timer_init(void) @@ -72,12 +72,25 @@ __ost_set_count(TIMER_CHAN, TIMER_FDATA); __ost_enable_channel(TIMER_CHAN); + __cpm_start_ost(); + lastdec = TIMER_FDATA; timestamp = 0; return 0; } +/* Timer interrupt activation. */ + +void timer_init_irq(void) +{ + __ost_enable_interrupt(TIMER_CHAN); + /* NOTE: Need flag clearing? */ + __intc_unmask_irq(TIMER_CHAN_IRQ); +} + +/* Board startup detection. */ + int is_started(void) { return REG_CPM_MSCR != 0; diff -r 62ee61016b75 -r 62866e8d0f3b stage2/board-minipc.h --- a/stage2/board-minipc.h Sat Jun 13 00:06:18 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -#ifndef __BOARD_MINIPC_H__ -#define __BOARD_MINIPC_H__ - -/* Initialisation functions. */ - -void gpio_init2(void); -void cpm_init(void); -void rtc_init(void); -int timer_init(void); -int is_started(void); - -#endif /* __BOARD_MINIPC_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b stage2/board-nanonote.c --- a/stage2/board-nanonote.c Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/board-nanonote.c Wed Feb 24 16:13:46 2016 +0100 @@ -6,18 +6,18 @@ * Copyright (C) Xiangfu Liu * Copyright (C) 2015 Paul Boddie * - * 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 3 of the License, or (at your option) any later - * version. + * 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 3 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. + * 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, see . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #include "board.h" @@ -57,6 +57,9 @@ __gpio_as_input(GPIO_KEYIN_8); __gpio_enable_pull(GPIO_KEYIN_8); + __gpio_as_input(GPIO_POWER); + __gpio_enable_pull(GPIO_POWER); + __gpio_as_output(GPIO_AUDIO_POP); __gpio_set_pin(GPIO_AUDIO_POP); @@ -112,11 +115,12 @@ unsigned long lastdec; /* - * timer without interrupts + * Timer without interrupts. */ void timer_init(void) { + __tcu_disable_pwm_output(TIMER_CHAN); __tcu_select_extalclk(TIMER_CHAN); __tcu_select_clk_div256(TIMER_CHAN); __tcu_set_count(TIMER_CHAN, 0); @@ -128,10 +132,23 @@ __tcu_start_timer_clock(TIMER_CHAN); __tcu_start_counter(TIMER_CHAN); + __cpm_start_tcu(); + lastdec = 0; timestamp = 0; } +/* Timer interrupt activation. */ + +void timer_init_irq(void) +{ + __tcu_unmask_full_match_irq(TIMER_CHAN); + __tcu_clear_full_match_flag(TIMER_CHAN); + __intc_unmask_irq(TIMER_CHAN_IRQ); +} + +/* Board startup detection. */ + int is_started(void) { return REG_CPM_CLKGR != 0; diff -r 62ee61016b75 -r 62866e8d0f3b stage2/board-nanonote.h --- a/stage2/board-nanonote.h Sat Jun 13 00:06:18 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -#ifndef __BOARD_NANONOTE_H__ -#define __BOARD_NANONOTE_H__ - -/* Initialisation functions. */ - -void gpio_init2(void); -void cpm_init(void); -void rtc_init(void); -void timer_init(void); -int is_started(void); - -#endif /* __BOARD_NANONOTE_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b stage2/board-specific.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage2/board-specific.h Wed Feb 24 16:13:46 2016 +0100 @@ -0,0 +1,13 @@ +#ifndef __BOARD_SPECIFIC_H__ +#define __BOARD_SPECIFIC_H__ + +/* Initialisation functions. */ + +void gpio_init2(void); +void cpm_init(void); +void rtc_init(void); +void timer_init(void); +void timer_init_irq(void); +int is_started(void); + +#endif /* __BOARD_SPECIFIC_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b stage2/board.c --- a/stage2/board.c Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/board.c Wed Feb 24 16:13:46 2016 +0100 @@ -1,23 +1,22 @@ /* * Common routines supporting board initialisation. * - * Copyright (C) 2000-2009 Wolfgang Denk, DENX Software Engineering, * Copyright (C) 2005-2006 Ingenic Semiconductor, * Copyright (C) Xiangfu Liu * Copyright (C) 2015 Paul Boddie * - * 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 3 of the License, or (at your option) any later - * version. + * 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 3 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. + * 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, see . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #include "sdram.h" @@ -157,63 +156,3 @@ { return TIMER_HZ; } - -/* CPU-specific routines from U-Boot. - See: uboot-xburst/files/arch/mips/cpu/xburst/cpu.c - See: u-boot/arch/mips/include/asm/cacheops.h -*/ - -#define Index_Store_Tag_I 0x08 -#define Index_Writeback_Inv_D 0x15 - -void flush_icache_all(void) -{ - u32 addr, t = 0; - - asm volatile ("mtc0 $0, $28"); /* Clear Taglo */ - asm volatile ("mtc0 $0, $29"); /* Clear TagHi */ - - for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE; - addr += CONFIG_SYS_CACHELINE_SIZE) { - asm volatile ( - ".set mips3\n\t" - " cache %0, 0(%1)\n\t" - ".set mips2\n\t" - : - : "I" (Index_Store_Tag_I), "r"(addr)); - } - - /* invalicate btb */ - asm volatile ( - ".set mips32\n\t" - "mfc0 %0, $16, 7\n\t" - "nop\n\t" - "ori %0,2\n\t" - "mtc0 %0, $16, 7\n\t" - ".set mips2\n\t" - : - : "r" (t)); -} - -void flush_dcache_all(void) -{ - u32 addr; - - for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE; - addr += CONFIG_SYS_CACHELINE_SIZE) { - asm volatile ( - ".set mips3\n\t" - " cache %0, 0(%1)\n\t" - ".set mips2\n\t" - : - : "I" (Index_Writeback_Inv_D), "r"(addr)); - } - - asm volatile ("sync"); -} - -void flush_cache_all(void) -{ - flush_dcache_all(); - flush_icache_all(); -} diff -r 62ee61016b75 -r 62866e8d0f3b stage2/board.h --- a/stage2/board.h Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/board.h Wed Feb 24 16:13:46 2016 +0100 @@ -4,20 +4,21 @@ /* Utility functions. */ void udelay(unsigned long usec); -void flush_cache_all(void); unsigned long get_memory_size(void); +#define TIMER_HZ CONFIG_SYS_HZ +#define TIMER_CHAN 0 +#define TIMER_FDATA 0xffff /* timer full data value, limited to 16 bits */ + #ifdef CONFIG_CPU_JZ4730 #include "jz4730.h" -#define READ_TIMER __ost_get_count(TIMER_CHAN) /* macro to read the 32 bit timer */ -#define TIMER_FDATA 0xffffffff /* timer full data value */ +#include "jz4730_compat.h" +#define READ_TIMER __ost_get_count(TIMER_CHAN) /* macro to read the 32 bit timer */ +#define TIMER_CHAN_IRQ IRQ_OST0 #else #include "jz4740.h" -#define READ_TIMER REG_TCU_TCNT(TIMER_CHAN) /* macro to read the 16 bit timer */ -#define TIMER_FDATA 0xffff /* timer full data value */ +#define READ_TIMER REG_TCU_TCNT(TIMER_CHAN) /* macro to read the 16 bit timer */ +#define TIMER_CHAN_IRQ IRQ_TCU0 #endif -#define TIMER_HZ CONFIG_SYS_HZ -#define TIMER_CHAN 0 - #endif /* __BOARD_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b stage2/cpu.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage2/cpu.c Wed Feb 24 16:13:46 2016 +0100 @@ -0,0 +1,235 @@ +/* + * CPU-specific routines originally from U-Boot. + * See: uboot-xburst/files/arch/mips/cpu/xburst/cpu.c + * See: u-boot/arch/mips/include/asm/cacheops.h + * + * Copyright (C) 2000-2009 Wolfgang Denk, DENX Software Engineering, + * Copyright (C) 2015, 2016 Paul Boddie + * + * 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 "cpu.h" +#include "sdram.h" + +void flush_icache_all(void) +{ + u32 addr, t = 0; + + asm volatile ("mtc0 $0, $28"); /* Clear Taglo */ + asm volatile ("mtc0 $0, $29"); /* Clear TagHi */ + + for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE; + addr += CONFIG_SYS_CACHELINE_SIZE) { + asm volatile ( + ".set mips3\n\t" + " cache %0, 0(%1)\n\t" + ".set mips2\n\t" + : + : "I" (Index_Store_Tag_I), "r"(addr)); + } + + /* invalicate btb */ + asm volatile ( + ".set mips32\n\t" + "mfc0 %0, $16, 7\n\t" + "nop\n\t" + "ori %0,2\n\t" + "mtc0 %0, $16, 7\n\t" + ".set mips2\n\t" + : + : "r" (t)); +} + +void flush_dcache_all(void) +{ + u32 addr; + + for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE; + addr += CONFIG_SYS_CACHELINE_SIZE) { + asm volatile ( + ".set mips3\n\t" + " cache %0, 0(%1)\n\t" + ".set mips2\n\t" + : + : "I" (Index_Writeback_Inv_D), "r"(addr)); + } + + asm volatile ("sync"); +} + +void flush_cache_all(void) +{ + flush_dcache_all(); + flush_icache_all(); +} + +void handle_error_level(void) +{ + asm volatile( + "mfc0 $t3, $12\n" /* CP0_STATUS */ + "li $t4, 0xfffffffb\n" /* ERL = 0 */ + "and $t3, $t3, $t4\n" + "mtc0 $t3, $12\n" + "nop\n"); +} + +void enable_interrupts(void) +{ + asm volatile( + "mfc0 $t3, $12\n" /* CP0_STATUS */ + "li $t4, 0x0000fc01\n" /* IE = enable interrupts */ + "or $t3, $t3, $t4\n" + "mtc0 $t3, $12\n" + "nop\n"); +} + +void init_interrupts(void) +{ + /* Set exception registers. */ + + asm volatile( + "mtc0 $zero, $18\n" /* CP0_WATCHLO */ + "li $t3, 0x00800000\n" /* IV = 1 (use 0x80000200 for interrupts) */ + "mtc0 $t3, $13\n" /* CP0_CAUSE */ + "mfc0 $t4, $12\n" /* CP0_STATUS */ + "li $t3, 0xffbfffff\n" /* BEV=0 */ + "and $t3, $t3, $t4\n" + "mtc0 $t3, $12\n" + "nop\n"); +} + +void enter_user_mode(void) +{ + asm volatile( + "mfc0 $t3, $12\n" /* CP0_STATUS */ + "li $t4, 0xffffffef\n" /* KSU = 2 (UM = 1) */ + "and $t3, $t3, $t4\n" + "mtc0 $t3, $12\n" + "nop\n"); +} + +void init_tlb(void) +{ + asm volatile( + "li $t1, 1\n" /* index of first randomly-replaced entry */ + "mtc0 $t1, $6\n" /* CP0_WIRED */ + "nop\n"); + + map_page_index(0x80000000, 0x00000000, 16 * 1024 * 1024, 0x1f, 0, 0); +} + +void map_page_index(u32 virtual, u32 physical, u32 pagesize, u8 flags, u8 asid, u32 index) +{ + u32 start = virtual & 0xffffe000; /* VPN2 */ + u32 lower = ((physical & 0xfffff000) >> 6) | flags; + u32 upper = (((physical + pagesize) & 0xfffff000) >> 6) | flags; + u32 pagemask = ((pagesize - 1) & 0xfffff000) << 1; + + asm volatile( + "mtc0 %3, $5\n" /* CP0_PAGEMASK */ + + /* Set the index. */ + + "mtc0 %4, $0\n" /* CP0_INDEX */ + + /* Set physical address. */ + + "mtc0 %0, $2\n" /* CP0_ENTRYLO0 */ + "mtc0 %1, $3\n" /* CP0_ENTRYLO1 */ + + /* Set virtual address. */ + + "mtc0 %2, $10\n" /* CP0_ENTRYHI */ + "nop\n" + + "tlbwi\n" + "nop" + : + : "r" (lower), "r" (upper), "r" (start), "r" (pagemask), "r" (index) + ); +} + +void map_page(u32 virtual, u32 physical, u32 pagesize, u8 flags, u8 asid) +{ + u32 start = virtual & 0xffffe000; /* VPN2 */ + u32 lower = ((physical & 0xfffff000) >> 6) | flags; + u32 upper = (((physical + pagesize) & 0xfffff000) >> 6) | flags; + u32 pagemask = ((pagesize - 1) & 0xfffff000) << 1; + + asm volatile( + "mtc0 %3, $5\n" /* CP0_PAGEMASK */ + + /* Set physical address. */ + + "mtc0 %0, $2\n" /* CP0_ENTRYLO0 */ + "mtc0 %1, $3\n" /* CP0_ENTRYLO1 */ + + /* Set virtual address. */ + + "mtc0 %2, $10\n" /* CP0_ENTRYHI */ + "nop\n" + + "tlbwr\n" + "nop" + : + : "r" (lower), "r" (upper), "r" (start), "r" (pagemask) + ); +} + +void unmap_page(u32 virtual, u32 physical, u32 pagesize, u8 flags, u8 asid) +{ + u32 start = virtual & 0xffffe000; /* VPN2 */ + u32 lower = ((physical & 0xfffff000) >> 6) | flags; + u32 upper = (((physical + pagesize) & 0xfffff000) >> 6) | flags; + u32 pagemask = ((pagesize - 1) & 0xfffff000) << 1; + u32 index = 0; + + asm volatile( + "mtc0 %4, $5\n" /* CP0_PAGEMASK */ + + /* Set physical address. */ + + "mtc0 %1, $2\n" /* CP0_ENTRYLO0 */ + "mtc0 %2, $3\n" /* CP0_ENTRYLO1 */ + + /* Set virtual address. */ + + "mtc0 %3, $10\n" /* CP0_ENTRYHI */ + "nop\n" + + /* Find an existing mapping. */ + + "tlbp\n" + "nop\n" + + /* Read the index register to see if a match was found. */ + + "mfc0 %0, $0\n" /* CP0_INDEX */ + "nop" + : "=r" (index) + : "r" (lower), "r" (upper), "r" (start), "r" (pagemask) + ); + + /* Return if the page is not mapped. */ + + if (index & 0x80000000) + return; + + /* Otherwise, invalidate the mapping. */ + + map_page_index(virtual, physical, pagesize, flags & 0xfd, asid, index); +} diff -r 62ee61016b75 -r 62866e8d0f3b stage2/cpu.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage2/cpu.h Wed Feb 24 16:13:46 2016 +0100 @@ -0,0 +1,16 @@ +#ifndef __CPU_H__ +#define __CPU_H__ + +#include "xburst_types.h" + +void flush_cache_all(void); +void handle_error_level(void); +void enter_user_mode(void); +void enable_interrupts(void); +void init_interrupts(void); +void init_tlb(void); +void map_page(u32, u32, u32, u8, u8); +void map_page_index(u32, u32, u32, u8, u8, u32); +void unmap_page(u32, u32, u32, u8, u8); + +#endif /* __CPU_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b stage2/entry.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage2/entry.S Wed Feb 24 16:13:46 2016 +0100 @@ -0,0 +1,44 @@ +/* + * Interrupt and TLB miss handling support. + * + * Copyright (C) 2015, 2016 Paul Boddie + * + * 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 3 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, see . + */ + +.text +.extern tlb_handler +.extern interrupt_handler +.globl _tlb_entry +.globl _irq_entry +.globl _end_entries +.set noreorder + +_tlb_entry: + lui $k0, %hi(_GLOBAL_OFFSET_TABLE_) + ori $k0, $k0, %lo(_GLOBAL_OFFSET_TABLE_) + la $k0, tlb_handler + jr $k0 + nop + +_irq_entry: + lui $k0, %hi(_GLOBAL_OFFSET_TABLE_) + ori $k0, $k0, %lo(_GLOBAL_OFFSET_TABLE_) + la $k0, interrupt_handler + jr $k0 + nop + +_end_entries: + +.set reorder diff -r 62ee61016b75 -r 62866e8d0f3b stage2/handlers.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage2/handlers.S Wed Feb 24 16:13:46 2016 +0100 @@ -0,0 +1,147 @@ +/* + * Handler routines. + * + * Copyright (C) 2015 Nicholas FitzRoy-Dale + * Copyright (C) 2015, 2016 Paul Boddie + * + * 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 3 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, see . + */ + +.text +.extern tlb_handle +.extern irq_handle +.globl tlb_handler +.globl interrupt_handler +.set noreorder +.set noat + +tlb_handler: + sw $ra, -112($sp) + jal save_state + nop + + /* Invoke the handler. */ + + jal tlb_handle + nop + + j load_and_return + nop + +interrupt_handler: + sw $ra, -112($sp) + jal save_state + nop + + /* Invoke the handler. */ + + jal irq_handle + nop + + j load_and_return + nop + +save_state: + + /* Save the status, mask interrupts. */ + + mfc0 $k0, $12 /* CP0_STATUS */ + li $k1, 0xffff03ff + and $k1, $k0, $k1 + mtc0 $k1, $12 + sw $k0, -120($sp) + + sw $at, -4($sp) + sw $v0, -8($sp) + sw $v1, -12($sp) + sw $a0, -16($sp) + sw $a1, -20($sp) + sw $a2, -24($sp) + sw $a3, -28($sp) + sw $t0, -32($sp) + sw $t1, -36($sp) + sw $t2, -40($sp) + sw $t3, -44($sp) + sw $t4, -48($sp) + sw $t5, -52($sp) + sw $t6, -56($sp) + sw $t7, -60($sp) + sw $s0, -64($sp) + sw $s1, -68($sp) + sw $s2, -72($sp) + sw $s3, -76($sp) + sw $s4, -80($sp) + sw $s5, -84($sp) + sw $s6, -88($sp) + sw $s7, -92($sp) + sw $t8, -96($sp) + sw $t9, -100($sp) + sw $gp, -104($sp) + sw $fp, -108($sp) + /* sw $ra, -112($sp) */ + + mfc0 $k0, $14 /* CP0_EPC */ + nop + sw $k0, -116($sp) + + addi $sp, $sp, -120 + j $ra + nop + +load_and_return: + + addi $sp, $sp, 120 + + lw $at, -4($sp) + lw $v0, -8($sp) + lw $v1, -12($sp) + lw $a0, -16($sp) + lw $a1, -20($sp) + lw $a2, -24($sp) + lw $a3, -28($sp) + lw $t0, -32($sp) + lw $t1, -36($sp) + lw $t2, -40($sp) + lw $t3, -44($sp) + lw $t4, -48($sp) + lw $t5, -52($sp) + lw $t6, -56($sp) + lw $t7, -60($sp) + lw $s0, -64($sp) + lw $s1, -68($sp) + lw $s2, -72($sp) + lw $s3, -76($sp) + lw $s4, -80($sp) + lw $s5, -84($sp) + lw $s6, -88($sp) + lw $s7, -92($sp) + lw $t8, -96($sp) + lw $t9, -100($sp) + lw $gp, -104($sp) + lw $fp, -108($sp) + lw $ra, -112($sp) + + lw $k0, -116($sp) + mtc0 $k0, $14 /* CP0_EPC */ + nop + + lw $k0, -120($sp) + mtc0 $k0, $12 /* CP0_STATUS */ + nop + + eret + nop + +.set reorder +.set at diff -r 62ee61016b75 -r 62866e8d0f3b stage2/head2.S --- a/stage2/head2.S Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/head2.S Wed Feb 24 16:13:46 2016 +0100 @@ -1,20 +1,41 @@ /* - * Entry point of the firmware. - * The firmware code are executed in the ICache. - * Do not edit! - * Copyright (C) 2006 Ingenic Semiconductor Inc. + * Initialisation code for the stage 2 payload. + * + * Copyright 2009 (C) Qi Hardware Inc. + * Author: Wolfgang Spraul + * + * Copyright (C) 2015, 2016 Paul Boddie * + * 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 3 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, see . */ - .text - .extern c_main - - .globl _start - .set noreorder +#include "sdram.h" + +.text +.extern c_main +.extern _irq_entry +.extern _end_entries +.globl _start +.set noreorder + _start: b real_start nop - .word 0x0 // its address == start address + 8 + + /* Apparently reserved region which, if used, breaks the USB Boot process. */ + + .word 0x0 .word 0x0 .word 0x0 .word 0x0 @@ -23,11 +44,57 @@ .word 0x0 .word 0x0 -real_start: - /* setup stack, jump to C code */ - add $29, $20, 0x3ffff0 // sp locate at start address offset 0x2ffff0 - add $25, $20, 0x40 // t9 = c_main() - j $25 +real_start: + /* Initialise the stack. */ + + la $sp, 0x80080000 + + /* Initialise the globals pointer. */ + + lui $gp, %hi(_GLOBAL_OFFSET_TABLE_) + ori $gp, $gp, %lo(_GLOBAL_OFFSET_TABLE_) + + move $k0, $ra + + /* Copy TLB handling instructions. */ + + la $t0, _tlb_entry /* start */ + li $t1, 0x80000000 + la $t2, _irq_entry /* end */ + jal _copy nop - .set reorder + /* Copy IRQ handling instructions. */ + + la $t0, _irq_entry /* start */ + li $t1, 0x80000200 + la $t2, _end_entries /* end */ + jal _copy + nop + + move $ra, $k0 + + /* Enable caching. */ + + li $t0, CONFIG_CM_CACHABLE_NONCOHERENT + mtc0 $t0, $16 /* CP0_CONFIG */ + nop + + /* Start the program. */ + + la $t9, c_main /* load the address of the routine */ + j c_main + nop + +_copy: + /* Copy via $t3 the region from $t0 to $t2 into $t1. */ + + lw $t3, 0($t0) + addiu $t0, $t0, 4 + sw $t3, 0($t1) + bne $t0, $t2, _copy + addiu $t1, $t1, 4 /* executed in delay slot before branch */ + j $ra + nop + +.set reorder diff -r 62ee61016b75 -r 62866e8d0f3b stage2/irq.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage2/irq.c Wed Feb 24 16:13:46 2016 +0100 @@ -0,0 +1,128 @@ +/* + * Interrupt handling. + * + * Copyright (C) 2015, 2016 Paul Boddie + * + * 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 3 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, see . + */ + +#ifdef CONFIG_CPU_JZ4730_MINIPC +#include "minipc.h" +#else +#include "nanonote.h" +#endif + +#include "board-specific.h" +#include "board.h" +#include "lcd.h" +#include "jzlcd.h" +#include "cpu.h" +#include "irq.h" + +extern vidinfo_t panel_info; + +void next_pixel(unsigned short *x, unsigned short *y) +{ + (*x)++; + if (*x >= panel_info.vl_col) { + *x = 0; + (*y)++; + if (*y >= panel_info.vl_row) + *y = 0; + } +} + +/* Tasks. */ + +void plot_pattern(unsigned short pixel_type, unsigned short x, unsigned short y) +{ + while (1) { + if (pixel_type) + test_pixel(x, y); + else + clear_pixel(x, y); + next_pixel(&x, &y); + udelay(100); + } +} + +/* Initialisation and handling. */ + +void irq_init() +{ + timer_init_irq(); + handle_error_level(); + init_interrupts(); + enable_interrupts(); +} + +void irq_handle() +{ + unsigned short i; + + /* Check interrupt identity. */ + + if (REG_INTC_IPR & (1 << TIMER_CHAN_IRQ)) { + + /* Update the pixel type. */ + + /* pixel_type = __gpio_get_pin(GPIO_POWER); */ + + /* Clear interrupt status. */ + + __intc_ack_irq(TIMER_CHAN_IRQ); + __tcu_clear_full_match_flag(TIMER_CHAN); + + /* Handle other interrupts, anyway. */ + + } else { + for (i = 0; i < 32; i++) { + if (REG_INTC_IPR & (1 << i)) + __intc_ack_irq(i); + } + } +} + +void start_task() +{ + enter_user_mode(); + plot_pattern(1, 0, 0); +} + +void tlb_handle() +{ + u32 context, virtual, physical; + + /* Obtain the bad virtual address. */ + + asm volatile( + "mfc0 %0, $4\n" /* CP0_CONTEXT */ + : "=r" (context) + ); + + /* Obtain a virtual address region with 8KB resolution. */ + + virtual = (context & 0x007ffff0) << 9; + + /* The appropriate physical address depends on the current task. */ + + physical = virtual; + + /* + Request a physical region mapping two 4KB pages. + Pages employ C=3, dirty, valid, with the task number as the ASID. + */ + + map_page(virtual, physical, 4 * 1024, 0x1f, 0); +} diff -r 62ee61016b75 -r 62866e8d0f3b stage2/irq.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stage2/irq.h Wed Feb 24 16:13:46 2016 +0100 @@ -0,0 +1,9 @@ +#ifndef __IRQ_H__ +#define __IRQ_H__ + +/* Initialisation functions. */ + +void irq_init(void); +void start_task(void); + +#endif /* __IRQ_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b stage2/jzlcd.c --- a/stage2/jzlcd.c Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/jzlcd.c Wed Feb 24 16:13:46 2016 +0100 @@ -2,7 +2,7 @@ * JzRISC LCD controller * * Copyright (C) Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -22,11 +22,9 @@ #include "sdram.h" #include "jzlcd.h" +#include "cpu.h" #include "board.h" -#define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1) -#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) - #define align2(n) (n)=((((n)+1)>>1)<<1) #define align4(n) (n)=((((n)+3)>>2)<<2) #define align8(n) (n)=((((n)+7)>>3)<<3) @@ -34,124 +32,335 @@ extern struct jzfb_info jzfb; extern vidinfo_t panel_info; -unsigned long lcd_get_size(void) +static unsigned short lcd_get_panels() { - int line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; - return line_length * panel_info.vl_row; + return ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ? 2 : 1; +} + + + +/* Functions returning region sizes. */ + +static unsigned long lcd_get_size(vidinfo_t *vid) +{ + /* Lines must be aligned to a word boundary. */ + unsigned long line_length = ALIGN((vid->vl_col * NBITS(vid->vl_bpix)) / 8, sizeof(u32)); + return line_length * vid->vl_row; } -unsigned long lcd_setmem(unsigned long addr) +static unsigned long lcd_get_aligned_size(vidinfo_t *vid) { - unsigned long size; + /* LCD_CTRL_BST_16 requires 16-word alignment. */ + return ALIGN(lcd_get_size(vid), 16 * sizeof(u32)); +} - size = lcd_get_size(); +static unsigned long lcd_get_min_size(vidinfo_t *vid) +{ + /* Lines must be aligned to a word boundary. */ + unsigned long line_length = ALIGN((vid->vl_col * 32) / 8, sizeof(u32)); + return line_length * vid->vl_row; +} - /* Round up to nearest full page, or MMU section if defined */ - size = ALIGN(size, PAGE_SIZE); - addr = ALIGN(addr - PAGE_SIZE + 1, PAGE_SIZE); +static unsigned long lcd_get_aligned_min_size(vidinfo_t *vid) +{ + /* LCD_CTRL_BST_16 requires 16-word alignment. */ + return ALIGN(lcd_get_min_size(vid), 16 * sizeof(u32)); +} - /* Allocate pages for the frame buffer. */ - addr -= size; - - return addr; +static unsigned long lcd_get_palette_size(vidinfo_t *vid) +{ + if (NBITS(vid->vl_bpix) < 12) + return NCOLORS(vid->vl_bpix) * sizeof(u16); + else + return 0; } -static int jz_lcd_init_mem(void *lcdbase, vidinfo_t *vid); -static void jz_lcd_desc_init(vidinfo_t *vid); -static int jz_lcd_hw_init(vidinfo_t *vid); +static unsigned long lcd_get_aligned_palette_size(vidinfo_t *vid) +{ + /* LCD_CTRL_BST_16 requires 16-word alignment. */ + return ALIGN(lcd_get_palette_size(vid), 16 * sizeof(u32)); +} -void lcd_ctrl_init (void **lcdbase) +static unsigned long lcd_get_descriptors_size() { - /* Start from the top of memory and obtain a framebuffer region. */ - *lcdbase = (void *) lcd_setmem(get_memory_size()); + return 3 * sizeof(struct jz_fb_dma_descriptor); +} - jz_lcd_init_mem(*lcdbase, &panel_info); - jz_lcd_desc_init(&panel_info); - jz_lcd_hw_init(&panel_info); +static unsigned long lcd_get_total_size(vidinfo_t *vid) +{ + unsigned long size = lcd_get_aligned_size(vid) * lcd_get_panels(); + unsigned long min_size = lcd_get_aligned_min_size(vid); + + /* Round up to nearest full page, or MMU section if defined. */ + return ALIGN((size >= min_size ? size : min_size) + lcd_get_aligned_palette_size(vid) + lcd_get_descriptors_size(), PAGE_SIZE); } -/* - * Before enabled lcd controller, lcd registers should be configured correctly. - */ -void lcd_enable (void) + + +/* Functions returning addresses of each data region. */ + +static unsigned long lcd_get_palette(unsigned long addr) { - REG_LCD_CTRL &= ~(1<<4); /* LCDCTRL.DIS */ - REG_LCD_CTRL |= 1<<3; /* LCDCTRL.ENA*/ -} - -void lcd_disable (void) -{ - REG_LCD_CTRL |= (1<<4); /* LCDCTRL.DIS, regular disable */ - /* REG_LCD_CTRL |= (1<<3); */ /* LCDCTRL.DIS, quickly disable */ + /* Allocate memory at the end of the region for the palette. */ + return addr - lcd_get_aligned_palette_size(&panel_info); } -static int jz_lcd_init_mem(void *lcdbase, vidinfo_t *vid) +static unsigned long lcd_get_descriptors(unsigned long addr) { - unsigned long palette_mem_size; - struct jz_fb_info *fbi = &vid->jz_fb; - int fb_size = vid->vl_row * (vid->vl_col * NBITS (vid->vl_bpix)) / 8; + /* Allocate memory before the palette for the descriptor array. */ + return lcd_get_palette(addr) - lcd_get_descriptors_size(); +} - fbi->screen = (unsigned long)lcdbase; - fbi->palette_size = 256; - palette_mem_size = fbi->palette_size * sizeof(u16); +static unsigned long lcd_get_framebuffer(unsigned long addr, unsigned short panel) +{ + /* Allocate pages for the frame buffer and palette. */ + return addr - lcd_get_total_size(&panel_info) + (panel * lcd_get_aligned_size(&panel_info)); +} - /* locate palette and descs at end of page following fb */ - fbi->palette = (unsigned long)lcdbase + fb_size + PAGE_SIZE - palette_mem_size; + - return 0; -} +/* Initialisation functions. */ static void jz_lcd_desc_init(vidinfo_t *vid) { + struct jz_fb_dma_descriptor *descriptors; struct jz_fb_info * fbi; + fbi = &vid->jz_fb; - fbi->dmadesc_fblow = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 3*16); - fbi->dmadesc_fbhigh = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 2*16); - fbi->dmadesc_palette = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 1*16); - #define BYTES_PER_PANEL (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8) + /* Allocate space for descriptors before the palette entries. */ - /* populate descriptors */ - fbi->dmadesc_fblow->fdadr = virt_to_phys(fbi->dmadesc_fblow); - fbi->dmadesc_fblow->fsadr = virt_to_phys((void *)(fbi->screen + BYTES_PER_PANEL)); - fbi->dmadesc_fblow->fidr = 0; - fbi->dmadesc_fblow->ldcmd = BYTES_PER_PANEL / 4 ; + descriptors = (struct jz_fb_dma_descriptor *) lcd_get_descriptors(get_memory_size()); + fbi->dmadesc_fblow = (struct jz_fb_dma_descriptor *) &descriptors[0]; + fbi->dmadesc_fbhigh = (struct jz_fb_dma_descriptor *) &descriptors[1]; + fbi->dmadesc_palette = (struct jz_fb_dma_descriptor *) &descriptors[2]; - fbi->fdadr1 = virt_to_phys(fbi->dmadesc_fblow); /* only used in dual-panel mode */ + /* Populate descriptors. */ - fbi->dmadesc_fbhigh->fsadr = virt_to_phys((void *)fbi->screen); - fbi->dmadesc_fbhigh->fidr = 0; - fbi->dmadesc_fbhigh->ldcmd = BYTES_PER_PANEL / 4; /* length in word */ + if (lcd_get_panels() == 2) + { + fbi->dmadesc_fblow->fdadr = fbi->dmadesc_fblow; + fbi->dmadesc_fblow->fsadr = lcd_get_framebuffer(get_memory_size(), 1); + fbi->dmadesc_fblow->fidr = 0; + fbi->dmadesc_fblow->ldcmd = lcd_get_size(vid) / 4 ; - fbi->dmadesc_palette->fsadr = virt_to_phys((void *)fbi->palette); - fbi->dmadesc_palette->fidr = 0; - fbi->dmadesc_palette->ldcmd = (fbi->palette_size * 2)/4 | (1<<28); + fbi->fdadr1 = fbi->dmadesc_fblow; /* only used in dual-panel mode */ + } - if(NBITS(vid->vl_bpix) < 12) + fbi->dmadesc_fbhigh->fsadr = fbi->screen; + fbi->dmadesc_fbhigh->fidr = 0; + fbi->dmadesc_fbhigh->ldcmd = lcd_get_size(vid) / 4; /* length in words */ + + if (NBITS(vid->vl_bpix) < 12) { + fbi->dmadesc_palette->fsadr = fbi->palette; + fbi->dmadesc_palette->fidr = 0; + fbi->dmadesc_palette->ldcmd = (lcd_get_palette_size(vid) / 4) | (1<<28); + /* assume any mode with <12 bpp is palette driven */ - fbi->dmadesc_palette->fdadr = virt_to_phys(fbi->dmadesc_fbhigh); - fbi->dmadesc_fbhigh->fdadr = virt_to_phys(fbi->dmadesc_palette); + fbi->dmadesc_palette->fdadr = fbi->dmadesc_fbhigh; + fbi->dmadesc_fbhigh->fdadr = fbi->dmadesc_palette; /* flips back and forth between pal and fbhigh */ - fbi->fdadr0 = virt_to_phys(fbi->dmadesc_palette); + fbi->fdadr0 = fbi->dmadesc_palette; } else { /* palette shouldn't be loaded in true-color mode */ - fbi->dmadesc_fbhigh->fdadr = virt_to_phys((void *)fbi->dmadesc_fbhigh); - fbi->fdadr0 = virt_to_phys(fbi->dmadesc_fbhigh); /* no pal just fbhigh */ + fbi->dmadesc_fbhigh->fdadr = fbi->dmadesc_fbhigh; + fbi->fdadr0 = fbi->dmadesc_fbhigh; /* no pal just fbhigh */ } flush_cache_all(); } -static int jz_lcd_hw_init(vidinfo_t *vid) +static unsigned int jz_lcd_stn_init(unsigned int stnH) +{ + unsigned int val = 0; + + switch (jzfb.bpp) { + case 1: + /* val |= LCD_CTRL_PEDN; */ + case 2: + val |= LCD_CTRL_FRC_2; + break; + case 4: + val |= LCD_CTRL_FRC_4; + break; + case 8: + default: + val |= LCD_CTRL_FRC_16; + break; + } + + switch (jzfb.cfg & STN_DAT_PINMASK) { + case STN_DAT_PIN1: + /* Do not adjust the hori-param value. */ + break; + case STN_DAT_PIN2: + align2(jzfb.hsw); + align2(jzfb.elw); + align2(jzfb.blw); + break; + case STN_DAT_PIN4: + align4(jzfb.hsw); + align4(jzfb.elw); + align4(jzfb.blw); + break; + case STN_DAT_PIN8: + align8(jzfb.hsw); + align8(jzfb.elw); + align8(jzfb.blw); + break; + } + + REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; + REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw); + + /* Screen setting */ + REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw); + REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w); + REG_LCD_DAV = (0 << 16) | (stnH); + + /* AC BIAs signal */ + REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw); + + return val; +} + +static void jz_lcd_tft_init() +{ + REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; + REG_LCD_HSYNC = (0 << 16) | jzfb.hsw; + REG_LCD_DAV =((jzfb.vsw+jzfb.bfw) << 16) | (jzfb.vsw +jzfb.bfw+jzfb.h); + REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w ); + REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) \ + | (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw); +} + +static void jz_lcd_samsung_init(unsigned int pclk) +{ + unsigned int total, tp_s, tp_e, ckv_s, ckv_e; + unsigned int rev_s, rev_e, inv_s, inv_e; + + jz_lcd_tft_init(); + + total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; + tp_s = jzfb.blw + jzfb.w + 1; + tp_e = tp_s + 1; + /* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */ + ckv_s = tp_s - pclk/(1000000000/4100); + ckv_e = tp_s + total; + rev_s = tp_s - 11; /* -11.5 clk */ + rev_e = rev_s + total; + inv_s = tp_s; + inv_e = inv_s + total; + REG_LCD_CLS = (tp_s << 16) | tp_e; + REG_LCD_PS = (ckv_s << 16) | ckv_e; + REG_LCD_SPL = (rev_s << 16) | rev_e; + REG_LCD_REV = (inv_s << 16) | inv_e; + jzfb.cfg |= STFT_REVHI | STFT_SPLHI; +} + +static void jz_lcd_sharp_init() +{ + unsigned int total, cls_s, cls_e, ps_s, ps_e; + unsigned int spl_s, spl_e, rev_s, rev_e; + + jz_lcd_tft_init(); + + total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; + spl_s = 1; + spl_e = spl_s + 1; + cls_s = 0; + cls_e = total - 60; /* > 4us (pclk = 80ns) */ + ps_s = cls_s; + ps_e = cls_e; + rev_s = total - 40; /* > 3us (pclk = 80ns) */ + rev_e = rev_s + total; + jzfb.cfg |= STFT_PSHI; + REG_LCD_SPL = (spl_s << 16) | spl_e; + REG_LCD_CLS = (cls_s << 16) | cls_e; + REG_LCD_PS = (ps_s << 16) | ps_e; + REG_LCD_REV = (rev_s << 16) | rev_e; +} + +static unsigned int jz_lcd_get_pixel_clock() +{ + unsigned int pclk; + + /* Derive pixel clock from frame clock. */ + + if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) { + pclk = jzfb.fclk * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) * + (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); + } else { + /* serial mode: Hsync period = 3*Width_Pixel */ + pclk = jzfb.fclk * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) * + (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); + } + + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL)) + pclk = (pclk * 3); + + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) + pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4); + + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) + pclk >>= 1; + + return pclk; +} + +static void jz_lcd_set_timing(unsigned int pclk) +{ + unsigned int val; + +#ifdef CONFIG_CPU_JZ4730 + val = __cpm_get_pllout() / pclk; + REG_CPM_CFCR2 = val - 1; + val = pclk * 4 ; + if ( val > 150000000 ) { + val = 150000000; + } + val = __cpm_get_pllout() / val; + val--; + if ( val > 0xF ) + val = 0xF; +#else + int pll_div; + + pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */ + pll_div = pll_div ? 1 : 2 ; + val = ( __cpm_get_pllout()/pll_div ) / pclk; + val--; + if ( val > 0x1ff ) { + val = 0x1ff; + } + __cpm_set_pixdiv(val); + + val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ + if ( val > 150000000 ) { + val = 150000000; + } + val = ( __cpm_get_pllout()/pll_div ) / val; + val--; + if ( val > 0x1f ) { + val = 0x1f; + } +#endif + __cpm_set_ldiv( val ); + REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ +} + +static int jz_lcd_hw_init(vidinfo_t *vid) { struct jz_fb_info *fbi = &vid->jz_fb; unsigned int val = 0; - unsigned int pclk; - unsigned int stnH; -#ifndef CONFIG_CPU_JZ4730 - int pll_div; -#endif + unsigned int pclk = jz_lcd_get_pixel_clock(); /* Setting Control register */ switch (jzfb.bpp) { @@ -186,228 +395,148 @@ switch (jzfb.cfg & MODE_MASK) { case MODE_STN_MONO_DUAL: case MODE_STN_COLOR_DUAL: + val |= jz_lcd_stn_init(jzfb.h >> 1); + break; + case MODE_STN_MONO_SINGLE: case MODE_STN_COLOR_SINGLE: - switch (jzfb.bpp) { - case 1: - /* val |= LCD_CTRL_PEDN; */ - case 2: - val |= LCD_CTRL_FRC_2; - break; - case 4: - val |= LCD_CTRL_FRC_4; - break; - case 8: - default: - val |= LCD_CTRL_FRC_16; - break; - } + val |= jz_lcd_stn_init(jzfb.h); break; - } - - val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */ - val |= LCD_CTRL_OFUP; /* OutFIFO underrun protect */ - switch (jzfb.cfg & MODE_MASK) { - case MODE_STN_MONO_DUAL: - case MODE_STN_COLOR_DUAL: - case MODE_STN_MONO_SINGLE: - case MODE_STN_COLOR_SINGLE: - switch (jzfb.cfg & STN_DAT_PINMASK) { - case STN_DAT_PIN1: - /* Do not adjust the hori-param value. */ - break; - case STN_DAT_PIN2: - align2(jzfb.hsw); - align2(jzfb.elw); - align2(jzfb.blw); - break; - case STN_DAT_PIN4: - align4(jzfb.hsw); - align4(jzfb.elw); - align4(jzfb.blw); - break; - case STN_DAT_PIN8: - align8(jzfb.hsw); - align8(jzfb.elw); - align8(jzfb.blw); - break; - } + case MODE_TFT_GEN: + case MODE_TFT_CASIO: + case MODE_8BIT_SERIAL_TFT: + case MODE_TFT_18BIT: + jz_lcd_tft_init(); + break; + + case MODE_TFT_SAMSUNG: + { + jz_lcd_samsung_init(pclk); break; } - REG_LCD_CTRL = val; - - switch (jzfb.cfg & MODE_MASK) { - case MODE_STN_MONO_DUAL: - case MODE_STN_COLOR_DUAL: - case MODE_STN_MONO_SINGLE: - case MODE_STN_COLOR_SINGLE: - if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) || - ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL)) - stnH = jzfb.h >> 1; - else - stnH = jzfb.h; - - REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; - REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw); - - /* Screen setting */ - REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw); - REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w); - REG_LCD_DAV = (0 << 16) | (stnH); - - /* AC BIAs signal */ - REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw); - - break; - - case MODE_TFT_GEN: case MODE_TFT_SHARP: - case MODE_TFT_CASIO: - case MODE_TFT_SAMSUNG: - case MODE_8BIT_SERIAL_TFT: - case MODE_TFT_18BIT: - REG_LCD_VSYNC = (0 << 16) | jzfb.vsw; - REG_LCD_HSYNC = (0 << 16) | jzfb.hsw; - REG_LCD_DAV =((jzfb.vsw+jzfb.bfw) << 16) | (jzfb.vsw +jzfb.bfw+jzfb.h); - REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w ); - REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) \ - | (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw); + { + jz_lcd_sharp_init(); break; } - switch (jzfb.cfg & MODE_MASK) { - case MODE_TFT_SAMSUNG: - { - unsigned int total, tp_s, tp_e, ckv_s, ckv_e; - unsigned int rev_s, rev_e, inv_s, inv_e; - - pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) * - (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */ - - total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; - tp_s = jzfb.blw + jzfb.w + 1; - tp_e = tp_s + 1; - /* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */ - ckv_s = tp_s - pclk/(1000000000/4100); - ckv_e = tp_s + total; - rev_s = tp_s - 11; /* -11.5 clk */ - rev_e = rev_s + total; - inv_s = tp_s; - inv_e = inv_s + total; - REG_LCD_CLS = (tp_s << 16) | tp_e; - REG_LCD_PS = (ckv_s << 16) | ckv_e; - REG_LCD_SPL = (rev_s << 16) | rev_e; - REG_LCD_REV = (inv_s << 16) | inv_e; - jzfb.cfg |= STFT_REVHI | STFT_SPLHI; - break; - } - case MODE_TFT_SHARP: - { - unsigned int total, cls_s, cls_e, ps_s, ps_e; - unsigned int spl_s, spl_e, rev_s, rev_e; - total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw; - spl_s = 1; - spl_e = spl_s + 1; - cls_s = 0; - cls_e = total - 60; /* > 4us (pclk = 80ns) */ - ps_s = cls_s; - ps_e = cls_e; - rev_s = total - 40; /* > 3us (pclk = 80ns) */ - rev_e = rev_s + total; - jzfb.cfg |= STFT_PSHI; - REG_LCD_SPL = (spl_s << 16) | spl_e; - REG_LCD_CLS = (cls_s << 16) | cls_e; - REG_LCD_PS = (ps_s << 16) | ps_e; - REG_LCD_REV = (rev_s << 16) | rev_e; - break; - } - case MODE_TFT_CASIO: + default: break; } /* Configure the LCD panel */ + + val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */ + val |= LCD_CTRL_OFUP; /* OutFIFO underrun protect */ + REG_LCD_CTRL = val; REG_LCD_CFG = jzfb.cfg; - /* Timing setting */ - __cpm_stop_lcd(); + /* Timing reset. */ - val = jzfb.fclk; /* frame clk */ - if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) { - pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) * - (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */ - } else { - /* serial mode: Hsync period = 3*Width_Pixel */ - pclk = val * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) * - (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */ - } + __cpm_stop_lcd(); + jz_lcd_set_timing(pclk); + __cpm_start_lcd(); + udelay(1000); - if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || - ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL)) - pclk = (pclk * 3); + /* Configure DMA. */ - if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) || - ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || - ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) || - ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) - pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4); + REG_LCD_DA0 = (unsigned long) fbi->fdadr0; /* frame descriptor */ if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) - pclk >>= 1; - -#ifdef CONFIG_CPU_JZ4730 - val = __cpm_get_pllout() / pclk; - REG_CPM_CFCR2 = val - 1; - val = pclk * 4 ; - if ( val > 150000000 ) { - val = 150000000; - } - val = __cpm_get_pllout() / val; - val--; - if ( val > 0xF ) - val = 0xF; - __cpm_set_lcdclk_div(val); - REG_CPM_CFCR |= CPM_CFCR_UPE; -#else - pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */ - pll_div = pll_div ? 1 : 2 ; - val = ( __cpm_get_pllout()/pll_div ) / pclk; - val--; - if ( val > 0x1ff ) { - val = 0x1ff; - } - __cpm_set_pixdiv(val); - - val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */ - if ( val > 150000000 ) { - val = 150000000; - } - val = ( __cpm_get_pllout()/pll_div ) / val; - val--; - if ( val > 0x1f ) { - val = 0x1f; - } - __cpm_set_ldiv( val ); - REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */ -#endif - __cpm_start_lcd(); - udelay(1000); - - REG_LCD_DA0 = fbi->fdadr0; /* frame descripter*/ - - if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) || - ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL)) - REG_LCD_DA1 = fbi->fdadr1; /* frame descripter*/ + REG_LCD_DA1 = (unsigned long) fbi->fdadr1; /* frame descriptor */ return 0; } -void lcd_setcolreg (unsigned short regno, unsigned short red, unsigned short green, unsigned short blue) +static inline u8 LCD_CODE(u8 bpp) +{ + u8 code = 0; + while (bpp && !(bpp & 1)) + { + bpp >>= 1; + code += 1; + } + return code; +} + +/* Public operations. */ + +void lcd_set_bpp(u8 bpp) { + jzfb.bpp = bpp; + panel_info.vl_bpix = LCD_CODE(bpp); +} + +void lcd_enable(void) +{ + /* Clear the disable bit and set the enable bit. */ + + REG_LCD_CTRL &= ~(1<<4); /* LCDCTRL.DIS */ + REG_LCD_CTRL |= 1<<3; /* LCDCTRL.ENA*/ +} + +void lcd_disable(void) +{ + REG_LCD_CTRL |= (1<<4); /* LCDCTRL.DIS, regular disable */ +} + +void lcd_quick_disable(void) +{ + REG_LCD_CTRL &= ~(1<<4); /* LCDCTRL.ENA, quick disable */ +} + +static inline u16 rgb8_to_rgb16(u8 rgb) +{ + return ((((rgb & 0xe0) >> 5) * 4) << 11) | ((((rgb & 0x1c) >> 2) * 9) << 6) | ((rgb & 0x03) * 10); } -void lcd_initcolregs (void) +static inline u16 rgb4_to_rgb16(u8 rgb) +{ + return ((((rgb & 8) >> 3) * 0x1f) << 11) | ((((rgb & 6) >> 1) * 0x15) << 5) | ((rgb & 1) * 0x1f); +} + +static void lcd_init_palette(vidinfo_t *vid) { + u16 *palette = (u16 *) lcd_get_palette(get_memory_size()); + u16 *end = (u16 *) palette + NCOLORS(vid->vl_bpix); + u8 value = 0; + + while (palette < end) + { + switch (vid->vl_bpix) + { + case LCD_COLOR4: + *palette = rgb4_to_rgb16(value); + break; + + case LCD_COLOR8: + default: + *palette = rgb8_to_rgb16(value); + break; + } + + value++; + palette++; + } } + +unsigned long lcd_ctrl_init() +{ + struct jz_fb_info *fbi = &panel_info.jz_fb; + + /* Start from the top of memory and obtain palette and framebuffer regions. */ + + fbi->screen = lcd_get_framebuffer(get_memory_size(), 0); + fbi->palette = lcd_get_palette(get_memory_size()); + + if (NBITS(panel_info.vl_bpix) < 12) + lcd_init_palette(&panel_info); + + jz_lcd_desc_init(&panel_info); + jz_lcd_hw_init(&panel_info); + + return fbi->screen; +} diff -r 62ee61016b75 -r 62866e8d0f3b stage2/jzlcd.h --- a/stage2/jzlcd.h Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/jzlcd.h Wed Feb 24 16:13:46 2016 +0100 @@ -4,7 +4,7 @@ * Copyright (C) 2001 Wolfgang Denk, DENX Software Engineering, wd@denx.de. * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. * Copyright (C) Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -25,8 +25,10 @@ #ifndef __JZLCD_H__ #define __JZLCD_H__ -unsigned long lcd_get_size(void); -void lcd_ctrl_init(void **lcdbase); +#include "xburst_types.h" + +void lcd_set_bpp(u8 bpp); +unsigned long lcd_ctrl_init(); void lcd_enable(void); void lcd_disable(void); @@ -51,10 +53,10 @@ * LCD controller stucture for JZSOC: JZ4740 */ struct jz_fb_dma_descriptor { - unsigned long fdadr; /* Frame descriptor address register */ - unsigned long fsadr; /* Frame source address register */ - unsigned long fidr; /* Frame ID register */ - unsigned long ldcmd; /* Command register */ + struct jz_fb_dma_descriptor *fdadr; /* Frame descriptor address register */ + unsigned long fsadr; /* Frame source address register */ + unsigned long fidr; /* Frame ID register */ + unsigned long ldcmd; /* Command register */ }; /* @@ -62,16 +64,16 @@ */ struct jz_fb_info { - unsigned long fdadr0; /* physical address of frame/palette descriptor */ - unsigned long fdadr1; /* physical address of frame descriptor */ + struct jz_fb_dma_descriptor *fdadr0; /* physical address of frame/palette descriptor */ + struct jz_fb_dma_descriptor *fdadr1; /* physical address of frame descriptor */ /* DMA descriptors */ struct jz_fb_dma_descriptor *dmadesc_fblow; struct jz_fb_dma_descriptor *dmadesc_fbhigh; struct jz_fb_dma_descriptor *dmadesc_palette; + unsigned long screen; /* address of frame buffer */ unsigned long palette; /* address of palette memory */ - unsigned int palette_size; }; /* @@ -85,6 +87,11 @@ struct jz_fb_info jz_fb; } vidinfo_t; +/* Alignment/rounding macros. */ + +#define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1) +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) + /* General values for colour depths and framebuffer characteristics. */ #define LCD_MONOCHROME 0 diff -r 62ee61016b75 -r 62866e8d0f3b stage2/lcd.c --- a/stage2/lcd.c Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/lcd.c Wed Feb 24 16:13:46 2016 +0100 @@ -2,20 +2,20 @@ * Ben NanoNote LCD initialisation, based on uboot-xburst and xburst-tools. * * Copyright (C) 2001-2002 Wolfgang Denk, DENX Software Engineering, - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * - * 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 3 of the License, or (at your option) any later - * version. + * 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 3 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. + * 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, see . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #ifdef CONFIG_CPU_JZ4730_MINIPC @@ -32,41 +32,196 @@ #include "board.h" extern vidinfo_t panel_info; +static unsigned long lcd_base; -static void test_pattern(void *lcd_base) +static unsigned int get_line_length() +{ + return ALIGN((panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8, sizeof(u32)); +} + +static u32 *get_pixel32(unsigned short h, unsigned short v) +{ + return (u32 *) (lcd_base + v * get_line_length()) + h; +} + +static u16 *get_pixel16(unsigned short h, unsigned short v) +{ + return (u16 *) (lcd_base + v * get_line_length()) + h; +} + +static u8 *get_pixel8(unsigned short h, unsigned short v) +{ + return (u8 *) (lcd_base + v * get_line_length()) + h; +} + +static u8 *get_pixel4(unsigned short h, unsigned short v) +{ + return (u8 *) (lcd_base + v * get_line_length()) + h / 2; +} + +static inline unsigned short div(unsigned short num, unsigned short denom, unsigned short scale) +{ + return (scale * num) / denom; +} + +static unsigned long pixel(u8 r, u8 g, u8 b, u8 rmax, u8 gmax, u8 bmax, u8 rshift, u8 gshift, u8 bshift) +{ + return (div(r, 255, rmax) << rshift) | (div(g, 255, gmax) << gshift) | (div(b, 255, bmax) << bshift); +} + +static void get_colour(unsigned short h, unsigned short v, u8 rgb[]) +{ + unsigned short v_max = panel_info.vl_row; + unsigned short h_max = panel_info.vl_col; + + rgb[0] = div(h, h_max, 255); + rgb[1] = div(v, v_max, 255); + rgb[2] = (rgb[0] + rgb[1]) / 2; +} + +static void test_pixel32(unsigned short h, unsigned short v) +{ + u32 *pix = get_pixel32(h, v); + u8 rgb[3]; + + get_colour(h, v, rgb); + *pix = (u32) pixel(rgb[0], rgb[1], rgb[2], 255, 255, 255, 16, 8, 0); +} + +static void test_pixel16_565(unsigned short h, unsigned short v) +{ + u16 *pix = get_pixel16(h, v); + u8 rgb[3]; + + get_colour(h, v, rgb); + *pix = (u16) pixel(rgb[0], rgb[1], rgb[2], 31, 63, 31, 11, 5, 0); +} + +static void test_pixel8(unsigned short h, unsigned short v) +{ + u8 *pix = get_pixel8(h, v); + u8 rgb[3]; + + get_colour(h, v, rgb); + *pix = (u8) pixel(rgb[0], rgb[1], rgb[2], 7, 7, 3, 5, 2, 0); +} + +static void test_pixel4(unsigned short h, unsigned short v) +{ + u8 *pix = get_pixel4(h, v); + u8 mask = h & 1 ? 0xf0 : 0x0f; + u8 rgb[3]; + + get_colour(h, v, rgb); + *pix = (*pix & mask) | ((u8) pixel(rgb[0], rgb[1], rgb[2], 1, 2, 1, 3, 1, 0) << (h & 1 ? 0 : 4)); +} + +void test_pixel(unsigned short h, unsigned short v) +{ + switch (panel_info.vl_bpix) + { + case LCD_COLOR32: + test_pixel32(h, v); + break; + + case LCD_COLOR8: + test_pixel8(h, v); + break; + + case LCD_COLOR4: + test_pixel4(h, v); + break; + + case LCD_COLOR16: + default: + test_pixel16_565(h, v); + break; + } +} + +void clear_pixel32(unsigned short h, unsigned short v) +{ + u32 *pix = get_pixel32(h, v); + *pix = 0; +} + +void clear_pixel16(unsigned short h, unsigned short v) +{ + u16 *pix = get_pixel16(h, v); + *pix = 0; +} + +void clear_pixel8(unsigned short h, unsigned short v) +{ + u8 *pix = get_pixel8(h, v); + *pix = 0; +} + +void clear_pixel4(unsigned short h, unsigned short v) +{ + u8 *pix = get_pixel4(h, v); + u8 mask = h & 1 ? 0xf0 : 0x0f; + *pix = *pix & mask; +} + +void clear_pixel(unsigned short h, unsigned short v) +{ + switch (panel_info.vl_bpix) + { + case LCD_COLOR32: + clear_pixel32(h, v); + break; + + case LCD_COLOR8: + clear_pixel8(h, v); + break; + + case LCD_COLOR4: + clear_pixel4(h, v); + break; + + case LCD_COLOR16: + default: + clear_pixel16(h, v); + break; + } +} + +void test_pattern() { unsigned short v_max = panel_info.vl_row; unsigned short h_max = panel_info.vl_col; unsigned short v, h; - u32 *pix = (u32 *)lcd_base; - /* WARNING: Code silently assumes 32 bit/pixel */ for (v = 0; v < v_max; v += 1) { for (h = 0; h < h_max; h += 1) { - *pix++ = ( - (((255 * (h_max - h)) / (h_max - 1)) << 16) + - ((((255 * h) / (h_max - 1) + (255 * (v_max - v)) / (v_max - 1)) / 2) << 8) + - ((255 * v) / (v_max - 1)) - ); + test_pixel(h, v); } } } -void lcd_clear(void *lcd_base) +void lcd_clear(unsigned long lcd_base) { - test_pattern(lcd_base); + unsigned short v_max = panel_info.vl_row; + unsigned short h_max = panel_info.vl_col; + unsigned short v, h; + unsigned long *pix = (unsigned long *)lcd_base; + + for (v = 0; v < v_max; v += 1) { + for (h = 0; h < h_max; h += 1) { + *pix++ = 0; + } + } } /* LCD initialisation. */ -static void *lcd_base; - void lcd_init(void) { __lcd_display_pin_init(); __lcd_display_on(); - lcd_ctrl_init(&lcd_base); + lcd_base = lcd_ctrl_init(); lcd_clear(lcd_base); lcd_enable(); } diff -r 62ee61016b75 -r 62866e8d0f3b stage2/lcd.h --- a/stage2/lcd.h Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/lcd.h Wed Feb 24 16:13:46 2016 +0100 @@ -5,4 +5,11 @@ void lcd_init(void); +/* Output functions. */ + +void test_pixel(unsigned short h, unsigned short v); +void clear_pixel(unsigned short h, unsigned short v); + +void test_pattern(); + #endif /* __LCD_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b stage2/minipc_claa070vc01.c --- a/stage2/minipc_claa070vc01.c Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/minipc_claa070vc01.c Wed Feb 24 16:13:46 2016 +0100 @@ -2,7 +2,7 @@ * MiniPC screen details * * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -26,9 +26,9 @@ struct jzfb_info jzfb = { MODE_TFT_GEN | PCLK_N | HSYNC_N | VSYNC_N, - 800, 480, 16, 60, 80, 20, 0, 0, 0, 0 + 800, 480, 32, 60, 80, 20, 0, 0, 0, 0 }; vidinfo_t panel_info = { - 800, 480, LCD_BPP, + 800, 480, LCD_COLOR32, }; diff -r 62ee61016b75 -r 62866e8d0f3b stage2/minipc_claa070vc01.h --- a/stage2/minipc_claa070vc01.h Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/minipc_claa070vc01.h Wed Feb 24 16:13:46 2016 +0100 @@ -2,7 +2,7 @@ * MiniPC panel-specific definitions * * Copyright (C) Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -23,36 +23,39 @@ #ifndef __MINIPC_CLAA070VC01_H__ #define __MINIPC_CLAA070VC01_H__ -#define __lcd_set_backlight_level(n) \ -do { \ - __gpio_as_pwm(); \ - REG_PWM_DUT(0) = n; \ - REG_PWM_PER(0) = 7; \ - REG_PWM_CTR(0) = 0xc1; \ -} while (0) +#include "board.h" +#include "minipc.h" -#define __lcd_close_backlight() \ -do { \ -__gpio_as_output(GPIO_PWM0);\ -__gpio_clear_pin(GPIO_PWM0);\ -} while (0) +static inline void __lcd_set_backlight_level(u16 n) +{ + __gpio_as_pwm(); + REG_PWM_DUT(0) = n; + REG_PWM_PER(0) = 7; + REG_PWM_CTR(0) = 0xc1; +} + +static inline void __lcd_close_backlight() +{ + __gpio_as_output(GPIO_PWM0); + __gpio_clear_pin(GPIO_PWM0); +} -#define __lcd_display_pin_init() \ -do { \ - __gpio_as_output(GPIO_DISP_OFF_N); \ - __lcd_set_backlight_level(8); \ -} while (0) +static inline void __lcd_display_pin_init() +{ + __gpio_as_output(GPIO_DISP_OFF_N); + __lcd_set_backlight_level(8); +} -#define __lcd_display_on() \ -do { \ - __gpio_set_pin(GPIO_DISP_OFF_N); \ - __lcd_set_backlight_level(8); \ -} while (0) +static inline void __lcd_display_on() +{ + __gpio_set_pin(GPIO_DISP_OFF_N); + __lcd_set_backlight_level(8); +} -#define __lcd_display_off() \ -do { \ - __lcd_close_backlight(); \ - __gpio_clear_pin(GPIO_DISP_OFF_N); \ -} while (0) +static inline void __lcd_display_off() +{ + __lcd_close_backlight(); + __gpio_clear_pin(GPIO_DISP_OFF_N); +} #endif /* __MINIPC_CLAA070VC01_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b stage2/nanonote_gpm940b0.c --- a/stage2/nanonote_gpm940b0.c Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/nanonote_gpm940b0.c Wed Feb 24 16:13:46 2016 +0100 @@ -2,7 +2,7 @@ * Ben NanoNote screen details * * Copyright (C) Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -30,5 +30,5 @@ }; vidinfo_t panel_info = { - 320, 240, LCD_BPP, + 320, 240, LCD_COLOR32, }; diff -r 62ee61016b75 -r 62866e8d0f3b stage2/nanonote_gpm940b0.h --- a/stage2/nanonote_gpm940b0.h Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/nanonote_gpm940b0.h Wed Feb 24 16:13:46 2016 +0100 @@ -2,7 +2,7 @@ * Ben NanoNote panel-specific definitions * * Copyright (C) Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -23,50 +23,56 @@ #ifndef __NANONOTE_GPM940B0_H__ #define __NANONOTE_GPM940B0_H__ -#define __spi_write_reg1(reg, val) \ -do { \ - unsigned char no; \ - unsigned short value; \ - unsigned char a=reg; \ - unsigned char b=val; \ - __gpio_set_pin(SPEN); \ - __gpio_set_pin(SPCK); \ - __gpio_clear_pin(SPDA); \ - __gpio_clear_pin(SPEN); \ - value=((a<<8)|(b&0xFF)); \ - for(no=0;no<16;no++) \ - { \ - __gpio_clear_pin(SPCK); \ - if((value&0x8000)==0x8000) \ - __gpio_set_pin(SPDA); \ - else \ - __gpio_clear_pin(SPDA); \ - __gpio_set_pin(SPCK); \ - value=(value<<1); \ - } \ - __gpio_set_pin(SPEN); \ -} while (0) +#include "board.h" +#include "nanonote.h" + +static inline void __spi_write_reg1(u8 reg, u8 val) +{ + u8 no, a=reg, b=val; + u16 value; + + __gpio_set_pin(SPEN); + __gpio_set_pin(SPCK); + __gpio_clear_pin(SPDA); + __gpio_clear_pin(SPEN); + + value = ((a << 8) | (b & 0xFF)); + + for (no=0; no<16; no++) + { + __gpio_clear_pin(SPCK); + + if ((value & 0x8000) == 0x8000) + __gpio_set_pin(SPDA); + else + __gpio_clear_pin(SPDA); -#define __lcd_display_pin_init() \ -do { \ - __cpm_start_tcu(); \ - __gpio_as_output(SPEN); \ - __gpio_as_output(SPCK); \ - __gpio_as_output(SPDA); \ -} while (0) + __gpio_set_pin(SPCK); + value = (value << 1); + } + __gpio_set_pin(SPEN); +} + +static inline void __lcd_display_pin_init() +{ + __cpm_start_tcu(); + __gpio_as_output(SPEN); + __gpio_as_output(SPCK); + __gpio_as_output(SPDA); +} -#define __lcd_display_on() \ -do { \ - __spi_write_reg1(0x05, 0x1e); \ - __spi_write_reg1(0x05, 0x5e); \ - __spi_write_reg1(0x07, 0x8d); \ - __spi_write_reg1(0x13, 0x01); \ - __spi_write_reg1(0x05, 0x5f); \ -} while (0) +static inline void __lcd_display_on() +{ + __spi_write_reg1(0x05, 0x1e); + __spi_write_reg1(0x05, 0x5e); + __spi_write_reg1(0x07, 0x8d); + __spi_write_reg1(0x13, 0x01); + __spi_write_reg1(0x05, 0x5f); +} -#define __lcd_display_off() \ -do { \ - __spi_write_reg1(0x05, 0x5e); \ -} while (0) +static inline void __lcd_display_off() +{ + __spi_write_reg1(0x05, 0x5e); +} #endif /* __NANONOTE_GPM940B0_H__ */ diff -r 62ee61016b75 -r 62866e8d0f3b stage2/stage2.c --- a/stage2/stage2.c Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/stage2.c Wed Feb 24 16:13:46 2016 +0100 @@ -2,71 +2,51 @@ * Ben NanoNote stage 2 payload test. * * Copyright (C) Wolfgang Spraul - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * - * 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 3 of the License, or (at your option) any later - * version. + * 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 3 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. + * 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, see . + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ -#ifdef CONFIG_CPU_JZ4730_MINIPC -#include "board-minipc.h" -#else -#include "board-nanonote.h" -#endif +#include "board-specific.h" +#include "irq.h" #include "lcd.h" +#include "cpu.h" void c_main(void) { - /* Relocate object locations. */ - - volatile unsigned int start_addr, got_start, got_end, addr, offset; volatile int started; - /* get absolute start address */ - __asm__ __volatile__( - "move %0, $20\n\t" - : "=r"(start_addr) - : - ); - - /* get related GOT address */ - __asm__ __volatile__( - "la $4, _GLOBAL_OFFSET_TABLE_\n\t" - "move %0, $4\n\t" - "la $5, _got_end\n\t" - "move %1, $5\n\t" - : "=r"(got_start),"=r"(got_end) - : - ); - - /* calculate offset and correct GOT*/ - offset = start_addr - 0x80000000; - got_start += offset; - got_end += offset; - - for ( addr = got_start + 8; addr < got_end; addr += 4 ) - *((volatile unsigned int *)(addr)) += offset; // add offset to correct all GOT + init_tlb(); + flush_cache_all(); /* The actual work. */ started = is_started(); - if (!started) { + + if (!started) + { gpio_init2(); cpm_init(); rtc_init(); timer_init(); } + lcd_init(); - while (1); + irq_init(); + + start_task(); + + while (1) asm volatile("wait"); } diff -r 62ee61016b75 -r 62866e8d0f3b stage2/stage2.ld --- a/stage2/stage2.ld Sat Jun 13 00:06:18 2015 +0200 +++ b/stage2/stage2.ld Wed Feb 24 16:13:46 2016 +0100 @@ -1,32 +1,31 @@ OUTPUT_ARCH(mips) ENTRY(_start) -MEMORY -{ - ram : ORIGIN = 0x80000000 , LENGTH = 3M -} SECTIONS { - . = ALIGN(4); - .text : { *(.text*) } > ram + /* Program memory section. */ + + . = 0x81c00000; + .text2 : { *(.text*) } . = ALIGN(4); - .rodata : { *(.rodata*) } > ram + .rodata : { *(.rodata*) } . = ALIGN(4); - .sdata : { *(.sdata*) } > ram + .sdata : { *(.sdata*) } . = ALIGN(4); - .data : { *(.data*) *(.scommon*) *(.reginfo*) } > ram + .data : { *(.data*) *(.scommon*) *(.reginfo*) } _gp = ALIGN(16); - .got : { *(.got*) } > ram + _got_start = ABSOLUTE(.); + .got : { *(.got*) } _got_end = ABSOLUTE(.); . = ALIGN(4); - .sbss : { *(.sbss*) } > ram - .bss : { *(.bss*) } > ram + .sbss : { *(.sbss*) } + .bss : { *(.bss*) } . = ALIGN (4); }