This commit is contained in:
Tom Rini 2015-08-08 20:20:17 -04:00
commit 15f8876b1d
22 changed files with 788 additions and 96 deletions

View file

@ -232,6 +232,13 @@ void sunxi_usb_phy_power_off(int index)
gpio_set_value(phy->gpio_vbus, 0);
}
int sunxi_usb_phy_power_is_on(int index)
{
struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];
return phy->power_on_count > 0;
}
int sunxi_usb_phy_vbus_detect(int index)
{
struct sunxi_usb_phy *phy = &sunxi_usb_phy[index];

View file

@ -267,6 +267,8 @@ struct sunxi_ccm_reg {
#define CCM_MBUS_CTRL_CLK_SRC_PLL5 0x2
#define CCM_MBUS_CTRL_GATE (0x1 << 31)
#define CCM_NAND_CTRL_ENABLE (0x1 << 31)
#define CCM_MMC_CTRL_M(x) ((x) - 1)
#define CCM_MMC_CTRL_OCLK_DLY(x) ((x) << 8)
#define CCM_MMC_CTRL_N(x) ((x) << 16)
@ -289,7 +291,7 @@ struct sunxi_ccm_reg {
#define CCM_LCD_CH0_CTRL_GATE (0x1 << 31)
#define CCM_LCD_CH1_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
/* We leave bit 11 set to 0, so sclk1 == sclk2 */
#define CCM_LCD_CH1_CTRL_HALF_SCLK1 (1 << 11)
#define CCM_LCD_CH1_CTRL_PLL3 (0 << 24)
#define CCM_LCD_CH1_CTRL_PLL7 (1 << 24)
#define CCM_LCD_CH1_CTRL_PLL3_2X (2 << 24)

View file

@ -290,6 +290,7 @@ struct sunxi_ccm_reg {
#define CCM_LCD_CH0_CTRL_GATE (0x1 << 31)
#define CCM_LCD_CH1_CTRL_M(n) ((((n) - 1) & 0xf) << 0)
#define CCM_LCD_CH1_CTRL_HALF_SCLK1 0 /* no seperate sclk1 & 2 on sun6i */
#define CCM_LCD_CH1_CTRL_PLL3 (0 << 24)
#define CCM_LCD_CH1_CTRL_PLL7 (1 << 24)
#define CCM_LCD_CH1_CTRL_PLL3_2X (2 << 24)

View file

@ -151,6 +151,10 @@ struct sunxi_de_be_reg {
u32 layer1_attr1_ctrl; /* 0x8a4 */
u32 layer2_attr1_ctrl; /* 0x8a8 */
u32 layer3_attr1_ctrl; /* 0x8ac */
u8 res5[0x110]; /* 0x8b0 */
u32 output_color_ctrl; /* 0x9c0 */
u8 res6[0xc]; /* 0x9c4 */
u32 output_color_coef[12]; /* 0x9d0 */
};
struct sunxi_lcdc_reg {
@ -298,7 +302,7 @@ struct sunxi_tve_reg {
u32 cbr_level; /* 0x10c */
u32 burst_phase; /* 0x110 */
u32 burst_width; /* 0x114 */
u8 res2[0x04]; /* 0x118 */
u32 unknown2; /* 0x118 */
u32 sync_vbi_level; /* 0x11c */
u32 white_level; /* 0x120 */
u32 active_num; /* 0x124 */
@ -331,11 +335,14 @@ struct sunxi_tve_reg {
#define SUNXI_DE_BE_HEIGHT(y) (((y) - 1) << 16)
#define SUNXI_DE_BE_MODE_ENABLE (1 << 0)
#define SUNXI_DE_BE_MODE_START (1 << 1)
#define SUNXI_DE_BE_MODE_DEFLICKER_ENABLE (1 << 4)
#define SUNXI_DE_BE_MODE_LAYER0_ENABLE (1 << 8)
#define SUNXI_DE_BE_MODE_INTERLACE_ENABLE (1 << 28)
#define SUNXI_DE_BE_LAYER_STRIDE(x) ((x) << 5)
#define SUNXI_DE_BE_REG_CTRL_LOAD_REGS (1 << 0)
#define SUNXI_DE_BE_LAYER_ATTR0_SRC_FE0 0x00000002
#define SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888 (0x09 << 8)
#define SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE 1
/*
* LCDC register constants.
@ -372,11 +379,12 @@ struct sunxi_tve_reg {
#define SUNXI_LCDC_TCON0_LVDS_INTF_ENABLE (1 << 31)
#define SUNXI_LCDC_TCON0_IO_POL_DCLK_PHASE(x) ((x) << 28)
#define SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(n) (((n) & 0x1f) << 4)
#define SUNXI_LCDC_TCON1_CTRL_INTERLACE_ENABLE (1 << 20)
#define SUNXI_LCDC_TCON1_CTRL_ENABLE (1 << 31)
#define SUNXI_LCDC_TCON1_TIMING_H_BP(n) (((n) - 1) << 0)
#define SUNXI_LCDC_TCON1_TIMING_H_TOTAL(n) (((n) - 1) << 16)
#define SUNXI_LCDC_TCON1_TIMING_V_BP(n) (((n) - 1) << 0)
#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n) (((n) * 2) << 16)
#define SUNXI_LCDC_TCON1_TIMING_V_TOTAL(n) ((n) << 16)
#ifdef CONFIG_SUNXI_GEN_SUN6I
#define SUNXI_LCDC_LVDS_ANA0 0x40040320
#define SUNXI_LCDC_LVDS_ANA0_EN_MB (1 << 31)
@ -494,9 +502,22 @@ struct sunxi_tve_reg {
*/
#define SUNXI_TVE_GCTRL_DAC_INPUT_MASK(dac) (0xf << (((dac) + 1) * 4))
#define SUNXI_TVE_GCTRL_DAC_INPUT(dac, sel) ((sel) << (((dac) + 1) * 4))
#define SUNXI_TVE_GCTRL_CFG0_VGA 0x20000000
#define SUNXI_TVE_GCTRL_DAC_CFG0_VGA 0x403e1ac7
#define SUNXI_TVE_GCTRL_UNKNOWN1_VGA 0x00000000
#define SUNXI_TVE_CFG0_VGA 0x20000000
#define SUNXI_TVE_CFG0_PAL 0x07030001
#define SUNXI_TVE_CFG0_NTSC 0x07030000
#define SUNXI_TVE_DAC_CFG0_VGA 0x403e1ac7
#define SUNXI_TVE_DAC_CFG0_COMPOSITE 0x403f0008
#define SUNXI_TVE_FILTER_COMPOSITE 0x00000120
#define SUNXI_TVE_CHROMA_FREQ_PAL_M 0x21e6efe3
#define SUNXI_TVE_CHROMA_FREQ_PAL_NC 0x21f69446
#define SUNXI_TVE_PORCH_NUM_PAL 0x008a0018
#define SUNXI_TVE_PORCH_NUM_NTSC 0x00760020
#define SUNXI_TVE_LINE_NUM_PAL 0x00160271
#define SUNXI_TVE_LINE_NUM_NTSC 0x0016020d
#define SUNXI_TVE_BLANK_BLACK_LEVEL_PAL 0x00fc00fc
#define SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC 0x00f0011a
#define SUNXI_TVE_UNKNOWN1_VGA 0x00000000
#define SUNXI_TVE_UNKNOWN1_COMPOSITE 0x18181818
#define SUNXI_TVE_AUTO_DETECT_EN_DET_EN(dac) (1 << ((dac) + 0))
#define SUNXI_TVE_AUTO_DETECT_EN_INT_EN(dac) (1 << ((dac) + 16))
#define SUNXI_TVE_AUTO_DETECT_INT_STATUS(dac) (1 << ((dac) + 0))
@ -512,6 +533,20 @@ struct sunxi_tve_reg {
#define SUNXI_TVE_CSC_REG1 0x3b6dace1
#define SUNXI_TVE_CSC_REG2 0x0e1d13dc
#define SUNXI_TVE_CSC_REG3 0x00108080
#define SUNXI_TVE_COLOR_BURST_PAL_M 0x00000000
#define SUNXI_TVE_CBR_LEVEL_PAL 0x00002828
#define SUNXI_TVE_CBR_LEVEL_NTSC 0x0000004f
#define SUNXI_TVE_BURST_PHASE_NTSC 0x00000000
#define SUNXI_TVE_BURST_WIDTH_COMPOSITE 0x0016447e
#define SUNXI_TVE_UNKNOWN2_PAL 0x0000e0e0
#define SUNXI_TVE_UNKNOWN2_NTSC 0x0000a0a0
#define SUNXI_TVE_SYNC_VBI_LEVEL_NTSC 0x001000f0
#define SUNXI_TVE_ACTIVE_NUM_COMPOSITE 0x000005a0
#define SUNXI_TVE_CHROMA_BW_GAIN_COMP 0x00000002
#define SUNXI_TVE_NOTCH_WIDTH_COMPOSITE 0x00000101
#define SUNXI_TVE_RESYNC_NUM_PAL 0x800d000c
#define SUNXI_TVE_RESYNC_NUM_NTSC 0x000e000c
#define SUNXI_TVE_SLAVE_PARA_COMPOSITE 0x00000000
int sunxi_simplefb_setup(void *blob);

View file

@ -158,6 +158,7 @@ enum sunxi_gpio_number {
#define SUN8I_GPB_UART2 2
#define SUN8I_A33_GPB_UART0 3
#define SUNXI_GPC_NAND 2
#define SUNXI_GPC_SDC2 3
#define SUN6I_GPC_SDC3 4

View file

@ -16,6 +16,7 @@ void sunxi_usb_phy_init(int index);
void sunxi_usb_phy_exit(int index);
void sunxi_usb_phy_power_on(int index);
void sunxi_usb_phy_power_off(int index);
int sunxi_usb_phy_power_is_on(int index);
int sunxi_usb_phy_vbus_detect(int index);
int sunxi_usb_phy_id_detect(int index);
void sunxi_usb_phy_enable_squelch_detect(int index, int enable);

View file

@ -410,6 +410,13 @@ config VIDEO_VGA_EXTERNAL_DAC_EN
Set the enable pin for the external VGA DAC. This takes a string in the
format understood by sunxi_name_to_gpio, e.g. PH1 for pin 1 of port H.
config VIDEO_COMPOSITE
boolean "Composite video output support"
depends on VIDEO && (MACH_SUN4I || MACH_SUN5I || MACH_SUN7I)
default n
---help---
Say Y here to add support for outputting composite video.
config VIDEO_LCD_MODE
string "LCD panel timing details"
depends on VIDEO

View file

@ -107,6 +107,28 @@ int dram_init(void)
return 0;
}
#if defined(CONFIG_SPL_NAND_SUNXI) && defined(CONFIG_SPL_BUILD)
static void nand_pinmux_setup(void)
{
unsigned int pin;
for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(6); pin++)
sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_NAND);
for (pin = SUNXI_GPC(8); pin <= SUNXI_GPC(22); pin++)
sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_NAND);
sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_NAND);
}
static void nand_clock_setup(void)
{
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
setbits_le32(&ccm->ahb_gate0, (CLK_GATE_OPEN << AHB_GATE_OFFSET_NAND0));
setbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE | AHB_DIV_1);
}
#endif
#ifdef CONFIG_GENERIC_MMC
static void mmc_pinmux_setup(int sdc)
{
@ -431,6 +453,11 @@ void sunxi_board_init(void)
power_failed |= axp221_set_eldo(3, CONFIG_AXP221_ELDO3_VOLT);
#endif
#ifdef CONFIG_SPL_NAND_SUNXI
nand_pinmux_setup();
nand_clock_setup();
#endif
printf("DRAM:");
ramsize = sunxi_dram_init();
printf(" %lu MiB\n", ramsize >> 20);

View file

@ -5,6 +5,7 @@ CONFIG_DRAM_CLK=408
CONFIG_DRAM_EMR1=4
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_USB0_VBUS_DET="PH5"
CONFIG_USB0_ID_DET="PH4"
CONFIG_VIDEO_LCD_MODE="x:1024,y:768,depth:24,pclk_khz:51000,le:19,ri:300,up:6,lo:31,hs:1,vs:1,sync:3,vmode:0"
CONFIG_VIDEO_LCD_POWER="PH8"
CONFIG_VIDEO_LCD_BL_EN="PH7"

View file

@ -5,6 +5,7 @@ CONFIG_DRAM_CLK=384
CONFIG_MMC0_CD_PIN="PH1"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_VIDEO_VGA=y
CONFIG_VIDEO_COMPOSITE=y
CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-m3"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL=y

View file

@ -7,6 +7,7 @@ CONFIG_MMC0_CD_PIN="PG0"
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_USB0_VBUS_PIN="PB04"
CONFIG_USB0_VBUS_DET="PG01"
CONFIG_USB0_ID_DET="PG2"
CONFIG_AXP_GPIO=y
CONFIG_VIDEO_LCD_MODE="x:480,y:800,depth:18,pclk_khz:25000,le:2,ri:93,up:2,lo:93,hs:1,vs:1,sync:3,vmode:0"
CONFIG_VIDEO_LCD_DCLK_PHASE=0

View file

@ -2,10 +2,15 @@ CONFIG_ARM=y
CONFIG_ARCH_SUNXI=y
CONFIG_MACH_SUN7I=y
CONFIG_DRAM_CLK=384
CONFIG_USB0_VBUS_PIN="PB9"
CONFIG_USB0_VBUS_DET="AXP0-VBUS-DETECT"
CONFIG_USB0_ID_DET="PH4"
CONFIG_AXP_GPIO=y
CONFIG_VIDEO_LCD_MODE="x:800,y:480,depth:24,pclk_khz:33000,le:45,ri:210,up:22,lo:22,hs:1,vs:1,sync:3,vmode:0"
CONFIG_VIDEO_LCD_POWER="PH8"
CONFIG_VIDEO_LCD_BL_EN="PH7"
CONFIG_VIDEO_LCD_BL_PWM="PB2"
CONFIG_USB_MUSB_HOST=y
CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-wexler-tab7200"
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPL=y

View file

@ -10,3 +10,5 @@ CONFIG_SYS_EXTRA_OPTIONS="AXP209_POWER,SUNXI_EMAC,MACPWR=SUNXI_GPH(19)"
# CONFIG_CMD_FLASH is not set
# CONFIG_CMD_FPGA is not set
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_MUSB_HOST=y
CONFIG_USB0_VBUS_PIN="PB9"

View file

@ -40,12 +40,15 @@ requires the CONFIG_VIDEO_LCD_MODE Kconfig value to be set.
The sunxi u-boot driver supports the following video-mode options:
- monitor=[none|dvi|hdmi|lcd] - Select the video output to use
- monitor=[none|dvi|hdmi|lcd|vga|composite-*] - Select the video output to use
none: Disable video output.
dvi/hdmi: Selects output over the hdmi connector with dvi resp. hdmi output
format, if edid is used the format is automatically selected.
lcd: Selects video output to a LCD screen.
vga: Selects bideo output over the VGA connector.
vga: Selects video output over the VGA connector.
composite-pal/composite-ntsc/composite-pal-m/composite-pal-nc:
Selects composite video output, note the specified resolution is
ignored with composite video output.
Defaults to monitor=dvi.
- hpd=[0|1] - Enable use of the hdmi HotPlug Detect feature

View file

@ -85,6 +85,46 @@ config SPL_NAND_DENALI
This is a small implementation of the Denali NAND controller
for use on SPL.
config SPL_NAND_SUNXI
bool "Support for NAND on Allwinner A20 in SPL"
depends on MACH_SUN7I
---help---
Enable support for NAND. This option allows SPL to read from
sunxi NAND using DMA transfers.
Depending on the NAND chip, values like ECC strength and page sizes
have to be configured.
config NAND_SUNXI_SPL_SYNDROME_PARTITIONS_END
hex "Size of syndrome partitions in sunxi NAND"
default 0x400000
depends on SPL_NAND_SUNXI
---help---
End address for boot partitions on NAND. Those partitions have a
different random seed that has to match the sunxi BROM setting.
config NAND_SUNXI_SPL_ECC_STRENGTH
int "ECC Strength for sunxi NAND"
default 40
depends on SPL_NAND_SUNXI
---help---
ECC strength used by the sunxi NAND SPL driver. This is specific to the
chosen NAND chip and has to match the value used by the sunxi BROM.
config NAND_SUNXI_SPL_ECC_PAGE_SIZE
hex "ECC page size for sunxi NAND"
default 0x400
depends on SPL_NAND_SUNXI
---help---
ECC page size used by the sunxi NAND SPL driver for syndrome partitions.
This setting has to match the value used by the sunxi BROM.
config NAND_SUNXI_SPL_PAGE_SIZE
hex "Page size for sunxi NAND"
default 0x2000
depends on SPL_NAND_SUNXI
---help---
Page size of the NAND flash used by the sunxi NAND SPL driver. This is
specific to the chosen NAND chip.
endif
endmenu

View file

@ -12,6 +12,7 @@ NORMAL_DRIVERS=y
endif
obj-$(CONFIG_SPL_NAND_AM33XX_BCH) += am335x_spl_bch.o
obj-$(CONFIG_SPL_NAND_SUNXI) += sunxi_nand_spl.o
obj-$(CONFIG_SPL_NAND_DENALI) += denali_spl.o
obj-$(CONFIG_SPL_NAND_DOCG4) += docg4_spl.o
obj-$(CONFIG_SPL_NAND_SIMPLE) += nand_spl_simple.o

View file

@ -0,0 +1,353 @@
/*
* Copyright (c) 2014-2015, Antmicro Ltd <www.antmicro.com>
* Copyright (c) 2015, AW-SOM Technologies <www.aw-som.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <config.h>
#include <asm/io.h>
#include <nand.h>
/* registers */
#define NFC_CTL 0x00000000
#define NFC_ST 0x00000004
#define NFC_INT 0x00000008
#define NFC_TIMING_CTL 0x0000000C
#define NFC_TIMING_CFG 0x00000010
#define NFC_ADDR_LOW 0x00000014
#define NFC_ADDR_HIGH 0x00000018
#define NFC_SECTOR_NUM 0x0000001C
#define NFC_CNT 0x00000020
#define NFC_CMD 0x00000024
#define NFC_RCMD_SET 0x00000028
#define NFC_WCMD_SET 0x0000002C
#define NFC_IO_DATA 0x00000030
#define NFC_ECC_CTL 0x00000034
#define NFC_ECC_ST 0x00000038
#define NFC_DEBUG 0x0000003C
#define NFC_ECC_CNT0 0x00000040
#define NFC_ECC_CNT1 0x00000044
#define NFC_ECC_CNT2 0x00000048
#define NFC_ECC_CNT3 0x0000004C
#define NFC_USER_DATA_BASE 0x00000050
#define NFC_EFNAND_STATUS 0x00000090
#define NFC_SPARE_AREA 0x000000A0
#define NFC_PATTERN_ID 0x000000A4
#define NFC_RAM0_BASE 0x00000400
#define NFC_RAM1_BASE 0x00000800
#define NFC_CTL_EN (1 << 0)
#define NFC_CTL_RESET (1 << 1)
#define NFC_CTL_RAM_METHOD (1 << 14)
#define NFC_ECC_EN (1 << 0)
#define NFC_ECC_PIPELINE (1 << 3)
#define NFC_ECC_EXCEPTION (1 << 4)
#define NFC_ECC_BLOCK_SIZE (1 << 5)
#define NFC_ECC_RANDOM_EN (1 << 9)
#define NFC_ECC_RANDOM_DIRECTION (1 << 10)
#define NFC_ADDR_NUM_OFFSET 16
#define NFC_SEND_ADR (1 << 19)
#define NFC_ACCESS_DIR (1 << 20)
#define NFC_DATA_TRANS (1 << 21)
#define NFC_SEND_CMD1 (1 << 22)
#define NFC_WAIT_FLAG (1 << 23)
#define NFC_SEND_CMD2 (1 << 24)
#define NFC_SEQ (1 << 25)
#define NFC_DATA_SWAP_METHOD (1 << 26)
#define NFC_ROW_AUTO_INC (1 << 27)
#define NFC_SEND_CMD3 (1 << 28)
#define NFC_SEND_CMD4 (1 << 29)
#define NFC_CMD_INT_FLAG (1 << 1)
#define NFC_READ_CMD_OFFSET 0
#define NFC_RANDOM_READ_CMD0_OFFSET 8
#define NFC_RANDOM_READ_CMD1_OFFSET 16
#define NFC_CMD_RNDOUTSTART 0xE0
#define NFC_CMD_RNDOUT 0x05
#define NFC_CMD_READSTART 0x30
#define NFC_PAGE_CMD (2 << 30)
#define SUNXI_DMA_CFG_REG0 0x300
#define SUNXI_DMA_SRC_START_ADDR_REG0 0x304
#define SUNXI_DMA_DEST_START_ADDRR_REG0 0x308
#define SUNXI_DMA_DDMA_BC_REG0 0x30C
#define SUNXI_DMA_DDMA_PARA_REG0 0x318
#define SUNXI_DMA_DDMA_CFG_REG_LOADING (1 << 31)
#define SUNXI_DMA_DDMA_CFG_REG_DMA_DEST_DATA_WIDTH_32 (2 << 25)
#define SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_DATA_WIDTH_32 (2 << 9)
#define SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_ADDR_MODE_IO (1 << 5)
#define SUNXI_DMA_DDMA_CFG_REG_DDMA_SRC_DRQ_TYPE_NFC (3 << 0)
#define SUNXI_DMA_DDMA_PARA_REG_SRC_WAIT_CYC (0x0F << 0)
#define SUNXI_DMA_DDMA_PARA_REG_SRC_BLK_SIZE (0x7F << 8)
/* minimal "boot0" style NAND support for Allwinner A20 */
/* temporary buffer in internal ram */
unsigned char temp_buf[CONFIG_NAND_SUNXI_SPL_ECC_PAGE_SIZE]
__aligned(0x10) __section(".text#");
/* random seed used by linux */
const uint16_t random_seed[128] = {
0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
};
/* random seed used for syndrome calls */
const uint16_t random_seed_syndrome = 0x4a80;
#define MAX_RETRIES 10
static int check_value_inner(int offset, int expected_bits,
int max_number_of_retries, int negation)
{
int retries = 0;
do {
int val = readl(offset) & expected_bits;
if (negation ? !val : val)
return 1;
mdelay(1);
retries++;
} while (retries < max_number_of_retries);
return 0;
}
static inline int check_value(int offset, int expected_bits,
int max_number_of_retries)
{
return check_value_inner(offset, expected_bits,
max_number_of_retries, 0);
}
static inline int check_value_negated(int offset, int unexpected_bits,
int max_number_of_retries)
{
return check_value_inner(offset, unexpected_bits,
max_number_of_retries, 1);
}
void nand_init(void)
{
uint32_t val;
val = readl(SUNXI_NFC_BASE + NFC_CTL);
/* enable and reset CTL */
writel(val | NFC_CTL_EN | NFC_CTL_RESET,
SUNXI_NFC_BASE + NFC_CTL);
if (!check_value_negated(SUNXI_NFC_BASE + NFC_CTL,
NFC_CTL_RESET, MAX_RETRIES)) {
printf("Couldn't initialize nand\n");
}
}
static void nand_read_page(unsigned int real_addr, int syndrome,
uint32_t *ecc_errors)
{
uint32_t val;
int ecc_off = 0;
uint16_t ecc_mode = 0;
uint16_t rand_seed;
uint32_t page;
uint16_t column;
uint32_t oob_offset;
switch (CONFIG_NAND_SUNXI_SPL_ECC_STRENGTH) {
case 16:
ecc_mode = 0;
ecc_off = 0x20;
break;
case 24:
ecc_mode = 1;
ecc_off = 0x2e;
break;
case 28:
ecc_mode = 2;
ecc_off = 0x32;
break;
case 32:
ecc_mode = 3;
ecc_off = 0x3c;
break;
case 40:
ecc_mode = 4;
ecc_off = 0x4a;
break;
case 48:
ecc_mode = 4;
ecc_off = 0x52;
break;
case 56:
ecc_mode = 4;
ecc_off = 0x60;
break;
case 60:
ecc_mode = 4;
ecc_off = 0x0;
break;
case 64:
ecc_mode = 4;
ecc_off = 0x0;
break;
default:
ecc_mode = 0;
ecc_off = 0;
}
if (ecc_off == 0) {
printf("Unsupported ECC strength (%d)!\n",
CONFIG_NAND_SUNXI_SPL_ECC_STRENGTH);
return;
}
/* clear temp_buf */
memset(temp_buf, 0, CONFIG_NAND_SUNXI_SPL_ECC_PAGE_SIZE);
/* set CMD */
writel(NFC_SEND_CMD1 | NFC_WAIT_FLAG | NAND_CMD_RESET,
SUNXI_NFC_BASE + NFC_CMD);
if (!check_value(SUNXI_NFC_BASE + NFC_ST, NFC_CMD_INT_FLAG,
MAX_RETRIES)) {
printf("Error while initilizing command interrupt\n");
return;
}
page = real_addr / CONFIG_NAND_SUNXI_SPL_PAGE_SIZE;
column = real_addr % CONFIG_NAND_SUNXI_SPL_PAGE_SIZE;
if (syndrome)
column += (column / CONFIG_NAND_SUNXI_SPL_ECC_PAGE_SIZE)
* ecc_off;
/* clear ecc status */
writel(0, SUNXI_NFC_BASE + NFC_ECC_ST);
/* Choose correct seed */
if (syndrome)
rand_seed = random_seed_syndrome;
else
rand_seed = random_seed[page % 128];
writel((rand_seed << 16) | NFC_ECC_RANDOM_EN | NFC_ECC_EN
| NFC_ECC_PIPELINE | (ecc_mode << 12),
SUNXI_NFC_BASE + NFC_ECC_CTL);
val = readl(SUNXI_NFC_BASE + NFC_CTL);
writel(val | NFC_CTL_RAM_METHOD, SUNXI_NFC_BASE + NFC_CTL);
if (syndrome) {
writel(CONFIG_NAND_SUNXI_SPL_ECC_PAGE_SIZE,
SUNXI_NFC_BASE + NFC_SPARE_AREA);
} else {
oob_offset = CONFIG_NAND_SUNXI_SPL_PAGE_SIZE
+ (column / CONFIG_NAND_SUNXI_SPL_ECC_PAGE_SIZE)
* ecc_off;
writel(oob_offset, SUNXI_NFC_BASE + NFC_SPARE_AREA);
}
/* SUNXI_DMA */
writel(0x0, SUNXI_DMA_BASE + SUNXI_DMA_CFG_REG0); /* clr dma cmd */
/* read from REG_IO_DATA */
writel(SUNXI_NFC_BASE + NFC_IO_DATA,
SUNXI_DMA_BASE + SUNXI_DMA_SRC_START_ADDR_REG0);
/* read to RAM */
writel((uint32_t)temp_buf,
SUNXI_DMA_BASE + SUNXI_DMA_DEST_START_ADDRR_REG0);
writel(SUNXI_DMA_DDMA_PARA_REG_SRC_WAIT_CYC
| SUNXI_DMA_DDMA_PARA_REG_SRC_BLK_SIZE,
SUNXI_DMA_BASE + SUNXI_DMA_DDMA_PARA_REG0);
writel(CONFIG_NAND_SUNXI_SPL_ECC_PAGE_SIZE,
SUNXI_DMA_BASE + SUNXI_DMA_DDMA_BC_REG0); /* 1kB */
writel(SUNXI_DMA_DDMA_CFG_REG_LOADING
| SUNXI_DMA_DDMA_CFG_REG_DMA_DEST_DATA_WIDTH_32
| SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_DATA_WIDTH_32
| SUNXI_DMA_DDMA_CFG_REG_DMA_SRC_ADDR_MODE_IO
| SUNXI_DMA_DDMA_CFG_REG_DDMA_SRC_DRQ_TYPE_NFC,
SUNXI_DMA_BASE + SUNXI_DMA_CFG_REG0);
writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET)
| (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET)
| (NFC_CMD_READSTART | NFC_READ_CMD_OFFSET), SUNXI_NFC_BASE
+ NFC_RCMD_SET);
writel(1, SUNXI_NFC_BASE + NFC_SECTOR_NUM);
writel(((page & 0xFFFF) << 16) | column,
SUNXI_NFC_BASE + NFC_ADDR_LOW);
writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_ADDR_HIGH);
writel(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_DATA_TRANS |
NFC_PAGE_CMD | NFC_WAIT_FLAG | (4 << NFC_ADDR_NUM_OFFSET) |
NFC_SEND_ADR | NFC_DATA_SWAP_METHOD | (syndrome ? NFC_SEQ : 0),
SUNXI_NFC_BASE + NFC_CMD);
if (!check_value(SUNXI_NFC_BASE + NFC_ST, (1 << 2),
MAX_RETRIES)) {
printf("Error while initializing dma interrupt\n");
return;
}
if (!check_value_negated(SUNXI_DMA_BASE + SUNXI_DMA_CFG_REG0,
SUNXI_DMA_DDMA_CFG_REG_LOADING, MAX_RETRIES)) {
printf("Error while waiting for dma transfer to finish\n");
return;
}
if (readl(SUNXI_NFC_BASE + NFC_ECC_ST))
(*ecc_errors)++;
}
int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
{
void *current_dest;
uint32_t count;
uint32_t current_count;
uint32_t ecc_errors = 0;
memset(dest, 0x0, size); /* clean destination memory */
for (current_dest = dest;
current_dest < (dest + size);
current_dest += CONFIG_NAND_SUNXI_SPL_ECC_PAGE_SIZE) {
nand_read_page(offs, offs
< CONFIG_NAND_SUNXI_SPL_SYNDROME_PARTITIONS_END,
&ecc_errors);
count = current_dest - dest;
if (size - count > CONFIG_NAND_SUNXI_SPL_ECC_PAGE_SIZE)
current_count = CONFIG_NAND_SUNXI_SPL_ECC_PAGE_SIZE;
else
current_count = size - count;
memcpy(current_dest,
temp_buf,
current_count);
offs += CONFIG_NAND_SUNXI_SPL_ECC_PAGE_SIZE;
}
return ecc_errors ? -1 : 0;
}
void nand_deselect(void) {}

View file

@ -67,7 +67,6 @@ static int ehci_usb_remove(struct udevice *dev)
if (ret)
return ret;
sunxi_usb_phy_power_off(priv->phy_index);
sunxi_usb_phy_exit(priv->phy_index);
#ifdef CONFIG_SUNXI_GEN_SUN6I

View file

@ -69,7 +69,6 @@ static int ohci_usb_remove(struct udevice *dev)
if (ret)
return ret;
sunxi_usb_phy_power_off(priv->phy_index);
sunxi_usb_phy_exit(priv->phy_index);
#ifdef CONFIG_SUNXI_GEN_SUN6I

View file

@ -196,8 +196,6 @@ static bool enabled = false;
static int sunxi_musb_enable(struct musb *musb)
{
int ret;
pr_debug("%s():\n", __func__);
musb_ep_select(musb->mregs, 0);
@ -210,17 +208,26 @@ static int sunxi_musb_enable(struct musb *musb)
musb_writeb(musb->mregs, USBC_REG_o_VEND0, 0);
if (is_host_enabled(musb)) {
ret = sunxi_usb_phy_vbus_detect(0);
if (ret == 1) {
printf("A charger is plugged into the OTG: ");
return -ENODEV;
int id = sunxi_usb_phy_id_detect(0);
if (id == 1 && sunxi_usb_phy_power_is_on(0))
sunxi_usb_phy_power_off(0);
if (!sunxi_usb_phy_power_is_on(0)) {
int vbus = sunxi_usb_phy_vbus_detect(0);
if (vbus == 1) {
printf("A charger is plugged into the OTG: ");
return -ENODEV;
}
}
ret = sunxi_usb_phy_id_detect(0);
if (ret == 1) {
if (id == 1) {
printf("No host cable detected: ");
return -ENODEV;
}
sunxi_usb_phy_power_on(0); /* port power on */
if (!sunxi_usb_phy_power_is_on(0))
sunxi_usb_phy_power_on(0);
}
USBC_ForceVbusValidToHigh(musb->mregs);
@ -236,9 +243,6 @@ static void sunxi_musb_disable(struct musb *musb)
if (!enabled)
return;
if (is_host_enabled(musb))
sunxi_usb_phy_power_off(0); /* port power off */
USBC_ForceVbusValidToLow(musb->mregs);
mdelay(200); /* Wait for the current session to timeout */

View file

@ -2,7 +2,7 @@
* Display driver for Allwinner SoCs.
*
* (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be>
* (C) Copyright 2014 Hans de Goede <hdegoede@redhat.com>
* (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
@ -40,8 +40,12 @@ enum sunxi_monitor {
sunxi_monitor_hdmi,
sunxi_monitor_lcd,
sunxi_monitor_vga,
sunxi_monitor_composite_pal,
sunxi_monitor_composite_ntsc,
sunxi_monitor_composite_pal_m,
sunxi_monitor_composite_pal_nc,
};
#define SUNXI_MONITOR_LAST sunxi_monitor_vga
#define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc
struct sunxi_display {
GraphicDevice graphic_device;
@ -50,6 +54,12 @@ struct sunxi_display {
unsigned int fb_size;
} sunxi_display;
const struct ctfb_res_modes composite_video_modes[2] = {
/* x y hz pixclk ps/kHz le ri up lo hs vs s vmode */
{ 720, 576, 50, 37037, 27000, 137, 5, 20, 27, 2, 2, 0, FB_VMODE_INTERLACED },
{ 720, 480, 60, 37037, 27000, 116, 20, 16, 27, 2, 2, 0, FB_VMODE_INTERLACED },
};
#ifdef CONFIG_VIDEO_HDMI
/*
@ -390,6 +400,25 @@ static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode,
static void sunxi_frontend_enable(void) {}
#endif
static bool sunxi_is_composite(void)
{
switch (sunxi_display.monitor) {
case sunxi_monitor_none:
case sunxi_monitor_dvi:
case sunxi_monitor_hdmi:
case sunxi_monitor_lcd:
case sunxi_monitor_vga:
return false;
case sunxi_monitor_composite_pal:
case sunxi_monitor_composite_ntsc:
case sunxi_monitor_composite_pal_m:
case sunxi_monitor_composite_pal_nc:
return true;
}
return false; /* Never reached */
}
/*
* This is the entity that mixes and matches the different layers and inputs.
* Allwinner calls it the back-end, but i like composer better.
@ -423,11 +452,18 @@ static void sunxi_composer_init(void)
setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_ENABLE);
}
static u32 sunxi_rgb2yuv_coef[12] = {
0x00000107, 0x00000204, 0x00000064, 0x00000108,
0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808,
0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808
};
static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
unsigned int address)
{
struct sunxi_de_be_reg * const de_be =
(struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
int i;
sunxi_frontend_mode_set(mode, address);
@ -445,6 +481,18 @@ static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode,
writel(SUNXI_DE_BE_LAYER_ATTR1_FMT_XRGB8888, &de_be->layer0_attr1_ctrl);
setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_LAYER0_ENABLE);
if (mode->vmode == FB_VMODE_INTERLACED)
setbits_le32(&de_be->mode,
SUNXI_DE_BE_MODE_DEFLICKER_ENABLE |
SUNXI_DE_BE_MODE_INTERLACE_ENABLE);
if (sunxi_is_composite()) {
writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE,
&de_be->output_color_ctrl);
for (i = 0; i < 12; i++)
writel(sunxi_rgb2yuv_coef[i],
&de_be->output_color_coef[i]);
}
}
static void sunxi_composer_enable(void)
@ -535,6 +583,9 @@ static void sunxi_lcdc_pll_set(int tcon, int dotclock,
(best_double ? CCM_LCD_CH1_CTRL_PLL3_2X :
CCM_LCD_CH1_CTRL_PLL3) |
CCM_LCD_CH1_CTRL_M(best_m), &ccm->lcd0_ch1_clk_cfg);
if (sunxi_is_composite())
setbits_le32(&ccm->lcd0_ch1_clk_cfg,
CCM_LCD_CH1_CTRL_HALF_SCLK1);
}
*clk_div = best_m;
@ -663,11 +714,16 @@ static void sunxi_lcdc_backlight_enable(void)
gpio_direction_output(pin, PWM_ON);
}
static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode)
static int sunxi_lcdc_get_clk_delay(const struct ctfb_res_modes *mode, int tcon)
{
int delay;
delay = mode->lower_margin + mode->vsync_len + mode->upper_margin - 2;
delay = mode->lower_margin + mode->vsync_len + mode->upper_margin;
if (mode->vmode == FB_VMODE_INTERLACED)
delay /= 2;
if (tcon == 1)
delay -= 2;
return (delay > 30) ? 30 : delay;
}
@ -692,7 +748,7 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
SUNXI_LCDC_CTRL_IO_MAP_TCON0);
clk_delay = sunxi_lcdc_get_clk_delay(mode);
clk_delay = sunxi_lcdc_get_clk_delay(mode, 0);
writel(SUNXI_LCDC_TCON0_CTRL_ENABLE |
SUNXI_LCDC_TCON0_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon0_ctrl);
@ -757,28 +813,33 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode,
writel(0, &lcdc->tcon0_io_tristate);
}
#if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA
#if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
int *clk_div, int *clk_double,
bool use_portd_hvsync)
{
struct sunxi_lcdc_reg * const lcdc =
(struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE;
int bp, clk_delay, total, val;
int bp, clk_delay, total, val, yres;
/* Use tcon1 */
clrsetbits_le32(&lcdc->ctrl, SUNXI_LCDC_CTRL_IO_MAP_MASK,
SUNXI_LCDC_CTRL_IO_MAP_TCON1);
clk_delay = sunxi_lcdc_get_clk_delay(mode);
clk_delay = sunxi_lcdc_get_clk_delay(mode, 1);
writel(SUNXI_LCDC_TCON1_CTRL_ENABLE |
((mode->vmode == FB_VMODE_INTERLACED) ?
SUNXI_LCDC_TCON1_CTRL_INTERLACE_ENABLE : 0) |
SUNXI_LCDC_TCON1_CTRL_CLK_DELAY(clk_delay), &lcdc->tcon1_ctrl);
writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
yres = mode->yres;
if (mode->vmode == FB_VMODE_INTERLACED)
yres /= 2;
writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
&lcdc->tcon1_timing_source);
writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
&lcdc->tcon1_timing_scale);
writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(mode->yres),
writel(SUNXI_LCDC_X(mode->xres) | SUNXI_LCDC_Y(yres),
&lcdc->tcon1_timing_out);
bp = mode->hsync_len + mode->left_margin;
@ -788,6 +849,8 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
bp = mode->vsync_len + mode->upper_margin;
total = mode->yres + mode->lower_margin + bp;
if (mode->vmode == FB_VMODE_NONINTERLACED)
total *= 2;
writel(SUNXI_LCDC_TCON1_TIMING_V_TOTAL(total) |
SUNXI_LCDC_TCON1_TIMING_V_BP(bp), &lcdc->tcon1_timing_v);
@ -811,7 +874,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode,
}
sunxi_lcdc_pll_set(1, mode->pixclock_khz, clk_div, clk_double);
}
#endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA */
#endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */
#ifdef CONFIG_VIDEO_HDMI
@ -925,9 +988,9 @@ static void sunxi_hdmi_enable(void)
#endif /* CONFIG_VIDEO_HDMI */
#ifdef CONFIG_VIDEO_VGA
#if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE
static void sunxi_vga_mode_set(void)
static void sunxi_tvencoder_mode_set(void)
{
struct sunxi_ccm_reg * const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
@ -937,16 +1000,75 @@ static void sunxi_vga_mode_set(void)
/* Clock on */
setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0);
/* Set TVE in VGA mode */
writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
writel(SUNXI_TVE_GCTRL_CFG0_VGA, &tve->cfg0);
writel(SUNXI_TVE_GCTRL_DAC_CFG0_VGA, &tve->dac_cfg0);
writel(SUNXI_TVE_GCTRL_UNKNOWN1_VGA, &tve->unknown1);
switch (sunxi_display.monitor) {
case sunxi_monitor_vga:
writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
SUNXI_TVE_GCTRL_DAC_INPUT(2, 3), &tve->gctrl);
writel(SUNXI_TVE_CFG0_VGA, &tve->cfg0);
writel(SUNXI_TVE_DAC_CFG0_VGA, &tve->dac_cfg0);
writel(SUNXI_TVE_UNKNOWN1_VGA, &tve->unknown1);
break;
case sunxi_monitor_composite_pal_nc:
writel(SUNXI_TVE_CHROMA_FREQ_PAL_NC, &tve->chroma_freq);
/* Fall through */
case sunxi_monitor_composite_pal:
writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
writel(SUNXI_TVE_CFG0_PAL, &tve->cfg0);
writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
writel(SUNXI_TVE_PORCH_NUM_PAL, &tve->porch_num);
writel(SUNXI_TVE_LINE_NUM_PAL, &tve->line_num);
writel(SUNXI_TVE_BLANK_BLACK_LEVEL_PAL, &tve->blank_black_level);
writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
writel(SUNXI_TVE_CBR_LEVEL_PAL, &tve->cbr_level);
writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
writel(SUNXI_TVE_UNKNOWN2_PAL, &tve->unknown2);
writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
writel(SUNXI_TVE_RESYNC_NUM_PAL, &tve->resync_num);
writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
break;
case sunxi_monitor_composite_pal_m:
writel(SUNXI_TVE_CHROMA_FREQ_PAL_M, &tve->chroma_freq);
writel(SUNXI_TVE_COLOR_BURST_PAL_M, &tve->color_burst);
/* Fall through */
case sunxi_monitor_composite_ntsc:
writel(SUNXI_TVE_GCTRL_DAC_INPUT(0, 1) |
SUNXI_TVE_GCTRL_DAC_INPUT(1, 2) |
SUNXI_TVE_GCTRL_DAC_INPUT(2, 3) |
SUNXI_TVE_GCTRL_DAC_INPUT(3, 4), &tve->gctrl);
writel(SUNXI_TVE_CFG0_NTSC, &tve->cfg0);
writel(SUNXI_TVE_DAC_CFG0_COMPOSITE, &tve->dac_cfg0);
writel(SUNXI_TVE_FILTER_COMPOSITE, &tve->filter);
writel(SUNXI_TVE_PORCH_NUM_NTSC, &tve->porch_num);
writel(SUNXI_TVE_LINE_NUM_NTSC, &tve->line_num);
writel(SUNXI_TVE_BLANK_BLACK_LEVEL_NTSC, &tve->blank_black_level);
writel(SUNXI_TVE_UNKNOWN1_COMPOSITE, &tve->unknown1);
writel(SUNXI_TVE_CBR_LEVEL_NTSC, &tve->cbr_level);
writel(SUNXI_TVE_BURST_PHASE_NTSC, &tve->burst_phase);
writel(SUNXI_TVE_BURST_WIDTH_COMPOSITE, &tve->burst_width);
writel(SUNXI_TVE_UNKNOWN2_NTSC, &tve->unknown2);
writel(SUNXI_TVE_SYNC_VBI_LEVEL_NTSC, &tve->sync_vbi_level);
writel(SUNXI_TVE_ACTIVE_NUM_COMPOSITE, &tve->active_num);
writel(SUNXI_TVE_CHROMA_BW_GAIN_COMP, &tve->chroma_bw_gain);
writel(SUNXI_TVE_NOTCH_WIDTH_COMPOSITE, &tve->notch_width);
writel(SUNXI_TVE_RESYNC_NUM_NTSC, &tve->resync_num);
writel(SUNXI_TVE_SLAVE_PARA_COMPOSITE, &tve->slave_para);
break;
case sunxi_monitor_none:
case sunxi_monitor_dvi:
case sunxi_monitor_hdmi:
case sunxi_monitor_lcd:
break;
}
}
static void sunxi_vga_enable(void)
static void sunxi_tvencoder_enable(void)
{
struct sunxi_tve_reg * const tve =
(struct sunxi_tve_reg *)SUNXI_TVE0_BASE;
@ -954,7 +1076,7 @@ static void sunxi_vga_enable(void)
setbits_le32(&tve->gctrl, SUNXI_TVE_GCTRL_ENABLE);
}
#endif /* CONFIG_VIDEO_VGA */
#endif /* CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE */
static void sunxi_drc_init(void)
{
@ -1069,16 +1191,29 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
#ifdef CONFIG_VIDEO_VGA
sunxi_composer_mode_set(mode, address);
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1);
sunxi_vga_mode_set();
sunxi_tvencoder_mode_set();
sunxi_composer_enable();
sunxi_lcdc_enable();
sunxi_vga_enable();
sunxi_tvencoder_enable();
#elif defined CONFIG_VIDEO_VGA_VIA_LCD
sunxi_composer_mode_set(mode, address);
sunxi_lcdc_tcon0_mode_set(mode, true);
sunxi_composer_enable();
sunxi_lcdc_enable();
sunxi_vga_external_dac_enable();
#endif
break;
case sunxi_monitor_composite_pal:
case sunxi_monitor_composite_ntsc:
case sunxi_monitor_composite_pal_m:
case sunxi_monitor_composite_pal_nc:
#ifdef CONFIG_VIDEO_COMPOSITE
sunxi_composer_mode_set(mode, address);
sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0);
sunxi_tvencoder_mode_set();
sunxi_composer_enable();
sunxi_lcdc_enable();
sunxi_tvencoder_enable();
#endif
break;
}
@ -1087,11 +1222,15 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode,
static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor)
{
switch (monitor) {
case sunxi_monitor_none: return "none";
case sunxi_monitor_dvi: return "dvi";
case sunxi_monitor_hdmi: return "hdmi";
case sunxi_monitor_lcd: return "lcd";
case sunxi_monitor_vga: return "vga";
case sunxi_monitor_none: return "none";
case sunxi_monitor_dvi: return "dvi";
case sunxi_monitor_hdmi: return "hdmi";
case sunxi_monitor_lcd: return "lcd";
case sunxi_monitor_vga: return "vga";
case sunxi_monitor_composite_pal: return "composite-pal";
case sunxi_monitor_composite_ntsc: return "composite-ntsc";
case sunxi_monitor_composite_pal_m: return "composite-pal-m";
case sunxi_monitor_composite_pal_nc: return "composite-pal-nc";
}
return NULL; /* never reached */
}
@ -1101,6 +1240,54 @@ ulong board_get_usable_ram_top(ulong total_size)
return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE;
}
static bool sunxi_has_hdmi(void)
{
#ifdef CONFIG_VIDEO_HDMI
return true;
#else
return false;
#endif
}
static bool sunxi_has_lcd(void)
{
char *lcd_mode = CONFIG_VIDEO_LCD_MODE;
return lcd_mode[0] != 0;
}
static bool sunxi_has_vga(void)
{
#if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_VGA_VIA_LCD
return true;
#else
return false;
#endif
}
static bool sunxi_has_composite(void)
{
#ifdef CONFIG_VIDEO_COMPOSITE
return true;
#else
return false;
#endif
}
static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi)
{
if (allow_hdmi && sunxi_has_hdmi())
return sunxi_monitor_dvi;
else if (sunxi_has_lcd())
return sunxi_monitor_lcd;
else if (sunxi_has_vga())
return sunxi_monitor_vga;
else if (sunxi_has_composite())
return sunxi_monitor_composite_pal;
else
return sunxi_monitor_none;
}
void *video_hw_init(void)
{
static GraphicDevice *graphic_device = &sunxi_display.graphic_device;
@ -1122,12 +1309,8 @@ void *video_hw_init(void)
hpd = video_get_option_int(options, "hpd", 1);
hpd_delay = video_get_option_int(options, "hpd_delay", 500);
edid = video_get_option_int(options, "edid", 1);
sunxi_display.monitor = sunxi_monitor_dvi;
#elif defined CONFIG_VIDEO_VGA_VIA_LCD
sunxi_display.monitor = sunxi_monitor_vga;
#else
sunxi_display.monitor = sunxi_monitor_lcd;
#endif
sunxi_display.monitor = sunxi_get_default_mon(true);
video_get_option_string(options, "monitor", mon, sizeof(mon),
sunxi_get_mon_desc(sunxi_display.monitor));
for (i = 0; i <= SUNXI_MONITOR_LAST; i++) {
@ -1152,16 +1335,7 @@ void *video_hw_init(void)
mode = &custom;
} else if (hpd) {
sunxi_hdmi_shutdown();
/* Fallback to lcd / vga / none */
if (lcd_mode[0]) {
sunxi_display.monitor = sunxi_monitor_lcd;
} else {
#if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA
sunxi_display.monitor = sunxi_monitor_vga;
#else
sunxi_display.monitor = sunxi_monitor_none;
#endif
}
sunxi_display.monitor = sunxi_get_default_mon(false);
} /* else continue with hdmi/dvi without a cable connected */
}
#endif
@ -1171,39 +1345,45 @@ void *video_hw_init(void)
return NULL;
case sunxi_monitor_dvi:
case sunxi_monitor_hdmi:
#ifdef CONFIG_VIDEO_HDMI
break;
#else
printf("HDMI/DVI not supported on this board\n");
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
#endif
case sunxi_monitor_lcd:
if (lcd_mode[0]) {
sunxi_display.depth = video_get_params(&custom, lcd_mode);
mode = &custom;
break;
if (!sunxi_has_hdmi()) {
printf("HDMI/DVI not supported on this board\n");
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
}
printf("LCD not supported on this board\n");
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
break;
case sunxi_monitor_lcd:
if (!sunxi_has_lcd()) {
printf("LCD not supported on this board\n");
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
}
sunxi_display.depth = video_get_params(&custom, lcd_mode);
mode = &custom;
break;
case sunxi_monitor_vga:
#if defined CONFIG_VIDEO_VGA_VIA_LCD || defined CONFIG_VIDEO_VGA
if (!sunxi_has_vga()) {
printf("VGA not supported on this board\n");
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
}
sunxi_display.depth = 18;
break;
#else
printf("VGA not supported on this board\n");
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
#endif
}
if (mode->vmode != FB_VMODE_NONINTERLACED) {
printf("Only non-interlaced modes supported, falling back to 1024x768\n");
mode = &res_mode_init[RES_MODE_1024x768];
} else {
printf("Setting up a %dx%d %s console\n", mode->xres,
mode->yres, sunxi_get_mon_desc(sunxi_display.monitor));
case sunxi_monitor_composite_pal:
case sunxi_monitor_composite_ntsc:
case sunxi_monitor_composite_pal_m:
case sunxi_monitor_composite_pal_nc:
if (!sunxi_has_composite()) {
printf("Composite video not supported on this board\n");
sunxi_display.monitor = sunxi_monitor_none;
return NULL;
}
if (sunxi_display.monitor == sunxi_monitor_composite_pal ||
sunxi_display.monitor == sunxi_monitor_composite_pal_nc)
mode = &composite_video_modes[0];
else
mode = &composite_video_modes[1];
sunxi_display.depth = 24;
break;
}
sunxi_display.fb_size =
@ -1215,6 +1395,10 @@ void *video_hw_init(void)
return NULL;
}
printf("Setting up a %dx%d%s %s console\n", mode->xres, mode->yres,
(mode->vmode == FB_VMODE_INTERLACED) ? "i" : "",
sunxi_get_mon_desc(sunxi_display.monitor));
gd->fb_base = gd->bd->bi_dram[0].start +
gd->bd->bi_dram[0].size - sunxi_display.fb_size;
sunxi_engines_init();
@ -1268,6 +1452,12 @@ int sunxi_simplefb_setup(void *blob)
pipeline = PIPELINE_PREFIX "de_be0-lcd0";
#endif
break;
case sunxi_monitor_composite_pal:
case sunxi_monitor_composite_ntsc:
case sunxi_monitor_composite_pal_m:
case sunxi_monitor_composite_pal_nc:
pipeline = PIPELINE_PREFIX "de_be0-lcd0-tve0";
break;
}
/* Find a prefilled simpefb node, matching out pipeline config */

