1.1 --- a/Makefile Sat Jun 06 18:03:55 2015 +0200
1.2 +++ b/Makefile Sat Jun 06 23:29:51 2015 +0200
1.3 @@ -42,9 +42,9 @@
1.4 # Ordering of objects is important and cannot be left to replacement rules.
1.5
1.6 SRC1 = head1.S stage1.c board-nanonote.c
1.7 -SRC2 = head2.S stage2.c board-nanonote.c
1.8 +SRC2 = head2.S stage2.c board-nanonote.c nanonote_gpm940b0.c
1.9 OBJ1 = head1.o stage1.o board-nanonote.o
1.10 -OBJ2 = head2.o stage2.o board-nanonote.o
1.11 +OBJ2 = head2.o stage2.o board-nanonote.o nanonote_gpm940b0.o
1.12 OBJ = $(OBJ1) $(OBJ2)
1.13
1.14 .PHONY: all clean distclean
2.1 --- a/board-nanonote.c Sat Jun 06 18:03:55 2015 +0200
2.2 +++ b/board-nanonote.c Sat Jun 06 23:29:51 2015 +0200
2.3 @@ -3,7 +3,8 @@
2.4 *
2.5 * Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>
2.6 * Copyright (C) Xiangfu Liu <xiangfu.z@gmail.com>
2.7 - * Copyright (c) 2006 Ingenic Semiconductor, <jlwei@ingenic.cn>
2.8 + * Copyright (C) 2006 Ingenic Semiconductor, <jlwei@ingenic.cn>
2.9 + * Copyright (C) 2003 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
2.10 *
2.11 * This program is free software; you can redistribute it and/or modify it under
2.12 * the terms of the GNU General Public License as published by the Free Software
2.13 @@ -234,3 +235,232 @@
2.14
2.15 /* everything is ok now */
2.16 }
2.17 +
2.18 +void rtc_init(void)
2.19 +{
2.20 + while ( !__rtc_write_ready()) ;
2.21 + __rtc_enable_alarm(); /* enable alarm */
2.22 +
2.23 + while ( !__rtc_write_ready())
2.24 + ;
2.25 + REG_RTC_RGR = 0x00007fff; /* type value */
2.26 +
2.27 + while ( !__rtc_write_ready())
2.28 + ;
2.29 + REG_RTC_HWFCR = 0x0000ffe0; /* Power on delay 2s */
2.30 +
2.31 + while ( !__rtc_write_ready())
2.32 + ;
2.33 + REG_RTC_HRCR = 0x00000fe0; /* reset delay 125ms */
2.34 +}
2.35 +
2.36 +/*
2.37 + * Timer routines
2.38 + */
2.39 +
2.40 +#define TIMER_CHAN 0
2.41 +#define TIMER_FDATA 0xffff /* Timer full data value */
2.42 +#define TIMER_HZ CONFIG_SYS_HZ
2.43 +
2.44 +#define READ_TIMER REG_TCU_TCNT(TIMER_CHAN) /* macro to read the 16 bit timer */
2.45 +
2.46 +static unsigned long timestamp;
2.47 +static unsigned long lastdec;
2.48 +
2.49 +void reset_timer_masked(void);
2.50 +unsigned long get_timer_masked(void);
2.51 +void udelay_masked(unsigned long usec);
2.52 +
2.53 +/*
2.54 + * timer without interrupts
2.55 + */
2.56 +
2.57 +int timer_init(void)
2.58 +{
2.59 + REG_TCU_TCSR(TIMER_CHAN) = TCU_TCSR_PRESCALE256 | TCU_TCSR_EXT_EN;
2.60 + REG_TCU_TCNT(TIMER_CHAN) = 0;
2.61 + REG_TCU_TDHR(TIMER_CHAN) = 0;
2.62 + REG_TCU_TDFR(TIMER_CHAN) = TIMER_FDATA;
2.63 +
2.64 + REG_TCU_TMSR = (1 << TIMER_CHAN) | (1 << (TIMER_CHAN + 16)); /* mask irqs */
2.65 + REG_TCU_TSCR = (1 << TIMER_CHAN); /* enable timer clock */
2.66 + REG_TCU_TESR = (1 << TIMER_CHAN); /* start counting up */
2.67 +
2.68 + lastdec = 0;
2.69 + timestamp = 0;
2.70 +
2.71 + return 0;
2.72 +}
2.73 +
2.74 +void reset_timer(void)
2.75 +{
2.76 + reset_timer_masked ();
2.77 +}
2.78 +
2.79 +unsigned long get_timer(unsigned long base)
2.80 +{
2.81 + return get_timer_masked () - base;
2.82 +}
2.83 +
2.84 +void set_timer(unsigned long t)
2.85 +{
2.86 + timestamp = t;
2.87 +}
2.88 +
2.89 +void udelay (unsigned long usec)
2.90 +{
2.91 + unsigned long tmo,tmp;
2.92 +
2.93 + /* normalize */
2.94 + if (usec >= 1000) {
2.95 + tmo = usec / 1000;
2.96 + tmo *= TIMER_HZ;
2.97 + tmo /= 1000;
2.98 + }
2.99 + else {
2.100 + if (usec >= 1) {
2.101 + tmo = usec * TIMER_HZ;
2.102 + tmo /= (1000*1000);
2.103 + }
2.104 + else
2.105 + tmo = 1;
2.106 + }
2.107 +
2.108 + /* check for rollover during this delay */
2.109 + tmp = get_timer (0);
2.110 + if ((tmp + tmo) < tmp )
2.111 + reset_timer_masked(); /* timer would roll over */
2.112 + else
2.113 + tmo += tmp;
2.114 +
2.115 + while (get_timer_masked () < tmo);
2.116 +}
2.117 +
2.118 +void reset_timer_masked (void)
2.119 +{
2.120 + /* reset time */
2.121 + lastdec = READ_TIMER;
2.122 + timestamp = 0;
2.123 +}
2.124 +
2.125 +unsigned long get_timer_masked (void)
2.126 +{
2.127 + unsigned long now = READ_TIMER;
2.128 +
2.129 + if (lastdec <= now) {
2.130 + /* normal mode */
2.131 + timestamp += (now - lastdec);
2.132 + } else {
2.133 + /* we have an overflow ... */
2.134 + timestamp += TIMER_FDATA + now - lastdec;
2.135 + }
2.136 + lastdec = now;
2.137 +
2.138 + return timestamp;
2.139 +}
2.140 +
2.141 +void udelay_masked (unsigned long usec)
2.142 +{
2.143 + unsigned long tmo;
2.144 + unsigned long endtime;
2.145 + signed long diff;
2.146 +
2.147 + /* normalize */
2.148 + if (usec >= 1000) {
2.149 + tmo = usec / 1000;
2.150 + tmo *= TIMER_HZ;
2.151 + tmo /= 1000;
2.152 + } else {
2.153 + if (usec > 1) {
2.154 + tmo = usec * TIMER_HZ;
2.155 + tmo /= (1000*1000);
2.156 + } else {
2.157 + tmo = 1;
2.158 + }
2.159 + }
2.160 +
2.161 + endtime = get_timer_masked () + tmo;
2.162 +
2.163 + do {
2.164 + unsigned long now = get_timer_masked ();
2.165 + diff = endtime - now;
2.166 + } while (diff >= 0);
2.167 +}
2.168 +
2.169 +/*
2.170 + * This function is derived from PowerPC code (read timebase as long long).
2.171 + * On MIPS it just returns the timer value.
2.172 + */
2.173 +unsigned long long get_ticks(void)
2.174 +{
2.175 + return get_timer(0);
2.176 +}
2.177 +
2.178 +/*
2.179 + * This function is derived from PowerPC code (timebase clock frequency).
2.180 + * On MIPS it returns the number of timer ticks per second.
2.181 + */
2.182 +unsigned long get_tbclk (void)
2.183 +{
2.184 + return TIMER_HZ;
2.185 +}
2.186 +
2.187 +/* CPU-specific routines from U-Boot.
2.188 + See: uboot-xburst/files/arch/mips/cpu/xburst/cpu.c
2.189 + See: u-boot/arch/mips/include/asm/cacheops.h
2.190 +*/
2.191 +
2.192 +#define Index_Store_Tag_I 0x08
2.193 +#define Index_Writeback_Inv_D 0x15
2.194 +
2.195 +void flush_icache_all(void)
2.196 +{
2.197 + u32 addr, t = 0;
2.198 +
2.199 + asm volatile ("mtc0 $0, $28"); /* Clear Taglo */
2.200 + asm volatile ("mtc0 $0, $29"); /* Clear TagHi */
2.201 +
2.202 + for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_ICACHE_SIZE;
2.203 + addr += CONFIG_SYS_CACHELINE_SIZE) {
2.204 + asm volatile (
2.205 + ".set mips3\n\t"
2.206 + " cache %0, 0(%1)\n\t"
2.207 + ".set mips2\n\t"
2.208 + :
2.209 + : "I" (Index_Store_Tag_I), "r"(addr));
2.210 + }
2.211 +
2.212 + /* invalicate btb */
2.213 + asm volatile (
2.214 + ".set mips32\n\t"
2.215 + "mfc0 %0, $16, 7\n\t"
2.216 + "nop\n\t"
2.217 + "ori %0,2\n\t"
2.218 + "mtc0 %0, $16, 7\n\t"
2.219 + ".set mips2\n\t"
2.220 + :
2.221 + : "r" (t));
2.222 +}
2.223 +
2.224 +void flush_dcache_all(void)
2.225 +{
2.226 + u32 addr;
2.227 +
2.228 + for (addr = KSEG0; addr < KSEG0 + CONFIG_SYS_DCACHE_SIZE;
2.229 + addr += CONFIG_SYS_CACHELINE_SIZE) {
2.230 + asm volatile (
2.231 + ".set mips3\n\t"
2.232 + " cache %0, 0(%1)\n\t"
2.233 + ".set mips2\n\t"
2.234 + :
2.235 + : "I" (Index_Writeback_Inv_D), "r"(addr));
2.236 + }
2.237 +
2.238 + asm volatile ("sync");
2.239 +}
2.240 +
2.241 +void flush_cache_all(void)
2.242 +{
2.243 + flush_dcache_all();
2.244 + flush_icache_all();
2.245 +}
3.1 --- a/board-nanonote.h Sat Jun 06 18:03:55 2015 +0200
3.2 +++ b/board-nanonote.h Sat Jun 06 23:29:51 2015 +0200
3.3 @@ -2,8 +2,13 @@
3.4 #define __BOARD_NANONOTE_H__
3.5
3.6 void gpio_init(void);
3.7 +void gpio_init2(void);
3.8 void cpm_init(void);
3.9 void pll_init(void);
3.10 void sdram_init(void);
3.11 +void rtc_init(void);
3.12 +int timer_init(void);
3.13 +void udelay(unsigned long usec);
3.14 +void flush_cache_all(void);
3.15
3.16 #endif /* __BOARD_NANONOTE_H__ */
4.1 --- a/include/jz4740.h Sat Jun 06 18:03:55 2015 +0200
4.2 +++ b/include/jz4740.h Sat Jun 06 23:29:51 2015 +0200
4.3 @@ -3214,12 +3214,18 @@
4.4 #define __cpm_suspend_usbphy() (REG_CPM_SCR |= CPM_SCR_USBPHY_DISABLE)
4.5 #define __cpm_enable_osc_in_sleep() (REG_CPM_SCR |= CPM_SCR_OSC_ENABLE)
4.6
4.7 +/* NOTE: Independent of usbboot parameters. */
4.8 +
4.9 +#define CONFIG_SYS_CPU_SPEED 336000000 /* CPU clock: 336 MHz */
4.10 +#define CONFIG_SYS_EXTAL 12000000 /* EXTAL freq: 12 MHz */
4.11 +#define CONFIG_SYS_HZ (CONFIG_SYS_EXTAL / 256) /* incrementer freq */
4.12
4.13 #ifdef CONFIG_SYS_EXTAL
4.14 #define JZ_EXTAL CONFIG_SYS_EXTAL
4.15 #else
4.16 #define JZ_EXTAL 3686400
4.17 #endif
4.18 +
4.19 #define JZ_EXTAL2 32768 /* RTC clock */
4.20
4.21 /* PLL output frequency */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/include/lcd.h Sat Jun 06 23:29:51 2015 +0200
5.3 @@ -0,0 +1,84 @@
5.4 +/*
5.5 + * U-Boot JzRISC lcd controller definitions
5.6 + *
5.7 + * (C) Copyright 2001 Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5.8 + * (C) Copyright Xiangfu Liu <xiangfu@sharism.cc>
5.9 + * (C) Copyright 2015 Paul Boddie <paul@boddie.org.uk>
5.10 + *
5.11 + * This program is free software; you can redistribute it and/or
5.12 + * modify it under the terms of the GNU General Public License as
5.13 + * published by the Free Software Foundation; either version 2 of
5.14 + * the License, or (at your option) any later version.
5.15 + *
5.16 + * This program is distributed in the hope that it will be useful,
5.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.19 + * GNU General Public License for more details.
5.20 + *
5.21 + * You should have received a copy of the GNU General Public License
5.22 + * along with this program; if not, write to the Free Software
5.23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
5.24 + * MA 02111-1307 USA
5.25 + */
5.26 +
5.27 +#ifndef _LCD_H_
5.28 +#define _LCD_H_
5.29 +
5.30 +/*
5.31 + * LCD controller stucture for JZSOC: JZ4740
5.32 + */
5.33 +struct jz_fb_dma_descriptor {
5.34 + unsigned long fdadr; /* Frame descriptor address register */
5.35 + unsigned long fsadr; /* Frame source address register */
5.36 + unsigned long fidr; /* Frame ID register */
5.37 + unsigned long ldcmd; /* Command register */
5.38 +};
5.39 +
5.40 +/*
5.41 + * Jz LCD info
5.42 + */
5.43 +struct jz_fb_info {
5.44 +
5.45 + unsigned long fdadr0; /* physical address of frame/palette descriptor */
5.46 + unsigned long fdadr1; /* physical address of frame descriptor */
5.47 +
5.48 + /* DMA descriptors */
5.49 + struct jz_fb_dma_descriptor * dmadesc_fblow;
5.50 + struct jz_fb_dma_descriptor * dmadesc_fbhigh;
5.51 + struct jz_fb_dma_descriptor * dmadesc_palette;
5.52 + unsigned long screen; /* address of frame buffer */
5.53 + unsigned long palette; /* address of palette memory */
5.54 + unsigned int palette_size;
5.55 +};
5.56 +
5.57 +typedef struct vidinfo {
5.58 + unsigned short vl_col; /* Number of columns (i.e. 640) */
5.59 + unsigned short vl_row; /* Number of rows (i.e. 480) */
5.60 + unsigned char vl_bpix; /* Bits per pixel, 0 = 1, 1 = 2, 2 = 4, 3 = 8 */
5.61 +
5.62 + struct jz_fb_info jz_fb;
5.63 +} vidinfo_t;
5.64 +
5.65 +extern vidinfo_t panel_info;
5.66 +
5.67 +#define LCD_MONOCHROME 0
5.68 +#define LCD_COLOR2 1
5.69 +#define LCD_COLOR4 2
5.70 +#define LCD_COLOR8 3
5.71 +#define LCD_COLOR16 4
5.72 +#define LCD_COLOR32 5
5.73 +
5.74 +/* Default to 8bpp if bit depth not specified */
5.75 +#ifndef LCD_BPP
5.76 +#define LCD_BPP LCD_COLOR8
5.77 +#endif
5.78 +
5.79 +#ifndef PAGE_SIZE
5.80 +#define PAGE_SIZE 4096
5.81 +#endif
5.82 +
5.83 +/* Calculate nr. of bits per pixel and nr. of colors */
5.84 +#define NBITS(bit_code) (1 << (bit_code))
5.85 +#define NCOLORS(bit_code) (1 << NBITS(bit_code))
5.86 +
5.87 +#endif /* _LCD_H_ */
6.1 --- a/include/nanonote.h Sat Jun 06 18:03:55 2015 +0200
6.2 +++ b/include/nanonote.h Sat Jun 06 23:29:51 2015 +0200
6.3 @@ -1,5 +1,6 @@
6.4 /*
6.5 - * Authors: Xiangfu Liu <xiangfu.z@gmail.com>
6.6 + * Copyright (C) Xiangfu Liu <xiangfu.z@gmail.com>
6.7 + * Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk>
6.8 *
6.9 * This program is free software; you can redistribute it and/or
6.10 * modify it under the terms of the GNU General Public License
6.11 @@ -14,31 +15,40 @@
6.12 #define __CONFIG_NANONOTE_H
6.13
6.14 /*
6.15 + * Cache Configuration
6.16 + */
6.17 +#define CONFIG_SYS_DCACHE_SIZE 16384
6.18 +#define CONFIG_SYS_ICACHE_SIZE 16384
6.19 +#define CONFIG_SYS_CACHELINE_SIZE 32
6.20 +#define KSEG0 0x80000000
6.21 +
6.22 +/*
6.23 * GPIO definition
6.24 * See: http://en.qi-hardware.com/wiki/Hardware_basics
6.25 */
6.26 -#define GPIO_LCD_CS (2 * 32 + 21)
6.27 -#define GPIO_AMP_EN (3 * 32 + 4)
6.28 +#define GPIO_LCD_CS (2 * 32 + 21)
6.29 +#define GPIO_AMP_EN (3 * 32 + 4)
6.30
6.31 -#define GPIO_SDPW_EN (3 * 32 + 2)
6.32 -#define GPIO_SD_DETECT (3 * 32 + 0)
6.33 +#define GPIO_SDPW_EN (3 * 32 + 2)
6.34 +#define GPIO_SD_DETECT (3 * 32 + 0)
6.35
6.36 -#define GPIO_BUZZ_PWM (3 * 32 + 27)
6.37 -#define GPIO_USB_DETECT (3 * 32 + 28)
6.38 +#define GPIO_BUZZ_PWM (3 * 32 + 27)
6.39 +#define GPIO_USB_DETECT (3 * 32 + 28)
6.40
6.41 -#define GPIO_AUDIO_POP (1 * 32 + 29)
6.42 -#define GPIO_COB_TEST (1 * 32 + 30)
6.43 +#define GPIO_AUDIO_POP (1 * 32 + 29)
6.44 +#define GPIO_COB_TEST (1 * 32 + 30)
6.45
6.46 -#define GPIO_KEYOUT_BASE (2 * 32 + 10)
6.47 -#define GPIO_KEYIN_BASE (3 * 32 + 18)
6.48 -#define GPIO_KEYIN_8 (3 * 32 + 26)
6.49 +#define GPIO_KEYOUT_BASE (2 * 32 + 10)
6.50 +#define GPIO_KEYIN_BASE (3 * 32 + 18)
6.51 +#define GPIO_KEYIN_8 (3 * 32 + 26)
6.52
6.53 -#define GPIO_SD_CD_N GPIO_SD_DETECT /* SD Card insert detect */
6.54 -#define GPIO_SD_VCC_EN_N GPIO_SDPW_EN /* SD Card Power Enable */
6.55 +#define GPIO_SD_CD_N GPIO_SD_DETECT /* SD Card insert detect */
6.56 +#define GPIO_SD_VCC_EN_N GPIO_SDPW_EN /* SD Card Power Enable */
6.57
6.58 -#define GPIO_SD_CMD (3 * 32 + 8)
6.59 +#define GPIO_SD_CMD (3 * 32 + 8)
6.60
6.61 -#define SPEN GPIO_LCD_CS /* LCDCS :Serial command enable */
6.62 -#define SPDA (2 * 32 + 22) /* LCDSCL:Serial command clock input */
6.63 -#define SPCK (2 * 32 + 23) /* LCDSDA:Serial command data input */
6.64 +#define SPEN GPIO_LCD_CS /* LCDCS :Serial command enable */
6.65 +#define SPDA (2 * 32 + 22) /* LCDSCL:Serial command clock input */
6.66 +#define SPCK (2 * 32 + 23) /* LCDSDA:Serial command data input */
6.67 +
6.68 #endif /* __CONFIG_NANONOTE_H */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/nanonote_gpm940b0.c Sat Jun 06 23:29:51 2015 +0200
7.3 @@ -0,0 +1,415 @@
7.4 +/*
7.5 + * JzRISC lcd controller
7.6 + *
7.7 + * Xiangfu Liu <xiangfu@sharism.cc>
7.8 + *
7.9 + * This program is free software; you can redistribute it and/or
7.10 + * modify it under the terms of the GNU General Public License as
7.11 + * published by the Free Software Foundation; either version 2 of
7.12 + * the License, or (at your option) any later version.
7.13 + *
7.14 + * This program is distributed in the hope that it will be useful,
7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.17 + * GNU General Public License for more details.
7.18 + *
7.19 + * You should have received a copy of the GNU General Public License
7.20 + * along with this program; if not, write to the Free Software
7.21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
7.22 + * MA 02111-1307 USA
7.23 + */
7.24 +
7.25 +#include "lcd.h"
7.26 +
7.27 +/* virt_to_phys() from u-boot/arch/mips/include/asm/addrspace.h
7.28 + via u-boot/arch/mips/include/asm/io.h */
7.29 +#define virt_to_phys(n) (((int) n) & 0x1fffffff)
7.30 +
7.31 +#include "jz4740.h"
7.32 +#include "nanonote_gpm940b0.h"
7.33 +#include "board-nanonote.h"
7.34 +
7.35 +#define align2(n) (n)=((((n)+1)>>1)<<1)
7.36 +#define align4(n) (n)=((((n)+3)>>2)<<2)
7.37 +#define align8(n) (n)=((((n)+7)>>3)<<3)
7.38 +
7.39 +struct jzfb_info {
7.40 + unsigned int cfg; /* panel mode and pin usage etc. */
7.41 + unsigned int w;
7.42 + unsigned int h;
7.43 + unsigned int bpp; /* bit per pixel */
7.44 + unsigned int fclk; /* frame clk */
7.45 + unsigned int hsw; /* hsync width, in pclk */
7.46 + unsigned int vsw; /* vsync width, in line count */
7.47 + unsigned int elw; /* end of line, in pclk */
7.48 + unsigned int blw; /* begin of line, in pclk */
7.49 + unsigned int efw; /* end of frame, in line count */
7.50 + unsigned int bfw; /* begin of frame, in line count */
7.51 +};
7.52 +
7.53 +static struct jzfb_info jzfb = {
7.54 + MODE_8BIT_SERIAL_TFT | PCLK_N | HSYNC_N | VSYNC_N,
7.55 + 320, 240, 32, 70, 1, 1, 273, 140, 1, 20
7.56 +};
7.57 +
7.58 +vidinfo_t panel_info = {
7.59 + 320, 240, LCD_BPP,
7.60 +};
7.61 +
7.62 +int lcd_line_length;
7.63 +int lcd_color_fg;
7.64 +int lcd_color_bg;
7.65 +/*
7.66 + * Frame buffer memory information
7.67 + */
7.68 +void *lcd_base; /* Start of framebuffer memory */
7.69 +void *lcd_console_address; /* Start of console buffer */
7.70 +
7.71 +short console_col;
7.72 +short console_row;
7.73 +
7.74 +void lcd_ctrl_init (void *lcdbase);
7.75 +void lcd_enable (void);
7.76 +void lcd_disable (void);
7.77 +
7.78 +static int jz_lcd_init_mem(void *lcdbase, vidinfo_t *vid);
7.79 +static void jz_lcd_desc_init(vidinfo_t *vid);
7.80 +static int jz_lcd_hw_init(vidinfo_t *vid);
7.81 +/* extern int flush_cache_all(void); */
7.82 +
7.83 +void lcd_ctrl_init (void *lcdbase)
7.84 +{
7.85 + jz_lcd_init_mem(lcdbase, &panel_info);
7.86 + jz_lcd_desc_init(&panel_info);
7.87 + jz_lcd_hw_init(&panel_info);
7.88 +}
7.89 +
7.90 +/*
7.91 + * Before enabled lcd controller, lcd registers should be configured correctly.
7.92 + */
7.93 +void lcd_enable (void)
7.94 +{
7.95 + REG_LCD_CTRL &= ~(1<<4); /* LCDCTRL.DIS */
7.96 + REG_LCD_CTRL |= 1<<3; /* LCDCTRL.ENA*/
7.97 +}
7.98 +
7.99 +void lcd_disable (void)
7.100 +{
7.101 + REG_LCD_CTRL |= (1<<4); /* LCDCTRL.DIS, regular disable */
7.102 + /* REG_LCD_CTRL |= (1<<3); */ /* LCDCTRL.DIS, quikly disable */
7.103 +}
7.104 +
7.105 +static int jz_lcd_init_mem(void *lcdbase, vidinfo_t *vid)
7.106 +{
7.107 + unsigned long palette_mem_size;
7.108 + struct jz_fb_info *fbi = &vid->jz_fb;
7.109 + int fb_size = vid->vl_row * (vid->vl_col * NBITS (vid->vl_bpix)) / 8;
7.110 +
7.111 + fbi->screen = (unsigned long)lcdbase;
7.112 + fbi->palette_size = 256;
7.113 + palette_mem_size = fbi->palette_size * sizeof(u16);
7.114 +
7.115 + /* debug("jz_lcd.c palette_mem_size = 0x%08lx\n", (unsigned long) palette_mem_size); */
7.116 + /* locate palette and descs at end of page following fb */
7.117 + fbi->palette = (unsigned long)lcdbase + fb_size + PAGE_SIZE - palette_mem_size;
7.118 +
7.119 + return 0;
7.120 +}
7.121 +
7.122 +static void jz_lcd_desc_init(vidinfo_t *vid)
7.123 +{
7.124 + struct jz_fb_info * fbi;
7.125 + fbi = &vid->jz_fb;
7.126 + fbi->dmadesc_fblow = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 3*16);
7.127 + fbi->dmadesc_fbhigh = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 2*16);
7.128 + fbi->dmadesc_palette = (struct jz_fb_dma_descriptor *)((unsigned int)fbi->palette - 1*16);
7.129 +
7.130 + #define BYTES_PER_PANEL (vid->vl_col * vid->vl_row * NBITS(vid->vl_bpix) / 8)
7.131 +
7.132 + /* populate descriptors */
7.133 + fbi->dmadesc_fblow->fdadr = virt_to_phys(fbi->dmadesc_fblow);
7.134 + fbi->dmadesc_fblow->fsadr = virt_to_phys((void *)(fbi->screen + BYTES_PER_PANEL));
7.135 + fbi->dmadesc_fblow->fidr = 0;
7.136 + fbi->dmadesc_fblow->ldcmd = BYTES_PER_PANEL / 4 ;
7.137 +
7.138 + fbi->fdadr1 = virt_to_phys(fbi->dmadesc_fblow); /* only used in dual-panel mode */
7.139 +
7.140 + fbi->dmadesc_fbhigh->fsadr = virt_to_phys((void *)fbi->screen);
7.141 + fbi->dmadesc_fbhigh->fidr = 0;
7.142 + fbi->dmadesc_fbhigh->ldcmd = BYTES_PER_PANEL / 4; /* length in word */
7.143 +
7.144 + fbi->dmadesc_palette->fsadr = virt_to_phys((void *)fbi->palette);
7.145 + fbi->dmadesc_palette->fidr = 0;
7.146 + fbi->dmadesc_palette->ldcmd = (fbi->palette_size * 2)/4 | (1<<28);
7.147 +
7.148 + if(NBITS(vid->vl_bpix) < 12)
7.149 + {
7.150 + /* assume any mode with <12 bpp is palette driven */
7.151 + fbi->dmadesc_palette->fdadr = virt_to_phys(fbi->dmadesc_fbhigh);
7.152 + fbi->dmadesc_fbhigh->fdadr = virt_to_phys(fbi->dmadesc_palette);
7.153 + /* flips back and forth between pal and fbhigh */
7.154 + fbi->fdadr0 = virt_to_phys(fbi->dmadesc_palette);
7.155 + } else {
7.156 + /* palette shouldn't be loaded in true-color mode */
7.157 + fbi->dmadesc_fbhigh->fdadr = virt_to_phys((void *)fbi->dmadesc_fbhigh);
7.158 + fbi->fdadr0 = virt_to_phys(fbi->dmadesc_fbhigh); /* no pal just fbhigh */
7.159 + }
7.160 +
7.161 + flush_cache_all();
7.162 +}
7.163 +
7.164 +static int jz_lcd_hw_init(vidinfo_t *vid)
7.165 +{
7.166 + struct jz_fb_info *fbi = &vid->jz_fb;
7.167 + unsigned int val = 0;
7.168 + unsigned int pclk;
7.169 + unsigned int stnH;
7.170 + int pll_div;
7.171 +
7.172 + /* Setting Control register */
7.173 + switch (jzfb.bpp) {
7.174 + case 1:
7.175 + val |= LCD_CTRL_BPP_1;
7.176 + break;
7.177 + case 2:
7.178 + val |= LCD_CTRL_BPP_2;
7.179 + break;
7.180 + case 4:
7.181 + val |= LCD_CTRL_BPP_4;
7.182 + break;
7.183 + case 8:
7.184 + val |= LCD_CTRL_BPP_8;
7.185 + break;
7.186 + case 15:
7.187 + val |= LCD_CTRL_RGB555;
7.188 + case 16:
7.189 + val |= LCD_CTRL_BPP_16;
7.190 + break;
7.191 + case 17 ... 32:
7.192 + val |= LCD_CTRL_BPP_18_24; /* target is 4bytes/pixel */
7.193 + break;
7.194 +
7.195 + default:
7.196 + /* printf("jz_lcd.c The BPP %d is not supported\n", jzfb.bpp); */
7.197 + val |= LCD_CTRL_BPP_16;
7.198 + break;
7.199 + }
7.200 +
7.201 + switch (jzfb.cfg & MODE_MASK) {
7.202 + case MODE_STN_MONO_DUAL:
7.203 + case MODE_STN_COLOR_DUAL:
7.204 + case MODE_STN_MONO_SINGLE:
7.205 + case MODE_STN_COLOR_SINGLE:
7.206 + switch (jzfb.bpp) {
7.207 + case 1:
7.208 + /* val |= LCD_CTRL_PEDN; */
7.209 + case 2:
7.210 + val |= LCD_CTRL_FRC_2;
7.211 + break;
7.212 + case 4:
7.213 + val |= LCD_CTRL_FRC_4;
7.214 + break;
7.215 + case 8:
7.216 + default:
7.217 + val |= LCD_CTRL_FRC_16;
7.218 + break;
7.219 + }
7.220 + break;
7.221 + }
7.222 +
7.223 + val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */
7.224 + val |= LCD_CTRL_OFUP; /* OutFIFO underrun protect */
7.225 +
7.226 + switch (jzfb.cfg & MODE_MASK) {
7.227 + case MODE_STN_MONO_DUAL:
7.228 + case MODE_STN_COLOR_DUAL:
7.229 + case MODE_STN_MONO_SINGLE:
7.230 + case MODE_STN_COLOR_SINGLE:
7.231 + switch (jzfb.cfg & STN_DAT_PINMASK) {
7.232 + case STN_DAT_PIN1:
7.233 + /* Do not adjust the hori-param value. */
7.234 + break;
7.235 + case STN_DAT_PIN2:
7.236 + align2(jzfb.hsw);
7.237 + align2(jzfb.elw);
7.238 + align2(jzfb.blw);
7.239 + break;
7.240 + case STN_DAT_PIN4:
7.241 + align4(jzfb.hsw);
7.242 + align4(jzfb.elw);
7.243 + align4(jzfb.blw);
7.244 + break;
7.245 + case STN_DAT_PIN8:
7.246 + align8(jzfb.hsw);
7.247 + align8(jzfb.elw);
7.248 + align8(jzfb.blw);
7.249 + break;
7.250 + }
7.251 + break;
7.252 + }
7.253 +
7.254 + REG_LCD_CTRL = val;
7.255 +
7.256 + switch (jzfb.cfg & MODE_MASK) {
7.257 + case MODE_STN_MONO_DUAL:
7.258 + case MODE_STN_COLOR_DUAL:
7.259 + case MODE_STN_MONO_SINGLE:
7.260 + case MODE_STN_COLOR_SINGLE:
7.261 + if (((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) ||
7.262 + ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL))
7.263 + stnH = jzfb.h >> 1;
7.264 + else
7.265 + stnH = jzfb.h;
7.266 +
7.267 + REG_LCD_VSYNC = (0 << 16) | jzfb.vsw;
7.268 + REG_LCD_HSYNC = ((jzfb.blw+jzfb.w) << 16) | (jzfb.blw+jzfb.w+jzfb.hsw);
7.269 +
7.270 + /* Screen setting */
7.271 + REG_LCD_VAT = ((jzfb.blw + jzfb.w + jzfb.hsw + jzfb.elw) << 16) | (stnH + jzfb.vsw + jzfb.bfw + jzfb.efw);
7.272 + REG_LCD_DAH = (jzfb.blw << 16) | (jzfb.blw + jzfb.w);
7.273 + REG_LCD_DAV = (0 << 16) | (stnH);
7.274 +
7.275 + /* AC BIAs signal */
7.276 + REG_LCD_PS = (0 << 16) | (stnH+jzfb.vsw+jzfb.efw+jzfb.bfw);
7.277 +
7.278 + break;
7.279 +
7.280 + case MODE_TFT_GEN:
7.281 + case MODE_TFT_SHARP:
7.282 + case MODE_TFT_CASIO:
7.283 + case MODE_TFT_SAMSUNG:
7.284 + case MODE_8BIT_SERIAL_TFT:
7.285 + case MODE_TFT_18BIT:
7.286 + REG_LCD_VSYNC = (0 << 16) | jzfb.vsw;
7.287 + REG_LCD_HSYNC = (0 << 16) | jzfb.hsw;
7.288 + REG_LCD_DAV =((jzfb.vsw+jzfb.bfw) << 16) | (jzfb.vsw +jzfb.bfw+jzfb.h);
7.289 + REG_LCD_DAH = ((jzfb.hsw + jzfb.blw) << 16) | (jzfb.hsw + jzfb.blw + jzfb.w );
7.290 + REG_LCD_VAT = (((jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw)) << 16) \
7.291 + | (jzfb.vsw + jzfb.bfw + jzfb.h + jzfb.efw);
7.292 + break;
7.293 + }
7.294 +
7.295 + switch (jzfb.cfg & MODE_MASK) {
7.296 + case MODE_TFT_SAMSUNG:
7.297 + {
7.298 + unsigned int total, tp_s, tp_e, ckv_s, ckv_e;
7.299 + unsigned int rev_s, rev_e, inv_s, inv_e;
7.300 +
7.301 + pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) *
7.302 + (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */
7.303 +
7.304 + total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;
7.305 + tp_s = jzfb.blw + jzfb.w + 1;
7.306 + tp_e = tp_s + 1;
7.307 + /* ckv_s = tp_s - jz_clocks.pixclk/(1000000000/4100); */
7.308 + ckv_s = tp_s - pclk/(1000000000/4100);
7.309 + ckv_e = tp_s + total;
7.310 + rev_s = tp_s - 11; /* -11.5 clk */
7.311 + rev_e = rev_s + total;
7.312 + inv_s = tp_s;
7.313 + inv_e = inv_s + total;
7.314 + REG_LCD_CLS = (tp_s << 16) | tp_e;
7.315 + REG_LCD_PS = (ckv_s << 16) | ckv_e;
7.316 + REG_LCD_SPL = (rev_s << 16) | rev_e;
7.317 + REG_LCD_REV = (inv_s << 16) | inv_e;
7.318 + jzfb.cfg |= STFT_REVHI | STFT_SPLHI;
7.319 + break;
7.320 + }
7.321 + case MODE_TFT_SHARP:
7.322 + {
7.323 + unsigned int total, cls_s, cls_e, ps_s, ps_e;
7.324 + unsigned int spl_s, spl_e, rev_s, rev_e;
7.325 + total = jzfb.blw + jzfb.w + jzfb.elw + jzfb.hsw;
7.326 + spl_s = 1;
7.327 + spl_e = spl_s + 1;
7.328 + cls_s = 0;
7.329 + cls_e = total - 60; /* > 4us (pclk = 80ns) */
7.330 + ps_s = cls_s;
7.331 + ps_e = cls_e;
7.332 + rev_s = total - 40; /* > 3us (pclk = 80ns) */
7.333 + rev_e = rev_s + total;
7.334 + jzfb.cfg |= STFT_PSHI;
7.335 + REG_LCD_SPL = (spl_s << 16) | spl_e;
7.336 + REG_LCD_CLS = (cls_s << 16) | cls_e;
7.337 + REG_LCD_PS = (ps_s << 16) | ps_e;
7.338 + REG_LCD_REV = (rev_s << 16) | rev_e;
7.339 + break;
7.340 + }
7.341 + case MODE_TFT_CASIO:
7.342 + break;
7.343 + }
7.344 +
7.345 + /* Configure the LCD panel */
7.346 + REG_LCD_CFG = jzfb.cfg;
7.347 +
7.348 + /* Timing setting */
7.349 + __cpm_stop_lcd();
7.350 +
7.351 + val = jzfb.fclk; /* frame clk */
7.352 + if ( (jzfb.cfg & MODE_MASK) != MODE_8BIT_SERIAL_TFT) {
7.353 + pclk = val * (jzfb.w + jzfb.hsw + jzfb.elw + jzfb.blw) *
7.354 + (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */
7.355 + } else {
7.356 + /* serial mode: Hsync period = 3*Width_Pixel */
7.357 + pclk = val * (jzfb.w*3 + jzfb.hsw + jzfb.elw + jzfb.blw) *
7.358 + (jzfb.h + jzfb.vsw + jzfb.efw + jzfb.bfw); /* Pixclk */
7.359 + }
7.360 +
7.361 + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||
7.362 + ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL))
7.363 + pclk = (pclk * 3);
7.364 +
7.365 + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_SINGLE) ||
7.366 + ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
7.367 + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_SINGLE) ||
7.368 + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
7.369 + pclk = pclk >> ((jzfb.cfg & STN_DAT_PINMASK) >> 4);
7.370 +
7.371 + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
7.372 + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
7.373 + pclk >>= 1;
7.374 +
7.375 + pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source,0:pllout/2 1: pllout */
7.376 + pll_div = pll_div ? 1 : 2 ;
7.377 + val = ( __cpm_get_pllout()/pll_div ) / pclk;
7.378 + val--;
7.379 + if ( val > 0x1ff ) {
7.380 + /* printf("CPM_LPCDR too large, set it to 0x1ff\n"); */
7.381 + val = 0x1ff;
7.382 + }
7.383 + __cpm_set_pixdiv(val);
7.384 +
7.385 + val = pclk * 3 ; /* LCDClock > 2.5*Pixclock */
7.386 + if ( val > 150000000 ) {
7.387 + /* printf("Warning: LCDClock=%d\n, LCDClock must less or equal to 150MHz.\n", val); */
7.388 + /* printf("Change LCDClock to 150MHz\n"); */
7.389 + val = 150000000;
7.390 + }
7.391 + val = ( __cpm_get_pllout()/pll_div ) / val;
7.392 + val--;
7.393 + if ( val > 0x1f ) {
7.394 + /* printf("CPM_CPCCR.LDIV too large, set it to 0x1f\n"); */
7.395 + val = 0x1f;
7.396 + }
7.397 + __cpm_set_ldiv( val );
7.398 + REG_CPM_CPCCR |= CPM_CPCCR_CE ; /* update divide */
7.399 +
7.400 + __cpm_start_lcd();
7.401 + udelay(1000);
7.402 +
7.403 + REG_LCD_DA0 = fbi->fdadr0; /* frame descripter*/
7.404 +
7.405 + if (((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ||
7.406 + ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL))
7.407 + REG_LCD_DA1 = fbi->fdadr1; /* frame descripter*/
7.408 +
7.409 + return 0;
7.410 +}
7.411 +
7.412 +void lcd_setcolreg (unsigned short regno, unsigned short red, unsigned short green, unsigned short blue)
7.413 +{
7.414 +}
7.415 +
7.416 +void lcd_initcolregs (void)
7.417 +{
7.418 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/nanonote_gpm940b0.h Sat Jun 06 23:29:51 2015 +0200
8.3 @@ -0,0 +1,135 @@
8.4 +/*
8.5 + * JzRISC lcd controller
8.6 + *
8.7 + * Xiangfu Liu <xiangfu@sharism.cc>
8.8 + *
8.9 + * This program is free software; you can redistribute it and/or
8.10 + * modify it under the terms of the GNU General Public License as
8.11 + * published by the Free Software Foundation; either version 2 of
8.12 + * the License, or (at your option) any later version.
8.13 + *
8.14 + * This program is distributed in the hope that it will be useful,
8.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.17 + * GNU General Public License for more details.
8.18 + *
8.19 + * You should have received a copy of the GNU General Public License
8.20 + * along with this program; if not, write to the Free Software
8.21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
8.22 + * MA 02111-1307 USA
8.23 + */
8.24 +
8.25 +#ifndef __QI_LB60_GPM940B0_H__
8.26 +#define __QI_LB60_GPM940B0_H__
8.27 +
8.28 +struct lcd_desc{
8.29 + unsigned int next_desc; /* LCDDAx */
8.30 + unsigned int databuf; /* LCDSAx */
8.31 + unsigned int frame_id; /* LCDFIDx */
8.32 + unsigned int cmd; /* LCDCMDx */
8.33 +};
8.34 +
8.35 +#define MODE_MASK 0x0f
8.36 +#define MODE_TFT_GEN 0x00
8.37 +#define MODE_TFT_SHARP 0x01
8.38 +#define MODE_TFT_CASIO 0x02
8.39 +#define MODE_TFT_SAMSUNG 0x03
8.40 +#define MODE_CCIR656_NONINT 0x04
8.41 +#define MODE_CCIR656_INT 0x05
8.42 +#define MODE_STN_COLOR_SINGLE 0x08
8.43 +#define MODE_STN_MONO_SINGLE 0x09
8.44 +#define MODE_STN_COLOR_DUAL 0x0a
8.45 +#define MODE_STN_MONO_DUAL 0x0b
8.46 +#define MODE_8BIT_SERIAL_TFT 0x0c
8.47 +
8.48 +#define MODE_TFT_18BIT (1<<7)
8.49 +
8.50 +#define STN_DAT_PIN1 (0x00 << 4)
8.51 +#define STN_DAT_PIN2 (0x01 << 4)
8.52 +#define STN_DAT_PIN4 (0x02 << 4)
8.53 +#define STN_DAT_PIN8 (0x03 << 4)
8.54 +#define STN_DAT_PINMASK STN_DAT_PIN8
8.55 +
8.56 +#define STFT_PSHI (1 << 15)
8.57 +#define STFT_CLSHI (1 << 14)
8.58 +#define STFT_SPLHI (1 << 13)
8.59 +#define STFT_REVHI (1 << 12)
8.60 +
8.61 +#define SYNC_MASTER (0 << 16)
8.62 +#define SYNC_SLAVE (1 << 16)
8.63 +
8.64 +#define DE_P (0 << 9)
8.65 +#define DE_N (1 << 9)
8.66 +
8.67 +#define PCLK_P (0 << 10)
8.68 +#define PCLK_N (1 << 10)
8.69 +
8.70 +#define HSYNC_P (0 << 11)
8.71 +#define HSYNC_N (1 << 11)
8.72 +
8.73 +#define VSYNC_P (0 << 8)
8.74 +#define VSYNC_N (1 << 8)
8.75 +
8.76 +#define DATA_NORMAL (0 << 17)
8.77 +#define DATA_INVERSE (1 << 17)
8.78 +
8.79 +
8.80 +/* Jz LCDFB supported I/O controls. */
8.81 +#define FBIOSETBACKLIGHT 0x4688
8.82 +#define FBIODISPON 0x4689
8.83 +#define FBIODISPOFF 0x468a
8.84 +#define FBIORESET 0x468b
8.85 +#define FBIOPRINT_REG 0x468c
8.86 +
8.87 +/*
8.88 + * LCD panel specific definition
8.89 + */
8.90 +#define MODE (0xc9) /* 8bit serial RGB */
8.91 +
8.92 +#define __spi_write_reg1(reg, val) \
8.93 +do { \
8.94 + unsigned char no; \
8.95 + unsigned short value; \
8.96 + unsigned char a=reg; \
8.97 + unsigned char b=val; \
8.98 + __gpio_set_pin(SPEN); \
8.99 + __gpio_set_pin(SPCK); \
8.100 + __gpio_clear_pin(SPDA); \
8.101 + __gpio_clear_pin(SPEN); \
8.102 + value=((a<<8)|(b&0xFF)); \
8.103 + for(no=0;no<16;no++) \
8.104 + { \
8.105 + __gpio_clear_pin(SPCK); \
8.106 + if((value&0x8000)==0x8000) \
8.107 + __gpio_set_pin(SPDA); \
8.108 + else \
8.109 + __gpio_clear_pin(SPDA); \
8.110 + __gpio_set_pin(SPCK); \
8.111 + value=(value<<1); \
8.112 + } \
8.113 + __gpio_set_pin(SPEN); \
8.114 +} while (0)
8.115 +
8.116 +#define __lcd_display_pin_init() \
8.117 +do { \
8.118 + __cpm_start_tcu(); \
8.119 + __gpio_as_output(SPEN); /* use SPDA */ \
8.120 + __gpio_as_output(SPCK); /* use SPCK */ \
8.121 + __gpio_as_output(SPDA); /* use SPDA */ \
8.122 +} while (0)
8.123 +
8.124 +#define __lcd_display_on() \
8.125 +do { \
8.126 + __spi_write_reg1(0x05, 0x1e); \
8.127 + __spi_write_reg1(0x05, 0x5e); \
8.128 + __spi_write_reg1(0x07, 0x8d); \
8.129 + __spi_write_reg1(0x13, 0x01); \
8.130 + __spi_write_reg1(0x05, 0x5f); \
8.131 +} while (0)
8.132 +
8.133 +#define __lcd_display_off() \
8.134 +do { \
8.135 + __spi_write_reg1(0x05, 0x5e); \
8.136 +} while (0)
8.137 +
8.138 +#endif /* __QI_LB60_GPM940B0_H__ */
9.1 --- a/stage2.c Sat Jun 06 18:03:55 2015 +0200
9.2 +++ b/stage2.c Sat Jun 06 23:29:51 2015 +0200
9.3 @@ -41,6 +41,8 @@
9.4
9.5 void c_main(void)
9.6 {
9.7 - __gpio_as_output(GPIO_SD_CMD);
9.8 - __gpio_set_pin(GPIO_SD_CMD);
9.9 + gpio_init2();
9.10 + cpm_init();
9.11 + rtc_init();
9.12 + timer_init();
9.13 }