summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxiaobo gu <xiaobo.gu@amlogic.com>2019-04-02 19:42:18 +0800
committerDongjin Kim <tobetter@gmail.com>2019-05-16 13:21:14 +0900
commit29e150af16b1499c997a19d6fe47ca15af5226a6 (patch)
treec898fe9554f0741d75a7ae528444c36eff337dc5
parent8bb65b9be4b5d1564528629c10bde86949e37951 (diff)
downloadu-boot-odroid-c1-29e150af16b1499c997a19d6fe47ca15af5226a6.tar.gz
tm2: add ab301 config [1/1]
PD#SWPL-6678 Problem: new board ab301 need add config Solution: add new config ab301 Verify: test pass on ab301 Change-Id: Ifcd2b0933fa3bd8861c32f0ae216b1573112538d Signed-off-by: xiaobo gu <xiaobo.gu@amlogic.com>
-rw-r--r--board/amlogic/Kconfig8
-rw-r--r--board/amlogic/configs/tm2_ab301_v1.h666
-rw-r--r--board/amlogic/defconfigs/tm2_ab301_v1_defconfig7
-rw-r--r--board/amlogic/tm2_ab301_v1/Kconfig28
-rw-r--r--board/amlogic/tm2_ab301_v1/Makefile10
-rw-r--r--board/amlogic/tm2_ab301_v1/aml-user-key.sigbin0 -> 6976 bytes
-rw-r--r--board/amlogic/tm2_ab301_v1/eth_setup.c50
-rw-r--r--board/amlogic/tm2_ab301_v1/firmware/ramdump.c45
-rw-r--r--board/amlogic/tm2_ab301_v1/firmware/ramdump.h75
-rw-r--r--board/amlogic/tm2_ab301_v1/firmware/scp_task/pwm_ctrl.h39
-rw-r--r--board/amlogic/tm2_ab301_v1/firmware/scp_task/pwr_ctrl.c224
-rw-r--r--board/amlogic/tm2_ab301_v1/firmware/timing.c650
-rw-r--r--board/amlogic/tm2_ab301_v1/lcd.c615
-rw-r--r--board/amlogic/tm2_ab301_v1/mtk-bt/LD_btmtk_usb.c1532
-rw-r--r--board/amlogic/tm2_ab301_v1/mtk-bt/LD_btmtk_usb.h127
-rw-r--r--board/amlogic/tm2_ab301_v1/mtk-bt/LD_usbbt.c448
-rw-r--r--board/amlogic/tm2_ab301_v1/mtk-bt/LD_usbbt.h129
-rw-r--r--board/amlogic/tm2_ab301_v1/mtk-bt/cmd_btmtk.c40
-rw-r--r--board/amlogic/tm2_ab301_v1/mtk-bt/errno.h131
-rw-r--r--board/amlogic/tm2_ab301_v1/mtk-bt/fs_platform.c141
-rw-r--r--board/amlogic/tm2_ab301_v1/tm2_ab301_v1.c798
21 files changed, 5763 insertions, 0 deletions
diff --git a/board/amlogic/Kconfig b/board/amlogic/Kconfig
index c790e370a6..7536e54b30 100644
--- a/board/amlogic/Kconfig
+++ b/board/amlogic/Kconfig
@@ -236,6 +236,10 @@ config TM2_SKT_V1
bool "Support amlogic tm2 skt v1 board"
default n
+config TM2_AB301_V1
+ bool "Support amlogic tm2 ab301 v1 board"
+ default n
+
config PXP_EMULATOR
bool "Support pxp environment"
default n
@@ -499,6 +503,10 @@ if TM2_SKT_V1
source "board/amlogic/tm2_skt_v1/Kconfig"
endif
+if TM2_AB301_V1
+source "board/amlogic/tm2_ab301_v1/Kconfig"
+endif
+
if ODROID_C2
source "board/hardkernel/odroidc2/Kconfig"
endif
diff --git a/board/amlogic/configs/tm2_ab301_v1.h b/board/amlogic/configs/tm2_ab301_v1.h
new file mode 100644
index 0000000000..d7370b4d30
--- /dev/null
+++ b/board/amlogic/configs/tm2_ab301_v1.h
@@ -0,0 +1,666 @@
+/*
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __BOARD_H__
+#define __BOARD_H__
+
+#include <asm/arch/cpu.h>
+
+#define CONFIG_SYS_GENERIC_BOARD 1
+#ifndef CONFIG_AML_MESON
+#warning "include warning"
+#endif
+
+/*
+ * platform power init config
+ */
+#define CONFIG_PLATFORM_POWER_INIT
+#define CONFIG_VCCK_INIT_VOLTAGE 800 // VCCK power up voltage
+#define CONFIG_VDDEE_INIT_VOLTAGE 800 // VDDEE power up voltage
+#define CONFIG_VDDEE_SLEEP_VOLTAGE 731 // VDDEE suspend voltage
+
+/* configs for CEC */
+#define CONFIG_CEC_OSD_NAME "AML_TV"
+#define CONFIG_CEC_WAKEUP
+/*if use bt-wakeup,open it*/
+#define CONFIG_BT_WAKEUP
+/*if use wifi-wakeup,open it*/
+//#define CONFIG_WIFI_WAKEUP
+/* SMP Definitinos */
+#define CPU_RELEASE_ADDR secondary_boot_func
+
+/* config saradc*/
+#define CONFIG_CMD_SARADC 1
+#define CONFIG_SARADC_CH 2
+
+/* Bootloader Control Block function
+ That is used for recovery and the bootloader to talk to each other
+ */
+#define CONFIG_BOOTLOADER_CONTROL_BLOCK
+
+/*a/b update */
+#define CONFIG_CMD_BOOTCTOL_AVB
+
+/* Serial config */
+#define CONFIG_CONS_INDEX 2
+#define CONFIG_BAUDRATE 115200
+#define CONFIG_AML_MESON_SERIAL 1
+#define CONFIG_SERIAL_MULTI 1
+
+//Enable ir remote wake up for bl30
+#define CONFIG_IR_REMOTE_POWER_UP_KEY_VAL1 0xef10fe01 //amlogic tv ir --- power
+#define CONFIG_IR_REMOTE_POWER_UP_KEY_VAL2 0XBB44FB04 //amlogic tv ir --- ch+
+#define CONFIG_IR_REMOTE_POWER_UP_KEY_VAL3 0xF20DFE01 //amlogic tv ir --- ch-
+#define CONFIG_IR_REMOTE_POWER_UP_KEY_VAL4 0XBA45BD02 //amlogic small ir--- power
+#define CONFIG_IR_REMOTE_POWER_UP_KEY_VAL5 0xe51afb04
+#define CONFIG_IR_REMOTE_POWER_UP_KEY_VAL6 0xFFFFFFFF
+#define CONFIG_IR_REMOTE_POWER_UP_KEY_VAL7 0xFFFFFFFF
+#define CONFIG_IR_REMOTE_POWER_UP_KEY_VAL8 0xFFFFFFFF
+#define CONFIG_IR_REMOTE_POWER_UP_KEY_VAL9 0xFFFFFFFF
+
+/*config the default parameters for adc power key*/
+#define CONFIG_ADC_POWER_KEY_CHAN 2 /*channel range: 0-7*/
+#define CONFIG_ADC_POWER_KEY_VAL 0 /*sample value range: 0-1023*/
+
+/* args/envs */
+#define CONFIG_SYS_MAXARGS 64
+#define CONFIG_EXTRA_ENV_SETTINGS \
+ "firstboot=1\0"\
+ "upgrade_step=0\0"\
+ "jtag=disable\0"\
+ "loadaddr=1080000\0"\
+ "model_name=FHD\0" \
+ "panel_type=lvds_1\0" \
+ "outputmode=1080p60hz\0" \
+ "hdmimode=1080p60hz\0" \
+ "cvbsmode=576cvbs\0" \
+ "display_width=1920\0" \
+ "display_height=1080\0" \
+ "display_bpp=16\0" \
+ "display_color_index=16\0" \
+ "display_layer=osd0\0" \
+ "display_color_fg=0xffff\0" \
+ "display_color_bg=0\0" \
+ "dtb_mem_addr=0x1000000\0" \
+ "fb_addr=0x3d800000\0" \
+ "fb_width=1920\0" \
+ "fb_height=1080\0" \
+ "frac_rate_policy=1\0" \
+ "usb_burning=update 1000\0" \
+ "fdt_high=0x20000000\0"\
+ "try_auto_burn=update 700 750;\0"\
+ "sdcburncfg=aml_sdc_burn.ini\0"\
+ "sdc_burning=sdc_burn ${sdcburncfg}\0"\
+ "wipe_data=successful\0"\
+ "wipe_cache=successful\0"\
+ "EnableSelinux=enforcing\0" \
+ "recovery_part=recovery\0"\
+ "recovery_offset=0\0"\
+ "cvbs_drv=0\0"\
+ "lock=10001000\0"\
+ "osd_reverse=0\0"\
+ "video_reverse=0\0"\
+ "active_slot=normal\0"\
+ "boot_part=boot\0"\
+ "powermode=standby\0"\
+ "Irq_check_en=0\0"\
+ "fs_type=""rootfstype=ramfs""\0"\
+ "initargs="\
+ "init=/init console=ttyS0,115200 no_console_suspend earlycon=aml-uart,0xff803000 printk.devkmsg=on ramoops.pstore_en=1 ramoops.record_size=0x8000 ramoops.console_size=0x4000 "\
+ "\0"\
+ "upgrade_check="\
+ "echo upgrade_step=${upgrade_step}; "\
+ "if itest ${upgrade_step} == 3; then "\
+ "run init_display; run storeargs; run update;"\
+ "else fi;"\
+ "\0"\
+ "storeargs="\
+ "setenv bootargs ${initargs} ${fs_type} logo=${display_layer},loaded,${fb_addr} powermode=${powermode} vout=${outputmode},enable panel_type=${panel_type} hdmimode=${hdmimode} cvbsmode=${cvbsmode} osd_reverse=${osd_reverse} video_reverse=${video_reverse} androidboot.selinux=${EnableSelinux} androidboot.firstboot=${firstboot} jtag=${jtag}; "\
+ "setenv bootargs ${bootargs} androidboot.hardware=amlogic;"\
+ "run cmdline_keys;"\
+ "\0"\
+ "switch_bootmode="\
+ "get_rebootmode;"\
+ "if test ${reboot_mode} = factory_reset; then "\
+ "run recovery_from_flash;"\
+ "else if test ${reboot_mode} = update; then "\
+ "run update;"\
+ "else if test ${reboot_mode} = cold_boot; then "\
+ /*"run try_auto_burn;uboot wake up "*/\
+ /*"echo powermode=${powermode}; "\
+ "if test ${powermode} = standby; then "\
+ "setMtkBT;systemoff; "\
+ "else if test ${powermode} = on; then "\
+ "run try_auto_burn; "\
+ "fi; fi; "\*/\
+ "else if test ${reboot_mode} = fastboot; then "\
+ "fastboot;"\
+ "fi;fi;fi;fi;"\
+ "\0" \
+ "storeboot="\
+ "get_system_as_root_mode;"\
+ "echo system_mode: ${system_mode};"\
+ "if test ${system_mode} = 1; then "\
+ "setenv fs_type ""ro rootwait skip_initramfs"";"\
+ "run storeargs;"\
+ "fi;"\
+ "get_valid_slot;"\
+ "get_avb_mode;"\
+ "echo active_slot: ${active_slot} avb2: ${avb2};"\
+ "if test ${active_slot} != normal; then "\
+ "setenv bootargs ${bootargs} androidboot.slot_suffix=${active_slot};"\
+ "fi;"\
+ "if test ${avb2} = 0; then "\
+ "if test ${active_slot} = _a; then "\
+ "setenv bootargs ${bootargs} root=/dev/mmcblk0p23;"\
+ "else if test ${active_slot} = _b; then "\
+ "setenv bootargs ${bootargs} root=/dev/mmcblk0p24;"\
+ "fi;fi;"\
+ "fi;"\
+ "if imgread kernel ${boot_part} ${loadaddr}; then bootm ${loadaddr}; fi;"\
+ "run update;"\
+ "\0"\
+ "factory_reset_poweroff_protect="\
+ "echo wipe_data=${wipe_data}; echo wipe_cache=${wipe_cache};"\
+ "if test ${wipe_data} = failed; then "\
+ "run init_display; run storeargs;"\
+ "if mmcinfo; then "\
+ "run recovery_from_sdcard;"\
+ "fi;"\
+ "if usb start 0; then "\
+ "run recovery_from_udisk;"\
+ "fi;"\
+ "run recovery_from_flash;"\
+ "fi; "\
+ "if test ${wipe_cache} = failed; then "\
+ "run init_display; run storeargs;"\
+ "if mmcinfo; then "\
+ "run recovery_from_sdcard;"\
+ "fi;"\
+ "if usb start 0; then "\
+ "run recovery_from_udisk;"\
+ "fi;"\
+ "run recovery_from_flash;"\
+ "fi; \0" \
+ "update="\
+ /*first usb burning, second sdc_burn, third ext-sd autoscr/recovery, last udisk autoscr/recovery*/\
+ "run usb_burning; "\
+ "run sdc_burning; "\
+ "if mmcinfo; then "\
+ "run recovery_from_sdcard;"\
+ "fi;"\
+ "if usb start 0; then "\
+ "run recovery_from_udisk;"\
+ "fi;"\
+ "run recovery_from_flash;"\
+ "\0"\
+ "recovery_from_sdcard="\
+ "if fatload mmc 0 ${loadaddr} aml_autoscript; then autoscr ${loadaddr}; fi;"\
+ "if fatload mmc 0 ${loadaddr} recovery.img; then "\
+ "if fatload mmc 0 ${dtb_mem_addr} dtb.img; then echo sd dtb.img loaded; fi;"\
+ "wipeisb; "\
+ "bootm ${loadaddr};fi;"\
+ "\0"\
+ "recovery_from_udisk="\
+ "if fatload usb 0 ${loadaddr} aml_autoscript; then autoscr ${loadaddr}; fi;"\
+ "if fatload usb 0 ${loadaddr} recovery.img; then "\
+ "if fatload usb 0 ${dtb_mem_addr} dtb.img; then echo udisk dtb.img loaded; fi;"\
+ "wipeisb; "\
+ "bootm ${loadaddr};fi;"\
+ "\0"\
+ "recovery_from_flash="\
+ "get_valid_slot;"\
+ "echo active_slot: ${active_slot};"\
+ "if test ${active_slot} = normal; then "\
+ "setenv bootargs ${bootargs} aml_dt=${aml_dt} recovery_part={recovery_part} recovery_offset={recovery_offset};"\
+ "if itest ${upgrade_step} == 3; then "\
+ "if ext4load mmc 1:2 ${dtb_mem_addr} /recovery/dtb.img; then echo cache dtb.img loaded; fi;"\
+ "if ext4load mmc 1:2 ${loadaddr} /recovery/recovery.img; then echo cache recovery.img loaded; wipeisb; bootm ${loadaddr}; fi;"\
+ "else fi;"\
+ "if imgread kernel ${recovery_part} ${loadaddr} ${recovery_offset}; then wipeisb; bootm ${loadaddr}; fi;"\
+ "else "\
+ "setenv bootargs ${bootargs} aml_dt=${aml_dt} recovery_part=${boot_part} recovery_offset=${recovery_offset};"\
+ "if imgread kernel ${boot_part} ${loadaddr}; then bootm ${loadaddr}; fi;"\
+ "fi;"\
+ "\0"\
+ "init_display="\
+ "osd open;osd clear;imgread pic logo bootup $loadaddr;bmp display $bootup_offset;bmp scale;vout output ${outputmode}"\
+ "\0"\
+ "cmdline_keys="\
+ "if keyman init 0x1234; then "\
+ "if keyman read usid ${loadaddr} str; then "\
+ "setenv bootargs ${bootargs} androidboot.serialno=${usid};"\
+ "setenv serial ${usid};"\
+ "else "\
+ "setenv bootargs ${bootargs} androidboot.serialno=1234567890;"\
+ "setenv serial 1234567890;"\
+ "fi;"\
+ "if keyman read mac ${loadaddr} str; then "\
+ "setenv bootargs ${bootargs} mac=${mac} androidboot.mac=${mac};"\
+ "fi;"\
+ "if keyman read deviceid ${loadaddr} str; then "\
+ "setenv bootargs ${bootargs} androidboot.deviceid=${deviceid};"\
+ "fi;"\
+ "fi;"\
+ "\0"\
+ "bcb_cmd="\
+ "get_rebootmode;"\
+ "get_valid_slot;"\
+ "\0"\
+ "upgrade_key="\
+ "if gpio input GPIOAO_3; then "\
+ "echo detect upgrade key; run update;"\
+ "fi;"\
+ "\0"\
+ "irremote_update="\
+ "if irkey 2500000 0xe31cfb04 0xb748fb04; then "\
+ "echo read irkey ok!; " \
+ "if itest ${irkey_value} == 0xe31cfb04; then " \
+ "run update;" \
+ "else if itest ${irkey_value} == 0xb748fb04; then " \
+ "run update;\n" \
+ "fi;fi;" \
+ "fi;\0" \
+
+#define CONFIG_PREBOOT \
+ "mw ff638630 0 2;"\
+ "run bcb_cmd; "\
+ "run factory_reset_poweroff_protect;"\
+ "run upgrade_check;"\
+ "run init_display;"\
+ "run storeargs;"\
+ "bcb uboot-command;"\
+ "run switch_bootmode;"
+
+
+#define CONFIG_BOOTCOMMAND "run storeboot"
+
+//#define CONFIG_ENV_IS_NOWHERE 1
+#define CONFIG_ENV_SIZE (64*1024)
+#define CONFIG_FIT 1
+#define CONFIG_OF_LIBFDT 1
+#define CONFIG_ANDROID_BOOT_IMAGE 1
+#define CONFIG_ANDROID_IMG 1
+#define CONFIG_SYS_BOOTM_LEN (64<<20) /* Increase max gunzip size*/
+
+/* cpu */
+#define CONFIG_CPU_CLK 1200 //MHz. Range: 360-2000, should be multiple of 24
+
+/* ATTENTION */
+/* DDR configs move to board/amlogic/[board]/firmware/timing.c */
+
+#define CONFIG_NR_DRAM_BANKS 1
+/* ddr functions */
+#define CONFIG_DDR_FULL_TEST 0 //0:disable, 1:enable. ddr full test
+#define CONFIG_CMD_DDR_D2PLL 0 //0:disable, 1:enable. d2pll cmd
+#define CONFIG_CMD_DDR_TEST 0 //0:disable, 1:enable. ddrtest cmd
+#define CONFIG_DDR_LOW_POWER 0 //0:disable, 1:enable. ddr clk gate for lp
+#define CONFIG_DDR_ZQ_PD 0 //0:disable, 1:enable. ddr zq power down
+#define CONFIG_DDR_USE_EXT_VREF 0 //0:disable, 1:enable. ddr use external vref
+#define CONFIG_DDR4_TIMING_TEST 0 //0:disable, 1:enable. ddr4 timing test function
+#define CONFIG_DDR_PLL_BYPASS 0 //0:disable, 1:enable. ddr pll bypass function
+#define CONFIG_DDR_NONSEC_SCRAMBLE 0 //0:disable, 1:enable. non-sec region scramble function
+
+/* storage: emmc/nand/sd */
+#define CONFIG_STORE_COMPATIBLE 1
+#define CONFIG_ENV_OVERWRITE
+#define CONFIG_CMD_SAVEENV
+/* fixme, need fix*/
+
+#if (defined(CONFIG_ENV_IS_IN_AMLNAND) || defined(CONFIG_ENV_IS_IN_MMC)) && defined(CONFIG_STORE_COMPATIBLE)
+#error env in amlnand/mmc already be compatible;
+#endif
+
+/*
+* storage
+* |---------|---------|
+* | |
+* emmc<--Compatible-->nand
+* |-------|-------|
+* | |
+* MTD<-Exclusive->NFTL
+*/
+/* axg only support slc nand */
+/* swither for mtd nand which is for slc only. */
+/* support for mtd */
+//#define CONFIG_AML_MTD 1
+/* support for nftl */
+//#define CONFIG_AML_NAND 1
+
+#if defined(CONFIG_AML_NAND) && defined(CONFIG_AML_MTD)
+#error CONFIG_AML_NAND/CONFIG_AML_MTD can not support at the sametime;
+#endif
+
+#ifdef CONFIG_AML_MTD
+
+/* bootlaoder is construct by bl2 and fip
+ * when DISCRETE_BOOTLOADER is enabled, bl2 & fip
+ * will not be stored continuously, and nand layout
+ * would be bl2|rsv|fip|normal, but not
+ * bl2|fip|rsv|noraml anymore
+ */
+#define CONFIG_DISCRETE_BOOTLOADER
+
+#ifdef CONFIG_DISCRETE_BOOTLOADER
+#define CONFIG_TPL_SIZE_PER_COPY 0x200000
+#define CONFIG_TPL_COPY_NUM 4
+#define CONFIG_TPL_PART_NAME "tpl"
+/* for bl2, restricted by romboot */
+#define CONFIG_BL2_COPY_NUM 8
+#endif /* CONFIG_DISCRETE_BOOTLOADER */
+
+#define CONFIG_CMD_NAND 1
+#define CONFIG_MTD_DEVICE y
+/* mtd parts of ourown.*/
+#define CONFIFG_AML_MTDPART 1
+/* mtd parts by env default way.*/
+/*
+#define MTDIDS_NAME_STR "aml_nand.0"
+#define MTDIDS_DEFAULT "nand1=" MTDIDS_NAME_STR
+#define MTDPARTS_DEFAULT "mtdparts=" MTDIDS_NAME_STR ":" \
+ "3M@8192K(logo)," \
+ "10M(recovery)," \
+ "8M(kernel)," \
+ "40M(rootfs)," \
+ "-(data)"
+*/
+#define CONFIG_CMD_UBI
+#define CONFIG_CMD_UBIFS
+#define CONFIG_RBTREE
+#define CONFIG_CMD_NAND_TORTURE 1
+#define CONFIG_CMD_MTDPARTS 1
+#define CONFIG_MTD_PARTITIONS 1
+#define CONFIG_SYS_MAX_NAND_DEVICE 2
+#define CONFIG_SYS_NAND_BASE_LIST {0}
+#endif
+/* endof CONFIG_AML_MTD */
+#define CONFIG_AML_SD_EMMC 1
+#ifdef CONFIG_AML_SD_EMMC
+ #define CONFIG_GENERIC_MMC 1
+ #define CONFIG_CMD_MMC 1
+ #define CONFIG_CMD_GPT 1
+ #define CONFIG_SYS_MMC_ENV_DEV 1
+ #define CONFIG_EMMC_DDR52_EN 0
+ #define CONFIG_EMMC_DDR52_CLK 35000000
+#endif
+#define CONFIG_PARTITIONS 1
+#define CONFIG_SYS_NO_FLASH 1
+
+/* meson SPI */
+#define CONFIG_AML_SPIFC
+#define CONFIG_AML_SPICC
+#if defined CONFIG_AML_SPIFC || defined CONFIG_AML_SPICC
+ #define CONFIG_OF_SPI
+ #define CONFIG_DM_SPI
+ #define CONFIG_CMD_SPI
+#endif
+/* SPI flash config */
+#ifdef CONFIG_AML_SPIFC
+ #define CONFIG_SPI_FLASH
+ #define CONFIG_DM_SPI_FLASH
+ #define CONFIG_CMD_SF
+ /* SPI flash surpport list */
+ #define CONFIG_SPI_FLASH_ATMEL
+ #define CONFIG_SPI_FLASH_EON
+ #define CONFIG_SPI_FLASH_GIGADEVICE
+ #define CONFIG_SPI_FLASH_MACRONIX
+ #define CONFIG_SPI_FLASH_SPANSION
+ #define CONFIG_SPI_FLASH_STMICRO
+ #define CONFIG_SPI_FLASH_SST
+ #define CONFIG_SPI_FLASH_WINBOND
+ #define CONFIG_SPI_FRAM_RAMTRON
+ #define CONFIG_SPI_M95XXX
+ #define CONFIG_SPI_FLASH_ESMT
+ /* SPI nand flash support */
+ #define CONFIG_SPI_NAND
+ #define CONFIG_BL2_SIZE (64 * 1024)
+#endif
+
+#if defined CONFIG_AML_MTD || defined CONFIG_SPI_NAND
+ #define CONFIG_CMD_NAND 1
+ #define CONFIG_MTD_DEVICE y
+ #define CONFIG_RBTREE
+ #define CONFIG_CMD_NAND_TORTURE 1
+ #define CONFIG_CMD_MTDPARTS 1
+ #define CONFIG_MTD_PARTITIONS 1
+ #define CONFIG_SYS_MAX_NAND_DEVICE 2
+ #define CONFIG_SYS_NAND_BASE_LIST {0}
+#endif
+
+/* vpu */
+#define CONFIG_AML_VPU 1
+//#define CONFIG_VPU_CLK_LEVEL_DFT 7
+
+/* DISPLAY & HDMITX */
+//#define CONFIG_AML_HDMITX20 1
+#define CONFIG_AML_CANVAS 1
+#define CONFIG_AML_VOUT 1
+#define CONFIG_AML_OSD 1
+#define CONFIG_OSD_SCALE_ENABLE 1
+#define CONFIG_CMD_BMP 1
+
+#if defined(CONFIG_AML_VOUT)
+//#define CONFIG_AML_CVBS 1
+#endif
+
+#define CONFIG_AML_LCD 1
+#define CONFIG_AML_LCD_TABLET 1
+#define CONFIG_AML_LCD_TV 1
+//#define CONFIG_AML_LCD_EXTERN 1
+
+#define CONFIG_AML_LOCAL_DIMMING
+#define CONFIG_AML_LOCAL_DIMMING_GLOBAL
+
+/* USB
+ * Enable CONFIG_MUSB_HCD for Host functionalities MSC, keyboard
+ * Enable CONFIG_MUSB_UDD for Device functionalities.
+ */
+/* #define CONFIG_MUSB_UDC 1 */
+#define CONFIG_CMD_USB 1
+#if defined(CONFIG_CMD_USB)
+ #define CONFIG_GXL_XHCI_BASE 0xff500000
+ #define CONFIG_GXL_USB_PHY2_BASE 0xffe09000
+ #define CONFIG_GXL_USB_PHY3_BASE 0xffe09080
+ #define CONFIG_USB_PHY_20 0xff636000
+ #define CONFIG_USB_PHY_21 0xff63A000
+ #define CONFIG_USB_PHY_22 0xff658000
+ #define CONFIG_USB_STORAGE 1
+ #define CONFIG_USB_XHCI 1
+ #define CONFIG_USB_XHCI_AMLOGIC_V2 1
+ #define CONFIG_USB_GPIO_PWR GPIOEE(GPIOH_6)
+ #define CONFIG_USB_GPIO_PWR_NAME "GPIOH_6"
+ #define CONFIG_USB_AMLOGIC_PHY_V2 1
+ #define CONFIG_USB_U2_PORT_NUM 3
+ //#define CONFIG_RTK_USB_BT 1
+ //#define CONFIG_USB_XHCI_AMLOGIC_USB3_V2 1
+#endif //#if defined(CONFIG_CMD_USB)
+
+#define CONFIG_TXLX_USB 1
+#define CONFIG_USB_DEVICE_V2 1
+#define USB_PHY2_PLL_PARAMETER_1 0x09400414
+#define USB_PHY2_PLL_PARAMETER_2 0x927e0000
+#define USB_PHY2_PLL_PARAMETER_3 0xAC5F69E5
+
+//UBOOT fastboot config
+#define CONFIG_CMD_FASTBOOT 1
+#define CONFIG_FASTBOOT_FLASH_MMC_DEV 1
+#define CONFIG_FASTBOOT_FLASH 1
+#define CONFIG_USB_GADGET 1
+#define CONFIG_USBDOWNLOAD_GADGET 1
+#define CONFIG_SYS_CACHELINE_SIZE 64
+#define CONFIG_FASTBOOT_MAX_DOWN_SIZE 0x8000000
+#define CONFIG_DEVICE_PRODUCT "marconi"
+
+//UBOOT Facotry usb/sdcard burning config
+#define CONFIG_AML_V2_FACTORY_BURN 1 //support facotry usb burning
+#define CONFIG_AML_FACTORY_BURN_LOCAL_UPGRADE 1 //support factory sdcard burning
+#define CONFIG_POWER_KEY_NOT_SUPPORTED_FOR_BURN 1 //There isn't power-key for factory sdcard burning
+#define CONFIG_SD_BURNING_SUPPORT_UI 1 //Displaying upgrading progress bar when sdcard/udisk burning
+
+#define CONFIG_AML_SECURITY_KEY 1
+#define CONFIG_UNIFY_KEY_MANAGE 1
+
+/* net */
+#define CONFIG_CMD_NET 1
+#if defined(CONFIG_CMD_NET)
+ #define CONFIG_DESIGNWARE_ETH 1
+ #define CONFIG_PHYLIB 1
+ #define CONFIG_NET_MULTI 1
+ #define CONFIG_CMD_PING 1
+ #define CONFIG_CMD_DHCP 1
+ #define CONFIG_CMD_RARP 1
+ #define CONFIG_HOSTNAME arm_gxbb
+// #define CONFIG_RANDOM_ETHADDR 1 /* use random eth addr, or default */
+ #define CONFIG_ETHADDR 00:15:18:01:81:31 /* Ethernet address */
+ #define CONFIG_IPADDR 10.18.9.97 /* Our ip address */
+ #define CONFIG_GATEWAYIP 10.18.9.1 /* Our getway ip address */
+ #define CONFIG_SERVERIP 10.18.9.113 /* Tftp server ip address */
+ #define CONFIG_NETMASK 255.255.255.0
+#endif /* (CONFIG_CMD_NET) */
+
+/* other devices */
+/* I2C DM driver*/
+//#define CONFIG_DM_I2C
+
+#if defined(CONFIG_DM_I2C)
+#define CONFIG_SYS_I2C_MESON 1
+#else
+#define CONFIG_SYS_I2C_AML 1
+#define CONFIG_SYS_I2C_SPEED 400000
+#endif
+
+/* PWM DM driver*/
+#define CONFIG_DM_PWM
+#define CONFIG_PWM_MESON
+
+#define CONFIG_EFUSE 1
+
+/* commands */
+#define CONFIG_CMD_CACHE 1
+#define CONFIG_CMD_BOOTI 1
+#define CONFIG_CMD_EFUSE 1
+#define CONFIG_CMD_I2C 1
+#define CONFIG_CMD_MEMORY 1
+#define CONFIG_CMD_FAT 1
+#define CONFIG_CMD_GPIO 1
+#define CONFIG_CMD_RUN
+#define CONFIG_CMD_REBOOT 1
+#define CONFIG_CMD_ECHO 1
+#define CONFIG_CMD_JTAG 1
+#define CONFIG_CMD_AUTOSCRIPT 1
+#define CONFIG_CMD_MISC 1
+#define CONFIG_CMD_PLLTEST 1
+#define CONFIG_CMD_INI 1
+
+/*file system*/
+#define CONFIG_DOS_PARTITION 1
+#define CONFIG_EFI_PARTITION 1
+#define CONFIG_AML_PARTITION 1
+#define CONFIG_MMC 1
+#define CONFIG_FS_FAT 1
+#define CONFIG_FS_EXT4 1
+#define CONFIG_LZO 1
+
+#define CONFIG_MDUMP_COMPRESS 1
+#define CONFIG_EXT4_WRITE 1
+#define CONFIG_CMD_EXT4 1
+#define CONFIG_CMD_EXT4_WRITE 1
+
+/* Cache Definitions */
+//#define CONFIG_SYS_DCACHE_OFF
+//#define CONFIG_SYS_ICACHE_OFF
+
+/* other functions */
+#define CONFIG_NEED_BL301 1
+#define CONFIG_NEED_BL32 1
+#define CONFIG_CMD_RSVMEM 1
+#define CONFIG_FIP_IMG_SUPPORT 1
+#define CONFIG_BOOTDELAY 1 //delay 1s
+#define CONFIG_SYS_LONGHELP 1
+#define CONFIG_CMD_MISC 1
+#define CONFIG_CMD_ITEST 1
+#define CONFIG_CMD_CPU_TEMP 1
+#define CONFIG_SYS_MEM_TOP_HIDE 0x08000000 //hide 128MB for kernel reserve
+#define CONFIG_CMD_LOADB 1
+//#define CONFIG_MULTI_DTB 1
+
+/* debug mode defines */
+//#define CONFIG_DEBUG_MODE 1
+#ifdef CONFIG_DEBUG_MODE
+#define CONFIG_DDR_CLK_DEBUG 636
+#define CONFIG_CPU_CLK_DEBUG 600
+#endif
+
+//support secure boot
+#define CONFIG_AML_SECURE_UBOOT 1
+
+#if defined(CONFIG_AML_SECURE_UBOOT)
+
+//for SRAM size limitation just disable NAND
+//as the socket board default has no NAND
+//#undef CONFIG_AML_NAND
+
+//unify build for generate encrypted bootloader "u-boot.bin.encrypt"
+#define CONFIG_AML_CRYPTO_UBOOT 1
+
+//unify build for generate encrypted kernel image
+//SRC : "board/amlogic/(board)/boot.img"
+//DST : "fip/boot.img.encrypt"
+//#define CONFIG_AML_CRYPTO_IMG 1
+
+#endif //CONFIG_AML_SECURE_UBOOT
+
+#define CONFIG_SECURE_STORAGE 1
+
+/* USB port for MT7668. */
+#define BT_USB_PORT_NUM 1
+
+//build with uboot auto test
+//#define CONFIG_AML_UBOOT_AUTO_TEST 1
+
+//board customer ID
+//#define CONFIG_CUSTOMER_ID (0x6472616F624C4D41)
+
+#if defined(CONFIG_CUSTOMER_ID)
+ #undef CONFIG_AML_CUSTOMER_ID
+ #define CONFIG_AML_CUSTOMER_ID CONFIG_CUSTOMER_ID
+#endif
+
+/* Choose One of Ethernet Type */
+#undef CONFIG_ETHERNET_NONE
+#define ETHERNET_INTERNAL_PHY
+#undef ETHERNET_EXTERNAL_PHY
+
+#define CONFIG_CMD_AML_MTEST 1
+#if defined(CONFIG_CMD_AML_MTEST)
+#if !defined(CONFIG_SYS_MEM_TOP_HIDE)
+#error CONFIG_CMD_AML_MTEST depends on CONFIG_SYS_MEM_TOP_HIDE;
+#endif
+#if !(CONFIG_SYS_MEM_TOP_HIDE)
+#error CONFIG_SYS_MEM_TOP_HIDE should not be zero;
+#endif
+#endif
+
+//to support TLV which can support to transfer info from BL2 to BL3X
+//#define CONFIG_AML_SUPPORT_TLV
+
+//DDR address to contain info from BL2 to BL3X
+//#define AML_BL2_TMASTER_DDR_ADDR (0x3000000)
+
+#endif
+
diff --git a/board/amlogic/defconfigs/tm2_ab301_v1_defconfig b/board/amlogic/defconfigs/tm2_ab301_v1_defconfig
new file mode 100644
index 0000000000..71b59e989c
--- /dev/null
+++ b/board/amlogic/defconfigs/tm2_ab301_v1_defconfig
@@ -0,0 +1,7 @@
+CONFIG_ARM=y
+CONFIG_TARGET_MESON_TM2=y
+CONFIG_TM2_AB301_V1=y
+CONFIG_DM=y
+CONFIG_DM_GPIO=y
+CONFIG_AML_GPIO=y
+CONFIG_MTK_BT_USB=y
diff --git a/board/amlogic/tm2_ab301_v1/Kconfig b/board/amlogic/tm2_ab301_v1/Kconfig
new file mode 100644
index 0000000000..30c9338289
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/Kconfig
@@ -0,0 +1,28 @@
+if TARGET_MESON_TM2
+
+config SYS_CPU
+ string
+ default "armv8"
+
+config SYS_BOARD
+ string
+ default "tm2_ab301_v1"
+
+config SYS_VENDOR
+ string
+ default "amlogic"
+
+config SYS_SOC
+ string
+ default "tm2"
+
+config SYS_CONFIG_NAME
+ default "tm2_ab301_v1"
+
+config MTK_BT_USB
+ bool "enable mtk bt usb function"
+ default n
+ help
+ select this item will enable mtk bt usb device
+
+endif
diff --git a/board/amlogic/tm2_ab301_v1/Makefile b/board/amlogic/tm2_ab301_v1/Makefile
new file mode 100644
index 0000000000..9cd0dda96a
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/Makefile
@@ -0,0 +1,10 @@
+
+obj-y += $(BOARD).o eth_setup.o
+obj-$(CONFIG_AML_LCD) += lcd.o
+
+ifeq ($(CONFIG_MTK_BT_USB),y)
+obj-y += ./mtk-bt/LD_btmtk_usb.o
+obj-y += ./mtk-bt/LD_usbbt.o
+obj-y += ./mtk-bt/cmd_btmtk.o
+obj-y += ./mtk-bt/fs_platform.o
+endif \ No newline at end of file
diff --git a/board/amlogic/tm2_ab301_v1/aml-user-key.sig b/board/amlogic/tm2_ab301_v1/aml-user-key.sig
new file mode 100644
index 0000000000..2ceabc16e0
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/aml-user-key.sig
Binary files differ
diff --git a/board/amlogic/tm2_ab301_v1/eth_setup.c b/board/amlogic/tm2_ab301_v1/eth_setup.c
new file mode 100644
index 0000000000..33b5db15b9
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/eth_setup.c
@@ -0,0 +1,50 @@
+
+/*
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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 <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <environment.h>
+#include <fdt_support.h>
+#include <libfdt.h>
+#include <asm/arch/eth_setup.h>
+/*
+ *
+ *setup eth device board socket
+ *
+ */
+struct eth_board_socket* eth_board_setup(char *name){
+ struct eth_board_socket* new_board;
+ new_board= (struct eth_board_socket*) malloc(sizeof(struct eth_board_socket));
+ if (NULL == new_board) return NULL;
+ if (name != NULL) {
+ new_board->name=(char*)malloc(strlen(name));
+ strncpy(new_board->name,name,strlen(name));
+ }else{
+ new_board->name="gxb";
+ }
+
+ new_board->eth_pinmux_setup=NULL ;
+ new_board->eth_clock_configure=NULL;
+ new_board->eth_hw_reset=NULL;
+ return new_board;
+}
+//pinmux HHI_GCLK_MPEG1[bit 3]
+//
diff --git a/board/amlogic/tm2_ab301_v1/firmware/ramdump.c b/board/amlogic/tm2_ab301_v1/firmware/ramdump.c
new file mode 100644
index 0000000000..e03dcd299e
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/firmware/ramdump.c
@@ -0,0 +1,45 @@
+
+#ifdef CONFIG_MDUMP_COMPRESS
+#include "ramdump.h"
+
+struct ram_compress_full __ramdump_data = {
+ .store_phy_addr = (void *)CONFIG_COMPRESSED_DATA_ADDR,
+ .full_memsize = CONFIG_DDR_TOTAL_SIZE,
+ .section_count = CONFIG_COMPRESS_SECTION,
+ .sections = {
+ {
+ /* memory afer compressed data address */
+ .phy_addr = (void *)CONFIG_COMPRESSED_DATA_ADDR,
+ .section_size = CONFIG_DDR_TOTAL_SIZE -
+ CONFIG_COMPRESSED_DATA_ADDR,
+ .section_index = 4,
+ .compress_type = RAM_COMPRESS_NORMAL,
+ },
+ {
+ /* memory before bl2 */
+ .phy_addr = (void *)CONFIG_COMPRESS_START_ADDR,
+ .section_size = CONFIG_BL2_IGNORE_ADDR -
+ CONFIG_COMPRESS_START_ADDR,
+ .section_index = 1,
+ .compress_type = RAM_COMPRESS_NORMAL,
+ },
+ {
+ /* memory in reserved bl2 */
+ .phy_addr = (void *)CONFIG_BL2_IGNORE_ADDR,
+ .section_size = CONFIG_BL2_IGNORE_SIZE,
+ .section_index = 2,
+ .compress_type = RAM_COMPRESS_SET,
+ .set_value = 0x0,
+ },
+ {
+ /* segment 4: normal compress */
+ .phy_addr = (void *)CONFIG_SEG4_ADDR,
+ .section_size = CONFIG_COMPRESSED_DATA_ADDR -
+ CONFIG_SEG4_ADDR,
+ .section_index = 3,
+ .compress_type = RAM_COMPRESS_NORMAL,
+ }
+ },
+};
+#endif /* CONFIG_MDUMP_COMPRESS */
+
diff --git a/board/amlogic/tm2_ab301_v1/firmware/ramdump.h b/board/amlogic/tm2_ab301_v1/firmware/ramdump.h
new file mode 100644
index 0000000000..1abd5fff96
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/firmware/ramdump.h
@@ -0,0 +1,75 @@
+#ifndef __RAM_DUMP_H__
+#define __RAM_DUMP_H__
+
+#include <config.h>
+#ifdef CONFIG_MDUMP_COMPRESS
+#define CONFIG_COMPRESS_SECTION 4
+
+#if CONFIG_COMPRESS_SECTION > 8
+#error ---> CONFIG_COMPRESS_SECTION out of range, max should be 8
+#endif
+/*
+ * Full Memory lay out for RAM compress:
+ *
+ * DDR_TOP -> +--------+
+ * | |
+ * | |
+ * | 4 |
+ * | |
+ * | |
+ * |~~~~~~~~| <- store compressing data
+ * |~~~~~~~~|
+ * |~~~~~~~~|
+ * |~~~~~~~~|
+ * |~~~~~~~~|
+ * |~~~~~~~~|
+ * |~~~~~~~~|
+ * |~~~~~~~~|
+ * |~~~~~~~~|
+ * COMPRESSED_DATA -> +--------+
+ * | |
+ * | 3 |
+ * | |
+ * BL2_IGNORE_END -> +--------+ -- IGNORE_SIZE
+ * ||||||||||
+ * ||||2|||||
+ * ||||||||||
+ * BL2_IGNORE_ADDR -> +--------+
+ * | |
+ * | 1 |
+ * | |
+ * COMPRESS_START_ADDR -> +--------+
+ */
+#define CONFIG_DDR_TOTAL_SIZE (CONFIG_DDR_SIZE << 20)
+#define CONFIG_COMPRESSED_DATA_ADDR (0x08000000)
+#define CONFIG_COMPRESSED_DATA_ADDR1 (0x08000000)
+
+#define CONFIG_COMPRESS_START_ADDR (0x00000000)
+#define CONFIG_BL2_IGNORE_ADDR (0x05000000)
+#define CONFIG_BL2_IGNORE_SIZE (0x00300000)
+#define CONFIG_SEG4_ADDR (CONFIG_BL2_IGNORE_ADDR + \
+ CONFIG_BL2_IGNORE_SIZE)
+
+enum {
+ RAM_COMPRESS_NORMAL = 1,
+ RAM_COMPRESS_COPY = 2,
+ RAM_COMPRESS_SET = 3 /* set ram content to same vale */
+};
+
+struct ram_compress_section {
+ void *phy_addr;
+ unsigned int section_size;
+ unsigned int section_index : 8;
+ unsigned int compress_type : 8;
+ unsigned int set_value : 16;
+};
+
+struct ram_compress_full {
+ void *store_phy_addr;
+ unsigned int full_memsize;
+ unsigned int section_count;
+ struct ram_compress_section sections[CONFIG_COMPRESS_SECTION];
+};
+
+#endif
+#endif /* __RAM_DUMP_H__ */
diff --git a/board/amlogic/tm2_ab301_v1/firmware/scp_task/pwm_ctrl.h b/board/amlogic/tm2_ab301_v1/firmware/scp_task/pwm_ctrl.h
new file mode 100644
index 0000000000..ba015539c7
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/firmware/scp_task/pwm_ctrl.h
@@ -0,0 +1,39 @@
+/*
+*table for Dynamic Voltage/Frequency Scaling
+*/
+#ifndef __PWM_CTRL_H__
+#define __PWM_CTRL_H__
+
+static int pwm_voltage_table_ee[][2] = {
+ { 0x1c0000, 681},
+ { 0x1b0001, 691},
+ { 0x1a0002, 701},
+ { 0x190003, 711},
+ { 0x180004, 721},
+ { 0x170005, 731},
+ { 0x160006, 741},
+ { 0x150007, 751},
+ { 0x140008, 761},
+ { 0x130009, 772},
+ { 0x12000a, 782},
+ { 0x11000b, 792},
+ { 0x10000c, 802},
+ { 0x0f000d, 812},
+ { 0x0e000e, 822},
+ { 0x0d000f, 832},
+ { 0x0c0010, 842},
+ { 0x0b0011, 852},
+ { 0x0a0012, 862},
+ { 0x090013, 872},
+ { 0x080014, 882},
+ { 0x070015, 892},
+ { 0x060016, 902},
+ { 0x050017, 912},
+ { 0x040018, 922},
+ { 0x030019, 932},
+ { 0x02001a, 942},
+ { 0x01001b, 952},
+ { 0x00001c, 962}
+};
+
+#endif //__PWM_CTRL_H__
diff --git a/board/amlogic/tm2_ab301_v1/firmware/scp_task/pwr_ctrl.c b/board/amlogic/tm2_ab301_v1/firmware/scp_task/pwr_ctrl.c
new file mode 100644
index 0000000000..0a1b98d53b
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/firmware/scp_task/pwr_ctrl.c
@@ -0,0 +1,224 @@
+
+/*
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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 <gpio.h>
+#include "pwm_ctrl.h"
+#ifdef CONFIG_CEC_WAKEUP
+#include <cec_tx_reg.h>
+#endif
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+static void set_vddee_voltage(unsigned int target_voltage)
+{
+ unsigned int to;
+
+ for (to = 0; to < ARRAY_SIZE(pwm_voltage_table_ee); to++) {
+ if (pwm_voltage_table_ee[to][1] >= target_voltage) {
+ break;
+ }
+ }
+
+ if (to >= ARRAY_SIZE(pwm_voltage_table_ee)) {
+ to = ARRAY_SIZE(pwm_voltage_table_ee) - 1;
+ }
+
+ writel(pwm_voltage_table_ee[to][0],AO_PWM_PWM_B);
+}
+static void power_off_ddr(unsigned int flag)
+{
+ if (flag) {
+ /*set test_n high to power on VDDQ1.5*/
+ writel(readl(AO_GPIO_TEST_N) | (1 << 31), AO_GPIO_TEST_N);
+ writel(readl(AO_GPIO_TEST_N) & (~(0xf << 8)), AO_GPIO_TEST_N);
+ } else {
+ /*set test_n low to power off VDDQ1.5*/
+ writel(readl(AO_GPIO_TEST_N) & (~(1 << 31)), AO_GPIO_TEST_N);
+ writel(readl(AO_GPIO_TEST_N) & (~(0xf << 8)), AO_GPIO_TEST_N);
+
+ }
+}
+
+static void power_off_at_24M(unsigned int suspend_from)
+{
+ /*set gpiaoao_2 low to power off VDDCPU*/
+ writel(readl(AO_GPIO_O) & (~(1 << 2)), AO_GPIO_O);
+ writel(readl(AO_GPIO_O_EN_N) & (~(1 << 2)), AO_GPIO_O_EN_N);
+ writel(readl(AO_RTI_PINMUX_REG0) & (~(0xf << 8)), AO_RTI_PINMUX_REG0);
+ _udelay(100);
+
+ if (suspend_from == SYS_POWEROFF) {
+ /*if poweroff set gpioao_3 low to power off VCC 5V*/
+ writel(readl(AO_GPIO_O) & (~(1 << 3)), AO_GPIO_O);
+ writel(readl(AO_GPIO_O_EN_N) & (~(1 << 3)), AO_GPIO_O_EN_N);
+ writel(readl(AO_RTI_PINMUX_REG0) & (~(0xf << 12)), AO_RTI_PINMUX_REG0);
+ }
+
+ /*step down ee voltage*/
+ set_vddee_voltage(CONFIG_VDDEE_SLEEP_VOLTAGE);
+ if (suspend_from == SYS_POWEROFF) {
+ power_off_ddr(0);
+ }
+}
+
+static void power_on_at_24M(unsigned int suspend_from)
+{
+
+ /*step up ee voltage*/
+ set_vddee_voltage(CONFIG_VDDEE_INIT_VOLTAGE);
+ _udelay(100);
+
+ /*set gpiaoao_2 high to power on VDDCPU*/
+ writel(readl(AO_GPIO_O) | (1 << 2), AO_GPIO_O);
+ writel(readl(AO_GPIO_O_EN_N) & (~(1 << 2)), AO_GPIO_O_EN_N);
+ writel(readl(AO_RTI_PINMUX_REG0) & (~(0xf << 8)), AO_RTI_PINMUX_REG0);
+ _udelay(100);
+
+ /*set gpioao_3 high to power on VCC 5V*/
+ writel(readl(AO_GPIO_O) | (1 << 3), AO_GPIO_O);
+ writel(readl(AO_GPIO_O_EN_N) & (~(1 << 3)), AO_GPIO_O_EN_N);
+ writel(readl(AO_RTI_PINMUX_REG0) & (~(0xf << 12)), AO_RTI_PINMUX_REG0);
+ _udelay(10000);
+ if (suspend_from == SYS_POWEROFF) {
+ power_off_ddr(1);
+ }
+
+}
+
+void get_wakeup_source(void *response, unsigned int suspend_from)
+{
+ struct wakeup_info *p = (struct wakeup_info *)response;
+ unsigned val;
+ unsigned i = 0;
+
+ p->status = RESPONSE_OK;
+ val = (POWER_KEY_WAKEUP_SRC | AUTO_WAKEUP_SRC | REMOTE_WAKEUP_SRC |
+ ETH_PHY_WAKEUP_SRC | BT_WAKEUP_SRC | CECB_WAKEUP_SRC);
+
+#ifdef CONFIG_WIFI_WAKEUP
+ if (suspend_from != SYS_POWEROFF)
+ val |= WIFI_WAKEUP_SRC;
+#endif
+
+#ifdef CONFIG_BT_WAKEUP
+ if (1/*suspend_from != SYS_POWEROFF*/)
+ val |= BT_WAKEUP_SRC;
+#endif
+
+ p->sources = val;
+ p->gpio_info_count = i;
+
+#ifdef CONFIG_WIFI_WAKEUP
+ if (suspend_from != SYS_POWEROFF) {
+ struct wakeup_gpio_info *gpio;
+ gpio = &(p->gpio_info[i]);
+ gpio->wakeup_id = WIFI_WAKEUP;
+ gpio->gpio_in_idx = GPIOC_12;
+ gpio->gpio_in_ao = 0;
+ gpio->gpio_out_idx = -1;
+ gpio->gpio_out_ao = 0;
+ gpio->irq = IRQ_GPIO1_NUM;
+ gpio->trig_type = GPIO_IRQ_FALLING_EDGE;
+ p->gpio_info_count = ++i;
+ }
+#endif
+#ifdef CONFIG_BT_WAKEUP
+ if (1/*suspend_from != SYS_POWEROFF*/) {
+ struct wakeup_gpio_info *gpio;
+ gpio = &(p->gpio_info[i]);
+ gpio->wakeup_id = BT_WAKEUP;
+ gpio->gpio_in_idx = GPIOC_14;
+ gpio->gpio_in_ao = 0;
+ gpio->gpio_out_idx = -1;
+ gpio->gpio_out_ao = 0;
+ gpio->irq = IRQ_GPIO1_NUM;
+ gpio->trig_type = GPIO_IRQ_FALLING_EDGE;
+ p->gpio_info_count = ++i;
+ }
+#endif
+}
+extern void __switch_idle_task(void);
+
+static unsigned int detect_key(unsigned int suspend_from)
+{
+ int exit_reason = 0;
+ unsigned *irq = (unsigned *)WAKEUP_SRC_IRQ_ADDR_BASE;
+ init_remote();
+#ifdef CONFIG_CEC_WAKEUP
+ if (hdmi_cec_func_config & 0x1) {
+ remote_cec_hw_reset();
+ cec_node_init();
+ }
+#endif
+
+ do {
+ #ifdef CONFIG_CEC_WAKEUP
+ if (irq[IRQ_AO_CECB] == IRQ_AO_CEC2_NUM) {
+ irq[IRQ_AO_CECB] = 0xFFFFFFFF;
+ if (cec_power_on_check())
+ exit_reason = CEC_WAKEUP;
+ }
+ #endif
+ if (irq[IRQ_AO_IR_DEC] == IRQ_AO_IR_DEC_NUM) {
+ irq[IRQ_AO_IR_DEC] = 0xFFFFFFFF;
+ if (remote_detect_key())
+ exit_reason = REMOTE_WAKEUP;
+ }
+ if (irq[IRQ_VRTC] == IRQ_VRTC_NUM) {
+ irq[IRQ_VRTC] = 0xFFFFFFFF;
+ exit_reason = RTC_WAKEUP;
+ }
+#ifdef CONFIG_WIFI_WAKEUP
+ if (irq[IRQ_GPIO1] == IRQ_GPIO1_NUM) {
+ irq[IRQ_GPIO1] = 0xFFFFFFFF;
+ if (suspend_from) {
+ if ( !(readl(PREG_PAD_GPIO3_EN_N) & (0x01 << 11))
+ && (readl(PREG_PAD_GPIO3_O) & (0x01 << 11))
+ && !(readl(PREG_PAD_GPIO3_I) & (0x01 << 12)))
+ exit_reason = WIFI_WAKEUP;
+ }
+ }
+#endif
+#ifdef CONFIG_BT_WAKEUP
+ if (irq[IRQ_GPIO1] == IRQ_GPIO1_NUM) {
+ irq[IRQ_GPIO1] = 0xFFFFFFFF;
+ if (1/*suspend_from*/) {
+ if ( (readl(PREG_PAD_GPIO3_EN_N) & (0x01 << 14))
+ && !(readl(PREG_PAD_GPIO3_I) & (0x01 << 14)))
+ exit_reason = BT_WAKEUP;
+ }
+ }
+#endif
+ if (exit_reason)
+ break;
+ else
+ __switch_idle_task();
+ } while (1);
+
+ return exit_reason;
+}
+
+static void pwr_op_init(struct pwr_op *pwr_op)
+{
+ pwr_op->power_off_at_24M = power_off_at_24M;
+ pwr_op->power_on_at_24M = power_on_at_24M;
+ pwr_op->detect_key = detect_key;
+ pwr_op->get_wakeup_source = get_wakeup_source;
+}
diff --git a/board/amlogic/tm2_ab301_v1/firmware/timing.c b/board/amlogic/tm2_ab301_v1/firmware/timing.c
new file mode 100644
index 0000000000..d54911624e
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/firmware/timing.c
@@ -0,0 +1,650 @@
+
+/*
+ * board/amlogic/txl_skt_v1/firmware/timing.c
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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 <asm/arch/secure_apb.h>
+#include <asm/arch/timing.h>
+#include <asm/arch/ddr_define.h>
+
+
+
+/* ddr config support multiple configs for boards which use same bootloader:
+ * config steps:
+ * 1. add a new data struct in __ddr_setting[]
+ * 2. config correct board_id, ddr_type, freq, etc..
+ */
+
+
+/* CAUTION!! */
+/* Confirm ddr configs with hardware designer,
+ * if you don't know how to config, then don't edit it
+ */
+
+/* Key configs */
+/*
+ * board_id: check hardware adc config
+ * dram_rank_config:
+ * #define CONFIG_DDR_CHL_AUTO 0xF
+ * #define CONFIG_DDR0_16BIT_CH0 0x1
+ * #define CONFIG_DDR0_16BIT_RANK01_CH0 0x4
+ * #define CONFIG_DDR0_32BIT_RANK0_CH0 0x2
+ * #define CONFIG_DDR0_32BIT_RANK01_CH01 0x3
+ * #define CONFIG_DDR0_32BIT_16BIT_RANK0_CH0 0x5
+ * #define CONFIG_DDR0_32BIT_16BIT_RANK01_CH0 0x6
+ * DramType:
+ * #define CONFIG_DDR_TYPE_DDR3 0
+ * #define CONFIG_DDR_TYPE_DDR4 1
+ * #define CONFIG_DDR_TYPE_LPDDR4 2
+ * #define CONFIG_DDR_TYPE_LPDDR3 3
+ * DRAMFreq:
+ * {pstate0, pstate1, pstate2, pstate3} //more than one pstate means use dynamic freq
+ *
+ */
+
+ddr_set_t __ddr_setting[] = {
+{
+ //tl1 ref(T309) lpddr4
+ .board_id = CONFIG_BOARD_ID_MASK,
+ .version = 1,
+ //.dram_rank_config = CONFIG_DDR0_32BIT_RANK01_CH0,
+ .dram_rank_config = CONFIG_DDR0_32BIT_RANK0_CH0,
+ .ddr_rfc_type = DDR_RFC_TYPE_LPDDR4_8Gbx1,
+ .DramType = CONFIG_DDR_TYPE_LPDDR4,
+ .DRAMFreq = {1200, 0, 0, 0},
+ .ddr_base_addr = CFG_DDR_BASE_ADDR,
+ .ddr_start_offset = CFG_DDR_START_OFFSET,
+ .DisabledDbyte = 0xf0,
+ .Is2Ttiming = 0,
+ .HdtCtrl = 0xa,
+ .dram_cs0_size_MB = 1024,//1024,
+ .dram_cs1_size_MB = 0,//1024,
+ .training_SequenceCtrl = {0x131f,0x61}, //ddr3 0x21f 0x31f
+ .phy_odt_config_rank = {0x30,0x30,0x30,0x30}, // // Odt pattern for accesses //targeting rank 0. [3:0] is used //for write ODT [7:4] is used for //read ODT
+ .dfi_odt_config = 0x0808,
+ .PllBypassEn = 0, //bit0-ps0,bit1-ps1
+ .ddr_rdbi_wr_enable = 0x3,
+ .clk_drv_ohm = 60,
+ .cs_drv_ohm = 40,
+ .ac_drv_ohm = 60,
+ .soc_data_drv_ohm_p = 48,
+ .soc_data_drv_ohm_n = 48,
+ .soc_data_odt_ohm_p = 0,
+ .soc_data_odt_ohm_n = 60,
+ .dram_data_drv_ohm = 48, //lpddr4 sdram only240/1-6
+ .dram_data_odt_ohm = 120,
+ .dram_ac_odt_ohm = 120,// 120,
+ .lpddr4_dram_vout_voltage_1_3_2_5_setting =0,///1, 1/3vddq 0 2/5 vddq
+ .soc_clk_slew_rate = 0x3ff,//0x253,
+ .soc_cs_slew_rate = 0x100,//0x253,
+ .soc_ac_slew_rate = 0x100,//0x253,
+ .soc_data_slew_rate = 0x1ff,
+ .vref_output_permil = 260,//200,
+ .vref_receiver_permil = 0,
+ .vref_dram_permil = 0,
+ //.vref_reverse = 0,
+ //.ac_trace_delay = {32-5,0,0,0,0,0,0x0,00},
+ //.ac_pinmux = {00,00},
+ .ddr_dmc_remap = {
+ [0] = ( 5 | 6 << 5 | 7 << 10 | 8<< 15 | 9<< 20 | 10 << 25 ),
+ [1] = ( 11| 0 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25 ),
+ [2] = ( 18| 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25 ),
+ [3] = ( 24| 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25 ),
+ [4] = ( 30| 12 << 5 | 13 << 10 | 14<< 15 | 0 << 20 | 0 << 25 ),
+ },
+ .ddr_lpddr34_ca_remap = {00,00},
+ //.ddr_lpddr34_dq_remap = {4,5,6,7,0,2,3,1, 15,14,13,12,11,9,10,8, 4,5,6,7,0,2,3,1, 15,14,13,12,11,9,10,8,},
+ .ddr_lpddr34_dq_remap = {4,5,6,7,0,2,3,1, 15,14,13,12,11,9,10,8, 20,18,17,16,23,22,19,21, 30,31,25,24,26,28,29,27},
+ .dram_rtt_nom_wr_park = {00,00},
+ .pll_ssc_mode = (1<<20) | (1<<8) | (2<<4) | 0,//center_ssc_1000ppm
+ .ddr_func = DDR_FUNC,
+ .magic = DRAM_CFG_MAGIC,
+ .diagnose = CONFIG_DIAGNOSE_DISABLE,
+ .bitTimeControl_2d = 1, //training time setting,=1,200ms;=7,2s
+},
+{
+ /// tl1 ref(x301) ddr3
+ .board_id =CONFIG_BOARD_ID_MASK,
+ .version = 1,
+ .dram_rank_config = CONFIG_DDR0_32BIT_RANK01_CH0,
+ .DramType = CONFIG_DDR_TYPE_DDR3,
+ .DRAMFreq = {1056, 0, 0, 0},
+ .ddr_base_addr = CFG_DDR_BASE_ADDR,
+ .ddr_start_offset = CFG_DDR_START_OFFSET,
+ .DisabledDbyte = 0xf0,
+ .Is2Ttiming = 1,
+ .HdtCtrl = 0xc8,//0xC8,
+ .dram_cs0_size_MB = 1024,
+ .dram_cs1_size_MB = 1024,// 1024,
+ .training_SequenceCtrl = {0x31f,0}, //ddr3 0x21f 0x31f
+ .phy_odt_config_rank = {0x23,0x13,0x30,0x30}, // // Odt pattern for accesses //targeting rank 0. [3:0] is used //for write ODT [7:4] is used for //read ODT
+ .dfi_odt_config = 0x0d0d,
+ .PllBypassEn = 0, //bit0-ps0,bit1-ps1
+ .ddr_rdbi_wr_enable = 0,
+ .clk_drv_ohm = 40,
+ .cs_drv_ohm = 40,
+ .ac_drv_ohm = 60,
+ .soc_data_drv_ohm_p = 40,
+ .soc_data_drv_ohm_n = 40,
+ .soc_data_odt_ohm_p = 48,//120, //48, ddr3 will use odt_ohm_p value
+ .soc_data_odt_ohm_n = 0,//120,
+ .dram_data_drv_ohm = 40, //ddr4 sdram only 34 or 48, skt board use 34 better
+ .dram_data_odt_ohm = 40,
+ .dram_ac_odt_ohm = 0,
+ .dram_data_wr_odt_ohm = 120,
+ .soc_clk_slew_rate = 0x300,
+ .soc_cs_slew_rate = 0x300,
+ .soc_ac_slew_rate = 0x300,
+ .soc_data_slew_rate = 0x200,
+ .vref_output_permil = 500,
+ .vref_receiver_permil = 500, //700,
+ .vref_dram_permil = 500, //700,
+// .vref_reverse = 0,
+// .ac_trace_delay = {32,32-10,32,32,32+10,32,32,32,32,32-10},
+// .ac_trace_delay = {32-10,32-15,32,32,32,32,32,32,32,32-10},
+ .ac_trace_delay = {32-15,32-20,32-10,32,32,32,32,32,32-10,32-15},
+ //{00,00},
+ .ac_pinmux = {00,00},
+#if 1
+ .ddr_dmc_remap = {
+ [0] = ( 5 | 7 << 5 | 8 << 10 | 9 << 15 | 10 << 20 | 11 << 25 ),
+ [1] = ( 12| 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25 ),
+ [2] = ( 17| 18 << 5 | 19 << 10 | 21 << 15 | 22 << 20 | 23 << 25 ),
+ [3] = ( 24| 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25 ),
+ [4] = ( 30| 13 << 5 | 20 << 10 | 6 << 15 | 0 << 20 | 0 << 25 ),
+ },
+#else
+ //16bit
+ .ddr_dmc_remap = {
+ [0] = ( 0 | 5 << 5 | 6<< 10 | 7 << 15 | 8 << 20 | 9 << 25 ),
+ [1] = ( 10| 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25 ),
+ [2] = ( 17|( 18 << 5) |( 19 << 10) |( 20 << 15) |( 21 << 20) | (22 << 25 )),
+ [3] = ( 23| 24 << 5 | 25 << 10 | 26 << 15 | 27 << 20 | 28 << 25 ),
+ [4] = ( 29| 11<< 5 | 12 << 10 | 13<< 15 | 0 << 20 | 0 << 25 ),
+ },
+#endif
+ .ddr_lpddr34_ca_remap = {00,00},
+ .ddr_lpddr34_dq_remap = {00,00},
+ .dram_rtt_nom_wr_park = {00,00},
+
+
+ .pll_ssc_mode = (1<<20) | (1<<8) | (2<<4) | 0,//center_ssc_1000ppm
+ .ddr_func = DDR_FUNC,
+ .magic = DRAM_CFG_MAGIC,
+},
+//*/
+{
+ /* tl1 skt (x309) ddr4 */
+ .board_id = CONFIG_BOARD_ID_MASK,
+ .version = 1,
+ .dram_rank_config = CONFIG_DDR0_32BIT_RANK0_CH0,
+ .DramType = CONFIG_DDR_TYPE_DDR4,
+ .DRAMFreq = {1200, 0, 0, 0},
+ .ddr_rfc_type = DDR_RFC_TYPE_DDR4_2Gbx8,
+ .ddr_base_addr = CFG_DDR_BASE_ADDR,
+ .ddr_start_offset = CFG_DDR_START_OFFSET,
+ .DisabledDbyte = 0xf0,
+ .Is2Ttiming = 1,
+ .HdtCtrl = 0xC8,
+ .dram_cs0_size_MB = 0xffff,
+ .dram_cs1_size_MB = 0,
+ .training_SequenceCtrl = {0x31f,0x61}, //ddr3 0x21f 0x31f
+ .phy_odt_config_rank = {0x23,0x13,0x30,0x30}, // // Odt pattern for accesses //targeting rank 0. [3:0] is used //for write ODT [7:4] is used for //read ODT
+ .dfi_odt_config = 0x0d0d,
+ .PllBypassEn = 0, //bit0-ps0,bit1-ps1
+ .ddr_rdbi_wr_enable = 0x1,//bit 0 read-dbi,bit 1 write dbi
+ .clk_drv_ohm = 40,
+ .cs_drv_ohm = 40,
+ .ac_drv_ohm = 40,
+ .soc_data_drv_ohm_p = 48,
+ .soc_data_drv_ohm_n = 48,
+ .soc_data_odt_ohm_p = 60,
+ .soc_data_odt_ohm_n = 0,
+ .dram_data_drv_ohm = 48,//48, //34, //ddr4 sdram only 34 or 48, skt board use 34 better
+ .dram_data_odt_ohm = 48, //60,
+ .dram_ac_odt_ohm = 0,
+ .soc_clk_slew_rate = 0x3ff,
+ .soc_cs_slew_rate = 0x3ff,
+ .soc_ac_slew_rate = 0x3ff,
+ .soc_data_slew_rate = 0x2ff,
+ .vref_output_permil = 500,
+ .vref_receiver_permil = 0,
+ .vref_dram_permil = 0,
+ //.vref_reverse = 0,
+ //.ac_trace_delay ={0x0,0x0},// {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40},
+ .ac_trace_delay = {32+10,32+10,32+10,32+10,32,32+10,32+10,32+10,32+10,32+10},
+ .ddr_dmc_remap = {
+ [0] = ( 5 | 7 << 5 | 8 << 10 | 9 << 15 | 10 << 20 | 11 << 25 ),
+ [1] = ( 12| 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25 ),
+ [2] = ( 17| 18 << 5 | 19 << 10 | 21 << 15 | 22 << 20 | 23 << 25 ),
+ [3] = ( 24| 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25 ),
+ [4] = ( 30| 13 << 5 | 20 << 10 | 6 << 15 | 0 << 20 | 0 << 25 ),
+ },
+ .ddr_lpddr34_ca_remap = {00,00},
+ .ddr_lpddr34_dq_remap = {00,00},
+ .dram_rtt_nom_wr_park = {00,00},
+
+ /* pll ssc config:
+ *
+ * pll_ssc_mode = (1<<20) | (1<<8) | ([strength] << 4) | [mode],
+ * ppm = strength * 500
+ * mode: 0=center, 1=up, 2=down
+ *
+ * eg:
+ * 1. config 1000ppm center ss. then mode=0, strength=2
+ * .pll_ssc_mode = (1<<20) | (1<<8) | (2 << 4) | 0,
+ * 2. config 3000ppm down ss. then mode=2, strength=6
+ * .pll_ssc_mode = (1<<20) | (1<<8) | (6 << 4) | 2,
+ */
+ .pll_ssc_mode = (1<<20) | (1<<8) | (2<<4) | 0,//center_ssc_1000ppm
+ .ddr_func = DDR_FUNC,
+ .magic = DRAM_CFG_MAGIC,
+ .slt_test_function={0x0,0x0}, //{0x1,0x0},enable slt 4 DRAMFreq test;{0x0,0x0},disable slt 4 DRAMFreq test;
+},
+/*
+{
+ // g12a skt (u209) ddr3
+ .board_id = CONFIG_BOARD_ID_MASK,
+ .version = 1,
+ .dram_rank_config = CONFIG_DDR0_32BIT_RANK0_CH0,
+ .DramType = CONFIG_DDR_TYPE_DDR3,
+ .DRAMFreq = {912, 0, 0, 0},
+ .ddr_base_addr = CFG_DDR_BASE_ADDR,
+ .ddr_start_offset = CFG_DDR_START_OFFSET,
+ .DisabledDbyte = 0xf0,
+ .Is2Ttiming = 1,
+ .HdtCtrl = 0x5,//0xC8,
+ .dram_cs0_size_MB = 1024,
+ .dram_cs1_size_MB =0,// 1024,
+ .training_SequenceCtrl = {0x31f,0}, //ddr3 0x21f 0x31f
+ .phy_odt_config_rank = {0x30,0x30,0x30,0x30}, // // Odt pattern for accesses //targeting rank 0. [3:0] is used //for write ODT [7:4] is used for //read ODT
+ .dfi_odt_config = 0x0c0c,
+ .PllBypassEn = 0, //bit0-ps0,bit1-ps1
+ .ddr_rdbi_wr_enable = 0,
+ .clk_drv_ohm = 40,
+ .cs_drv_ohm = 40,
+ .ac_drv_ohm = 40,
+ .soc_data_drv_ohm_p = 34,
+ .soc_data_drv_ohm_n = 34,
+ .soc_data_odt_ohm_p = 60, //48,
+ .soc_data_odt_ohm_n = 0,
+ .dram_data_drv_ohm = 34, //ddr4 sdram only 34 or 48, skt board use 34 better
+ .dram_data_odt_ohm = 60,
+ .dram_ac_odt_ohm = 0,
+ .soc_clk_slew_rate = 0x300,
+ .soc_cs_slew_rate = 0x300,
+ .soc_ac_slew_rate = 0x300,
+ .soc_data_slew_rate = 0x200,
+ .vref_output_permil = 500,
+ .vref_receiver_permil = 500, //700,
+ .vref_dram_permil = 500, //700,
+// .vref_reverse = 0,
+ .ac_trace_delay = {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40},
+ //{00,00},
+ .ac_pinmux = {00,00},
+#if 1
+ .ddr_dmc_remap = {
+ [0] = ( 5 | 7 << 5 | 8 << 10 | 9 << 15 | 10 << 20 | 11 << 25 ),
+ [1] = ( 12| 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25 ),
+ [2] = ( 17| 18 << 5 | 19 << 10 | 21 << 15 | 22 << 20 | 23 << 25 ),
+ [3] = ( 24| 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25 ),
+ [4] = ( 30| 13 << 5 | 20 << 10 | 6 << 15 | 0 << 20 | 0 << 25 ),
+ },
+#else
+ //16bit
+ .ddr_dmc_remap = {
+ [0] = ( 0 | 5 << 5 | 6<< 10 | 7 << 15 | 8 << 20 | 9 << 25 ),
+ [1] = ( 10| 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25 ),
+ [2] = ( 17|( 18 << 5) |( 19 << 10) |( 20 << 15) |( 21 << 20) | (22 << 25 )),
+ [3] = ( 23| 24 << 5 | 25 << 10 | 26 << 15 | 27 << 20 | 28 << 25 ),
+ [4] = ( 29| 11<< 5 | 12 << 10 | 13<< 15 | 0 << 20 | 0 << 25 ),
+ },
+#endif
+ .ddr_lpddr34_ca_remap = {00,00},
+ .ddr_lpddr34_dq_remap = {00,00},
+ .dram_rtt_nom_wr_park = {00,00},
+
+
+ .pll_ssc_mode = (1<<20) | (1<<8) | (2<<4) | 0,//center_ssc_1000ppm
+ .ddr_func = DDR_FUNC,
+ .magic = DRAM_CFG_MAGIC,
+},
+
+{
+ //g12a skt (u209) lpddr4
+ .board_id = CONFIG_BOARD_ID_MASK,
+ .version = 1,
+ //.dram_rank_config = CONFIG_DDR0_32BIT_RANK01_CH0,
+ .dram_rank_config = CONFIG_DDR0_32BIT_RANK01_CH01,
+ .ddr_rfc_type = DDR_RFC_TYPE_LPDDR4_4Gbx1,
+ .DramType = CONFIG_DDR_TYPE_LPDDR4,
+ .DRAMFreq = {1392, 0, 0, 0},
+ .ddr_base_addr = CFG_DDR_BASE_ADDR,
+ .ddr_start_offset = CFG_DDR_START_OFFSET,
+ .DisabledDbyte = 0xf0,
+ .Is2Ttiming = 0,
+ .HdtCtrl = 0xa,
+ .dram_cs0_size_MB = 1024,//1024,
+ .dram_cs1_size_MB = 1024,//1024,
+ .training_SequenceCtrl = {0x131f,0x61}, //ddr3 0x21f 0x31f
+ .phy_odt_config_rank = {0x30,0x30,0x30,0x30}, // // Odt pattern for accesses //targeting rank 0. [3:0] is used //for write ODT [7:4] is used for //read ODT
+ .dfi_odt_config = 0x0808,
+ .PllBypassEn = 0, //bit0-ps0,bit1-ps1
+ .ddr_rdbi_wr_enable = 0,
+ .clk_drv_ohm = 40,
+ .cs_drv_ohm = 40,
+ .ac_drv_ohm = 40,
+ .soc_data_drv_ohm_p = 40,
+ .soc_data_drv_ohm_n = 40,
+ .soc_data_odt_ohm_p = 0,
+ .soc_data_odt_ohm_n = 120,
+ .dram_data_drv_ohm = 40, //lpddr4 sdram only240/1-6
+ .dram_data_odt_ohm = 120,
+ .dram_ac_odt_ohm = 120,
+ .soc_clk_slew_rate = 0x3ff,//0x253,
+ .soc_cs_slew_rate = 0x100,//0x253,
+ .soc_ac_slew_rate = 0x100,//0x253,
+ .soc_data_slew_rate = 0x1ff,
+ .vref_output_permil = 350,//200,
+ .vref_receiver_permil = 200,
+ .vref_dram_permil = 350,
+ //.vref_reverse = 0,
+ .ac_trace_delay = {00,0x0,0,0,0,0,0x0,00},
+ .ac_pinmux = {00,00},
+ .ddr_dmc_remap = {
+ [0] = ( 5 | 6 << 5 | 7 << 10 | 8<< 15 | 9<< 20 | 10 << 25 ),
+ [1] = ( 11| 0 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25 ),
+ [2] = ( 18| 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25 ),
+ [3] = ( 24| 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25 ),
+ [4] = ( 30| 12 << 5 | 13 << 10 | 14<< 15 | 0 << 20 | 0 << 25 ),
+ },
+ .ddr_lpddr34_ca_remap = {00,00},
+ .ddr_lpddr34_dq_remap = {3,2,0,1,7,6,5,4,14,13,12,15,8,9,11,10,20,21,22,23,16,17,19,18,24,25,28,26,31,30,27,29},
+ .dram_rtt_nom_wr_park = {00,00},
+ .pll_ssc_mode = (1<<20) | (1<<8) | (2<<4) | 0,//center_ssc_1000ppm
+ .ddr_func = DDR_FUNC,
+ .magic = DRAM_CFG_MAGIC,
+ .diagnose = CONFIG_DIAGNOSE_DISABLE,
+},
+{
+ // g12a Y2 dongle
+ .board_id = CONFIG_BOARD_ID_MASK,
+ .version = 1,
+ //.dram_rank_config = CONFIG_DDR0_32BIT_RANK01_CH0,
+ .dram_rank_config = CONFIG_DDR0_32BIT_RANK0_CH01,
+ .ddr_rfc_type = DDR_RFC_TYPE_LPDDR4_4Gbx1,
+ .DramType = CONFIG_DDR_TYPE_LPDDR4,
+ .DRAMFreq = {1392, 0, 0, 0},
+ .ddr_base_addr = CFG_DDR_BASE_ADDR,
+ .ddr_start_offset = CFG_DDR_START_OFFSET,
+ .DisabledDbyte = 0xf0,
+ .Is2Ttiming = 0,
+ .HdtCtrl = 0xa,
+ .dram_cs0_size_MB = 1536,//1024,
+ .dram_cs1_size_MB = 0,//1024,
+ .training_SequenceCtrl = {0x131f,0x61}, //ddr3 0x21f 0x31f
+ .phy_odt_config_rank = {0x30,0x30,0x30,0x30}, // // Odt pattern for accesses //targeting rank 0. [3:0] is used //for write ODT [7:4] is used for //read ODT
+ .dfi_odt_config = 0x0808,
+ .PllBypassEn = 0, //bit0-ps0,bit1-ps1
+ .ddr_rdbi_wr_enable = 0,
+ .clk_drv_ohm = 40,
+ .cs_drv_ohm = 40,
+ .ac_drv_ohm = 40,
+ .soc_data_drv_ohm_p = 40,
+ .soc_data_drv_ohm_n = 40,
+ .soc_data_odt_ohm_p = 0,
+ .soc_data_odt_ohm_n = 120,
+ .dram_data_drv_ohm = 40, //lpddr4 sdram only240/1-6
+ .dram_data_odt_ohm = 120,
+ .dram_ac_odt_ohm = 120,
+ .soc_clk_slew_rate = 0x3ff,//0x253,
+ .soc_cs_slew_rate = 0x100,//0x253,
+ .soc_ac_slew_rate = 0x100,//0x253,
+ .soc_data_slew_rate = 0x1ff,
+ .vref_output_permil = 350,//200,
+ .vref_receiver_permil = 200,
+ .vref_dram_permil = 350,
+ //.vref_reverse = 0,
+ .ac_trace_delay = {00,0x0,0,0,0,0,0x0,00},
+ .ac_pinmux = {00,00},
+ .ddr_dmc_remap = {
+ [0] = ( 5 | 6 << 5 | 7 << 10 | 8<< 15 | 9<< 20 | 10 << 25 ),
+ [1] = ( 11| 0 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25 ),
+ [2] = ( 18| 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25 ),
+ [3] = ( 24| 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25 ),
+ [4] = ( 30| 12 << 5 | 13 << 10 | 14<< 15 | 0 << 20 | 0 << 25 ),
+ },
+ .ddr_lpddr34_ca_remap = {00,00},
+ .ddr_lpddr34_dq_remap = {00,00},
+ .dram_rtt_nom_wr_park = {00,00},
+ .pll_ssc_mode = (1<<20) | (1<<8) | (2<<4) | 0,//center_ssc_1000ppm
+ .ddr_func = DDR_FUNC,
+ .magic = DRAM_CFG_MAGIC,
+},
+{
+ // lpddr3
+ .board_id = CONFIG_BOARD_ID_MASK,
+ .version = 1,
+ //.dram_rank_config = CONFIG_DDR0_32BIT_RANK01_CH0,
+ .dram_rank_config = CONFIG_DDR0_32BIT_RANK01_CH0,
+ .ddr_rfc_type = DDR_RFC_TYPE_LPDDR4_4Gbx1,
+ .DramType = CONFIG_DDR_TYPE_LPDDR3,
+ .DRAMFreq = {600, 0, 0, 0},
+ .ddr_base_addr = CFG_DDR_BASE_ADDR,
+ .ddr_start_offset = CFG_DDR_START_OFFSET,
+ .DisabledDbyte = 0xf0,
+ .Is2Ttiming = 0,
+ .HdtCtrl = 0xa,//0xa,
+ .dram_cs0_size_MB = 1024,//1024,
+ .dram_cs1_size_MB = 1024,//1024,
+ .training_SequenceCtrl = {0x131f,0}, //ddr3 0x21f 0x31f
+ .phy_odt_config_rank = {0x30,0x30,0x30,0x30}, // // Odt pattern for accesses //targeting rank 0. [3:0] is used //for write ODT [7:4] is used for //read ODT
+ .dfi_odt_config = 0x00c,
+ .PllBypassEn = 0, //bit0-ps0,bit1-ps1
+ .ddr_rdbi_wr_enable = 0,
+ .pll_ssc_mode = (1<<20) | (1<<8) | (2<<4) | 0,//center_ssc_1000ppm
+ .clk_drv_ohm = 40,
+ .cs_drv_ohm = 40,
+ .ac_drv_ohm = 40,
+ .soc_data_drv_ohm_p = 40,
+ .soc_data_drv_ohm_n = 40,
+ .soc_data_odt_ohm_p = 60,
+ .soc_data_odt_ohm_n = 0,
+ .dram_data_drv_ohm = 30, //
+ .dram_data_odt_ohm = 120,
+ .dram_ac_odt_ohm = 0,
+ .soc_clk_slew_rate = 0x3ff,//0x253,
+ .soc_cs_slew_rate = 0x3ff,//0x253,
+ .soc_ac_slew_rate = 0x3ff,//0x253,
+ .soc_data_slew_rate = 0x2ff,
+ .vref_output_permil = 800,//200,
+ .vref_receiver_permil = 700,//875, //700 for drv 40 odt 60 is better ,why?
+ .vref_dram_permil = 500,//875,
+ //.vref_reverse = 0,
+ .ac_trace_delay = {0x10,0x0,0x10-6,0x10-6,0x10-6,0x0,0x0,0x0,0x0,0x0},
+ .ac_pinmux = {00,00},
+ .ddr_dmc_remap = {
+ [0] = ( 5 | 6 << 5 | 7 << 10 | 8<< 15 | 9<< 20 | 10 << 25 ),
+ [1] = ( 11| 29 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25 ),
+ [2] = ( 18| 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25 ),
+ [3] = ( 24| 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 30 << 25 ),
+ [4] = ( 31| 12 << 5 | 13 << 10 | 14<< 15 | 0 << 20 | 0 << 25 ),
+ },
+ .ddr_lpddr34_ca_remap = {21/8,8/8,31/8,1/8},// {2,7,1,4,5,6,0,3,9,8},
+ .ddr_lpddr34_dq_remap = {1,2,7,4,0,3,5,6,8,12,14,9,11,10,15,13,21,22,16,17,23,20,19,18,31,29,26,27,30,28,25,24},
+ //{21,22,16,17,23,20,19,18,8,12,14,9,11,10,15,13,31,29,26,27,30,28,25,24,1,2,7,4,0,3,5,6},
+ .dram_rtt_nom_wr_park = {00,00},
+ .ddr_func = DDR_FUNC,
+ .magic = DRAM_CFG_MAGIC,
+ .diagnose = CONFIG_DIAGNOSE_DISABLE,
+},
+*/
+};
+
+pll_set_t __pll_setting = {
+ .cpu_clk = CONFIG_CPU_CLK / 24 * 24,
+#ifdef CONFIG_PXP_EMULATOR
+ .pxp = 1,
+#else
+ .pxp = 0,
+#endif
+ .spi_ctrl = 0,
+ .lCustomerID = CONFIG_AML_CUSTOMER_ID,
+#ifdef CONFIG_DEBUG_MODE
+ .debug_mode = CONFIG_DEBUG_MODE,
+ .ddr_clk_debug = CONFIG_DDR_CLK_DEBUG,
+ .cpu_clk_debug = CONFIG_CPU_CLK_DEBUG,
+#endif
+
+#ifdef CONFIG_AML_SUPPORT_TLV
+ .nCFGTAddr = AML_BL2_TMASTER_DDR_ADDR,
+#endif
+
+};
+
+ddr_reg_t __ddr_reg[] = {
+ /* demo, user defined override register */
+ {0xaabbccdd, 0, 0, 0, 0, 0},
+ {0x11223344, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+};
+
+#define VCCK_VAL CONFIG_VCCK_INIT_VOLTAGE
+#define VDDEE_VAL CONFIG_VDDEE_INIT_VOLTAGE
+/* VCCK PWM table */
+#if (VCCK_VAL == 800)
+ #define VCCK_VAL_REG 0x0018000A
+#elif (VCCK_VAL == 810)
+ #define VCCK_VAL_REG 0x0017000B
+#elif (VCCK_VAL == 820)
+ #define VCCK_VAL_REG 0x0016000C
+#elif (VCCK_VAL == 830)
+ #define VCCK_VAL_REG 0x0015000D
+#elif (VCCK_VAL == 840)
+ #define VCCK_VAL_REG 0x0014000E
+#elif (VCCK_VAL == 850)
+ #define VCCK_VAL_REG 0x0013000F
+#elif (VCCK_VAL == 860)
+ #define VCCK_VAL_REG 0x00120010
+#elif (VCCK_VAL == 870)
+ #define VCCK_VAL_REG 0x00110011
+#elif (VCCK_VAL == 880)
+ #define VCCK_VAL_REG 0x00100012
+#elif (VCCK_VAL == 890)
+ #define VCCK_VAL_REG 0x000F0013
+#elif (VCCK_VAL == 900)
+ #define VCCK_VAL_REG 0x000E0014
+#elif (VCCK_VAL == 910)
+ #define VCCK_VAL_REG 0x000D0015
+#elif (VCCK_VAL == 920)
+ #define VCCK_VAL_REG 0x000C0016
+#elif (VCCK_VAL == 930)
+ #define VCCK_VAL_REG 0x000B0017
+#elif (VCCK_VAL == 940)
+ #define VCCK_VAL_REG 0x000A0018
+#elif (VCCK_VAL == 950)
+ #define VCCK_VAL_REG 0x00090019
+#elif (VCCK_VAL == 960)
+ #define VCCK_VAL_REG 0x0008001A
+#elif (VCCK_VAL == 970)
+ #define VCCK_VAL_REG 0x0007001B
+#elif (VCCK_VAL == 980)
+ #define VCCK_VAL_REG 0x0006001C
+#elif (VCCK_VAL == 990)
+ #define VCCK_VAL_REG 0x0005001D
+#elif (VCCK_VAL == 1000)
+ #define VCCK_VAL_REG 0x0004001E
+#elif (VCCK_VAL == 1010)
+ #define VCCK_VAL_REG 0x0003001F
+#else
+ #error "VCCK val out of range\n"
+#endif
+
+/* VDDEE PWM table */
+#if (VDDEE_VAL == 740)
+ #define VDDEE_VAL_REG 0x00120000
+#elif (VDDEE_VAL == 750)
+ #define VDDEE_VAL_REG 0x00110001
+#elif (VDDEE_VAL == 760)
+ #define VDDEE_VAL_REG 0x00100002
+#elif (VDDEE_VAL == 770)
+ #define VDDEE_VAL_REG 0x000f0003
+#elif (VDDEE_VAL == 780)
+ #define VDDEE_VAL_REG 0x000e0004
+#elif (VDDEE_VAL == 790)
+ #define VDDEE_VAL_REG 0x000d0005
+#elif (VDDEE_VAL == 800)
+ #define VDDEE_VAL_REG 0x000c0006
+#elif (VDDEE_VAL == 810)
+ #define VDDEE_VAL_REG 0x000b0007
+#elif (VDDEE_VAL == 820)
+ #define VDDEE_VAL_REG 0x000a0008
+#elif (VDDEE_VAL == 830)
+ #define VDDEE_VAL_REG 0x00090009
+#elif (VDDEE_VAL == 840)
+ #define VDDEE_VAL_REG 0x0008000a
+#elif (VDDEE_VAL == 850)
+ #define VDDEE_VAL_REG 0x0007000b
+#elif (VDDEE_VAL == 860)
+ #define VDDEE_VAL_REG 0x0006000c
+#elif (VDDEE_VAL == 870)
+ #define VDDEE_VAL_REG 0x0005000d
+#elif (VDDEE_VAL == 880)
+ #define VDDEE_VAL_REG 0x0004000e
+#elif (VDDEE_VAL == 890)
+ #define VDDEE_VAL_REG 0x0003000f
+#elif (VDDEE_VAL == 900)
+ #define VDDEE_VAL_REG 0x00020010
+#elif (VDDEE_VAL == 910)
+ #define VDDEE_VAL_REG 0x00010011
+#elif (VDDEE_VAL == 920)
+ #define VDDEE_VAL_REG 0x00000012
+#else
+ #error "VDDEE val out of range\n"
+#endif
+
+/* for PWM use */
+/* PWM driver check http://scgit.amlogic.com:8080/#/c/38093/ */
+#define GPIO_O_EN_N_REG3 ((0xff634400 + (0x19 << 2)))
+#define GPIO_O_REG3 ((0xff634400 + (0x1a << 2)))
+#define GPIO_I_REG3 ((0xff634400 + (0x1b << 2)))
+#define AO_PIN_MUX_REG0 ((0xff800000 + (0x05 << 2)))
+#define AO_PIN_MUX_REG1 ((0xff800000 + (0x06 << 2)))
+
+bl2_reg_t __bl2_reg[] = {
+ /* demo, user defined override register */
+ /* eg: PWM init */
+
+ /* PWM_AO_D */
+ /* VCCK_VAL_REG: check PWM table */
+ {AO_PWM_PWM_D, VCCK_VAL_REG, 0xffffffff, 0, BL2_INIT_STAGE_1, 0},
+ {AO_PWM_MISC_REG_CD, ((1 << 23) | (1 << 1)), (0x7f << 16), 0, BL2_INIT_STAGE_1, 0},
+ {AO_PIN_MUX_REG1, (3 << 20), (0xF << 20), 0, BL2_INIT_STAGE_1, 0},
+ /* PWM_AO_B */
+ /* VDDEE_VAL_REG: check PWM table */
+ {AO_PWM_PWM_B, VDDEE_VAL_REG, 0xffffffff, 0, BL2_INIT_STAGE_1, 0},
+ {AO_PWM_MISC_REG_AB, ((1 << 23) | (1 << 1)), (0x7f << 16), 0, BL2_INIT_STAGE_1, 0},
+ {AO_PIN_MUX_REG1, (3 << 16), (0xF << 16), 0, BL2_INIT_STAGE_1, 0},
+ /* Enable 5V_EN ,set gpioao_3 low --> several millisecond--set high in board_init*/
+ {AO_GPIO_O_EN_N, (0 << 3), (1 << 3), 0, BL2_INIT_STAGE_1, 0},
+ {AO_GPIO_O, (0 << 3), (1 << 3), 0, BL2_INIT_STAGE_1, 0},
+ /* Enable VCCK GPIOAO_2*/
+ {AO_GPIO_O_EN_N, (0 << 2), (1 << 2), 0, BL2_INIT_STAGE_1, 0},
+ {AO_GPIO_O, (1 << 2), (1 << 2), 0, BL2_INIT_STAGE_1, 0},
+};
diff --git a/board/amlogic/tm2_ab301_v1/lcd.c b/board/amlogic/tm2_ab301_v1/lcd.c
new file mode 100644
index 0000000000..c40d6bb692
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/lcd.c
@@ -0,0 +1,615 @@
+/*
+ * AMLOGIC LCD panel driver.
+ *
+ * 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 named License,
+ * or 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.
+ *
+ */
+
+#include <common.h>
+#include <amlogic/aml_lcd.h>
+#ifdef CONFIG_AML_LOCAL_DIMMING
+#include <amlogic/aml_ldim.h>
+#endif
+
+static char lcd_cpu_gpio[LCD_CPU_GPIO_NUM_MAX][LCD_CPU_GPIO_NAME_MAX] = {
+ "GPIOAO_4",
+ "invalid", /* ending flag */
+};
+
+static struct lcd_power_step_s lcd_power_on_step[] = {
+ {LCD_POWER_TYPE_CPU, 0,1,20,}, /* panel vcc */
+ {LCD_POWER_TYPE_SIGNAL,0,0,0,},
+ {LCD_POWER_TYPE_MAX, 0,0,0,}, /* ending flag */
+};
+static struct lcd_power_step_s lcd_power_off_step[] = {
+ {LCD_POWER_TYPE_SIGNAL,0,0,0,},
+ {LCD_POWER_TYPE_CPU, 0,0,200,}, /* panel vcc */
+ {LCD_POWER_TYPE_MAX, 0,0,0,}, /* ending flag */
+};
+
+static struct lcd_power_step_s lcd_power_on_step_p2p[] = {
+ {LCD_POWER_TYPE_CPU, 0,1,20,}, /* panel vcc */
+ {LCD_POWER_TYPE_EXTERN,0,0,100,}, /* init external voltage */
+ {LCD_POWER_TYPE_SIGNAL,0,0,0,},
+ {LCD_POWER_TYPE_MAX, 0,0,0,}, /* ending flag */
+};
+static struct lcd_power_step_s lcd_power_off_step_p2p[] = {
+ {LCD_POWER_TYPE_SIGNAL,0,0,0,},
+ {LCD_POWER_TYPE_CPU, 0,0,200,}, /* panel vcc */
+ {LCD_POWER_TYPE_MAX, 0,0,0,}, /* ending flag */
+};
+
+static char lcd_bl_gpio[BL_GPIO_NUM_MAX][LCD_CPU_GPIO_NAME_MAX] = {
+ "GPIOAO_11",
+ "GPIOZ_5",
+ "GPIOZ_6",
+ "invalid", /* ending flag */
+};
+
+#ifdef CONFIG_AML_LOCAL_DIMMING
+static char lcd_bl_ldim_gpio[BL_GPIO_NUM_MAX][LCD_CPU_GPIO_NAME_MAX] = {
+ "GPIOH_10", /* LD_EN */
+ "GPIOZ_5", /* DIMMING_PWM */
+ "GPIOZ_6", /* LD_EN2 */
+ "invalid", /* ending flag */
+};
+#endif
+
+struct ext_lcd_config_s ext_lcd_config[LCD_NUM_MAX] = {
+ {/* normal*/
+ "lvds_0",LCD_LVDS,8,
+ /* basic timing */
+ 1920,1080,2200,1125,44,148,0,5,36,0,
+ /* clk_attr */
+ 0,0,1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* lvds_attr */
+ 1,1,0,0,0,0xf,0x0,Rsv_val,Rsv_val,Rsv_val,
+ /* power step */
+ lcd_power_on_step, lcd_power_off_step,
+ /* backlight */
+ 60,255,10,128,128,
+ BL_CTRL_PWM,0,1,0,200,200,
+ BL_PWM_POSITIVE,BL_PWM_C,180,100,25,1,0,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ 10,10,Rsv_val},
+
+ {/* for HDMI convert*/
+ "lvds_1",LCD_LVDS,8,
+ /* basic timing */
+ 1920,1080,2200,1125,44,148,0,5,36,0,
+ /* clk_attr */
+ 1,0,1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* lvds_attr */
+ 1,1,0,0,0,0xf,0x0,Rsv_val,Rsv_val,Rsv_val,
+ /* power step */
+ lcd_power_on_step, lcd_power_off_step,
+ /* backlight */
+ 60,255,10,128,128,
+ BL_CTRL_MAX,0,1,0,200,200,
+ BL_PWM_POSITIVE,BL_PWM_C,180,100,25,1,0,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ 10,10,Rsv_val},
+
+ {/*public 2-region vx1 : 3840x2160@60hz 8lane */
+ "vbyone_0",LCD_VBYONE,10,
+ /* basic timing */
+ 3840,2160,4400,2250,33,477,0,6,81,0,
+ /* clk_attr */
+ 2,0,1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* vbyone_attr */
+ 8,2,4,4,0xf,0x1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* power step */
+ lcd_power_on_step, lcd_power_off_step,
+ /* backlight */
+ 60,255,10,128,128,
+ BL_CTRL_PWM,0,1,0,200,200,
+ BL_PWM_POSITIVE,BL_PWM_C,180,100,25,1,0,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ 10,10,Rsv_val},
+
+ {/*public 1-region vx1 : 3840x2160@60hz 8lane */
+ "vbyone_1",LCD_VBYONE,10,
+ /* basic timing */
+ 3840,2160,4400,2250,33,477,0,6,81,0,
+ /* clk_attr */
+ 2,0,1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* vbyone_attr */
+ 8,1,4,4,0xf,0x1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* power step */
+ lcd_power_on_step, lcd_power_off_step,
+ /* backlight */
+ 60,255,10,128,128,
+ BL_CTRL_PWM,0,1,0,200,200,
+ BL_PWM_POSITIVE,BL_PWM_C,180,100,25,1,0,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ 10,10,Rsv_val},
+
+ {/*public p2p ceds : 3840x2160@60hz 12lane */
+ "p2p_0",LCD_P2P,8,
+ /* basic timing */
+ 3840,2160,5000,2250,16,29,0,6,81,0,
+ /* clk_attr */
+ 2,0,1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* p2p attr */
+ 0x0,12,0x76543210,0xba98,0,0,0xf,0x1,Rsv_val,Rsv_val,
+ /* power step */
+ lcd_power_on_step_p2p, lcd_power_off_step_p2p,
+ /* backlight */
+ 60,255,10,128,128,
+ BL_CTRL_MAX,0,1,0,200,200,
+ BL_PWM_POSITIVE,BL_PWM_C,180,100,25,1,0,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ 10,10,Rsv_val},
+
+ {/*public p2p ceds : 3840x2160@60hz 6lane */
+ "p2p_1",LCD_P2P,8,
+ /* basic timing */
+ 3840,2160,5000,2250,16,29,0,6,81,0,
+ /* clk_attr */
+ 2,0,1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* p2p attr */
+ 0x0,6,0x76543210,0xba98,0,0,0xf,0x1,Rsv_val,Rsv_val,
+ /* power step */
+ lcd_power_on_step_p2p, lcd_power_off_step_p2p,
+ /* backlight */
+ 60,255,10,128,128,
+ BL_CTRL_MAX,0,1,0,200,200,
+ BL_PWM_POSITIVE,BL_PWM_C,180,100,25,1,0,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ 10,10,Rsv_val},
+
+ {/*public p2p chpi : 3840x2160@60hz 6lane */
+ "p2p_2",LCD_P2P,8,
+ /* basic timing */
+ 3840,2160,4400,2250,16,29,0,6,81,0,
+ /* clk_attr */
+ 2,0,1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* p2p attr */
+ 0x10,6,0x76543210,0xba98,0,0,0xf,0x1,Rsv_val,Rsv_val,
+ /* power step */
+ lcd_power_on_step_p2p, lcd_power_off_step_p2p,
+ /* backlight */
+ 60,255,10,128,128,
+ BL_CTRL_MAX,0,1,0,200,200,
+ BL_PWM_POSITIVE,BL_PWM_C,180,100,25,1,0,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ 10,10,Rsv_val},
+
+ {/*public p2p chpi : 3840x2160@60hz 12lane */
+ "p2p_3",LCD_P2P,8,
+ /* basic timing */
+ 3840,2160,4400,2250,16,29,0,6,81,0,
+ /* clk_attr */
+ 2,0,1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* p2p attr */
+ 0x10,12,0x76543210,0xba98,0,0,0xf,0x1,Rsv_val,Rsv_val,
+ /* power step */
+ lcd_power_on_step_p2p, lcd_power_off_step_p2p,
+ /* backlight */
+ 60,255,10,128,128,
+ BL_CTRL_MAX,0,1,0,200,200,
+ BL_PWM_POSITIVE,BL_PWM_C,180,100,25,1,0,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ 10,10,Rsv_val},
+
+ {/* 1920*1080*/
+ "mlvds_0",LCD_MLVDS,8,
+ /* basic timing */
+ 1920,1080,2200,1125,44,148,0,5,36,0,
+ /* clk_attr */
+ 2,0,1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* minilvds_attr */
+ 6,0x76543210,0xba98,0x660,0,0,0xf,0x0,Rsv_val,Rsv_val,
+ /* power step */
+ lcd_power_on_step, lcd_power_off_step,
+ /* backlight */
+ 60,255,10,128,128,
+ BL_CTRL_MAX,0,1,0,200,200,
+ BL_PWM_POSITIVE,BL_PWM_C,180,100,25,1,0,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ 10,10,Rsv_val},
+
+ {/* 1366*768*/
+ "mlvds_1",LCD_MLVDS,8,
+ /* basic timing */
+ 1366,768,1560,806,56,64,0,3,28,0,
+ /* clk_attr */
+ 2,0,1,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ /* minilvds_attr */
+ 6,0x76543210,0xba98,0x660,0,0,0xf,0x0,Rsv_val,Rsv_val,
+ /* power step */
+ lcd_power_on_step, lcd_power_off_step,
+ /* backlight */
+ 60,255,10,128,128,
+ BL_CTRL_MAX,0,1,0,200,200,
+ BL_PWM_POSITIVE,BL_PWM_C,180,100,25,1,0,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ Rsv_val,Rsv_val,Rsv_val,Rsv_val,
+ 10,10,Rsv_val},
+
+ {.panel_type = "invalid"},
+};
+
+static struct lcd_pinmux_ctrl_s lcd_pinmux_ctrl[LCD_PINMX_MAX] = {
+ {
+ .name = "lcd_vbyone_pin", //GPIOH_15/16
+ .pinmux_set = {{8, 0x30000000}, {9, 0x00000003}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{8, 0xf0000000}, {9, 0x0000000f}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "lcd_minilvds_pin", //GPIOH_0~15
+ .pinmux_set = {{7, 0x11111111}, {8, 0x11111111}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{7, 0xffffffff}, {8, 0xffffffff}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "lcd_p2p_pin", //GPIOH_0~19
+ .pinmux_set = {{7, 0x11111111}, {8, 0x11111111}, {9, 0x11111}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{7, 0xffffffff}, {8, 0xffffffff}, {9, 0xfffff}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "invalid",
+ },
+};
+
+static struct lcd_pinmux_ctrl_s bl_pinmux_ctrl[BL_PINMUX_MAX] = {
+ {
+ .name = "bl_pwm_on_pin", //GPIOZ_5
+ .pinmux_set = {{2, 0x00400000}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{2, 0x00f00000}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "bl_pwm_vs_on_pin", //GPIOZ_5
+ .pinmux_set = {{2, 0x00300000}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{2, 0x00f00000}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "bl_pwm_combo_0_on_pin", //GPIOZ_5
+ .pinmux_set = {{2, 0x00400000}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{2, 0x00f00000}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "bl_pwm_combo_1_on_pin", //GPIOZ_6
+ .pinmux_set = {{2, 0x04000000}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{2, 0x0f000000}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "bl_pwm_combo_0_vs_on_pin", //GPIOZ_5
+ .pinmux_set = {{2, 0x00300000}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{2, 0x00f00000}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "bl_pwm_combo_1_vs_on_pin", //GPIOZ_6
+ .pinmux_set = {{2, 0x03000000}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{2, 0x0f000000}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "invalid",
+ },
+};
+
+#ifdef CONFIG_AML_LOCAL_DIMMING
+static struct lcd_pinmux_ctrl_s ldim_pinmux_ctrl[] = {
+ {
+ .name = "ldim_pwm_pin", //GPIOZ_5
+ .pinmux_set = {{2, 0x00400000}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{2, 0x00f00000}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "ldim_pwm_vs_pin", //GPIOZ_5
+ .pinmux_set = {{2, 0x00300000}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{2, 0x00f00000}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "analog_pwm_pin", //GPIOZ_6
+ .pinmux_set = {{2, 0x04000000}, {LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{2, 0x0f000000}, {LCD_PINMUX_END, 0x0}},
+ },
+ {
+ .name = "invalid",
+ .pinmux_set = {{LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{LCD_PINMUX_END, 0x0}},
+ },
+};
+#endif
+
+static struct vbyone_config_s lcd_vbyone_config = {
+ .lane_count = 8,
+ .byte_mode = 4,
+ .region_num = 2,
+ .color_fmt = 4,
+};
+
+static struct lvds_config_s lcd_lvds_config = {
+ .lvds_repack = 1, //0=JEDIA mode, 1=VESA mode
+ .dual_port = 1, //0=single port, 1=double port
+ .pn_swap = 0, //0=normal, 1=swap
+ .port_swap = 0, //0=normal, 1=swap
+ .lane_reverse = 0, //0=normal, 1=swap
+};
+
+static struct mlvds_config_s lcd_mlvds_config = {
+ .channel_num = 6,
+ .channel_sel0 = 0x45603012,
+ .channel_sel1 = 0x0,
+ .clk_phase = 0x0,
+ .pn_swap = 0, //0=normal, 1=swap
+ .bit_swap = 0, //0=normal, 1=swap
+};
+
+static struct p2p_config_s lcd_p2p_config = {
+ .p2p_type = 0,
+ .lane_num = 12,
+ .channel_sel0 = 0x76543210,
+ .channel_sel1 = 0xba98,
+ .pn_swap = 0, //0=normal, 1=swap
+ .bit_swap = 0, //0=normal, 1=swap
+};
+
+static struct lcd_power_ctrl_s lcd_power_ctrl = {
+ .power_on_step = {
+ {
+ .type = LCD_POWER_TYPE_MAX, /* ending flag */
+ },
+ },
+ .power_off_step = {
+ {
+ .type = LCD_POWER_TYPE_MAX, /* ending flag */
+ },
+ },
+};
+
+struct lcd_config_s lcd_config_dft = {
+ .lcd_mode = LCD_MODE_TV,
+ .lcd_key_valid = 0,
+ .lcd_basic = {
+ .model_name = "default",
+ .lcd_type = LCD_TYPE_MAX,
+ .lcd_bits = 8,
+ .h_active = 1920,
+ .v_active = 1080,
+ .h_period = 2200,
+ .v_period = 1125,
+
+ .screen_width = 16,
+ .screen_height = 9,
+ },
+
+ .lcd_timing = {
+ .clk_auto = 1,
+ .lcd_clk = 60,
+ .ss_level = 0,
+ .fr_adjust_type = 0,
+
+ .hsync_width = 44,
+ .hsync_bp = 148,
+ .hsync_pol = 0,
+ .vsync_width = 5,
+ .vsync_bp = 36,
+ .vsync_pol = 0,
+ },
+
+ .lcd_control = {
+ .lvds_config = &lcd_lvds_config,
+ .vbyone_config = &lcd_vbyone_config,
+ .mlvds_config = &lcd_mlvds_config,
+ .p2p_config = &lcd_p2p_config,
+ },
+ .lcd_power = &lcd_power_ctrl,
+
+ .pinctrl_ver = 2,
+ .lcd_pinmux = lcd_pinmux_ctrl,
+ .pinmux_set = {{LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{LCD_PINMUX_END, 0x0}},
+};
+
+#ifdef CONFIG_AML_LCD_EXTERN
+static char lcd_ext_gpio[LCD_EXTERN_GPIO_NUM_MAX][LCD_EXTERN_GPIO_LEN_MAX] = {
+ "invalid", /* ending flag */
+};
+
+static unsigned char init_on_table[LCD_EXTERN_INIT_ON_MAX] = {
+ 0xc0, 2, 0x01, 0x2b,
+ 0xc0, 2, 0x02, 0x05,
+ 0xc0, 2, 0x03, 0x00,
+ 0xc0, 2, 0x04, 0x00,
+ 0xc0, 2, 0x05, 0x0c,
+ 0xc0, 2, 0x06, 0x04,
+ 0xc0, 2, 0x07, 0x21,
+ 0xc0, 2, 0x08, 0x0f,
+ 0xc0, 2, 0x09, 0x04,
+ 0xc0, 2, 0x0a, 0x00,
+ 0xc0, 2, 0x0b, 0x04,
+ 0xc0, 2, 0xff, 0x00,
+ 0xfd, 1, 100 /* delay 100ms */
+
+ 0xc1, 2, 0x01, 0xca,
+ 0xc1, 2, 0x02, 0x3b,
+ 0xc1, 2, 0x03, 0x33,
+ 0xc1, 2, 0x04, 0x05,
+ 0xc1, 2, 0x05, 0x2c,
+ 0xc1, 2, 0x06, 0xf2,
+ 0xc1, 2, 0x07, 0x9c,
+ 0xc1, 2, 0x08, 0x1b,
+ 0xc1, 2, 0x09, 0x82,
+ 0xc1, 2, 0x0a, 0x3d,
+ 0xc1, 2, 0x0b, 0x20,
+ 0xc1, 2, 0x0c, 0x11,
+ 0xc1, 2, 0x0d, 0xc4,
+ 0xc1, 2, 0x0e, 0x1a,
+ 0xc1, 2, 0x0f, 0x31,
+ 0xc1, 2, 0x10, 0x4c,
+ 0xc1, 2, 0x11, 0x12,
+ 0xc1, 2, 0x12, 0x90,
+ 0xc1, 2, 0x13, 0xf7,
+ 0xc1, 2, 0x14, 0x0c,
+ 0xc1, 2, 0x15, 0x20,
+ 0xc1, 2, 0x16, 0x13,
+ 0xff, 0, /* ending */
+};
+
+static unsigned char init_off_table[LCD_EXTERN_INIT_OFF_MAX] = {
+ 0xff, 0, /* ending */
+};
+
+struct lcd_extern_common_s ext_common_dft = {
+ .lcd_ext_key_valid = 0,
+ .lcd_ext_num = 1,
+ .pinmux_set = {{LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{LCD_PINMUX_END, 0x0}},
+};
+struct lcd_extern_config_s ext_config_dtf[LCD_EXTERN_NUM_MAX] = {
+ {
+ .index = 0,
+ .name = "i2c_ANX6862_7911",
+ .type = LCD_EXTERN_I2C, /* LCD_EXTERN_I2C, LCD_EXTERN_SPI, LCD_EXTERN_MAX */
+ .status = 1, /* 0=disable, 1=enable */
+ .i2c_addr = 0x20, /* 7bit i2c address */
+ .i2c_addr2 = 0x74, /* 7bit i2c address, 0xff for none */
+ .i2c_bus = LCD_EXTERN_I2C_BUS_1, /* LCD_EXTERN_I2C_BUS_0/1/2/3/4 */
+ .cmd_size = 0xff,
+ .table_init_on = init_on_table,
+ .table_init_off = init_off_table,
+ },
+ {
+ .index = LCD_EXTERN_INDEX_INVALID,
+ },
+};
+#endif
+
+struct bl_config_s bl_config_dft = {
+ .name = "default",
+ .bl_key_valid = 0,
+
+ .level_default = 100,
+ .level_min = 10,
+ .level_max = 255,
+ .level_mid = 128,
+ .level_mid_mapping = 128,
+ .level = 0,
+
+ .method = BL_CTRL_MAX,
+ .power_on_delay = 200,
+ .power_off_delay = 200,
+
+ .en_gpio = 0xff,
+ .en_gpio_on = 1,
+ .en_gpio_off = 0,
+
+ .bl_pwm = NULL,
+ .bl_pwm_combo0 = NULL,
+ .bl_pwm_combo1 = NULL,
+ .pwm_on_delay = 10,
+ .pwm_off_delay = 10,
+
+ .bl_extern_index = 0xff,
+
+ .pinctrl_ver = 2,
+ .bl_pinmux = bl_pinmux_ctrl,
+ .pinmux_set = {{LCD_PINMUX_END, 0x0}},
+ .pinmux_clr = {{LCD_PINMUX_END, 0x0}},
+};
+
+#ifdef CONFIG_AML_LOCAL_DIMMING
+static unsigned char ldim_init_on[LDIM_INIT_ON_MAX];
+static unsigned char ldim_init_off[LDIM_INIT_OFF_MAX];
+struct ldim_dev_config_s ldim_config_dft = {
+ .type = LDIM_DEV_TYPE_NORMAL,
+ .cs_hold_delay = 0,
+ .cs_clk_delay = 0,
+ .en_gpio = 0xff,
+ .en_gpio_on = 1,
+ .en_gpio_off = 0,
+ .lamp_err_gpio = 0xff,
+ .fault_check = 0,
+ .write_check = 0,
+ .dim_min = 0x7f, /* min 3% duty */
+ .dim_max = 0xfff,
+ .init_loaded = 0,
+ .cmd_size = 0xff,
+ .init_on = ldim_init_on,
+ .init_off = ldim_init_off,
+ .init_on_cnt = sizeof(ldim_init_on),
+ .init_off_cnt = sizeof(ldim_init_off),
+ .ldim_pwm_config = {
+ .index = 0,
+ .pwm_method = BL_PWM_POSITIVE,
+ .pwm_port = BL_PWM_MAX,
+ .pwm_duty_max = 100,
+ .pwm_duty_min = 0,
+ },
+ .analog_pwm_config = {
+ .index = 1,
+ .pwm_method = BL_PWM_POSITIVE,
+ .pwm_port = BL_PWM_MAX,
+ .pwm_duty_max = 100,
+ .pwm_duty_min = 20,
+ },
+ .pinctrl_ver = 1,
+ .ldim_pinmux = ldim_pinmux_ctrl,
+};
+#endif
+
+void lcd_config_bsp_init(void)
+{
+ int i, j;
+
+ for (i = 0; i < LCD_CPU_GPIO_NUM_MAX; i++) {
+ if (strcmp(lcd_cpu_gpio[i], "invalid") == 0)
+ break;
+ strcpy(lcd_power_ctrl.cpu_gpio[i], lcd_cpu_gpio[i]);
+ }
+ for (j = i; j < LCD_CPU_GPIO_NUM_MAX; j++)
+ strcpy(lcd_power_ctrl.cpu_gpio[j], "invalid");
+ for (i = 0; i < BL_GPIO_NUM_MAX; i++) {
+ if (strcmp(lcd_bl_gpio[i], "invalid") == 0)
+ break;
+ strcpy(bl_config_dft.gpio_name[i], lcd_bl_gpio[i]);
+ }
+ for (j = i; j < BL_GPIO_NUM_MAX; j++)
+ strcpy(bl_config_dft.gpio_name[j], "invalid");
+
+#ifdef CONFIG_AML_LCD_EXTERN
+ for (i = 0; i < LCD_EXTERN_NUM_MAX; i++) {
+ if (ext_config_dtf[i].index == LCD_EXTERN_INDEX_INVALID)
+ break;
+ }
+ ext_common_dft.lcd_ext_num = i;
+
+ for (i = 0; i < LCD_EXTERN_GPIO_NUM_MAX; i++) {
+ if (strcmp(lcd_ext_gpio[i], "invalid") == 0)
+ break;
+ strcpy(ext_common_dft.gpio_name[i], lcd_ext_gpio[i]);
+ }
+ for (j = i; j < LCD_EXTERN_GPIO_NUM_MAX; j++)
+ strcpy(ext_common_dft.gpio_name[j], "invalid");
+
+#endif
+#ifdef CONFIG_AML_LOCAL_DIMMING
+ strcpy(ldim_config_dft.name, "invalid");
+ strcpy(ldim_config_dft.pinmux_name, "invalid");
+ for (i = 0; i < BL_GPIO_NUM_MAX; i++) {
+ if (strcmp(lcd_bl_ldim_gpio[i], "invalid") == 0)
+ break;
+ strcpy(ldim_config_dft.gpio_name[i], lcd_bl_ldim_gpio[i]);
+ }
+ for (j = i; j < BL_GPIO_NUM_MAX; j++)
+ strcpy(ldim_config_dft.gpio_name[j], "invalid");
+#endif
+}
diff --git a/board/amlogic/tm2_ab301_v1/mtk-bt/LD_btmtk_usb.c b/board/amlogic/tm2_ab301_v1/mtk-bt/LD_btmtk_usb.c
new file mode 100644
index 0000000000..a67d229749
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/mtk-bt/LD_btmtk_usb.c
@@ -0,0 +1,1532 @@
+/*
+* Copyright (c) 2014 MediaTek Inc.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* 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.
+*/
+
+/** steve wang 2015/11/26 */
+//---------------------------------------------------------------------------
+#include "LD_usbbt.h"
+#include "LD_btmtk_usb.h"
+#include "errno.h"
+
+//- Local Configuration -----------------------------------------------------
+#define LD_VERSION "1.2.0.1"
+
+#define BUFFER_SIZE (1024 * 4) /* Size of RX Queue */
+#define BT_SEND_HCI_CMD_BEFORE_SUSPEND 1
+#define LD_SUPPORT_FW_DUMP 0
+#define LD_BT_ALLOC_BUF 0
+#define LD_NOT_FIX_BUILD_WARN 0
+
+#define FIDX 0x5A /* Unify WoBLE APCF Filtering Index */
+
+#ifndef strtol
+#define strtol simple_strtol
+#endif
+
+//---------------------------------------------------------------------------
+static char driver_version[64] = { 0 };
+static unsigned char probe_counter = 0;
+static volatile int metaMode;
+static volatile int metaCount;
+/* 0: False; 1: True */
+static int isbtready;
+static int isUsbDisconnet;
+static volatile int is_assert = 0;
+
+//---------------------------------------------------------------------------
+static inline int is_mt7630(struct LD_btmtk_usb_data *data)
+{
+ return ((data->chip_id & 0xffff0000) == 0x76300000);
+}
+
+//---------------------------------------------------------------------------
+static inline int is_mt7650(struct LD_btmtk_usb_data *data)
+{
+ return ((data->chip_id & 0xffff0000) == 0x76500000);
+}
+
+//---------------------------------------------------------------------------
+static inline int is_mt7632(struct LD_btmtk_usb_data *data)
+{
+ return ((data->chip_id & 0xffff0000) == 0x76320000);
+}
+
+//---------------------------------------------------------------------------
+static inline int is_mt7662(struct LD_btmtk_usb_data *data)
+{
+ return ((data->chip_id & 0xffff0000) == 0x76620000);
+}
+
+//---------------------------------------------------------------------------
+static inline int is_mt7662T(struct LD_btmtk_usb_data *data)
+{
+ return ((data->chip_id & 0xffffffff) == 0x76620100);
+}
+
+//---------------------------------------------------------------------------
+static inline int is_mt7632T(struct LD_btmtk_usb_data *data)
+{
+ return ((data->chip_id & 0xffffffff) == 0x76320100);
+}
+
+//---------------------------------------------------------------------------
+static inline int is_mt7668(struct LD_btmtk_usb_data *data)
+{
+ return ((data->chip_id & 0xffff) == 0x7668);
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_io_read32(struct LD_btmtk_usb_data *data, u32 reg, u32 *val)
+{
+ u8 request = data->r_request;
+ int ret;
+
+ ret = data->hcif->usb_control_msg(data->udev, MTKBT_CTRL_RX_EP, request,
+ DEVICE_VENDOR_REQUEST_IN, 0, (u16)reg, data->io_buf, sizeof(u32),
+ CONTROL_TIMEOUT_JIFFIES);
+
+ if (ret < 0)
+ {
+ *val = 0xffffffff;
+ usb_debug("error(%d), reg=%x, value=%x\n", ret, reg, *val);
+ return ret;
+ }
+
+ os_memmove(val, data->io_buf, sizeof(u32));
+ *val = le32_to_cpu(*val);
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_io_read32_7668(struct LD_btmtk_usb_data *data, u32 reg, u32 *val)
+{
+ int ret = -1;
+ __le16 reg_high;
+ __le16 reg_low;
+
+ reg_high = ((reg >> 16) & 0xFFFF);
+ reg_low = (reg & 0xFFFF);
+
+ ret = data->hcif->usb_control_msg(data->udev, MTKBT_CTRL_RX_EP, 0x63,
+ DEVICE_VENDOR_REQUEST_IN, reg_high, reg_low, data->io_buf, sizeof(u32),
+ CONTROL_TIMEOUT_JIFFIES);
+ if (ret < 0) {
+ *val = 0xFFFFFFFF;
+ usb_debug("error(%d), reg=%X, value=%X\n", ret, reg, *val);
+ return ret;
+ }
+
+ os_memmove(val, data->io_buf, sizeof(u32));
+ *val = le32_to_cpu(*val);
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_io_write32(struct LD_btmtk_usb_data *data, u32 reg, u32 val)
+{
+ u16 value, index;
+ u8 request = data->w_request;
+ mtkbt_dev_t *udev = data->udev;
+ int ret;
+
+ index = (u16) reg;
+ value = val & 0x0000ffff;
+
+ ret = data->hcif->usb_control_msg(udev, MTKBT_CTRL_TX_EP, request, DEVICE_VENDOR_REQUEST_OUT,
+ value, index, NULL, 0, CONTROL_TIMEOUT_JIFFIES);
+
+ if (ret < 0)
+ {
+ usb_debug("error(%d), reg=%x, value=%x\n", ret, reg, val);
+ return ret;
+ }
+
+ index = (u16) (reg + 2);
+ value = (val & 0xffff0000) >> 16;
+
+ ret = data->hcif->usb_control_msg(udev, MTKBT_CTRL_TX_EP, request, DEVICE_VENDOR_REQUEST_OUT,
+ value, index, NULL, 0, CONTROL_TIMEOUT_JIFFIES);
+
+ if (ret < 0)
+ {
+ usb_debug("error(%d), reg=%x, value=%x\n", ret, reg, val);
+ return ret;
+ }
+ if (ret > 0)
+ {
+ ret = 0;
+ }
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_send_wmt_cmd(struct LD_btmtk_usb_data *data, const u8 *cmd,
+ const int cmd_len, const u8 *event, const int event_len, u32 delay, u8 retry)
+{
+ int ret = -1;
+ BOOL check = FALSE;
+
+ if (!data || !data->hcif || !data->io_buf || !cmd) {
+ usb_debug("incorrect cmd pointer\n");
+ return -1;
+ }
+ if (event != NULL && event_len > 0)
+ check = TRUE;
+
+ /* send WMT command */
+ ret = data->hcif->usb_control_msg(data->udev, MTKBT_CTRL_TX_EP, 0x01,
+ DEVICE_CLASS_REQUEST_OUT, 0x30, 0x00, (void *)cmd, cmd_len,
+ CONTROL_TIMEOUT_JIFFIES);
+ if (ret < 0) {
+ usb_debug("command send failed(%d)\n", ret);
+ return ret;
+ }
+
+ if (event_len == -1) {
+ /* If event_len is -1, DO NOT read event, since FW wouldn't feedback */
+ return 0;
+ }
+
+retry_get:
+ MTK_MDELAY(delay);
+
+ /* check WMT event */
+ ret = data->hcif->usb_control_msg(data->udev, MTKBT_CTRL_RX_EP, 0x01,
+ DEVICE_VENDOR_REQUEST_IN, 0x30, 0x00, data->io_buf, LD_BT_MAX_EVENT_SIZE,
+ CONTROL_TIMEOUT_JIFFIES);
+ if (ret < 0) {
+ usb_debug("event get failed(%d)\n", ret);
+ if (check == TRUE) return ret;
+ else return 0;
+ }
+
+ if (check == TRUE) {
+ if (ret >= event_len && memcmp(event, data->io_buf, event_len) == 0) {
+ return ret;
+ } else if (retry > 0) {
+ usb_debug("retry to get event(%d)\n", retry);
+ retry--;
+ goto retry_get;
+ } else {
+ usb_debug("can't get expect event\n");
+ }
+ }
+ return -1;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_send_hci_cmd(struct LD_btmtk_usb_data *data, const u8 *cmd,
+ const int cmd_len, const u8 *event, const int event_len)
+{
+ /** @RETURN
+ * length if event compare successfully.,
+ * 0 if doesn't check event.,
+ * < 0 if error.
+ */
+#define USB_CTRL_IO_TIMO 100
+#define USB_INTR_MSG_TIMO 2000
+ int ret = -1;
+ int len = 0;
+ int i = 0;
+ u8 retry = 0;
+ BOOL check = FALSE;
+
+ if (!data || !data->hcif || !data->io_buf || !cmd) {
+ usb_debug("incorrect cmd pointer\n");
+ return -1;
+ }
+ if (event != NULL && event_len > 0)
+ check = TRUE;
+
+ /* send HCI command */
+ ret = data->hcif->usb_control_msg(data->udev, MTKBT_CTRL_TX_EP, 0,
+ DEVICE_CLASS_REQUEST_OUT, 0, 0, (u8 *)cmd, cmd_len, USB_CTRL_IO_TIMO);
+ if (ret < 0) {
+ usb_debug("send command failed: %d\n", ret);
+ return ret;
+ }
+
+ if (event_len == -1) {
+ /* If event_len is -1, DO NOT read event, since FW wouldn't feedback */
+ return 0;
+ }
+
+ /* check HCI event */
+ do {
+ ret = data->hcif->usb_interrupt_msg(data->udev, MTKBT_INTR_EP, data->io_buf,
+ LD_BT_MAX_EVENT_SIZE, &len, USB_INTR_MSG_TIMO);
+ if (ret < 0) {
+ usb_debug("event get failed: %d\n", ret);
+ if (check == TRUE) return ret;
+ else return 0;
+ }
+
+ if (check == TRUE) {
+ if (len >= event_len) {
+ for (i = 0; i < event_len; i++) {
+ if (event[i] != data->io_buf[i])
+ break;
+ }
+ } else {
+ usb_debug("event length is not match(%d/%d)\n", len, event_len);
+ }
+ if (i != event_len) {
+ usb_debug("got unknown event(%d)\n", len);
+ } else {
+ return len; /* actually read length */
+ }
+ MTK_MDELAY(10);
+ ++retry;
+ }
+ usb_debug("try get event again\n");
+ } while (retry < 3);
+ return -1;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_send_hci_suspend_cmd(struct LD_btmtk_usb_data *data)
+{
+ int ret = -1;
+ /* mtkbt_dev_t *udev = data->udev; */
+#if SUPPORT_HISENSE_WoBLE
+ u8 cmd[] = {0xC9, 0xFC, 0x02, 0x01, 0x0D}; // for Hisense WoBLE
+
+ usb_debug("issue wake up command for Hisense\n");
+#else
+ u8 cmd[] = {0xC9, 0xFC, 0x0D, 0x01, 0x0E, 0x00, 0x05, 0x43,
+ 0x52, 0x4B, 0x54, 0x4D, 0x20, 0x04, 0x32, 0x00};
+
+ usb_debug("issue wake up command for '0E: MTK WoBLE Ver2'\n");
+#endif
+
+ ret = btmtk_usb_send_hci_cmd(data, cmd, sizeof(cmd), NULL, -1);
+ if (ret < 0) {
+ usb_debug("error(%d)\n", ret);
+ return ret;
+ }
+ usb_debug("send suspend cmd OK\n");
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_send_hci_reset_cmd(struct LD_btmtk_usb_data *data)
+{
+ u8 cmd[] = { 0x03, 0x0C, 0x00 };
+ u8 event[] = { 0x0E, 0x04, 0x01, 0x03, 0x0C, 0x00 };
+ int ret = -1;
+
+ ret = btmtk_usb_send_hci_cmd(data, cmd, sizeof(cmd), event, sizeof(event));
+ if (ret < 0) {
+ usb_debug("failed(%d)\n", ret);
+ } else {
+ usb_debug("OK\n");
+ }
+
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_send_hci_set_ce_cmd(struct LD_btmtk_usb_data *data)
+{
+ u8 cmd[] = { 0xD1, 0xFC, 0x04, 0x0C, 0x07, 0x41, 0x00 };
+ u8 event[] = { 0x0E, 0x08, 0x01, 0xD1, 0xFC, 0x00 };
+ int ret = -1;
+
+ ret = btmtk_usb_send_hci_cmd(data, cmd, sizeof(cmd), event, sizeof(event));
+ if (ret < 0) {
+ usb_debug("failed(%d)\n", ret);
+
+ } else if (ret == sizeof(event) + 4) {
+ if (data->io_buf[6] & 0x01) {
+ usb_debug("warning, 0x41070c[0] is 1!\n");
+ ret = 0;
+ } else {
+ u8 cmd2[11] = { 0xD0, 0xFC, 0x08, 0x0C, 0x07, 0x41, 0x00 };
+
+ cmd2[7] = data->io_buf[6] | 0x01;
+ cmd2[8] = data->io_buf[7];
+ cmd2[9] = data->io_buf[8];
+ cmd2[10] = data->io_buf[9];
+
+ ret = btmtk_usb_send_hci_cmd(data, cmd2, sizeof(cmd2), NULL, 0);
+ if (ret < 0) {
+ usb_debug("write 0x41070C failed(%d)\n", ret);
+ } else {
+ usb_debug("OK");
+ ret = 0;
+ }
+ }
+ } else {
+ usb_debug("failed, incorrect response length(%d)\n", ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_send_check_rom_patch_result_cmd(struct LD_btmtk_usb_data *data)
+{
+ /* Send HCI Reset */
+ {
+ int ret = 0;
+ unsigned char buf[8] = { 0 };
+ buf[0] = 0xD1;
+ buf[1] = 0xFC;
+ buf[2] = 0x04;
+ buf[3] = 0x00;
+ buf[4] = 0xE2;
+ buf[5] = 0x40;
+ buf[6] = 0x00;
+ ret = data->hcif->usb_control_msg(data->udev, MTKBT_CTRL_TX_EP,0x0, DEVICE_CLASS_REQUEST_OUT,
+ 0x00, 0x00, buf, 0x07, 100);
+ if (ret < 0)
+ {
+ usb_debug("error1(%d)\n", ret);
+ return ret;
+ }
+ }
+ /* Get response of HCI reset */
+ {
+ int ret = 0;
+ unsigned char buf[LD_BT_MAX_EVENT_SIZE] = { 0 };
+ int actual_length = 0;
+ ret = data->hcif->usb_interrupt_msg(data->udev, MTKBT_INTR_EP, buf, LD_BT_MAX_EVENT_SIZE,
+ &actual_length, 2000);
+ if (ret < 0)
+ {
+ usb_debug("error2(%d)\n", ret);
+ return ret;
+ }
+ usb_debug("Check rom patch result : ");
+
+ if (buf[6] == 0 && buf[7] == 0 && buf[8] == 0 && buf[9] == 0)
+ {
+ usb_debug("NG\n");
+ }
+ else
+ {
+ usb_debug("OK\n");
+ }
+ }
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_switch_iobase(struct LD_btmtk_usb_data *data, int base)
+{
+ int ret = 0;
+
+ switch (base)
+ {
+ case SYSCTL:
+ data->w_request = 0x42;
+ data->r_request = 0x47;
+ break;
+ case WLAN:
+ data->w_request = 0x02;
+ data->r_request = 0x07;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static void btmtk_usb_cap_init(struct LD_btmtk_usb_data *data)
+{
+ btmtk_usb_io_read32(data, 0x00, &data->chip_id);
+ if (data->chip_id == 0)
+ btmtk_usb_io_read32_7668(data, 0x80000008, &data->chip_id);
+
+ //usb_debug("chip id = %x\n", data->chip_id);
+
+ if (is_mt7630(data) || is_mt7650(data)) {
+ data->need_load_fw = 1;
+ data->need_load_rom_patch = 0;
+ data->fw_header_image = NULL;
+ data->fw_bin_file_name = (unsigned char*)strdup("mtk/mt7650.bin");
+ data->fw_len = 0;
+
+ } else if (is_mt7662T(data) || is_mt7632T(data)) {
+ usb_debug("btmtk:This is 7662T chip\n");
+ data->need_load_fw = 0;
+ data->need_load_rom_patch = 1;
+ data->rom_patch_bin_file_name = os_kzalloc(32, MTK_GFP_ATOMIC);
+ if (!data->rom_patch_bin_file_name) {
+ usb_debug("Can't allocate memory (32)\n");
+ return;
+ }
+ os_memcpy(data->rom_patch_bin_file_name, "mt7662t_patch_e1_hdr.bin", 24);
+ data->rom_patch_offset = 0xBC000;
+ data->rom_patch_len = 0;
+
+ } else if (is_mt7632(data) || is_mt7662(data)) {
+ usb_debug("btmtk:This is 7662 chip\n");
+ data->need_load_fw = 0;
+ data->need_load_rom_patch = 1;
+ data->rom_patch_bin_file_name = os_kzalloc(32, MTK_GFP_ATOMIC);
+ if (!data->rom_patch_bin_file_name) {
+ usb_debug("Can't allocate memory (32)\n");
+ return;
+ }
+ os_memcpy(data->rom_patch_bin_file_name, "mt7662_patch_e3_hdr.bin", 23);
+ data->rom_patch_offset = 0x90000;
+ data->rom_patch_len = 0;
+
+ } else if (is_mt7668(data)) {
+ unsigned int chip_ver = 0;
+
+ data->need_load_fw = 0;
+ data->need_load_rom_patch = 1;
+ data->rom_patch_bin_file_name = os_kzalloc(32, MTK_GFP_ATOMIC);
+ if (!data->rom_patch_bin_file_name) {
+ usb_debug("Can't allocate memory (32)\n");
+ return;
+ }
+ btmtk_usb_io_read32_7668(data, 0x80000000, &chip_ver);
+ if (chip_ver == 0x8A00) {
+ usb_debug("btmtk:This is 7668 E1 chip\n");
+ os_memcpy(data->rom_patch_bin_file_name, "mt7668_patch_e1_hdr.bin", 23);
+ } else if (chip_ver == 0x8B10) {
+ usb_debug("btmtk:This is 7668 E2 chip\n");
+ os_memcpy(data->rom_patch_bin_file_name, "mt7668_patch_e2_hdr.bin", 23);
+ } else {
+ usb_debug("btmtk: Can't recognize version 0x%04X\n", chip_ver);
+ if (data->rom_patch_bin_file_name) os_kfree(data->rom_patch_bin_file_name);
+ }
+ data->chip_id |= chip_ver << 16;
+ data->rom_patch_offset = 0x2000000;
+ data->rom_patch_len = 0;
+
+ } else {
+ usb_debug("unknow chip(%x)\n", data->chip_id);
+ }
+}
+
+#if CRC_CHECK
+//---------------------------------------------------------------------------
+static u16 checksume16(u8 *pData, int len)
+{
+ int sum = 0;
+
+ while (len > 1)
+ {
+ sum += *((u16 *) pData);
+
+ pData = pData + 2;
+
+ if (sum & 0x80000000)
+ {
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ }
+ len -= 2;
+ }
+
+ if (len)
+ sum += *((u8 *) pData);
+
+ while (sum >> 16)
+ {
+ sum = (sum & 0xFFFF) + (sum >> 16);
+ }
+
+ return ~sum;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_chk_crc(struct LD_btmtk_usb_data *data, u32 checksum_len)
+{
+ int ret = 0;
+ mtkbt_dev_t *udev = data->udev;
+
+ usb_debug("\n");
+
+ os_memmove(data->io_buf, &data->rom_patch_offset, 4);
+ os_memmove(&data->io_buf[4], &checksum_len, 4);
+
+ ret = data->hcif->usb_control_msg(udev, MTKBT_CTRL_TX_EP,0x1, DEVICE_VENDOR_REQUEST_OUT,
+ 0x20, 0x00, data->io_buf, 8, CONTROL_TIMEOUT_JIFFIES);
+
+ if (ret < 0)
+ {
+ usb_debug("error(%d)\n", ret);
+ }
+
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static u16 btmtk_usb_get_crc(struct LD_btmtk_usb_data *data)
+{
+ int ret = 0;
+ mtkbt_dev_t *udev = data->udev;
+ u16 crc, count = 0;
+
+ usb_debug("\n");
+
+ while (1)
+ {
+ ret =
+ data->hcif->usb_control_msg(udev, MTKBT_CTRL_RX_EP, 0x01, DEVICE_VENDOR_REQUEST_IN,
+ 0x21, 0x00, data->io_buf, 2, CONTROL_TIMEOUT_JIFFIES);
+
+ if (ret < 0)
+ {
+ crc = 0xFFFF;
+ usb_debug("error(%d)\n", ret);
+ }
+
+ os_memmove(&crc, data->io_buf, 2);
+
+ crc = le16_to_cpu(crc);
+
+ if (crc != 0xFFFF)
+ break;
+
+ MTK_MDELAY(100);
+
+ if (count++ > 100)
+ {
+ usb_debug("Query CRC over %d times\n", count);
+ break;
+ }
+ }
+
+ return crc;
+}
+#endif /* CRC_CHECK */
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_send_wmt_reset_cmd(struct LD_btmtk_usb_data *data)
+{
+ /* reset command */
+ u8 cmd[] = { 0x6F, 0xFC, 0x05, 0x01, 0x07, 0x01, 0x00, 0x04 };
+ u8 event[] = { 0xE4, 0x05, 0x02, 0x07, 0x01, 0x00, 0x00 };
+ int ret = -1;
+
+ ret = btmtk_usb_send_wmt_cmd(data, cmd, sizeof(cmd), event, sizeof(event), 20, 0);
+ if (ret < 0) {
+ usb_debug("Check reset wmt result : NG\n");
+ } else {
+ usb_debug("Check reset wmt result : OK\n");
+ ret = 0;
+ }
+
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static u16 btmtk_usb_get_rom_patch_result(struct LD_btmtk_usb_data *data)
+{
+ int ret = 0;
+
+ ret = data->hcif->usb_control_msg(data->udev, MTKBT_CTRL_RX_EP, 0x01,
+ DEVICE_VENDOR_REQUEST_IN, 0x30, 0x00, data->io_buf, 7,
+ CONTROL_TIMEOUT_JIFFIES);
+
+ if (ret < 0)
+ {
+ usb_debug("error(%d)\n", ret);
+ }
+
+ if (data->io_buf[0] == 0xe4 &&
+ data->io_buf[1] == 0x05 &&
+ data->io_buf[2] == 0x02 &&
+ data->io_buf[3] == 0x01 &&
+ data->io_buf[4] == 0x01 &&
+ data->io_buf[5] == 0x00 &&
+ data->io_buf[6] == 0x00)
+ {
+ //usb_debug("Get rom patch result : OK\n");
+ }
+ else
+ {
+ usb_debug("Get rom patch result : NG\n");
+ }
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+#define SHOW_FW_DETAILS(s) \
+ usb_debug("%s = %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c", s, \
+ tmp_str[0], tmp_str[1], tmp_str[2], tmp_str[3], \
+ tmp_str[4], tmp_str[5], tmp_str[6], tmp_str[7], \
+ tmp_str[8], tmp_str[9], tmp_str[10], tmp_str[11], \
+ tmp_str[12], tmp_str[13], tmp_str[14], tmp_str[15])
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_load_rom_patch(struct LD_btmtk_usb_data *data)
+{
+ u32 loop = 0;
+ u32 value;
+ s32 sent_len;
+ int ret = 0;
+ u32 patch_len = 0;
+ u32 cur_len = 0;
+ int real_len = 0;
+ int first_block = 1;
+ unsigned char phase;
+ void *buf;
+ char *pos;
+ unsigned char *tmp_str;
+
+ //usb_debug("begin\n");
+load_patch_protect:
+ btmtk_usb_switch_iobase(data, WLAN);
+ btmtk_usb_io_read32(data, SEMAPHORE_03, &value);
+ loop++;
+
+ if ((value & 0x01) == 0x00)
+ {
+ if (loop < 1000)
+ {
+ MTK_MDELAY(1);
+ goto load_patch_protect;
+ }
+ else
+ {
+ usb_debug("btmtk_usb_load_rom_patch ERR! Can't get semaphore! Continue\n");
+ }
+ }
+
+ btmtk_usb_switch_iobase(data, SYSCTL);
+
+ btmtk_usb_io_write32(data, 0x1c, 0x30);
+
+ btmtk_usb_switch_iobase(data, WLAN);
+
+ /* check ROM patch if upgrade */
+ if ((MT_REV_GTE(data, mt7662, REV_MT76x2E3)) || (MT_REV_GTE(data, mt7632, REV_MT76x2E3)))
+ {
+ btmtk_usb_io_read32(data, CLOCK_CTL, &value);
+ if ((value & 0x01) == 0x01)
+ {
+ usb_debug("btmtk_usb_load_rom_patch : no need to load rom patch\n");
+ btmtk_usb_send_hci_reset_cmd(data);
+ goto error;
+ }
+ }
+ else
+ {
+ btmtk_usb_io_read32(data, COM_REG0, &value);
+ if ((value & 0x02) == 0x02)
+ {
+ usb_debug("btmtk_usb_load_rom_patch : no need to load rom patch\n");
+ btmtk_usb_send_hci_reset_cmd(data);
+ goto error;
+ }
+ }
+
+ buf = os_kzalloc(UPLOAD_PATCH_UNIT, MTK_GFP_ATOMIC);
+ if (!buf)
+ {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ pos = buf;
+
+ LD_load_code_from_bin(&data->rom_patch, (char *)data->rom_patch_bin_file_name, NULL,
+ data->udev, &data->rom_patch_len);
+
+ if (!data->rom_patch)
+ {
+ usb_debug("please assign a rom patch(/system/etc/firmware/%s)or(/lib/firmware/%s)\n",
+ data->rom_patch_bin_file_name,
+ data->rom_patch_bin_file_name);
+ ret = -1;
+ goto error;
+ }
+
+ tmp_str = data->rom_patch;
+ SHOW_FW_DETAILS("FW Version");
+ SHOW_FW_DETAILS("build Time");
+
+ tmp_str = data->rom_patch + 16;
+ usb_debug("platform = %c%c%c%c\n", tmp_str[0], tmp_str[1], tmp_str[2], tmp_str[3]);
+
+ tmp_str = data->rom_patch + 20;
+ usb_debug("HW/SW version = %c%c%c%c\n", tmp_str[0], tmp_str[1], tmp_str[2], tmp_str[3]);
+
+ tmp_str = data->rom_patch + 24;
+ usb_debug("Patch version = %c%c%c%c\n", tmp_str[0], tmp_str[1], tmp_str[2], tmp_str[3]);
+
+ usb_debug("\nloading rom patch...\n");
+
+ cur_len = 0x00;
+ patch_len = data->rom_patch_len - PATCH_INFO_SIZE;
+
+ /* loading rom patch */
+ while (1)
+ {
+ s32 sent_len_max = UPLOAD_PATCH_UNIT - PATCH_HEADER_SIZE;
+ real_len = 0;
+ sent_len =
+ (patch_len - cur_len) >= sent_len_max ? sent_len_max : (patch_len - cur_len);
+
+ //usb_debug("patch_len = %d\n", patch_len);
+ //usb_debug("cur_len = %d\n", cur_len);
+ //usb_debug("sent_len = %d\n", sent_len);
+
+ if (sent_len > 0)
+ {
+ if (first_block == 1)
+ {
+ if (sent_len < sent_len_max)
+ phase = PATCH_PHASE3;
+ else
+ phase = PATCH_PHASE1;
+ first_block = 0;
+ }
+ else if (sent_len == sent_len_max)
+ {
+ if (patch_len - cur_len == sent_len_max)
+ phase = PATCH_PHASE3;
+ else
+ phase = PATCH_PHASE2;
+ }
+ else
+ {
+ phase = PATCH_PHASE3;
+ }
+
+ /* prepare HCI header */
+ pos[0] = 0x6F;
+ pos[1] = 0xFC;
+ pos[2] = (sent_len + 5) & 0xFF;
+ pos[3] = ((sent_len + 5) >> 8) & 0xFF;
+
+ /* prepare WMT header */
+ pos[4] = 0x01;
+ pos[5] = 0x01;
+ pos[6] = (sent_len + 1) & 0xFF;
+ pos[7] = ((sent_len + 1) >> 8) & 0xFF;
+
+ pos[8] = phase;
+
+ os_memcpy(&pos[9], data->rom_patch + PATCH_INFO_SIZE + cur_len, sent_len);
+
+ //usb_debug("sent_len + PATCH_HEADER_SIZE = %d, phase = %d\n",
+ //sent_len + PATCH_HEADER_SIZE, phase);
+
+ ret = data->hcif->usb_bulk_msg(data->udev, MTKBT_BULK_TX_EP, buf, sent_len + PATCH_HEADER_SIZE, &real_len, 0);
+
+ if (ret)
+ {
+ usb_debug("upload rom_patch err: %d\n", ret);
+ goto error;
+ }
+
+ MTK_MDELAY(1);
+
+ cur_len += sent_len;
+
+ }
+ else
+ {
+ usb_debug("loading rom patch... Done\n");
+ break;
+ }
+ }
+
+ MTK_MDELAY(20);
+ ret = btmtk_usb_get_rom_patch_result(data);
+ MTK_MDELAY(20);
+
+ /* Send Checksum request */
+ #if CRC_CHECK
+ int total_checksum = checksume16(data->rom_patch + PATCH_INFO_SIZE, patch_len);
+ btmtk_usb_chk_crc(data, patch_len);
+ MTK_MDELAY(20);
+ if (total_checksum != btmtk_usb_get_crc(data))
+ {
+ usb_debug("checksum fail!, local(0x%x) <> fw(0x%x)\n", total_checksum,
+ btmtk_usb_get_crc(data));
+ ret = -1;
+ goto error;
+ }
+ else
+ {
+ usb_debug("crc match!\n");
+ }
+ #endif
+ MTK_MDELAY(20);
+ /* send check rom patch result request */
+ btmtk_usb_send_check_rom_patch_result_cmd(data);
+ MTK_MDELAY(20);
+ /* CHIP_RESET */
+ ret = btmtk_usb_send_wmt_reset_cmd(data);
+ MTK_MDELAY(20);
+ /* BT_RESET */
+ btmtk_usb_send_hci_reset_cmd(data);
+ /* for WoBLE/WoW low power */
+ btmtk_usb_send_hci_set_ce_cmd(data);
+
+ error:
+ btmtk_usb_io_write32(data, SEMAPHORE_03, 0x1);
+ //usb_debug("end\n");
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_send_wmt_power_on_cmd_7668(struct LD_btmtk_usb_data *data)
+{
+ u8 count = 0; /* retry 3 times */
+ u8 cmd[] = { 0x6F, 0xFC, 0x06, 0x01, 0x06, 0x02, 0x00, 0x00, 0x01 };
+ u8 event[] = { 0xE4, 0x05, 0x02, 0x06, 0x01, 0x00 }; /* event[6] is key */
+ int ret = -1; /* if successful, 0 */
+
+ do {
+ ret = btmtk_usb_send_wmt_cmd(data, cmd, sizeof(cmd), event, sizeof(event), 100, 10);
+ if (ret < 0) {
+ usb_debug("failed(%d)\n", ret);
+ } else if (ret == sizeof(event) + 1) {
+ switch (data->io_buf[6]) {
+ case 0: /* successful */
+ usb_debug("OK\n");
+ ret = 0;
+ break;
+ case 2: /* retry */
+ usb_debug("Try again\n");
+ continue;
+ default:
+ usb_debug("Unknown result: %02X\n", data->io_buf[6]);
+ return -1;
+ }
+ } else {
+ usb_debug("failed, incorrect response length(%d)\n", ret);
+ return -1;
+ }
+ } while (++count < 3 && ret > 0);
+
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_send_hci_tci_set_sleep_cmd_7668(struct LD_btmtk_usb_data *data)
+{
+ u8 cmd[] = { 0x7A, 0xFC, 0x07, 0x05, 0x40, 0x06, 0x40, 0x06, 0x00, 0x00 };
+ u8 event[] = { 0x0E, 0x04, 0x01, 0x7A, 0xFC, 0x00 };
+ int ret = -1; /* if successful, 0 */
+
+ ret = btmtk_usb_send_hci_cmd(data, cmd, sizeof(cmd), event, sizeof(event));
+ if (ret < 0) {
+ usb_debug("failed(%d)\n", ret);
+ } else {
+ usb_debug("OK\n");
+ ret = 0;
+ }
+
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_get_vendor_cap(struct LD_btmtk_usb_data *data)
+{
+ u8 cmd[] = { 0x53, 0xFD, 0x00 };
+ u8 event[6] = { 0x0E, 0x12, 0x01, 0x53, 0xFD, 0x00, /* ... */ };
+ int ret = -1;
+
+ // TODO: should not compare whole event
+ ret = btmtk_usb_send_hci_cmd(data, cmd, sizeof(cmd), event, sizeof(event));
+ if (ret < 0) {
+ usb_debug("Failed(%d)\n", ret);
+ } else {
+ usb_debug("OK\n");
+ ret = 0;
+ }
+
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_send_read_bdaddr(struct LD_btmtk_usb_data *data)
+{
+ u8 cmd[] = { 0x09, 0x10, 0x00 };
+ u8 event[] = { 0x0E, 0x0A, 0x01, 0x09, 0x10, 0x00, /* 6 bytes are BDADDR */ };
+ int ret = -1;
+
+ ret = btmtk_usb_send_hci_cmd(data, cmd, sizeof(cmd), event, sizeof(event));
+ if (ret < 0 || ret != 12 /* Event actual length */) {
+ usb_debug("Failed(%d)\n", ret);
+ return ret;
+ }
+
+ os_memcpy(data->local_addr, data->io_buf + 6, BD_ADDR_LEN);
+ usb_debug("ADDR: %02X-%02X-%02X-%02X-%02X-%02X\n",
+ data->local_addr[5], data->local_addr[4], data->local_addr[3],
+ data->local_addr[2], data->local_addr[1], data->local_addr[0]);
+ ret = 0;
+
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_set_apcf(struct LD_btmtk_usb_data *data, BOOL bin_file)
+{
+ int i = 0, ret = -1;
+ // Legacy RC pattern
+ u8 manufacture_data[] = { 0x57, 0xFD, 0x27, 0x06, 0x00, FIDX,
+ 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x43, 0x52, 0x4B, 0x54, 0x4D, /* manufacturer data */
+ 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* mask */
+ u8 filter_cmd[] = { 0x57, 0xFD, 0x0A, 0x01, 0x00, FIDX, 0x20, 0x00,
+ 0x00, 0x00, 0x01, 0x80, 0x00 };
+ u8 event[] = { 0x0E, 0x07, 0x01, 0x57, 0xFD, 0x00, /* ... */ };
+
+ if (bin_file) {
+ if (data->wake_dev_len) {
+ /* wake_on_ble.conf using 90(0x5A-FIDX) as filter_index */
+ u8 pos = 0;
+ u8 broadcast_addr[] = { 0x57, 0xFD, 0x0A, 0x02, 0x00, FIDX,
+ 0x55, 0x44, 0x33, 0x22, 0x11, 0x00, // ADDRESS
+ 0x00 }; // 0: Public, 1: Random
+ u8 adv_pattern[] = { 0x57, 0xFD, 0x15, 0x06, 0x00, FIDX,
+ 0x71, 0x01, // VID
+ 0x04, 0x11, // PID
+ 0x00, 0x00, 0x00, 0x00, // IR key code
+ 0x00, // sequence number
+ 0xFF, 0xFF, // mask~
+ 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00 };
+
+ // BDADDR
+ for (i = 0; i < data->wake_dev[1]; i++) {
+ broadcast_addr[11] = data->wake_dev[2 + i * BD_ADDR_LEN + 0];
+ broadcast_addr[10] = data->wake_dev[2 + i * BD_ADDR_LEN + 1];
+ broadcast_addr[9] = data->wake_dev[2 + i * BD_ADDR_LEN + 2];
+ broadcast_addr[8] = data->wake_dev[2 + i * BD_ADDR_LEN + 3];
+ broadcast_addr[7] = data->wake_dev[2 + i * BD_ADDR_LEN + 4];
+ broadcast_addr[6] = data->wake_dev[2 + i * BD_ADDR_LEN + 5];
+ ret = btmtk_usb_send_hci_cmd(data, broadcast_addr, sizeof(broadcast_addr),
+ event, sizeof(event));
+ if (ret < 0) {
+ usb_debug("Set broadcast address fail\n");
+ continue;
+ }
+ // mask broadcast address as a filter condition
+ filter_cmd[6] = 0x21;
+ }
+ usb_debug("There are %d broadcast address filter(s) from %s\n", i, WAKE_DEV_RECORD);
+
+ /** VID/PID in conf is LITTLE endian, but PID in ADV is BIG endian */
+ pos = 2 + data->wake_dev[1] * 6;
+ for (i = 0; i < data->wake_dev[pos]; i++) {
+ adv_pattern[6] = data->wake_dev[pos + (i * 4) + 1];
+ adv_pattern[7] = data->wake_dev[pos + (i * 4) + 2];
+ adv_pattern[9] = data->wake_dev[pos + (i * 4) + 3];
+ adv_pattern[8] = data->wake_dev[pos + (i * 4) + 4];
+ ret = btmtk_usb_send_hci_cmd(data, adv_pattern, sizeof(adv_pattern),
+ event, sizeof(event));
+ if (ret < 0) {
+ usb_debug("Set advertising patten fail\n");
+ return ret;
+ }
+ }
+ usb_debug("There are %d manufacture data filter(s) from %s\n", i, WAKE_DEV_RECORD);
+
+ // Filtering parameters
+ ret = btmtk_usb_send_hci_cmd(data, filter_cmd, sizeof(filter_cmd),
+ event, sizeof(event));
+ if (ret < 0) {
+ usb_debug("Set filtering parm fail\n");
+ return ret;
+ }
+
+ // if wake_on_ble.conf exist, no need use default woble_setting.bin
+ } else {
+ // woble_setting.bin
+ usb_debug("Set APCF filter from woble_setting.bin\n");
+ for (i = 0; i < APCF_SETTING_COUNT; i++) {
+ if (!data->apcf_cmd[i].len)
+ continue;
+ ret = btmtk_usb_send_hci_cmd(data, data->apcf_cmd[i].value, data->apcf_cmd[i].len,
+ event, sizeof(event));
+ if (ret < 0) {
+ usb_debug("Set apcf_cmd[%d] data fail\n", i);
+ return ret;
+ }
+ }
+ }
+
+ } else {
+ // Use default
+ usb_debug("Using default APCF filter\n");
+ os_memcpy(manufacture_data + 9, data->local_addr, BD_ADDR_LEN);
+ ret = btmtk_usb_send_hci_cmd(data, manufacture_data,
+ sizeof(manufacture_data), event, sizeof(event));
+ if (ret < 0) {
+ usb_debug("Set manufacture data fail\n");
+ return ret;
+ }
+
+ ret = btmtk_usb_send_hci_cmd(data, filter_cmd, sizeof(filter_cmd),
+ event, sizeof(event));
+ if (ret < 0) {
+ usb_debug("Set manufacture data fail\n");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+static BOOL btmtk_usb_check_need_load_patch_7668(struct LD_btmtk_usb_data *data)
+{
+ /* TRUE: need load patch., FALSE: do not need */
+ u8 cmd[] = { 0x6F, 0xFC, 0x05, 0x01, 0x17, 0x01, 0x00, 0x01 };
+ u8 event[] = { 0xE4, 0x05, 0x02, 0x17, 0x01, 0x00, /* 0x02 */ }; /* event[6] is key */
+ int ret = -1;
+
+ ret = btmtk_usb_send_wmt_cmd(data, cmd, sizeof(cmd), event, sizeof(event), 20, 0);
+ /* can't get correct event, need load patch */
+ if (ret < 0) {
+ usb_debug("check need load patch or not fail(%d)", ret);
+ return TRUE;
+ }
+
+ if (ret == sizeof(event) + 1 && (data->io_buf[6] == 0x00 || data->io_buf[6] == 0x01))
+ return FALSE; /* Do not need */
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+static int btmtk_usb_load_rom_patch_7668(struct LD_btmtk_usb_data *data)
+{
+ int ret = 0;
+ int first_block = 1;
+ int real_len = 0;
+ void *buf = NULL;
+ char *tmp_str = NULL;
+ u8 *pos = NULL;
+ u8 phase = 0;
+ u32 cur_len = 0;
+ u32 patch_len = 0;
+ s32 sent_len = 0;
+
+ //usb_debug("begin\n");
+ if (btmtk_usb_check_need_load_patch_7668(data) == FALSE) {
+ usb_debug("No need to load rom patch\n");
+ return btmtk_usb_send_wmt_reset_cmd(data);
+ }
+
+ buf = os_kzalloc(UPLOAD_PATCH_UNIT, MTK_GFP_ATOMIC);
+ if (!buf) {
+ return -ENOMEM;
+ }
+
+ pos = buf;
+ LD_load_code_from_bin(&data->rom_patch, (char *)data->rom_patch_bin_file_name, NULL,
+ data->udev, &data->rom_patch_len);
+ if (!data->rom_patch || !data->rom_patch_len) {
+ usb_debug("please assign a rom patch(/system/etc/firmware/%s) or (/lib/firmware/%s)\n",
+ data->rom_patch_bin_file_name, data->rom_patch_bin_file_name);
+ return -1;
+ }
+
+ tmp_str = (char *)data->rom_patch;
+ SHOW_FW_DETAILS("FW Version");
+ SHOW_FW_DETAILS("build Time");
+
+ tmp_str = (char *)data->rom_patch + 16;
+ usb_debug("platform = %c%c%c%c\n", tmp_str[0], tmp_str[1], tmp_str[2], tmp_str[3]);
+
+ tmp_str = (char *)data->rom_patch + 20;
+ usb_debug("HW/SW version = %c%c%c%c\n", tmp_str[0], tmp_str[1], tmp_str[2], tmp_str[3]);
+
+ tmp_str = (char *)data->rom_patch + 24;
+ patch_len = data->rom_patch_len - PATCH_INFO_SIZE;
+ //usb_debug("patch_len = %d\n", patch_len);
+ usb_debug("loading rom patch...\n");
+
+ /* loading rom patch */
+ while (1) {
+ s32 sent_len_max = UPLOAD_PATCH_UNIT - PATCH_HEADER_SIZE;
+
+ real_len = 0;
+ sent_len = (patch_len - cur_len) >= sent_len_max ? sent_len_max : (patch_len - cur_len);
+ if (sent_len > 0) {
+ if (first_block == 1) {
+ if (sent_len < sent_len_max)
+ phase = PATCH_PHASE3;
+ else
+ phase = PATCH_PHASE1;
+ first_block = 0;
+ } else if (sent_len == sent_len_max) {
+ if (patch_len - cur_len == sent_len_max)
+ phase = PATCH_PHASE3;
+ else
+ phase = PATCH_PHASE2;
+ } else {
+ phase = PATCH_PHASE3;
+ }
+
+ /* prepare HCI header */
+ pos[0] = 0x6F;
+ pos[1] = 0xFC;
+ pos[2] = (sent_len + 5) & 0xFF;
+ pos[3] = ((sent_len + 5) >> 8) & 0xFF;
+
+ /* prepare WMT header */
+ pos[4] = 0x01;
+ pos[5] = 0x01;
+ pos[6] = (sent_len + 1) & 0xFF;
+ pos[7] = ((sent_len + 1) >> 8) & 0xFF;
+
+ pos[8] = phase;
+
+ os_memcpy(&pos[9], data->rom_patch + PATCH_INFO_SIZE + cur_len, sent_len);
+ //usb_debug("sent_len = %d, cur_len = %d, phase = %d\n", sent_len, cur_len, phase);
+
+ ret = data->hcif->usb_bulk_msg(data->udev, MTKBT_BULK_TX_EP, buf,
+ sent_len + PATCH_HEADER_SIZE, &real_len, 0);
+ if (ret) {
+ usb_debug("upload rom_patch err: %d\n", ret);
+ return -1;
+ }
+ cur_len += sent_len;
+ MTK_MDELAY(1);
+ btmtk_usb_get_rom_patch_result(data);
+ MTK_MDELAY(1);
+
+ } else {
+ usb_debug("loading rom patch... Done\n");
+ break;
+ }
+ os_memset(buf, 0, UPLOAD_PATCH_UNIT);
+ }
+ MTK_MDELAY(20);
+ /* CHIP_RESET */
+ ret = btmtk_usb_send_wmt_reset_cmd(data);
+ MTK_MDELAY(20);
+
+ //usb_debug("end\n");
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+void btmtk_usb_woble_setting_parsing(struct LD_btmtk_usb_data *data, woble_setting_type type)
+{
+#define ONE_BYTE_HEX_MAX_LEN 8
+ int i = 0;
+ char *cmd = NULL;
+ char *head = NULL;
+ char *next_cmd = NULL;
+ char prefix[32] = {0};
+ u8 tmp_len = 0;
+ u8 tmp[128] = {0};
+ long int set_addr = 0;
+ long int addr_pos = 0;
+
+ switch (type) {
+ case TYPE_APCF_CMD:
+ cmd = "APCF";
+ break;
+ default:
+ usb_debug("Incorrect Type\n");
+ return;
+ }
+
+ for (i = 0; i < APCF_SETTING_COUNT; ++i) {
+ snprintf(prefix, sizeof(prefix), "%s%02d:", cmd, i);
+ head = strstr((char *)data->woble_setting, prefix);
+
+ if (head) {
+ head += strlen(prefix); /* move to first numeral */
+ next_cmd = strstr(head, ":"); // next command start position
+
+ tmp_len = 0;
+ memset(tmp, 0, sizeof(tmp));
+ do {
+ tmp[tmp_len++] = strtol(head, &head, 0);
+
+ // for next one
+ head = strstr(head, "0x");
+ if (next_cmd && head > next_cmd)
+ break; // command end
+ } while (tmp_len < sizeof(tmp));
+
+ if (tmp_len) {
+ int j = 0; // FOR DEBUG
+
+ /* Save command */
+ data->apcf_cmd[i].value = os_kzalloc(tmp_len, MTK_GFP_ATOMIC);
+ os_memcpy(data->apcf_cmd[i].value, tmp, tmp_len);
+ data->apcf_cmd[i].len = tmp_len;
+
+ if (type == TYPE_APCF_CMD) {
+ /* Check need BD address or not */
+ snprintf(prefix, sizeof(prefix), "%s_ADD_MAC%02d:", cmd, i);
+ head = strstr((char *)data->woble_setting, prefix);
+ head += strlen(prefix);
+ set_addr = strtol(head, &head, 0);
+
+ if (set_addr == 1) {
+ snprintf(prefix, sizeof(prefix), "%s_ADD_MAC_LOCATION%02d:", cmd, i);
+ head = strstr((char *)data->woble_setting, prefix);
+ head += strlen(prefix);
+ addr_pos = strtol(head, &head, 0);
+
+ if (addr_pos)
+ os_memcpy(data->apcf_cmd[i].value + addr_pos,
+ data->local_addr, BD_ADDR_LEN);
+ }
+ }
+ // FOR DEBUG
+ usb_debug("Load for APCF settings only\n");
+ usb_debug("%02X:", i);
+ for (j = 0; j < data->apcf_cmd[i].len; j++)
+ printf(" %02X", data->apcf_cmd[i].value[j]);
+ printf("\n");
+ }
+ }
+ }
+}
+
+//---------------------------------------------------------------------------
+int btmtk_usb_load_woble_setting(struct LD_btmtk_usb_data *data)
+{
+ int i = 0;
+ BOOL woble_setting_bin = FALSE;
+ BOOL wake_on_ble_conf = FALSE;
+
+ if (!data)
+ return -EINVAL;
+
+ /* For woble_setting.bin */
+ data->woble_setting = NULL;
+ data->woble_setting_len = 0;
+
+ LD_load_code_from_bin(&data->woble_setting, WOBLE_SETTING_FILE_NAME, NULL,
+ data->udev, &data->woble_setting_len);
+ if (data->woble_setting == NULL || data->woble_setting_len == 0) {
+ usb_debug("Please make sure %s in the /system/etc(lib)/firmware\n",
+ WOBLE_SETTING_FILE_NAME);
+ woble_setting_bin = FALSE;
+ } else {
+ btmtk_usb_woble_setting_parsing(data, TYPE_APCF_CMD);
+ for (i = 0; i < APCF_SETTING_COUNT; i++)
+ if (data->apcf_cmd[i].len)
+ break;
+ if (i == APCF_SETTING_COUNT) {
+ woble_setting_bin = FALSE;
+ if (data->woble_setting) {
+ data->woble_setting_len = 0;
+ os_kfree(data->woble_setting);
+ data->woble_setting = NULL;
+ }
+ } else {
+ woble_setting_bin = TRUE;
+ }
+ }
+
+ /* For wake_on_ble.conf */
+ data->wake_dev = NULL;
+ data->wake_dev_len = 0;
+
+ LD_load_code_from_bin(&data->wake_dev, WAKE_DEV_RECORD, WAKE_DEV_RECORD_PATH,
+ data->udev, &data->wake_dev_len);
+ if (data->wake_dev == NULL || data->wake_dev_len == 0) {
+ usb_debug("There is no DEVICE RECORD for wake-up\n");
+ wake_on_ble_conf = FALSE;
+ } else {
+ // content check
+ if (data->wake_dev[0] != data->wake_dev_len || data->wake_dev_len < 3) {
+ usb_debug("Incorrect total length on %s\n", WAKE_DEV_RECORD);
+ data->wake_dev_len = 0;
+ os_kfree(data->wake_dev);
+ data->wake_dev = NULL;
+ wake_on_ble_conf = FALSE;
+ } else {
+ wake_on_ble_conf = TRUE;
+ }
+ }
+
+ if (woble_setting_bin == FALSE && wake_on_ble_conf == FALSE)
+ return -ENOENT;
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+int btmtk_usb_set_unify_woble(struct LD_btmtk_usb_data *data)
+{
+ int ret = -1;
+ // Filter Index: 0x5B
+ /*u8 cmd[] = { 0xC9, 0xFC, 0x1F, 0x01, 0x20, 0x02, 0x00, 0x01, 0x02, 0x01,
+ 0x01, 0x05, 0x10, 0x09, 0x00, 0xC0, 0x00, 0x02, 0x40, FIDX, 0x04,
+ 0x11, 0x12, 0x00, 0x00, 0x02, 0x42, 0x15, 0x02, 0x25, 0x00, 0x02,
+ 0x41, 0x19 };*/
+
+ u8 cmd[] = { 0xC9, 0xFC, 0x14, 0x01, 0x20, 0x02, 0x00, 0x01,
+ 0x02, 0x01, 0x00, 0x05, 0x10, 0x01, 0x00, 0x40, 0x06,
+ 0x02, 0x40, 0x5A, 0x02, 0x41, 0x0F };
+ u8 event[] = { 0xE6, 0x02, 0x08, 0x00 };
+
+ usb_debug("%s: APCF filtering index: %d\n", __func__, FIDX);
+ ret = btmtk_usb_send_hci_cmd(data, cmd, sizeof(cmd), event, sizeof(event));
+ if (ret < 0)
+ usb_debug("Failed(%d)\n", ret);
+ return ret;
+}
+
+//---------------------------------------------------------------------------
+void LD_btmtk_usb_SetWoble(mtkbt_dev_t *dev)
+{
+ struct LD_btmtk_usb_data *data = BT_INST(dev)->priv_data;
+ int ret = -1;
+
+ usb_debug("\n");
+ if (!data) {
+ usb_debug("btmtk data NULL!\n");
+ return;
+ }
+
+ if (is_mt7668(data)) {
+ /* Power on sequence */
+ btmtk_usb_send_wmt_power_on_cmd_7668(data);
+ btmtk_usb_send_hci_tci_set_sleep_cmd_7668(data);
+ btmtk_usb_send_hci_reset_cmd(data);
+
+ /* Unify WoBLE flow */
+ btmtk_usb_get_vendor_cap(data);
+ btmtk_usb_send_read_bdaddr(data);
+ ret = btmtk_usb_load_woble_setting(data);
+ if (ret) {
+ usb_debug("Using lagecy WoBLE setting(%d)!!!\n", ret);
+ btmtk_usb_set_apcf(data, FALSE);
+ } else
+ btmtk_usb_set_apcf(data, TRUE);
+ btmtk_usb_set_unify_woble(data);
+ } else {
+ btmtk_usb_send_hci_suspend_cmd(data);
+ }
+
+ // Clean & free buffer
+ if (data->woble_setting) {
+ int i = 0;
+ os_kfree(data->woble_setting);
+ data->woble_setting = NULL;
+ data->woble_setting_len = 0;
+ for (i = 0; i < APCF_SETTING_COUNT; i++) {
+ os_kfree(data->apcf_cmd[i].value);
+ data->apcf_cmd[i].len = 0;
+ }
+ }
+ if (data->wake_dev) {
+ os_kfree(data->wake_dev);
+ data->wake_dev = NULL;
+ data->wake_dev_len = 0;
+ }
+
+ return;
+}
+
+//---------------------------------------------------------------------------
+int LD_btmtk_usb_probe(mtkbt_dev_t *dev)
+{
+ struct LD_btmtk_usb_data *data;
+ int err = 0;
+
+ usb_debug("=========================================\n");
+ usb_debug("Mediatek Bluetooth USB driver ver %s\n", LD_VERSION);
+ usb_debug("=========================================\n");
+ os_memcpy(driver_version, LD_VERSION, sizeof(LD_VERSION));
+ probe_counter++;
+ isbtready = 0;
+ is_assert = 0;
+ //usb_debug("LD_btmtk_usb_probe begin\n");
+ usb_debug("probe_counter = %d\n", probe_counter);
+
+ data = (struct LD_btmtk_usb_data *)os_kzalloc(sizeof(*data), MTK_GFP_ATOMIC);
+ if (!data) {
+ usb_debug("[ERR] end Error 1\n");
+ return -ENOMEM;
+ }
+
+ data->hcif = BT_INST(dev)->hci_if;
+
+ data->cmdreq_type = USB_TYPE_CLASS;
+
+ data->udev = dev;
+
+ data->meta_tx = 0;
+
+ data->io_buf = os_kmalloc(LD_BT_MAX_EVENT_SIZE, MTK_GFP_ATOMIC);
+
+ btmtk_usb_switch_iobase(data, WLAN);
+
+ /* clayton: according to the chip id, load f/w or rom patch */
+ btmtk_usb_cap_init(data);
+
+ if (data->need_load_rom_patch) {
+ if (is_mt7668(data))
+ err = btmtk_usb_load_rom_patch_7668(data);
+ else
+ err = btmtk_usb_load_rom_patch(data);
+ //btmtk_usb_send_hci_suspend_cmd(data);
+ if (err < 0) {
+ if (data->io_buf) os_kfree(data->io_buf);
+ if (data->rom_patch_bin_file_name) os_kfree(data->rom_patch_bin_file_name);
+ os_kfree(data);
+ usb_debug("[ERR] end Error 2\n");
+ return err;
+ }
+ }
+
+ // Clean & free buffer
+ if (data->rom_patch_bin_file_name)
+ os_kfree(data->rom_patch_bin_file_name);
+
+
+ isUsbDisconnet = 0;
+ BT_INST(dev)->priv_data = data;
+ isbtready = 1;
+
+ //usb_debug("btmtk_usb_probe end\n");
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+void LD_btmtk_usb_disconnect(mtkbt_dev_t *dev)
+{
+ struct LD_btmtk_usb_data *data = BT_INST(dev)->priv_data;
+
+ usb_debug("\n");
+
+ if (!data)
+ return;
+
+ isbtready = 0;
+ metaCount = 0;
+
+ if (data->need_load_rom_patch)
+ os_kfree(data->rom_patch);
+
+ if (data->need_load_fw)
+ os_kfree(data->fw_image);
+
+ usb_debug("unregister bt irq\n");
+
+ isUsbDisconnet = 1;
+ usb_debug("btmtk: stop all URB\n");
+ os_kfree(data->io_buf);
+ os_kfree(data);
+}
+
+//---------------------------------------------------------------------------
diff --git a/board/amlogic/tm2_ab301_v1/mtk-bt/LD_btmtk_usb.h b/board/amlogic/tm2_ab301_v1/mtk-bt/LD_btmtk_usb.h
new file mode 100644
index 0000000000..68e90c5fa6
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/mtk-bt/LD_btmtk_usb.h
@@ -0,0 +1,127 @@
+#ifndef __LD_BTMTK_USB_H__
+#define __LD_BTMTK_USB_H__
+
+#include "LD_usbbt.h"
+
+/* Memory map for MTK BT */
+/* SYS Control */
+#define SYSCTL 0x400000
+
+/* WLAN */
+#define WLAN 0x410000
+
+/* MCUCTL */
+#define CLOCK_CTL 0x0708
+#define INT_LEVEL 0x0718
+#define COM_REG0 0x0730
+#define SEMAPHORE_00 0x07B0
+#define SEMAPHORE_01 0x07B4
+#define SEMAPHORE_02 0x07B8
+#define SEMAPHORE_03 0x07BC
+
+/* Chip definition */
+
+#define CONTROL_TIMEOUT_JIFFIES (300)
+#define DEVICE_VENDOR_REQUEST_OUT 0x40
+#define DEVICE_VENDOR_REQUEST_IN 0xc0
+#define DEVICE_CLASS_REQUEST_OUT 0x20
+#define DEVICE_CLASS_REQUEST_IN 0xa0
+
+#define BTUSB_MAX_ISOC_FRAMES 10
+#define BTUSB_INTR_RUNNING 0
+#define BTUSB_BULK_RUNNING 1
+#define BTUSB_ISOC_RUNNING 2
+#define BTUSB_SUSPENDING 3
+#define BTUSB_DID_ISO_RESUME 4
+
+/* ROM Patch */
+#define PATCH_HCI_HEADER_SIZE 4
+#define PATCH_WMT_HEADER_SIZE 5
+#define PATCH_HEADER_SIZE (PATCH_HCI_HEADER_SIZE + PATCH_WMT_HEADER_SIZE)
+#define UPLOAD_PATCH_UNIT 2048
+#define PATCH_INFO_SIZE 30
+#define PATCH_PHASE1 1
+#define PATCH_PHASE2 2
+#define PATCH_PHASE3 3
+
+#define LD_BT_MAX_EVENT_SIZE 260
+#define BD_ADDR_LEN 6
+
+#define WAKE_DEV_RECORD "wake_on_ble.conf"
+#define WAKE_DEV_RECORD_PATH "/data/misc/bluedroid"
+#define WOBLE_SETTING_FILE_NAME "woble_setting.bin"
+#define APCF_SETTING_COUNT 10
+
+typedef enum {
+ TYPE_APCF_CMD,
+} woble_setting_type;
+
+struct apcf_cmd_tlv {
+ //u8 type
+ u8 len;
+ u8 *value;
+};
+
+struct LD_btmtk_usb_data {
+ mtkbt_dev_t *udev; /* store the usb device informaiton */
+
+ unsigned long flags;
+ int meta_tx;
+ HC_IF *hcif;
+
+ u8 cmdreq_type;
+
+ unsigned int sco_num;
+ int isoc_altsetting;
+ int suspend_count;
+
+ /* request for different io operation */
+ u8 w_request;
+ u8 r_request;
+
+ /* io buffer for usb control transfer */
+ unsigned char *io_buf;
+
+ unsigned char *fw_image;
+ unsigned char *fw_header_image;
+ unsigned char *fw_bin_file_name;
+
+ unsigned char *rom_patch;
+ unsigned char *rom_patch_header_image;
+ unsigned char *rom_patch_bin_file_name;
+ u32 chip_id;
+ u8 need_load_fw;
+ u8 need_load_rom_patch;
+ u32 rom_patch_offset;
+ u32 rom_patch_len;
+ u32 fw_len;
+
+ u8 local_addr[BD_ADDR_LEN];
+ u8 *woble_setting;
+ u32 woble_setting_len;
+ u8 *wake_dev; /* ADDR:NAP-UAP-LAP, VID/PID:Both Little endian */
+ u32 wake_dev_len;
+ struct apcf_cmd_tlv apcf_cmd[APCF_SETTING_COUNT];
+};
+
+
+int LD_btmtk_usb_probe(mtkbt_dev_t *dev);
+void LD_btmtk_usb_disconnect(mtkbt_dev_t *dev);
+void LD_btmtk_usb_SetWoble(mtkbt_dev_t *dev);
+
+#define REV_MT76x2E3 0x0022
+
+#define MT_REV_LT(_data, _chip, _rev) \
+ is_##_chip(_data) && (((_data)->chip_id & 0x0000ffff) < (_rev))
+
+#define MT_REV_GTE(_data, _chip, _rev) \
+ is_##_chip(_data) && (((_data)->chip_id & 0x0000ffff) >= (_rev))
+
+/*
+ * Load code method
+ */
+enum LOAD_CODE_METHOD {
+ BIN_FILE_METHOD,
+ HEADER_METHOD,
+};
+#endif
diff --git a/board/amlogic/tm2_ab301_v1/mtk-bt/LD_usbbt.c b/board/amlogic/tm2_ab301_v1/mtk-bt/LD_usbbt.c
new file mode 100644
index 0000000000..1aa46e13aa
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/mtk-bt/LD_usbbt.c
@@ -0,0 +1,448 @@
+#include <command.h>
+#include <common.h>
+#include <usb.h>
+#include <stdio_dev.h>
+#include "LD_usbbt.h"
+#include "LD_btmtk_usb.h"
+
+/* Reset BT-module */
+extern void reset_mt7668(void);
+
+os_usb_vid_pid array_mtk_vid_pid[] = {
+ {0x0E8D, 0x7668, "MTK7668"}, // 7668
+ {0x0E8D, 0x76A0, "MTK7662T"}, // 7662T
+ {0x0E8D, 0x76A1, "MTK7632T"}, // 7632T
+};
+
+int max_mtk_wifi_id = (sizeof(array_mtk_vid_pid) / sizeof(array_mtk_vid_pid[0]));
+os_usb_vid_pid *pmtk_wifi = &array_mtk_vid_pid[0];
+
+static mtkbt_dev_t *g_DrvData = NULL;
+
+/* Amlogic need do adaptation. */
+extern int vfs_mount(char *volume);
+extern unsigned long vfs_getsize(char *filedir);
+extern int vfs_read(void* addr,char* filedir,unsigned int offset,unsigned int size );
+
+VOID *os_memcpy(VOID *dst, const VOID *src, UINT32 len)
+{
+ return memcpy(dst, src, len);
+}
+
+VOID *os_memmove(VOID *dest, const void *src,UINT32 len)
+{
+ return memmove(dest, src, len);
+}
+
+VOID *os_memset(VOID *s, int c, size_t n)
+{
+ return memset(s,c,n);
+}
+
+VOID *os_kzalloc(size_t size, unsigned int flags)
+{
+ VOID *ptr = malloc(size);
+
+ os_memset(ptr, 0, size);
+ return ptr;
+}
+
+void LD_load_code_from_bin(unsigned char **image, char *bin_name, char *path, mtkbt_dev_t *dev, u32 *code_len)
+{
+ char mtk_patch_bin_patch[128] = "\0";
+
+ /** implement by MTK
+ * path: /system/etc/firmware/mt76XX_patch_eX_hdr.bin
+ * If argument "path" is NULL, access "/system/etc/firmware" directly like as request_firmware
+ * if argument "path" is not NULL, so far only support directory "userdata"
+ * NOTE: latest vfs_mount seems decided this time access directory
+ */
+ if (path == NULL && vfs_mount("system") != 0) {
+ usb_debug("vfs_mount - system fail\n");
+ return;
+ } else if (path != NULL && vfs_mount("userdata") != 0) {
+ usb_debug("vfs_mount - userdata fail\n");
+ return;
+ }
+
+ if (path) {
+ snprintf(mtk_patch_bin_patch, sizeof(mtk_patch_bin_patch), "%s/%s", path, bin_name);
+ printf("File: %s\n", mtk_patch_bin_patch);
+ } else {
+ snprintf(mtk_patch_bin_patch, sizeof(mtk_patch_bin_patch), "%s/%s", "/vendor/firmware", bin_name);
+ printf("mtk_patch_bin_patch: %s\n", mtk_patch_bin_patch);
+ }
+ *code_len = vfs_getsize(mtk_patch_bin_patch);
+ if (*code_len == 0) {
+ usb_debug("Get file size fail\n");
+ return;
+ }
+
+ // malloc buffer to store bt patch file data
+ *image = malloc(*code_len);
+ if (vfs_read(*image, mtk_patch_bin_patch, 0, *code_len) != 0)
+ {
+ usb_debug("vfs_read fail\n");
+ return;
+ }
+ usb_debug("Load file OK\n");
+ //usb_dump((unsigned int)*image, 0x200); //Amlogic had better dump the first segment of fw data.
+ return;
+}
+
+static int usb_bt_bulk_msg(
+ mtkbt_dev_t *dev,
+ u32 epType,
+ u8 *data,
+ int size,
+ int* realsize,
+ int timeout /* not used */
+)
+{
+ int ret =0 ;
+ if (dev == NULL || dev->udev == NULL || dev->bulk_tx_ep == NULL)
+ {
+ usb_debug("bulk out error 00\n");
+ return -1;
+ }
+
+ //usb_debug("[usb_bt_bulk_msg]ep_addr:%x\n", dev->bulk_tx_ep->bEndpointAddress);
+ //usb_debug("[usb_bt_bulk_msg]ep_maxpkt:%x\n", dev->bulk_tx_ep->wMaxPacketSize);
+
+ if (epType == MTKBT_BULK_TX_EP)
+ {
+ ret = usb_bulk_msg(dev->udev,usb_sndbulkpipe(dev->udev,dev->bulk_tx_ep->bEndpointAddress),data,size,realsize,2000);
+
+ if (ret)
+ {
+ usb_debug("bulk out error 01\n");
+ return -1;
+ }
+
+ if (*realsize == size)
+ {
+ //usb_debug("bulk out success 01,size =0x%x\n",size);
+ return 0;
+ }
+ else
+ {
+ usb_debug("bulk out fail 02,size =0x%x,realsize =0x%x\n",size,*realsize);
+ }
+ }
+ return -1;
+}
+
+static int usb_bt_control_msg(
+ mtkbt_dev_t *dev,
+ u32 epType,
+ u8 request,
+ u8 requesttype,
+ u16 value,
+ u16 index,
+ u8 *data,
+ int data_length,
+ int timeout /* not used */
+)
+{
+ int ret = -1;
+ if (epType == MTKBT_CTRL_TX_EP)
+ {
+ ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), request,
+ requesttype, value, index, data, data_length,timeout);
+ }
+ else if (epType == MTKBT_CTRL_RX_EP)
+ {
+ ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), request,
+ requesttype, value, index, data, data_length,timeout);
+ }
+ else
+ {
+ usb_debug("control message wrong Type =0x%x\n",epType);
+ }
+
+ if (ret < 0)
+ {
+ usb_debug("Err1(%d)\n", ret);
+ return ret;
+ }
+ return ret;
+}
+
+static int usb_bt_interrupt_msg(
+ mtkbt_dev_t *dev,
+ u32 epType,
+ u8 *data,
+ int size,
+ int* realsize,
+ int timeout /* unit of 1ms */
+)
+{
+ int ret = -1;
+
+ usb_debug("epType = 0x%x\n",epType);
+
+ if (epType == MTKBT_INTR_EP)
+ {
+ ret = usb_submit_int_msg(dev->udev,usb_rcvintpipe(dev->udev,dev->intr_ep->bEndpointAddress),data,size,realsize,timeout);
+ }
+
+ if (ret < 0 )
+ {
+ usb_debug("Err1(%d)\n", ret);
+ return ret;
+ }
+ usb_debug("ret = 0x%x\n",ret);
+ return ret;
+}
+
+static HC_IF usbbt_host_interface =
+{
+ usb_bt_bulk_msg,
+ usb_bt_control_msg,
+ usb_bt_interrupt_msg,
+};
+
+static void Ldbtusb_diconnect (btusbdev_t *dev)
+{
+ LD_btmtk_usb_disconnect(g_DrvData);
+
+ if (g_DrvData)
+ {
+ os_kfree(g_DrvData);
+ }
+ g_DrvData = NULL;
+}
+
+static int Ldbtusb_SetWoble(btusbdev_t *dev)
+{
+ if (!g_DrvData)
+ {
+ usb_debug("usb set woble fail ,because no drv data\n");
+ return -1;
+ }
+ else
+ {
+ LD_btmtk_usb_SetWoble(g_DrvData);
+ usb_debug("usb set woble end\n");
+ }
+ return 0;
+}
+
+int Ldbtusb_connect (btusbdev_t *dev)
+{
+ int ret = 0;
+
+ struct usb_endpoint_descriptor *ep_desc;
+ struct usb_interface *iface;
+ int i;
+ iface = &dev->config.if_desc[0];
+
+ if (g_DrvData == NULL)
+ {
+ g_DrvData = os_kmalloc(sizeof(mtkbt_dev_t),MTK_GFP_ATOMIC);
+
+ if (!g_DrvData)
+ {
+ usb_debug("Not enough memory for mtkbt virtual usb device.\n");
+ return -1;
+ }
+ else
+ {
+ os_memset(g_DrvData,0,sizeof(mtkbt_dev_t));
+ g_DrvData->udev = dev;
+ g_DrvData->connect = Ldbtusb_connect;
+ g_DrvData->disconnect = Ldbtusb_diconnect;
+ g_DrvData->SetWoble = Ldbtusb_SetWoble;
+ }
+ }
+ else
+ {
+ return -1;
+ }
+
+ for (i = 0; i < iface->desc.bNumEndpoints; i++)
+ {
+ ep_desc = &iface->ep_desc[i];
+
+ if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
+ {
+ if (ep_desc->bEndpointAddress & USB_DIR_IN)
+ {
+ g_DrvData->bulk_rx_ep = ep_desc;
+ }
+ else
+ {
+ g_DrvData->bulk_tx_ep = ep_desc;
+ }
+ continue;
+ }
+
+ /* is it an interrupt endpoint? */
+ if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+ {
+ g_DrvData->intr_ep = ep_desc;
+ continue;
+ }
+ }
+ if (!g_DrvData->intr_ep || !g_DrvData->bulk_tx_ep || !g_DrvData->bulk_rx_ep)
+ {
+ os_kfree(g_DrvData);
+ g_DrvData = NULL;
+ usb_debug("btmtk_usb_probe end Error 3\n");
+ return -1;
+ }
+
+ /* Init HostController interface */
+ g_DrvData->hci_if = &usbbt_host_interface;
+
+ /* btmtk init */
+ ret = LD_btmtk_usb_probe(g_DrvData);
+
+ if (ret != 0)
+ {
+ usb_debug("usb probe fail\n");
+ if (g_DrvData)
+ {
+ os_kfree(g_DrvData);
+ }
+ g_DrvData = NULL;
+ return -1;
+ }
+ else
+ {
+ usb_debug("usbbt probe success\n");
+ }
+ return ret;
+}
+
+static int checkUsbDevicePort(struct usb_device* udev, u16 vendorID, u16 productID, u8 port)
+{
+ struct usb_device* pdev = NULL;
+ int i;
+#if defined (CONFIG_USB_PREINIT)
+ usb_stop(port);
+ if (usb_post_init(port) == 0)
+#else
+ /* Attention:
+ * if BT_USB_PORT_NUM is defined,
+ * Amlogic can only initialize MTK7668 USB port, but NOT all ports.
+ */
+ usb_stop();
+ if (usb_init() == 0) //if (usb_init(port) == 0)
+#endif
+ {
+ /* get device */
+ for (i=0; i<USB_MAX_DEVICE; i++) {
+ pdev = usb_get_dev_index(i);
+ printf("pdev->descriptor.idVendor=0x%x; pdev->descriptor.idProduct=0x%x\n",pdev->descriptor.idVendor,pdev->descriptor.idProduct);
+ if ((pdev != NULL) && (pdev->descriptor.idVendor == vendorID) && (pdev->descriptor.idProduct == productID)) // MTK 7662
+ {
+ usb_debug("OK\n");
+ memcpy(udev, pdev, sizeof(struct usb_device));
+ return 0 ;
+ }
+ }
+ }
+ return -1;
+}
+
+static int findUsbDevice(struct usb_device* udev)
+{
+ int ret = -1;
+ u8 idx = 0;
+ u8 i = 0;
+ usb_debug("IN\n");
+ if (udev == NULL)
+ {
+ usb_error("udev can not be NULL\n");
+ return -1;
+ }
+
+#ifdef BT_USB_PORT_NUM
+ /* check mtk bt usb port */
+ idx = BT_USB_PORT_NUM;
+ usb_debug("find mtk bt usb device from usb port[%d]\n", idx);
+ while (i < 1 /*max_mtk_wifi_id*/) {
+ ret = checkUsbDevicePort(udev, (pmtk_wifi + i)->vid, (pmtk_wifi + i)->pid, idx);
+ if (ret == 0) break;
+ i++;
+ }
+ if (ret == 0)
+ {
+ return 0;
+ }
+#else
+ // not find mt bt usb device from given usb port, so poll every usb port.
+ char portNumStr[10] = "\0";
+ #if defined(ENABLE_FIFTH_EHC)
+ const char u8UsbPortCount = 5;
+ #elif defined(ENABLE_FOURTH_EHC)
+ const char u8UsbPortCount = 4;
+ #elif defined(ENABLE_THIRD_EHC)
+ const char u8UsbPortCount = 3;
+ #elif defined(ENABLE_SECOND_EHC)
+ const char u8UsbPortCount = 2;
+ #else
+ const char u8UsbPortCount = 1;
+ #endif
+ for (idx = 0; idx < u8UsbPortCount; idx++)
+ {
+ i = 0;
+ while (i < max_mtk_wifi_id) {
+ ret = checkUsbDevicePort(udev, (pmtk_wifi + i)->vid, (pmtk_wifi + i)->pid, idx);
+ if (ret == 0) break;
+ i++;
+ }
+ if (ret == 0)
+ {
+ // set bt_usb_port to store mt bt usb device port
+ snprintf(portNumStr, sizeof(portNumStr), "%d", idx);
+ setenv(BT_USB_PORT, portNumStr);
+ saveenv();
+ return 0;
+ }
+ }
+#endif
+
+ usb_error("Not find usb device\n");
+ return -1;
+}
+
+int do_setMtkBT( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int ret = 0;
+ struct usb_device udev;
+ memset(&udev, 0, sizeof(struct usb_device));
+ usb_debug("IN\n");
+ if (argc < 1)
+ {
+ cmd_usage(cmdtp);
+ return -1;
+ }
+
+ /* Reset BT-module */
+ reset_mt7668();
+
+ // MTK USB controller
+ ret = findUsbDevice(&udev);
+ if (ret != 0)
+ {
+ usb_error("find bt usb device failed\n");
+ return -1;
+ }
+ ret = Ldbtusb_connect(&udev);
+ if (ret != 0)
+ {
+ usb_error("connect to bt usb device failed\n");
+ return -1;
+ }
+ ret = Ldbtusb_SetWoble(&udev);
+ if (ret != 0)
+ {
+ usb_error("set bt usb device woble cmd failed\n");
+ return -1;
+ }
+ usb_debug("OK\n");
+ return ret;
+}
+
diff --git a/board/amlogic/tm2_ab301_v1/mtk-bt/LD_usbbt.h b/board/amlogic/tm2_ab301_v1/mtk-bt/LD_usbbt.h
new file mode 100644
index 0000000000..3fcf8d89d8
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/mtk-bt/LD_usbbt.h
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2008-2010 coresystems GmbH
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __LD_USBBT_H__
+#define __LD_USBBT_H__
+#include <common.h>
+#include <malloc.h>
+#include <usb.h>
+
+#define MTKBT_CTRL_TX_EP 0
+#define MTKBT_CTRL_RX_EP 1
+#define MTKBT_INTR_EP 2
+#define MTKBT_BULK_TX_EP 3
+#define MTKBT_BULK_RX_EP 4
+
+#define MTK_GFP_ATOMIC 1
+
+#define CRC_CHECK 0
+
+#define BTLDER "[BT-LOADER] "
+#define USB_TYPE_STANDARD (0x00 << 5)
+#define USB_TYPE_CLASS (0x01 << 5)
+#define USB_TYPE_VENDOR (0x02 << 5)
+#define USB_TYPE_RESERVED (0x03 << 5)
+
+#define USB_DEBUG
+
+#ifdef USB_DEBUG
+#define usb_debug(fmt,...) printf("%s: "fmt, __func__, ##__VA_ARGS__)
+#else
+#define usb_debug(fmt,...)
+#endif
+
+#define usb_error(fmt,...) \
+ printf("%s: "fmt, __func__, ##__VA_ARGS__)
+
+#define os_kmalloc(size,flags) malloc(size)
+#define os_kfree(ptr) free(ptr)
+
+#define MTK_UDELAY(x) udelay(x)
+#define MTK_MDELAY(x) mdelay(x)
+
+
+//#define btusbdev_t struct usb_interface
+#define btusbdev_t struct usb_device
+
+#undef NULL
+#define NULL ((void *)0)
+#define s32 signed int
+#ifndef TRUE
+ #define TRUE 1
+#endif
+#ifndef FALSE
+ #define FALSE 0
+#endif
+
+#ifndef VOID
+#define VOID void
+#endif
+
+typedef unsigned int UINT32;
+typedef signed int INT32;
+typedef unsigned char UINT8;
+typedef unsigned long ULONG;
+typedef unsigned char BOOL;
+
+typedef struct __USBBT_DEVICE__ mtkbt_dev_t;
+
+typedef struct {
+ int (*usb_bulk_msg) (mtkbt_dev_t *dev, u32 epType, u8 *data, int size, int* realsize, int timeout);
+ int (*usb_control_msg) (mtkbt_dev_t *dev, u32 epType, u8 request, u8 requesttype, u16 value, u16 index,
+ u8 *data, int data_length, int timeout);
+ int (*usb_interrupt_msg)(mtkbt_dev_t *dev, u32 epType, u8 *data, int size, int* realsize, int timeout);
+} HC_IF;
+
+struct __USBBT_DEVICE__
+{
+ void *priv_data;
+ btusbdev_t* intf;
+ struct usb_device *udev;
+ struct usb_endpoint_descriptor *intr_ep;
+ struct usb_endpoint_descriptor *bulk_tx_ep;
+ struct usb_endpoint_descriptor *bulk_rx_ep;
+ struct usb_endpoint_descriptor *isoc_tx_ep;
+ struct usb_endpoint_descriptor *isoc_rx_ep;
+ HC_IF *hci_if;
+ int (*connect)(btusbdev_t *dev);
+ void (*disconnect)(btusbdev_t *dev);
+ int (*SetWoble)(btusbdev_t *dev);
+};//mtkbt_dev_t;
+
+#define BT_INST(dev) (dev)
+
+int Ldbtusb_connect (btusbdev_t *dev);
+VOID *os_memcpy(VOID *dst, const VOID *src, UINT32 len);
+VOID *os_memmove(VOID *dest, const void *src,UINT32 len);
+VOID *os_memset(VOID *s, int c, size_t n);
+VOID *os_kzalloc(size_t size, unsigned int flags);
+
+void LD_load_code_from_bin(unsigned char **image, char *bin_name, char *path, mtkbt_dev_t *dev,u32 *code_len);
+
+int do_setMtkBT( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+#endif
diff --git a/board/amlogic/tm2_ab301_v1/mtk-bt/cmd_btmtk.c b/board/amlogic/tm2_ab301_v1/mtk-bt/cmd_btmtk.c
new file mode 100644
index 0000000000..c287cab663
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/mtk-bt/cmd_btmtk.c
@@ -0,0 +1,40 @@
+#include <command.h>
+#include <common.h>
+#include "LD_usbbt.h"
+
+extern int fwGetFileSize(const char *file_path);
+extern int fwReadFileToBuffer(const char *file_path, unsigned char data_buf[]);
+
+int vfs_mount(char *volume)
+{
+ return 0;
+}
+
+/* Amlogic need to implement. */
+unsigned long vfs_getsize(char *filedir)
+{
+ int fileSize = 0;
+ fileSize = fwGetFileSize(filedir);
+ if (fileSize > 0)
+ {
+ printf("vfs_getsize %s size is %d\n", filedir, fileSize);
+ return fileSize;
+ }
+
+ printf("vfs_getsize %s failed\n", filedir);
+ return 0;
+}
+
+/* Amlogic need to implement. */
+int vfs_read(void *addr, char *filedir, unsigned int offset, unsigned int size)
+{
+ int ret = -1;
+ ret = fwReadFileToBuffer(filedir, addr);
+ if (ret > 0)
+ {
+ printf("vfs_read load %s to buffer success\n", filedir);
+ return 0;
+ }
+ printf("vfs_read load %s failed\n", filedir);
+ return -1;
+}
diff --git a/board/amlogic/tm2_ab301_v1/mtk-bt/errno.h b/board/amlogic/tm2_ab301_v1/mtk-bt/errno.h
new file mode 100644
index 0000000000..5a4806deba
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/mtk-bt/errno.h
@@ -0,0 +1,131 @@
+#ifndef _GENERIC_ERRNO_H
+#define _GENERIC_ERRNO_H
+
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Argument list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func */
+#define ERANGE 34 /* Math result not representable */
+#define EDEADLK 35 /* Resource deadlock would occur */
+#define ENAMETOOLONG 36 /* File name too long */
+#define ENOLCK 37 /* No record locks available */
+#define ENOSYS 38 /* Function not implemented */
+#define ENOTEMPTY 39 /* Directory not empty */
+#define ELOOP 40 /* Too many symbolic links encountered */
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+#define ENOMSG 42 /* No message of desired type */
+#define EIDRM 43 /* Identifier removed */
+#define ECHRNG 44 /* Channel number out of range */
+#define EL2NSYNC 45 /* Level 2 not synchronized */
+#define EL3HLT 46 /* Level 3 halted */
+#define EL3RST 47 /* Level 3 reset */
+#define ELNRNG 48 /* Link number out of range */
+#define EUNATCH 49 /* Protocol driver not attached */
+#define ENOCSI 50 /* No CSI structure available */
+#define EL2HLT 51 /* Level 2 halted */
+#define EBADE 52 /* Invalid exchange */
+#define EBADR 53 /* Invalid request descriptor */
+#define EXFULL 54 /* Exchange full */
+#define ENOANO 55 /* No anode */
+#define EBADRQC 56 /* Invalid request code */
+#define EBADSLT 57 /* Invalid slot */
+
+#define EDEADLOCK EDEADLK
+
+#define EBFONT 59 /* Bad font file format */
+#define ENOSTR 60 /* Device not a stream */
+#define ENODATA 61 /* No data available */
+#define ETIME 62 /* Timer expired */
+#define ENOSR 63 /* Out of streams resources */
+#define ENONET 64 /* Machine is not on the network */
+#define ENOPKG 65 /* Package not installed */
+#define EREMOTE 66 /* Object is remote */
+#define ENOLINK 67 /* Link has been severed */
+#define EADV 68 /* Advertise error */
+#define ESRMNT 69 /* Srmount error */
+#define ECOMM 70 /* Communication error on send */
+#define EPROTO 71 /* Protocol error */
+#define EMULTIHOP 72 /* Multihop attempted */
+#define EDOTDOT 73 /* RFS specific error */
+#define EBADMSG 74 /* Not a data message */
+#define EOVERFLOW 75 /* Value too large for defined data type */
+#define ENOTUNIQ 76 /* Name not unique on network */
+#define EBADFD 77 /* File descriptor in bad state */
+#define EREMCHG 78 /* Remote address changed */
+#define ELIBACC 79 /* Can not access a needed shared library */
+#define ELIBBAD 80 /* Accessing a corrupted shared library */
+#define ELIBSCN 81 /* .lib section in a.out corrupted */
+#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
+#define ELIBEXEC 83 /* Cannot exec a shared library directly */
+#define EILSEQ 84 /* Illegal byte sequence */
+#define ERESTART 85 /* Interrupted system call should be restarted */
+#define ESTRPIPE 86 /* Streams pipe error */
+#define EUSERS 87 /* Too many users */
+#define ENOTSOCK 88 /* Socket operation on non-socket */
+#define EDESTADDRREQ 89 /* Destination address required */
+#define EMSGSIZE 90 /* Message too long */
+#define EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define ENOPROTOOPT 92 /* Protocol not available */
+#define EPROTONOSUPPORT 93 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define EPFNOSUPPORT 96 /* Protocol family not supported */
+#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
+#define EADDRINUSE 98 /* Address already in use */
+#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define ENETDOWN 100 /* Network is down */
+#define ENETUNREACH 101 /* Network is unreachable */
+#define ENETRESET 102 /* Network dropped connection because of reset */
+#define ECONNABORTED 103 /* Software caused connection abort */
+#define ECONNRESET 104 /* Connection reset by peer */
+#define ENOBUFS 105 /* No buffer space available */
+#define EISCONN 106 /* Transport endpoint is already connected */
+#define ENOTCONN 107 /* Transport endpoint is not connected */
+#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
+#define ETOOMANYREFS 109 /* Too many references: cannot splice */
+#define ETIMEDOUT 110 /* Connection timed out */
+#define ECONNREFUSED 111 /* Connection refused */
+#define EHOSTDOWN 112 /* Host is down */
+#define EHOSTUNREACH 113 /* No route to host */
+#define EALREADY 114 /* Operation already in progress */
+#define EINPROGRESS 115 /* Operation now in progress */
+#define ESTALE 116 /* Stale NFS file handle */
+#define EUCLEAN 117 /* Structure needs cleaning */
+#define ENOTNAM 118 /* Not a XENIX named type file */
+#define ENAVAIL 119 /* No XENIX semaphores available */
+#define EISNAM 120 /* Is a named type file */
+#define EREMOTEIO 121 /* Remote I/O error */
+#define EDQUOT 122 /* Quota exceeded */
+#define ENOMEDIUM 123 /* No medium found */
+#define EMEDIUMTYPE 124 /* Wrong medium type */
+
+#endif
diff --git a/board/amlogic/tm2_ab301_v1/mtk-bt/fs_platform.c b/board/amlogic/tm2_ab301_v1/mtk-bt/fs_platform.c
new file mode 100644
index 0000000000..33a7ac38d4
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/mtk-bt/fs_platform.c
@@ -0,0 +1,141 @@
+#include <command.h>
+#include <common.h>
+#include <emmc_partitions.h>
+#include <fs.h>
+
+#define CS_BLCOK_DEV_INTERFACE "mmc"
+#define CS_BLCOK_DEV_MARJOR_NUM "1"
+#define CC_MAX_INI_FILE_NAME_LEN (512)
+#define CC_MAX_INI_FILE_LINE_LEN (256)
+
+/*File functions*/
+static int splitFilePath(const char *file_path, char part_name[], char file_name[], const char *ext_name) {
+ int i = 0;
+ char *tmp_start_ptr = NULL;
+ char *tmp_end_ptr = NULL;
+
+ if (file_path == NULL) {
+ printf("%s, file_path is NULL!!!\n", __FUNCTION__);
+ return -1;
+ }
+
+ tmp_start_ptr = strchr((char*)file_path,'/');
+ if (tmp_start_ptr != file_path) {
+ printf("%s, we need one abstract file path!!! %s.\n", __FUNCTION__, file_path);
+ return -1;
+ }
+
+ tmp_end_ptr = strchr(tmp_start_ptr + 1,'/');
+ if (tmp_end_ptr == NULL) {
+ printf("%s, there is only partition name in the path!!!\n", __FUNCTION__);
+ return -1;
+ }
+
+ strncpy(part_name, tmp_start_ptr + 1, tmp_end_ptr - tmp_start_ptr - 1);
+ part_name[tmp_end_ptr - tmp_start_ptr - 1] = '\0';
+ /*ALOGD("%s, partition name is %s\n", __FUNCTION__, part_name);*/
+
+ tmp_start_ptr = tmp_end_ptr;
+
+ i = 0;
+ while (*tmp_end_ptr && i < CC_MAX_INI_FILE_NAME_LEN) {
+ tmp_end_ptr++;
+ i++;
+ }
+ if (i >= CC_MAX_INI_FILE_NAME_LEN) {
+ printf("%s, file path is too long (%d)!!!\n", __FUNCTION__, i);
+ return -1;
+ }
+
+ strncpy(file_name, tmp_start_ptr, i);
+ file_name[i] = '\0';
+ /*ALOGD("%s, file name is %s\n", __FUNCTION__, file_name);*/
+
+ if (ext_name != NULL) {
+ if (strlen(ext_name) > 0) {
+ while (tmp_end_ptr != tmp_start_ptr && *tmp_end_ptr != '.') {
+ tmp_end_ptr--;
+ }
+
+ if (*tmp_end_ptr != '.') {
+ printf("%s, the file path \"%s\" doesn't have ext name!!!\n", __FUNCTION__, file_path);
+ return -1;
+ } else {
+ if (strncmp(tmp_end_ptr + 1, ext_name, 128)) {
+ printf("%s, the ext name of file path \"%s\" not equal to the special ext name \"%s\"!!!\n", __FUNCTION__, file_path, ext_name);
+ return -1;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int setBlockDevice_fs(const char *part_name) {
+ int part_no = 0;
+ char part_buf[128] = {0};
+ char tmp_buf[128] = {0};
+ printf("set blk\n");
+ part_no = get_partition_num_by_name((char *)part_name);
+ /*printf("%s, part_no is %d\n", __FUNCTION__, part_no);*/
+ if (part_no >= 0) {
+ strcpy(part_buf, CS_BLCOK_DEV_MARJOR_NUM);
+ strcat(part_buf, ":");
+
+ sprintf(tmp_buf, "%x", part_no);
+ strcat(part_buf, tmp_buf);
+
+ return fs_set_blk_dev(CS_BLCOK_DEV_INTERFACE, part_buf, FS_TYPE_EXT);
+ }
+ printf("set blk done\n");
+ return -1;
+}
+
+int fwGetFileSize(const char *file_path) {
+ loff_t file_size = 0;
+ char part_name[CC_MAX_INI_FILE_NAME_LEN];
+ char file_name[CC_MAX_INI_FILE_NAME_LEN];
+
+ memset((void *)part_name, 0, CC_MAX_INI_FILE_NAME_LEN);
+ memset((void *)file_name, 0, CC_MAX_INI_FILE_NAME_LEN);
+ if (splitFilePath(file_path, part_name, file_name, NULL) < 0) {
+ return -1;
+ }
+ printf("setBlockDevice_fs start ....\n");
+ if (setBlockDevice_fs(part_name) < 0) {
+ return -1;
+ }
+ printf("setBlockDevice_fs %s end ....\n",file_name);
+ if (fs_size(file_name, &file_size)) {
+ return -1;
+ }
+ printf("setBlockDevice_fs %s end ....\n",file_name);
+ return file_size;
+}
+
+int fwReadFileToBuffer(const char *file_path,unsigned char data_buf[]) {
+
+ int tmp_ret = -1;
+ loff_t rd_cnt = 0;
+ char part_name[CC_MAX_INI_FILE_NAME_LEN];
+ char file_name[CC_MAX_INI_FILE_NAME_LEN];
+
+ memset((void *)part_name, 0, CC_MAX_INI_FILE_NAME_LEN);
+ memset((void *)file_name, 0, CC_MAX_INI_FILE_NAME_LEN);
+ if (splitFilePath(file_path, part_name, file_name, NULL) < 0) {
+ return -1;
+ }
+
+ if (setBlockDevice_fs(part_name) < 0) {
+ return -1;
+ }
+
+ tmp_ret = fs_read(file_name, (unsigned long)data_buf, 0, 0, &rd_cnt);
+ if (tmp_ret < 0) {
+ return -1;
+ }
+
+ flush_dcache_range((unsigned long )data_buf, (unsigned long )data_buf + rd_cnt);
+ return rd_cnt;
+}
diff --git a/board/amlogic/tm2_ab301_v1/tm2_ab301_v1.c b/board/amlogic/tm2_ab301_v1/tm2_ab301_v1.c
new file mode 100644
index 0000000000..2a71ca978c
--- /dev/null
+++ b/board/amlogic/tm2_ab301_v1/tm2_ab301_v1.c
@@ -0,0 +1,798 @@
+
+/*
+ *
+ * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
+ *
+ * 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 <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <environment.h>
+#include <fdt_support.h>
+#include <libfdt.h>
+#include <asm/cpu_id.h>
+#include <asm/arch/secure_apb.h>
+#ifdef CONFIG_SYS_I2C_AML
+#include <aml_i2c.h>
+#endif
+#ifdef CONFIG_SYS_I2C_MESON
+#include <amlogic/i2c.h>
+#endif
+#ifdef CONFIG_PWM_MESON
+#include <pwm.h>
+#include <amlogic/pwm.h>
+#endif
+#include <dm.h>
+#ifdef CONFIG_AML_VPU
+#include <vpu.h>
+#endif
+#include <vpp.h>
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+#include <amlogic/aml_v2_burning.h>
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
+#ifdef CONFIG_AML_HDMITX20
+#include <amlogic/hdmi.h>
+#endif
+#ifdef CONFIG_AML_LCD
+#include <amlogic/aml_lcd.h>
+#endif
+#include <asm/arch/eth_setup.h>
+#include <phy.h>
+#include <linux/mtd/partitions.h>
+#include <linux/sizes.h>
+#include <asm-generic/gpio.h>
+#include <dm.h>
+#ifdef CONFIG_AML_SPIFC
+#include <amlogic/spifc.h>
+#endif
+#ifdef CONFIG_AML_SPICC
+#include <amlogic/spicc.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+//new static eth setup
+struct eth_board_socket* eth_board_skt;
+
+
+int serial_set_pin_port(unsigned long port_base)
+{
+ //UART in "Always On Module"
+ //GPIOAO_0==tx,GPIOAO_1==rx
+ //setbits_le32(P_AO_RTI_PIN_MUX_REG,3<<11);
+ return 0;
+}
+
+int dram_init(void)
+{
+ gd->ram_size = PHYS_SDRAM_1_SIZE;
+ return 0;
+}
+
+/* secondary_boot_func
+ * this function should be write with asm, here, is is only for compiling pass
+ * */
+void secondary_boot_func(void)
+{
+}
+#ifdef ETHERNET_INTERNAL_PHY
+void internalPhyConfig(struct phy_device *phydev)
+{
+}
+
+static int dwmac_meson_cfg_pll(void)
+{
+ writel(0x39C0040A, P_ETH_PLL_CTL0);
+ writel(0x927E0000, P_ETH_PLL_CTL1);
+ writel(0xAC5F49E5, P_ETH_PLL_CTL2);
+ writel(0x00000000, P_ETH_PLL_CTL3);
+ udelay(200);
+ writel(0x19C0040A, P_ETH_PLL_CTL0);
+ return 0;
+}
+
+static int dwmac_meson_cfg_analog(void)
+{
+ /*Analog*/
+ writel(0x20200000, P_ETH_PLL_CTL5);
+ writel(0x0000c002, P_ETH_PLL_CTL6);
+ writel(0x00000023, P_ETH_PLL_CTL7);
+
+ return 0;
+}
+
+static int dwmac_meson_cfg_ctrl(void)
+{
+ /*config phyid should between a 0~0xffffffff*/
+ /*please don't use 44000181, this has been used by internal phy*/
+ writel(0x33000180, P_ETH_PHY_CNTL0);
+
+ /*use_phy_smi | use_phy_ip | co_clkin from eth_phy_top*/
+ writel(0x260, P_ETH_PHY_CNTL2);
+
+ writel(0x74043, P_ETH_PHY_CNTL1);
+ writel(0x34043, P_ETH_PHY_CNTL1);
+ writel(0x74043, P_ETH_PHY_CNTL1);
+ return 0;
+}
+
+static void setup_net_chip(void)
+{
+ eth_aml_reg0_t eth_reg0;
+
+ eth_reg0.d32 = 0;
+ eth_reg0.b.phy_intf_sel = 4;
+ eth_reg0.b.rx_clk_rmii_invert = 0;
+ eth_reg0.b.rgmii_tx_clk_src = 0;
+ eth_reg0.b.rgmii_tx_clk_phase = 0;
+ eth_reg0.b.rgmii_tx_clk_ratio = 4;
+ eth_reg0.b.phy_ref_clk_enable = 1;
+ eth_reg0.b.clk_rmii_i_invert = 1;
+ eth_reg0.b.clk_en = 1;
+ eth_reg0.b.adj_enable = 1;
+ eth_reg0.b.adj_setup = 0;
+ eth_reg0.b.adj_delay = 9;
+ eth_reg0.b.adj_skew = 0;
+ eth_reg0.b.cali_start = 0;
+ eth_reg0.b.cali_rise = 0;
+ eth_reg0.b.cali_sel = 0;
+ eth_reg0.b.rgmii_rx_reuse = 0;
+ eth_reg0.b.eth_urgent = 0;
+ setbits_le32(P_PREG_ETH_REG0, eth_reg0.d32);// rmii mode
+
+ dwmac_meson_cfg_pll();
+ dwmac_meson_cfg_analog();
+ dwmac_meson_cfg_ctrl();
+
+ /* eth core clock */
+ setbits_le32(HHI_GCLK_MPEG1, (0x1 << 3));
+ /* eth phy clock */
+ setbits_le32(HHI_GCLK_MPEG0, (0x1 << 4));
+
+ /* eth phy pll, clk50m */
+ setbits_le32(HHI_FIX_PLL_CNTL3, (0x1 << 5));
+
+ /* power on memory */
+ clrbits_le32(HHI_MEM_PD_REG0, (1 << 3) | (1<<2));
+}
+#endif
+
+#ifdef ETHERNET_EXTERNAL_PHY
+
+static int dwmac_meson_cfg_drive_strength(void)
+{
+ writel(0xaaaaaaa5, P_PAD_DS_REG4A);
+ return 0;
+}
+
+static void setup_net_chip_ext(void)
+{
+ eth_aml_reg0_t eth_reg0;
+ writel(0x11111111, P_PERIPHS_PIN_MUX_6);
+ writel(0x111111, P_PERIPHS_PIN_MUX_7);
+
+ eth_reg0.d32 = 0;
+ eth_reg0.b.phy_intf_sel = 1;
+ eth_reg0.b.rx_clk_rmii_invert = 0;
+ eth_reg0.b.rgmii_tx_clk_src = 0;
+ eth_reg0.b.rgmii_tx_clk_phase = 1;
+ eth_reg0.b.rgmii_tx_clk_ratio = 4;
+ eth_reg0.b.phy_ref_clk_enable = 1;
+ eth_reg0.b.clk_rmii_i_invert = 0;
+ eth_reg0.b.clk_en = 1;
+ eth_reg0.b.adj_enable = 0;
+ eth_reg0.b.adj_setup = 0;
+ eth_reg0.b.adj_delay = 0;
+ eth_reg0.b.adj_skew = 0;
+ eth_reg0.b.cali_start = 0;
+ eth_reg0.b.cali_rise = 0;
+ eth_reg0.b.cali_sel = 0;
+ eth_reg0.b.rgmii_rx_reuse = 0;
+ eth_reg0.b.eth_urgent = 0;
+ setbits_le32(P_PREG_ETH_REG0, eth_reg0.d32);// rmii mode
+
+ setbits_le32(HHI_GCLK_MPEG1, 0x1 << 3);
+ /* power on memory */
+ clrbits_le32(HHI_MEM_PD_REG0, (1 << 3) | (1<<2));
+}
+#endif
+extern struct eth_board_socket* eth_board_setup(char *name);
+extern int designware_initialize(ulong base_addr, u32 interface);
+
+int board_eth_init(bd_t *bis)
+{
+#ifdef CONFIG_ETHERNET_NONE
+ return 0;
+#endif
+
+#ifdef ETHERNET_EXTERNAL_PHY
+ dwmac_meson_cfg_drive_strength();
+ setup_net_chip_ext();
+#endif
+#ifdef ETHERNET_INTERNAL_PHY
+ setup_net_chip();
+#endif
+ udelay(1000);
+ designware_initialize(ETH_BASE, PHY_INTERFACE_MODE_RMII);
+ return 0;
+}
+
+#if CONFIG_AML_SD_EMMC
+#include <mmc.h>
+#include <asm/arch/sd_emmc.h>
+static int sd_emmc_init(unsigned port)
+{
+ switch (port)
+ {
+ case SDIO_PORT_A:
+ break;
+ case SDIO_PORT_B:
+ //todo add card detect
+ /* check card detect */
+ clrbits_le32(P_PERIPHS_PIN_MUX_9, 0xF << 24);
+ setbits_le32(P_PREG_PAD_GPIO1_EN_N, 1 << 6);
+ setbits_le32(P_PAD_PULL_UP_EN_REG1, 1 << 6);
+ setbits_le32(P_PAD_PULL_UP_REG1, 1 << 6);
+ break;
+ case SDIO_PORT_C:
+ //enable pull up
+ //clrbits_le32(P_PAD_PULL_UP_REG3, 0xff<<0);
+ break;
+ default:
+ break;
+ }
+
+ return cpu_sd_emmc_init(port);
+}
+
+extern unsigned sd_debug_board_1bit_flag;
+
+
+static void sd_emmc_pwr_prepare(unsigned port)
+{
+ cpu_sd_emmc_pwr_prepare(port);
+}
+
+static void sd_emmc_pwr_on(unsigned port)
+{
+ switch (port)
+ {
+ case SDIO_PORT_A:
+ break;
+ case SDIO_PORT_B:
+// clrbits_le32(P_PREG_PAD_GPIO5_O,(1<<31)); //CARD_8
+// clrbits_le32(P_PREG_PAD_GPIO5_EN_N,(1<<31));
+ /// @todo NOT FINISH
+ break;
+ case SDIO_PORT_C:
+ break;
+ default:
+ break;
+ }
+ return;
+}
+static void sd_emmc_pwr_off(unsigned port)
+{
+ /// @todo NOT FINISH
+ switch (port)
+ {
+ case SDIO_PORT_A:
+ break;
+ case SDIO_PORT_B:
+// setbits_le32(P_PREG_PAD_GPIO5_O,(1<<31)); //CARD_8
+// clrbits_le32(P_PREG_PAD_GPIO5_EN_N,(1<<31));
+ break;
+ case SDIO_PORT_C:
+ break;
+ default:
+ break;
+ }
+ return;
+}
+
+// #define CONFIG_TSD 1
+static void board_mmc_register(unsigned port)
+{
+ struct aml_card_sd_info *aml_priv=cpu_sd_emmc_get(port);
+ if (aml_priv == NULL)
+ return;
+
+ aml_priv->sd_emmc_init=sd_emmc_init;
+ aml_priv->sd_emmc_detect=sd_emmc_detect;
+ aml_priv->sd_emmc_pwr_off=sd_emmc_pwr_off;
+ aml_priv->sd_emmc_pwr_on=sd_emmc_pwr_on;
+ aml_priv->sd_emmc_pwr_prepare=sd_emmc_pwr_prepare;
+ aml_priv->desc_buf = malloc(NEWSD_MAX_DESC_MUN*(sizeof(struct sd_emmc_desc_info)));
+
+ if (NULL == aml_priv->desc_buf)
+ printf(" desc_buf Dma alloc Fail!\n");
+ else
+ printf("aml_priv->desc_buf = 0x%p\n",aml_priv->desc_buf);
+
+ sd_emmc_register(aml_priv);
+}
+int board_mmc_init(bd_t *bis)
+{
+#ifdef CONFIG_VLSI_EMULATOR
+ //board_mmc_register(SDIO_PORT_A);
+#else
+ //board_mmc_register(SDIO_PORT_B);
+#endif
+ board_mmc_register(SDIO_PORT_B);
+ board_mmc_register(SDIO_PORT_C);
+// board_mmc_register(SDIO_PORT_B1);
+ return 0;
+}
+
+#ifdef CONFIG_SYS_I2C_AML
+#if 0
+static void board_i2c_set_pinmux(void){
+ /*********************************************/
+ /* | I2C_Master_AO |I2C_Slave | */
+ /*********************************************/
+ /* | I2C_SCK | I2C_SCK_SLAVE | */
+ /* GPIOAO_4 | [AO_PIN_MUX: 6] | [AO_PIN_MUX: 2] | */
+ /*********************************************/
+ /* | I2C_SDA | I2C_SDA_SLAVE | */
+ /* GPIOAO_5 | [AO_PIN_MUX: 5] | [AO_PIN_MUX: 1] | */
+ /*********************************************/
+
+ //disable all other pins which share with I2C_SDA_AO & I2C_SCK_AO
+ clrbits_le32(P_AO_RTI_PIN_MUX_REG, ((1<<2)|(1<<24)|(1<<1)|(1<<23)));
+ //enable I2C MASTER AO pins
+ setbits_le32(P_AO_RTI_PIN_MUX_REG,
+ (MESON_I2C_MASTER_AO_GPIOAO_4_BIT | MESON_I2C_MASTER_AO_GPIOAO_5_BIT));
+
+ udelay(10);
+};
+#endif
+struct aml_i2c_platform g_aml_i2c_plat = {
+ .wait_count = 1000000,
+ .wait_ack_interval = 5,
+ .wait_read_interval = 5,
+ .wait_xfer_interval = 5,
+ .master_no = AML_I2C_MASTER_AO,
+ .use_pio = 0,
+ .master_i2c_speed = AML_I2C_SPPED_400K,
+ .master_ao_pinmux = {
+ .scl_reg = (unsigned long)MESON_I2C_MASTER_AO_GPIOAO_4_REG,
+ .scl_bit = MESON_I2C_MASTER_AO_GPIOAO_4_BIT,
+ .sda_reg = (unsigned long)MESON_I2C_MASTER_AO_GPIOAO_5_REG,
+ .sda_bit = MESON_I2C_MASTER_AO_GPIOAO_5_BIT,
+ }
+};
+#if 0
+static void board_i2c_init(void)
+{
+ //set I2C pinmux with PCB board layout
+ board_i2c_set_pinmux();
+
+ //Amlogic I2C controller initialized
+ //note: it must be call before any I2C operation
+ aml_i2c_init();
+
+ udelay(10);
+}
+#endif
+#endif
+#endif
+
+#if defined(CONFIG_BOARD_EARLY_INIT_F)
+int board_early_init_f(void){
+ /*add board early init function here*/
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_USB_XHCI_AMLOGIC_V2
+#include <asm/arch/usb-v2.h>
+#include <asm/arch/gpio.h>
+#define CONFIG_GXL_USB_U2_PORT_NUM CONFIG_USB_U2_PORT_NUM
+
+#ifdef CONFIG_USB_XHCI_AMLOGIC_USB3_V2
+#define CONFIG_GXL_USB_U3_PORT_NUM 1
+#else
+#define CONFIG_GXL_USB_U3_PORT_NUM 0
+#endif
+#if 0
+static void gpio_set_vbus_power(char is_power_on)
+{
+ int ret;
+
+ ret = gpio_request(CONFIG_USB_GPIO_PWR,
+ CONFIG_USB_GPIO_PWR_NAME);
+ if (ret && ret != -EBUSY) {
+ printf("gpio: requesting pin %u failed\n",
+ CONFIG_USB_GPIO_PWR);
+ return;
+ }
+
+ if (is_power_on) {
+ gpio_direction_output(CONFIG_USB_GPIO_PWR, 1);
+ } else {
+ gpio_direction_output(CONFIG_USB_GPIO_PWR, 0);
+ }
+}
+#endif
+struct amlogic_usb_config g_usb_config_GXL_skt={
+ CONFIG_GXL_XHCI_BASE,
+ USB_ID_MODE_HARDWARE,
+ NULL,//gpio_set_vbus_power,//gpio_set_vbus_power, //set_vbus_power
+ CONFIG_GXL_USB_PHY2_BASE,
+ CONFIG_GXL_USB_PHY3_BASE,
+ CONFIG_GXL_USB_U2_PORT_NUM,
+ CONFIG_GXL_USB_U3_PORT_NUM,
+ .usb_phy2_pll_base_addr = {
+ CONFIG_USB_PHY_20,
+ CONFIG_USB_PHY_21,
+ CONFIG_USB_PHY_22,
+ }
+};
+
+#endif /*CONFIG_USB_XHCI_AMLOGIC*/
+
+#ifdef CONFIG_AML_HDMITX20
+static void hdmi_tx_set_hdmi_5v(void)
+{
+}
+#endif
+
+/*
+ * mtd nand partition table, only care the size!
+ * offset will be calculated by nand driver.
+ */
+#ifdef CONFIG_AML_MTD
+static struct mtd_partition normal_partition_info[] = {
+#ifdef CONFIG_DISCRETE_BOOTLOADER
+ /* MUST NOT CHANGE this part unless u know what you are doing!
+ * inherent parition for descrete bootloader to store fip
+ * size is determind by TPL_SIZE_PER_COPY*TPL_COPY_NUM
+ * name must be same with TPL_PART_NAME
+ */
+ {
+ .name = "tpl",
+ .offset = 0,
+ .size = 0,
+ },
+#endif
+ {
+ .name = "logo",
+ .offset = 0,
+ .size = 2*SZ_1M,
+ },
+ {
+ .name = "recovery",
+ .offset = 0,
+ .size = 16*SZ_1M,
+ },
+ {
+ .name = "boot",
+ .offset = 0,
+ .size = 16*SZ_1M,
+ },
+ {
+ .name = "system",
+ .offset = 0,
+ .size = 64*SZ_1M,
+ },
+ /* last partition get the rest capacity */
+ {
+ .name = "data",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+struct mtd_partition *get_aml_mtd_partition(void)
+{
+ return normal_partition_info;
+}
+int get_aml_partition_count(void)
+{
+ return ARRAY_SIZE(normal_partition_info);
+}
+#endif /* CONFIG_AML_MTD */
+
+#ifdef CONFIG_AML_SPIFC
+/*
+ * BOOT_3: NOR_HOLDn:reg0[15:12]=3
+ * BOOT_4: NOR_D:reg0[19:16]=3
+ * BOOT_5: NOR_Q:reg0[23:20]=3
+ * BOOT_6: NOR_C:reg0[27:24]=3
+ * BOOT_7: NOR_WPn:reg0[31:28]=3
+ * BOOT_13: NOR_CS:reg1[23:20]=3
+ */
+#define SPIFC_NUM_CS 1
+static int spifc_cs_gpios[SPIFC_NUM_CS] = {GPIOEE(BOOT_13)};
+
+static int spifc_pinctrl_enable(void *pinctrl, bool enable)
+{
+ unsigned int val;
+
+ val = readl(P_PERIPHS_PIN_MUX_0);
+ val &= ~(0xfffff << 12);
+ if (enable)
+ val |= 0x33333 << 12;
+ writel(val, P_PERIPHS_PIN_MUX_0);
+
+ val = readl(P_PERIPHS_PIN_MUX_1);
+ val &= ~(0xf << 20);
+ writel(val, P_PERIPHS_PIN_MUX_1);
+ return 0;
+}
+
+static const struct spifc_platdata spifc_platdata = {
+ .reg = 0xffd14000,
+ .mem_map = 0xf6000000,
+ .pinctrl_enable = spifc_pinctrl_enable,
+ .num_chipselect = SPIFC_NUM_CS,
+ .cs_gpios = spifc_cs_gpios,
+};
+
+U_BOOT_DEVICE(spifc) = {
+ .name = "spifc",
+ .platdata = &spifc_platdata,
+};
+#endif /* CONFIG_AML_SPIFC */
+
+#ifdef CONFIG_AML_SPICC
+/* generic config in arch gpio/clock.c */
+extern int spicc0_clk_set_rate(int rate);
+extern int spicc0_clk_enable(bool enable);
+extern int spicc0_pinctrl_enable(bool enable);
+
+static const struct spicc_platdata spicc0_platdata = {
+ .compatible = "amlogic,meson-g12a-spicc",
+ .reg = (void __iomem *)0xffd13000,
+ .clk_rate = 666666666,
+ .clk_set_rate = spicc0_clk_set_rate,
+ .clk_enable = spicc0_clk_enable,
+ .pinctrl_enable = spicc0_pinctrl_enable,
+ /* case one slave without cs: {"no_cs", 0} */
+ .cs_gpio_names = {"GPIOH_20", 0},
+};
+
+U_BOOT_DEVICE(spicc0) = {
+ .name = "spicc",
+ .platdata = &spicc0_platdata,
+};
+#endif /* CONFIG_AML_SPICC */
+
+extern void aml_pwm_cal_init(int mode);
+
+#ifdef CONFIG_SYS_I2C_MESON
+static const struct meson_i2c_platdata i2c_data[] = {
+ { 0, 0xffd1f000, 166666666, 3, 15, 100000 },
+ { 1, 0xffd1e000, 166666666, 3, 15, 100000 },
+ { 2, 0xffd1d000, 166666666, 3, 15, 100000 },
+ { 3, 0xffd1c000, 166666666, 3, 15, 100000 },
+ { 4, 0xff805000, 166666666, 3, 15, 100000 },
+};
+
+U_BOOT_DEVICES(meson_i2cs) = {
+ { "i2c_meson", &i2c_data[0] },
+ { "i2c_meson", &i2c_data[1] },
+ { "i2c_meson", &i2c_data[2] },
+ { "i2c_meson", &i2c_data[3] },
+ { "i2c_meson", &i2c_data[4] },
+};
+
+/*
+ *GPIOAO_10//I2C_SDA_AO
+ *GPIOAO_11//I2C_SCK_AO
+ *pinmux configuration seperated with i2c controller configuration
+ * config it when you use
+ */
+void set_i2c_ao_pinmux(void)
+{
+ return;
+}
+#endif /*end CONFIG_SYS_I2C_MESON*/
+
+#ifdef CONFIG_PWM_MESON
+static const struct meson_pwm_platdata pwm_data[] = {
+ { PWM_AB, 0xffd1b000, IS_DOUBLE_CHANNEL, IS_BLINK },
+ { PWM_CD, 0xffd1a000, IS_DOUBLE_CHANNEL, IS_BLINK },
+ { PWM_EF, 0xffd19000, IS_DOUBLE_CHANNEL, IS_BLINK },
+ { PWMAO_AB, 0xff807000, IS_DOUBLE_CHANNEL, IS_BLINK },
+ { PWMAO_CD, 0xff802000, IS_DOUBLE_CHANNEL, IS_BLINK },
+};
+
+U_BOOT_DEVICES(meson_pwm) = {
+ { "amlogic,general-pwm", &pwm_data[0] },
+ { "amlogic,general-pwm", &pwm_data[1] },
+ { "amlogic,general-pwm", &pwm_data[2] },
+ { "amlogic,general-pwm", &pwm_data[3] },
+ { "amlogic,general-pwm", &pwm_data[4] },
+};
+#endif /*end CONFIG_PWM_MESON*/
+
+int board_init(void)
+{
+ int val;
+
+ /* For usb reboot sequence,set GPIOAO_2 low in bl2_stage_init, set high here */
+ val = readl(AO_GPIO_O);
+ val |= 1 << 3;
+ writel(val, AO_GPIO_O);
+ //Please keep CONFIG_AML_V2_FACTORY_BURN at first place of board_init
+ //As NOT NEED other board init If USB BOOT MODE
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+ if ((0x1b8ec003 != readl(P_PREG_STICKY_REG2)) && (0x1b8ec004 != readl(P_PREG_STICKY_REG2))) {
+ aml_try_factory_usb_burning(0, gd->bd);
+ }
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
+#ifdef CONFIG_USB_XHCI_AMLOGIC_V2
+ board_usb_pll_disable(&g_usb_config_GXL_skt);
+ board_usb_init(&g_usb_config_GXL_skt,BOARD_USB_MODE_HOST);
+#endif /*CONFIG_USB_XHCI_AMLOGIC*/
+
+#if 0
+ aml_pwm_cal_init(0);
+#endif//
+#ifdef CONFIG_AML_NAND
+ extern int amlnf_init(unsigned char flag);
+ amlnf_init(0);
+#endif
+#ifdef CONFIG_SYS_I2C_MESON
+ set_i2c_ao_pinmux();
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_BOARD_LATE_INIT
+/* Reset BT-module */
+void reset_mt7668(void)
+{
+ /* Reset BT-module by reset-pin -- GPIOAO_5 */
+ clrbits_le32(P_AO_GPIO_O_EN_N, 1 << 5);
+ clrbits_le32(P_AO_GPIO_O_EN_N, 1 << 21);
+ mdelay(200);
+ setbits_le32(P_AO_GPIO_O_EN_N, 1 << 21);
+ mdelay(100);
+}
+int board_late_init(void)
+{
+ //update env before anyone using it
+ run_command("get_rebootmode; echo reboot_mode=${reboot_mode}; "\
+ "if test ${reboot_mode} = factory_reset; then "\
+ "defenv_reserv;setenv upgrade_step 2;save; fi;", 0);
+ run_command("if itest ${upgrade_step} == 1; then "\
+ "defenv_reserv; setenv upgrade_step 2; saveenv; fi;", 0);
+ /*add board late init function here*/
+#ifndef DTB_BIND_KERNEL
+ int ret;
+ ret = run_command("store dtb read $dtb_mem_addr", 1);
+ if (ret) {
+ printf("%s(): [store dtb read $dtb_mem_addr] fail\n", __func__);
+#ifdef CONFIG_DTB_MEM_ADDR
+ char cmd[64];
+ printf("load dtb to %x\n", CONFIG_DTB_MEM_ADDR);
+ sprintf(cmd, "store dtb read %x", CONFIG_DTB_MEM_ADDR);
+ ret = run_command(cmd, 1);
+ if (ret) {
+ printf("%s(): %s fail\n", __func__, cmd);
+ }
+#endif
+ }
+#elif defined(CONFIG_DTB_MEM_ADDR)
+ {
+ char cmd[128];
+ int ret;
+ if (!getenv("dtb_mem_addr")) {
+ sprintf(cmd, "setenv dtb_mem_addr 0x%x", CONFIG_DTB_MEM_ADDR);
+ run_command(cmd, 0);
+ }
+ sprintf(cmd, "imgread dtb boot ${dtb_mem_addr}");
+ ret = run_command(cmd, 0);
+ if (ret) {
+ printf("%s(): cmd[%s] fail, ret=%d\n", __func__, cmd, ret);
+ }
+ }
+#endif// #ifndef DTB_BIND_KERNEL
+
+ /* load unifykey */
+ run_command("keyunify init 0x1234", 0);
+#ifdef CONFIG_AML_VPU
+ vpu_probe();
+#endif
+ vpp_init();
+
+ run_command("ini_model", 0);
+#ifdef CONFIG_AML_HDMITX20
+ hdmi_tx_set_hdmi_5v();
+ hdmi_tx_init();
+#endif
+#ifdef CONFIG_AML_CVBS
+ run_command("cvbs init", 0);
+#endif
+#ifdef CONFIG_AML_LCD
+ lcd_probe();
+#endif
+
+#ifdef CONFIG_AML_V2_FACTORY_BURN
+ if (0x1b8ec003 == readl(P_PREG_STICKY_REG2))
+ aml_try_factory_usb_burning(1, gd->bd);
+ aml_try_factory_sdcard_burning(0, gd->bd);
+#endif// #ifdef CONFIG_AML_V2_FACTORY_BURN
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_AML_TINY_USBTOOL
+int usb_get_update_result(void)
+{
+ unsigned long upgrade_step;
+ upgrade_step = simple_strtoul (getenv ("upgrade_step"), NULL, 16);
+ printf("upgrade_step = %d\n", (int)upgrade_step);
+ if (upgrade_step == 1)
+ {
+ run_command("defenv", 1);
+ run_command("setenv upgrade_step 2", 1);
+ run_command("saveenv", 1);
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+}
+#endif
+
+phys_size_t get_effective_memsize(void)
+{
+ // >>16 -> MB, <<20 -> real size, so >>16<<20 = <<4
+#if defined(CONFIG_SYS_MEM_TOP_HIDE)
+ return (((readl(AO_SEC_GP_CFG0)) & 0xFFFF0000) << 4) - CONFIG_SYS_MEM_TOP_HIDE;
+#else
+ return (((readl(AO_SEC_GP_CFG0)) & 0xFFFF0000) << 4);
+#endif
+}
+
+#ifdef CONFIG_MULTI_DTB
+int checkhw(char * name)
+{
+ char loc_name[64] = {0};
+
+ /* add your logic code here */
+
+
+ /* set aml_dt */
+ strcpy(name, loc_name);
+ setenv("aml_dt", loc_name);
+ return 0;
+}
+#endif
+
+extern int do_setMtkBT( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+U_BOOT_CMD(
+ setMtkBT, CONFIG_SYS_MAXARGS, 1, do_setMtkBT,
+ "load MTK BT driver, and set woble\n",
+ NULL
+);
+
+const char * const _env_args_reserve_[] =
+{
+ "aml_dt",
+ "firstboot",
+ "lock",
+ "upgrade_step",
+ "model_name",
+
+ NULL//Keep NULL be last to tell END
+};
+