View file

@ -139,6 +139,16 @@
#define CONFIG_INITRD_TAG
#define CONFIG_SERIAL_TAG
#if defined(CONFIG_SPL_NAND_SUNXI)
#define CONFIG_SPL_NAND_DRIVERS
#define CONFIG_SPL_NAND_SUPPORT
#define CONFIG_SYS_NAND_SPL_KERNEL_OFFS 0x280000
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x008000
#endif
/* mmc config */
#if !defined(CONFIG_UART0_PORT_F)
#define CONFIG_MMC
@ -252,6 +262,7 @@ extern int soft_i2c_gpio_scl;
#define CONFIG_CONS_INDEX 1 /* UART0 */
#endif
#ifdef CONFIG_REQUIRE_SERIAL_CONSOLE
#if CONFIG_CONS_INDEX == 1
#ifdef CONFIG_MACH_SUN9I
#define OF_STDOUT_PATH "/soc/serial@07000000:115200"
@ -267,6 +278,7 @@ extern int soft_i2c_gpio_scl;
#else
#error Unsupported console port nr. Please fix stdout-path in sunxi-common.h.
#endif
#endif /* ifdef CONFIG_REQUIRE_SERIAL_CONSOLE */
/* GPIO */
#define CONFIG_SUNXI_GPIO