Merge branch 'master' of git://git.denx.de/u-boot-imx

This commit is contained in:
Wolfgang Denk 2010-05-21 22:22:23 +02:00
commit 8a452c2c17
16 changed files with 967 additions and 107 deletions

View File

@ -67,7 +67,7 @@ int print_cpuinfo(void)
u32 cpurev;
cpurev = get_cpu_rev();
printf("CPU: Freescale i.MX51 family %d.%dV at %d MHz\n",
printf("CPU: Freescale i.MX51 family rev%d.%d at %d MHz\n",
(cpurev & 0xF0) >> 4,
(cpurev & 0x0F) >> 4,
mxc_get_clock(MXC_ARM_CLK) / 1000000);

View File

@ -26,6 +26,7 @@
#include <asm/arch/mx31.h>
#include <asm/arch/mx31-regs.h>
#include <nand.h>
#include <fsl_pmic.h>
#include "qong_fpga.h"
DECLARE_GLOBAL_DATA_PTR;
@ -128,6 +129,13 @@ int board_init (void)
mx31_gpio_mux(MUX_RTS1__UART1_RTS_B);
mx31_gpio_mux(MUX_CTS1__UART1_CTS_B);
/* setup pins for SPI (pmic) */
mx31_gpio_mux(MUX_CSPI2_SS0__CSPI2_SS0_B);
mx31_gpio_mux(MUX_CSPI2_MOSI__CSPI2_MOSI);
mx31_gpio_mux(MUX_CSPI2_MISO__CSPI2_MISO);
mx31_gpio_mux(MUX_CSPI2_SCLK__CSPI2_CLK);
mx31_gpio_mux(MUX_CSPI2_SPI_RDY__CSPI2_DATAREADY_B);
/* board id for linux */
gd->bd->bi_arch_number = MACH_TYPE_QONG;
gd->bd->bi_boot_params = (0x80000100); /* adress of boot parameters */
@ -135,6 +143,18 @@ int board_init (void)
return 0;
}
int board_late_init(void)
{
u32 val;
/* Enable RTC battery */
val = pmic_reg_read(REG_POWER_CTL0);
pmic_reg_write(REG_POWER_CTL0, val | COINCHEN);
pmic_reg_write(REG_INT_STATUS1, RTCRSTI);
return 0;
}
int checkboard (void)
{
printf("Board: DAVE/DENX Qong\n");

View File

@ -27,9 +27,12 @@
#include <asm/arch/iomux.h>
#include <asm/errno.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/crm_regs.h>
#include <i2c.h>
#include <mmc.h>
#include <fsl_esdhc.h>
#include <fsl_pmic.h>
#include <mc13892.h>
#include "mx51evk.h"
DECLARE_GLOBAL_DATA_PTR;
@ -39,8 +42,8 @@ struct io_board_ctrl *mx51_io_board;
#ifdef CONFIG_FSL_ESDHC
struct fsl_esdhc_cfg esdhc_cfg[2] = {
{MMC_SDHC1_BASE_ADDR, 1, 1},
{MMC_SDHC2_BASE_ADDR, 1, 1},
{MMC_SDHC1_BASE_ADDR, 1},
{MMC_SDHC2_BASE_ADDR, 1},
};
#endif
@ -147,6 +150,130 @@ static void setup_iomux_fec(void)
mxc_iomux_set_pad(MX51_PIN_NANDF_D11, 0x2180);
}
#ifdef CONFIG_MXC_SPI
static void setup_iomux_spi(void)
{
/* 000: Select mux mode: ALT0 mux port: MOSI of instance: ecspi1 */
mxc_request_iomux(MX51_PIN_CSPI1_MOSI, IOMUX_CONFIG_ALT0);
mxc_iomux_set_pad(MX51_PIN_CSPI1_MOSI, 0x105);
/* 000: Select mux mode: ALT0 mux port: MISO of instance: ecspi1. */
mxc_request_iomux(MX51_PIN_CSPI1_MISO, IOMUX_CONFIG_ALT0);
mxc_iomux_set_pad(MX51_PIN_CSPI1_MISO, 0x105);
/* de-select SS1 of instance: ecspi1. */
mxc_request_iomux(MX51_PIN_CSPI1_SS1, IOMUX_CONFIG_ALT3);
mxc_iomux_set_pad(MX51_PIN_CSPI1_SS1, 0x85);
/* 000: Select mux mode: ALT0 mux port: SS0 ecspi1 */
mxc_request_iomux(MX51_PIN_CSPI1_SS0, IOMUX_CONFIG_ALT0);
mxc_iomux_set_pad(MX51_PIN_CSPI1_SS0, 0x185);
/* 000: Select mux mode: ALT0 mux port: RDY of instance: ecspi1. */
mxc_request_iomux(MX51_PIN_CSPI1_RDY, IOMUX_CONFIG_ALT0);
mxc_iomux_set_pad(MX51_PIN_CSPI1_RDY, 0x180);
/* 000: Select mux mode: ALT0 mux port: SCLK of instance: ecspi1. */
mxc_request_iomux(MX51_PIN_CSPI1_SCLK, IOMUX_CONFIG_ALT0);
mxc_iomux_set_pad(MX51_PIN_CSPI1_SCLK, 0x105);
}
#endif
static void power_init(void)
{
unsigned int val;
unsigned int reg;
struct mxc_ccm_reg *mxc_ccm = (struct mxc_ccm_reg *)MXC_CCM_BASE;
/* Write needed to Power Gate 2 register */
val = pmic_reg_read(REG_POWER_MISC);
val &= ~PWGT2SPIEN;
pmic_reg_write(REG_POWER_MISC, val);
/* Write needed to update Charger 0 */
pmic_reg_write(REG_CHARGE, VCHRG0 | VCHRG1 | VCHRG2 |
ICHRG0 | ICHRG1 | ICHRG2 | ICHRG3 | ICHRGTR0 |
OVCTRL1 | UCHEN | CHRGLEDEN | CYCLB);
/* power up the system first */
pmic_reg_write(REG_POWER_MISC, PWUP);
/* Set core voltage to 1.1V */
val = pmic_reg_read(REG_SW_0);
val = (val & (~0x1F)) | 0x14;
pmic_reg_write(REG_SW_0, val);
/* Setup VCC (SW2) to 1.25 */
val = pmic_reg_read(REG_SW_1);
val = (val & (~0x1F)) | 0x1A;
pmic_reg_write(REG_SW_1, val);
/* Setup 1V2_DIG1 (SW3) to 1.25 */
val = pmic_reg_read(REG_SW_2);
val = (val & (~0x1F)) | 0x1A;
pmic_reg_write(REG_SW_2, val);
udelay(50);
/* Raise the core frequency to 800MHz */
writel(0x0, &mxc_ccm->cacrr);
/* Set switchers in Auto in NORMAL mode & STANDBY mode */
/* Setup the switcher mode for SW1 & SW2*/
val = pmic_reg_read(REG_SW_4);
val = (val & ~((SWMODE_MASK << SWMODE1_SHIFT) |
(SWMODE_MASK << SWMODE2_SHIFT)));
val |= (SWMODE_AUTO_AUTO << SWMODE1_SHIFT) |
(SWMODE_AUTO_AUTO << SWMODE2_SHIFT);
pmic_reg_write(REG_SW_4, val);
/* Setup the switcher mode for SW3 & SW4 */
val = pmic_reg_read(REG_SW_5);
val = (val & ~((SWMODE_MASK << SWMODE3_SHIFT) |
(SWMODE_MASK << SWMODE4_SHIFT)));
val |= (SWMODE_AUTO_AUTO << SWMODE3_SHIFT) |
(SWMODE_AUTO_AUTO << SWMODE4_SHIFT);
pmic_reg_write(REG_SW_5, val);
/* Set VDIG to 1.65V, VGEN3 to 1.8V, VCAM to 2.6V */
val = pmic_reg_read(REG_SETTING_0);
val &= ~(VCAM_MASK | VGEN3_MASK | VDIG_MASK);
val |= VDIG_1_65 | VGEN3_1_8 | VCAM_2_6;
pmic_reg_write(REG_SETTING_0, val);
/* Set VVIDEO to 2.775V, VAUDIO to 3V, VSD to 3.15V */
val = pmic_reg_read(REG_SETTING_1);
val &= ~(VVIDEO_MASK | VSD_MASK | VAUDIO_MASK);
val |= VSD_3_15 | VAUDIO_3_0 | VVIDEO_2_775;
pmic_reg_write(REG_SETTING_1, val);
/* Configure VGEN3 and VCAM regulators to use external PNP */
val = VGEN3CONFIG | VCAMCONFIG;
pmic_reg_write(REG_MODE_1, val);
udelay(200);
reg = readl(GPIO2_BASE_ADDR + 0x0);
reg &= ~0x4000; /* Lower reset line */
writel(reg, GPIO2_BASE_ADDR + 0x0);
reg = readl(GPIO2_BASE_ADDR + 0x4);
reg |= 0x4000; /* configure GPIO lines as output */
writel(reg, GPIO2_BASE_ADDR + 0x4);
/* Reset the ethernet controller over GPIO */
writel(0x1, IOMUXC_BASE_ADDR + 0x0AC);
/* Enable VGEN3, VCAM, VAUDIO, VVIDEO, VSD regulators */
val = VGEN3EN | VGEN3CONFIG | VCAMEN | VCAMCONFIG |
VVIDEOEN | VAUDIOEN | VSDEN;
pmic_reg_write(REG_MODE_1, val);
udelay(500);
reg = readl(GPIO2_BASE_ADDR + 0x0);
reg |= 0x4000;
writel(reg, GPIO2_BASE_ADDR + 0x0);
}
#ifdef CONFIG_FSL_ESDHC
int board_mmc_getcd(u8 *cd, struct mmc *mmc)
{
@ -284,9 +411,21 @@ int board_init(void)
setup_iomux_uart();
setup_iomux_fec();
return 0;
}
#ifdef BOARD_LATE_INIT
int board_late_init(void)
{
#ifdef CONFIG_MXC_SPI
setup_iomux_spi();
power_init();
#endif
return 0;
}
#endif
int checkboard(void)
{
puts("Board: MX51EVK ");

View File

@ -145,6 +145,9 @@ int board_init()
mx25_uart_init_pins();
#endif
/* board id for linux */
gd->bd->bi_arch_number = MACH_TYPE_TX25;
gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
return 0;
}

View File

@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_LAW) += fsl_law.o
COBJS-$(CONFIG_NS87308) += ns87308.o
COBJS-$(CONFIG_STATUS_LED) += status_led.o
COBJS-$(CONFIG_TWL4030_LED) += twl4030_led.o
COBJS-$(CONFIG_FSL_PMIC) += fsl_pmic.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)

200
drivers/misc/fsl_pmic.c Normal file
View File

@ -0,0 +1,200 @@
/*
* (C) Copyright 2008-2009 Freescale Semiconductor, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <config.h>
#include <common.h>
#include <spi.h>
#include <asm/errno.h>
#include <linux/types.h>
#include <fsl_pmic.h>
static struct spi_slave *slave;
struct spi_slave *pmic_spi_probe(void)
{
return spi_setup_slave(CONFIG_FSL_PMIC_BUS,
CONFIG_FSL_PMIC_CS,
CONFIG_FSL_PMIC_CLK,
CONFIG_FSL_PMIC_MODE);
}
void pmic_spi_free(struct spi_slave *slave)
{
if (slave)
spi_free_slave(slave);
}
u32 pmic_reg(u32 reg, u32 val, u32 write)
{
u32 pmic_tx, pmic_rx;
if (!slave) {
slave = pmic_spi_probe();
if (!slave)
return -1;
}
if (reg > 63 || write > 1) {
printf("<reg num> = %d is invalid. Should be less then 63\n",
reg);
return -1;
}
if (spi_claim_bus(slave))
return -1;
pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF);
if (spi_xfer(slave, 4 << 3, &pmic_tx, &pmic_rx,
SPI_XFER_BEGIN | SPI_XFER_END)) {
spi_release_bus(slave);
return -1;
}
if (write) {
pmic_tx &= ~(1 << 31);
if (spi_xfer(slave, 4 << 3, &pmic_tx, &pmic_rx,
SPI_XFER_BEGIN | SPI_XFER_END)) {
spi_release_bus(slave);
return -1;
}
}
spi_release_bus(slave);
return pmic_rx;
}
void pmic_reg_write(u32 reg, u32 value)
{
pmic_reg(reg, value, 1);
}
u32 pmic_reg_read(u32 reg)
{
return pmic_reg(reg, 0, 0);
}
void pmic_show_pmic_info(void)
{
u32 rev_id;
rev_id = pmic_reg_read(REG_IDENTIFICATION);
printf("PMIC ID: 0x%08x [Rev: ", rev_id);
switch (rev_id & 0x1F) {
case 0x1:
puts("1.0");
break;
case 0x9:
puts("1.1");
break;
case 0xA:
puts("1.2");
break;
case 0x10:
puts("2.0");
break;
case 0x11:
puts("2.1");
break;
case 0x18:
puts("3.0");
break;
case 0x19:
puts("3.1");
break;
case 0x1A:
puts("3.2");
break;
case 0x2:
puts("3.2A");
break;
case 0x1B:
puts("3.3");
break;
case 0x1D:
puts("3.5");
break;
default:
puts("unknown");
break;
}
puts("]\n");
}
static void pmic_dump(int numregs)
{
u32 val;
int i;
pmic_show_pmic_info();
for (i = 0; i < numregs; i++) {
val = pmic_reg_read(i);
if (!(i % 8))
printf ("\n0x%02x: ", i);
printf("%08x ", val);
}
puts("\n");
}
int do_pmic(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
char *cmd;
int nregs;
u32 val;
/* at least two arguments please */
if (argc < 2) {
cmd_usage(cmdtp);
return 1;
}
cmd = argv[1];
if (strcmp(cmd, "dump") == 0) {
if (argc < 3) {
cmd_usage(cmdtp);
return 1;
}
nregs = simple_strtoul(argv[2], NULL, 16);
pmic_dump(nregs);
return 0;
}
if (strcmp(cmd, "write") == 0) {
if (argc < 4) {
cmd_usage(cmdtp);
return 1;
}
nregs = simple_strtoul(argv[2], NULL, 16);
val = simple_strtoul(argv[3], NULL, 16);
pmic_reg_write(nregs, val);
return 0;
}
/* No subcommand found */
return 1;
}
U_BOOT_CMD(
pmic, CONFIG_SYS_MAXARGS, 1, do_pmic,
"Freescale PMIC (Atlas)",
"dump [numregs] dump registers\n"
"pmic write <reg> <value> - write register"
);

View File

@ -23,53 +23,30 @@
#include <common.h>
#include <rtc.h>
#include <spi.h>
static struct spi_slave *slave;
#include <fsl_pmic.h>
int rtc_get(struct rtc_time *rtc)
{
u32 day1, day2, time;
u32 reg;
int err, tim, i = 0;
if (!slave) {
/* FIXME: Verify the max SCK rate */
slave = spi_setup_slave(CONFIG_MC13783_SPI_BUS,
CONFIG_MC13783_SPI_CS, 1000000,
SPI_MODE_2 | SPI_CS_HIGH);
if (!slave)
return -1;
}
if (spi_claim_bus(slave))
return -1;
int tim, i = 0;
do {
reg = 0x2c000000;
err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day1,
SPI_XFER_BEGIN | SPI_XFER_END);
day1 = pmic_reg_read(REG_RTC_DAY);
if (day1 < 0)
return -1;
if (err)
return err;
time = pmic_reg_read(REG_RTC_TIME);
if (time < 0)
return -1;
reg = 0x28000000;
err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time,
SPI_XFER_BEGIN | SPI_XFER_END);
day2 = pmic_reg_read(REG_RTC_DAY);
if (day2 < 0)
return -1;
if (err)
return err;
reg = 0x2c000000;
err = spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day2,
SPI_XFER_BEGIN | SPI_XFER_END);
if (err)
return err;
} while (day1 != day2 && i++ < 3);
spi_release_bus(slave);
tim = day1 * 86400 + time;
to_tm(tim, rtc);
rtc->tm_yday = 0;
@ -80,34 +57,15 @@ int rtc_get(struct rtc_time *rtc)
int rtc_set(struct rtc_time *rtc)
{
u32 time, day, reg;
if (!slave) {
/* FIXME: Verify the max SCK rate */
slave = spi_setup_slave(CONFIG_MC13783_SPI_BUS,
CONFIG_MC13783_SPI_CS, 1000000,
SPI_MODE_2 | SPI_CS_HIGH);
if (!slave)
return -1;
}
u32 time, day;
time = mktime(rtc->tm_year, rtc->tm_mon, rtc->tm_mday,
rtc->tm_hour, rtc->tm_min, rtc->tm_sec);
day = time / 86400;
time %= 86400;
if (spi_claim_bus(slave))
return -1;
reg = 0x2c000000 | day | 0x80000000;
spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&day,
SPI_XFER_BEGIN | SPI_XFER_END);
reg = 0x28000000 | time | 0x80000000;
spi_xfer(slave, 32, (uchar *)&reg, (uchar *)&time,
SPI_XFER_BEGIN | SPI_XFER_END);
spi_release_bus(slave);
pmic_reg_write(REG_RTC_DAY, day);
pmic_reg_write(REG_RTC_TIME, time);
return 0;
}

View File

@ -31,7 +31,7 @@
#error "i.MX27 CSPI not supported due to drastic differences in register definisions" \
"See linux mxc_spi driver from Freescale for details."
#else
#elif defined(CONFIG_MX31)
#include <asm/arch/mx31.h>
@ -56,6 +56,9 @@
#define MXC_CSPICTRL_CHIPSELECT(x) (((x) & 0x3) << 24)
#define MXC_CSPICTRL_BITCOUNT(x) (((x) & 0x1f) << 8)
#define MXC_CSPICTRL_DATARATE(x) (((x) & 0x7) << 16)
#define MXC_CSPICTRL_TC (1 << 8)
#define MXC_CSPICTRL_RXOVF (1 << 6)
#define MXC_CSPICTRL_MAXBITS 0x1f
#define MXC_CSPIPERIOD_32KHZ (1 << 15)
@ -65,12 +68,63 @@ static unsigned long spi_bases[] = {
0x53f84000,
};
#define OUT MX31_GPIO_DIRECTION_OUT
#define mxc_gpio_direction mx31_gpio_direction
#define mxc_gpio_set mx31_gpio_set
#elif defined(CONFIG_MX51)
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
#define MXC_CSPIRXDATA 0x00
#define MXC_CSPITXDATA 0x04
#define MXC_CSPICTRL 0x08
#define MXC_CSPICON 0x0C
#define MXC_CSPIINT 0x10
#define MXC_CSPIDMA 0x14
#define MXC_CSPISTAT 0x18
#define MXC_CSPIPERIOD 0x1C
#define MXC_CSPIRESET 0x00
#define MXC_CSPICTRL_EN (1 << 0)
#define MXC_CSPICTRL_MODE (1 << 1)
#define MXC_CSPICTRL_XCH (1 << 2)
#define MXC_CSPICTRL_CHIPSELECT(x) (((x) & 0x3) << 12)
#define MXC_CSPICTRL_BITCOUNT(x) (((x) & 0xfff) << 20)
#define MXC_CSPICTRL_PREDIV(x) (((x) & 0xF) << 12)
#define MXC_CSPICTRL_POSTDIV(x) (((x) & 0xF) << 8)
#define MXC_CSPICTRL_SELCHAN(x) (((x) & 0x3) << 18)
#define MXC_CSPICTRL_MAXBITS 0xfff
#define MXC_CSPICTRL_TC (1 << 7)
#define MXC_CSPICTRL_RXOVF (1 << 6)
#define MXC_CSPIPERIOD_32KHZ (1 << 15)
/* Bit position inside CTRL register to be associated with SS */
#define MXC_CSPICTRL_CHAN 18
/* Bit position inside CON register to be associated with SS */
#define MXC_CSPICON_POL 4
#define MXC_CSPICON_PHA 0
#define MXC_CSPICON_SSPOL 12
static unsigned long spi_bases[] = {
CSPI1_BASE_ADDR,
CSPI2_BASE_ADDR,
CSPI3_BASE_ADDR,
};
#define mxc_gpio_direction(gpio, dir) (0)
#define mxc_gpio_set(gpio, value) {}
#define OUT 1
#else
#error "Unsupported architecture"
#endif
struct mxc_spi_slave {
struct spi_slave slave;
unsigned long base;
u32 ctrl_reg;
#if defined(CONFIG_MX51)
u32 cfg_reg;
#endif
int gpio;
};
@ -89,34 +143,161 @@ static inline void reg_write(unsigned long addr, u32 val)
*(volatile unsigned long*)addr = val;
}
void spi_cs_activate(struct spi_slave *slave)
{
struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
if (mxcs->gpio > 0)
mxc_gpio_set(mxcs->gpio, mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL);
}
void spi_cs_deactivate(struct spi_slave *slave)
{
struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
if (mxcs->gpio > 0)
mxc_gpio_set(mxcs->gpio,
!(mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL));
}
#ifdef CONFIG_MX51
static s32 spi_cfg(struct mxc_spi_slave *mxcs, unsigned int cs,
unsigned int max_hz, unsigned int mode)
{
u32 clk_src = mxc_get_clock(MXC_CSPI_CLK);
s32 pre_div = 0, post_div = 0, i, reg_ctrl, reg_config;
u32 ss_pol = 0, sclkpol = 0, sclkpha = 0;
if (max_hz == 0) {
printf("Error: desired clock is 0\n");
return -1;
}
reg_ctrl = reg_read(mxcs->base + MXC_CSPICTRL);
/* Reset spi */
reg_write(mxcs->base + MXC_CSPICTRL, 0);
reg_write(mxcs->base + MXC_CSPICTRL, (reg_ctrl | 0x1));
/*
* The following computation is taken directly from Freescale's code.
*/
if (clk_src > max_hz) {
pre_div = clk_src / max_hz;
if (pre_div > 16) {
post_div = pre_div / 16;
pre_div = 15;
}
if (post_div != 0) {
for (i = 0; i < 16; i++) {
if ((1 << i) >= post_div)
break;
}
if (i == 16) {
printf("Error: no divider for the freq: %d\n",
max_hz);
return -1;
}
post_div = i;
}
}
debug("pre_div = %d, post_div=%d\n", pre_div, post_div);
reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_SELCHAN(3)) |
MXC_CSPICTRL_SELCHAN(cs);
reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_PREDIV(0x0F)) |
MXC_CSPICTRL_PREDIV(pre_div);
reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_POSTDIV(0x0F)) |
MXC_CSPICTRL_POSTDIV(post_div);
/* always set to master mode */
reg_ctrl |= 1 << (cs + 4);
/* We need to disable SPI before changing registers */
reg_ctrl &= ~MXC_CSPICTRL_EN;
if (mode & SPI_CS_HIGH)
ss_pol = 1;
if (!(mode & SPI_CPOL))
sclkpol = 1;
if (mode & SPI_CPHA)
sclkpha = 1;
reg_config = reg_read(mxcs->base + MXC_CSPICON);
/*
* Configuration register setup
* The MX51 has support different setup for each SS
*/
reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_SSPOL))) |
(ss_pol << (cs + MXC_CSPICON_SSPOL));
reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_POL))) |
(sclkpol << (cs + MXC_CSPICON_POL));
reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_PHA))) |
(sclkpha << (cs + MXC_CSPICON_PHA));
debug("reg_ctrl = 0x%x\n", reg_ctrl);
reg_write(mxcs->base + MXC_CSPICTRL, reg_ctrl);
debug("reg_config = 0x%x\n", reg_config);
reg_write(mxcs->base + MXC_CSPICON, reg_config);
/* save config register and control register */
mxcs->ctrl_reg = reg_ctrl;
mxcs->cfg_reg = reg_config;
/* clear interrupt reg */
reg_write(mxcs->base + MXC_CSPIINT, 0);
reg_write(mxcs->base + MXC_CSPISTAT,
MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
return 0;
}
#endif
static u32 spi_xchg_single(struct spi_slave *slave, u32 data, int bitlen,
unsigned long flags)
{
struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
unsigned int cfg_reg = reg_read(mxcs->base + MXC_CSPICTRL);
mxcs->ctrl_reg = (mxcs->ctrl_reg & ~MXC_CSPICTRL_BITCOUNT(31)) |
if (flags & SPI_XFER_BEGIN)
spi_cs_activate(slave);
mxcs->ctrl_reg = (mxcs->ctrl_reg &
~MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS)) |
MXC_CSPICTRL_BITCOUNT(bitlen - 1);
if (cfg_reg != mxcs->ctrl_reg)
reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg);
reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg | MXC_CSPICTRL_EN);
#ifdef CONFIG_MX51
reg_write(mxcs->base + MXC_CSPICON, mxcs->cfg_reg);
#endif
if (mxcs->gpio > 0 && (flags & SPI_XFER_BEGIN))
mx31_gpio_set(mxcs->gpio, mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL);
/* Clear interrupt register */
reg_write(mxcs->base + MXC_CSPISTAT,
MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
debug("Sending SPI 0x%x\n", data);
reg_write(mxcs->base + MXC_CSPITXDATA, data);
reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg | MXC_CSPICTRL_XCH);
/* FIFO is written, now starts the transfer setting the XCH bit */
reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg |
MXC_CSPICTRL_EN | MXC_CSPICTRL_XCH);
while (reg_read(mxcs->base + MXC_CSPICTRL) & MXC_CSPICTRL_XCH)
/* Wait until the TC (Transfer completed) bit is set */
while ((reg_read(mxcs->base + MXC_CSPISTAT) & MXC_CSPICTRL_TC) == 0)
;
if (mxcs->gpio > 0 && (flags & SPI_XFER_END)) {
mx31_gpio_set(mxcs->gpio,
!(mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL));
}
/* Transfer completed, clear any pending request */
reg_write(mxcs->base + MXC_CSPISTAT,
MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
data = reg_read(mxcs->base + MXC_CSPIRXDATA);
debug("SPI Rx: 0x%x\n", data);
if (flags & SPI_XFER_END)
spi_cs_deactivate(slave);
return data;
return reg_read(mxcs->base + MXC_CSPIRXDATA);
}
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
@ -176,7 +357,7 @@ static int decode_cs(struct mxc_spi_slave *mxcs, unsigned int cs)
if (cs > 3) {
mxcs->gpio = cs >> 8;
cs &= 3;
ret = mx31_gpio_direction(mxcs->gpio, MX31_GPIO_DIRECTION_OUT);
ret = mxc_gpio_direction(mxcs->gpio, OUT);
if (ret) {
printf("mxc_spi: cannot setup gpio %d\n", mxcs->gpio);
return -EINVAL;
@ -210,6 +391,20 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
cs = ret;
mxcs->slave.bus = bus;
mxcs->slave.cs = cs;
mxcs->base = spi_bases[bus];
#ifdef CONFIG_MX51
/* Can be used for i.MX31 too ? */
ctrl_reg = 0;
ret = spi_cfg(mxcs, cs, max_hz, mode);
if (ret) {
printf("mxc_spi: cannot setup SPI controller\n");
free(mxcs);
return NULL;
}
#else
ctrl_reg = MXC_CSPICTRL_CHIPSELECT(cs) |
MXC_CSPICTRL_BITCOUNT(31) |
MXC_CSPICTRL_DATARATE(7) | /* FIXME: calculate data rate */
@ -222,12 +417,8 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
ctrl_reg |= MXC_CSPICTRL_POL;
if (mode & SPI_CS_HIGH)
ctrl_reg |= MXC_CSPICTRL_SSPOL;
mxcs->slave.bus = bus;
mxcs->slave.cs = cs;
mxcs->base = spi_bases[bus];
mxcs->ctrl_reg = ctrl_reg;
#endif
return &mxcs->slave;
}

View File

@ -56,22 +56,7 @@ void lcd_panel_disable(void)
#define msleep(a) udelay(a * 1000)
#ifndef CONFIG_DISPLAY_VBEST_VGG322403
#define XRES 240
#define YRES 320
#define PANEL_TYPE IPU_PANEL_TFT
#define PIXEL_CLK 185925
#define PIXEL_FMT IPU_PIX_FMT_RGB666
#define H_START_WIDTH 9 /* left_margin */
#define H_SYNC_WIDTH 1 /* hsync_len */
#define H_END_WIDTH (16 + 1) /* right_margin + hsync_len */
#define V_START_WIDTH 7 /* upper_margin */
#define V_SYNC_WIDTH 1 /* vsync_len */
#define V_END_WIDTH (9 + 1) /* lower_margin + vsync_len */
#define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL)
#define IF_CONF 0
#define IF_CLK_DIV 0x175
#else /* Display Vbest VGG322403 */
#if defined(CONFIG_DISPLAY_VBEST_VGG322403)
#define XRES 320
#define YRES 240
#define PANEL_TYPE IPU_PANEL_TFT
@ -86,6 +71,36 @@ void lcd_panel_disable(void)
#define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL)
#define IF_CONF 0
#define IF_CLK_DIV 0x175
#elif defined(CONFIG_DISPLAY_COM57H5M10XRC)
#define XRES 640
#define YRES 480
#define PANEL_TYPE IPU_PANEL_TFT
#define PIXEL_CLK 40000
#define PIXEL_FMT IPU_PIX_FMT_RGB666
#define H_START_WIDTH 120 /* left_margin */
#define H_SYNC_WIDTH 30 /* hsync_len */
#define H_END_WIDTH (10 + 30) /* right_margin + hsync_len */
#define V_START_WIDTH 35 /* upper_margin */
#define V_SYNC_WIDTH 3 /* vsync_len */
#define V_END_WIDTH (7 + 3) /* lower_margin + vsync_len */
#define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL)
#define IF_CONF 0
#define IF_CLK_DIV 0x175
#else
#define XRES 240
#define YRES 320
#define PANEL_TYPE IPU_PANEL_TFT
#define PIXEL_CLK 185925
#define PIXEL_FMT IPU_PIX_FMT_RGB666
#define H_START_WIDTH 9 /* left_margin */
#define H_SYNC_WIDTH 1 /* hsync_len */
#define H_END_WIDTH (16 + 1) /* right_margin + hsync_len */
#define V_START_WIDTH 7 /* upper_margin */
#define V_SYNC_WIDTH 1 /* vsync_len */
#define V_END_WIDTH (9 + 1) /* lower_margin + vsync_len */
#define SIG_POL (DI_D3_DRDY_SHARP_POL | DI_D3_CLK_POL)
#define IF_CONF 0
#define IF_CLK_DIV 0x175
#endif
#define LCD_COLOR_IPU LCD_COLOR16

View File

@ -68,10 +68,13 @@
#define CONFIG_DEFAULT_SPI_BUS 1
#define CONFIG_DEFAULT_SPI_MODE (SPI_MODE_2 | SPI_CS_HIGH)
#define CONFIG_FSL_PMIC
#define CONFIG_FSL_PMIC_BUS 1
#define CONFIG_FSL_PMIC_CS 0
#define CONFIG_FSL_PMIC_CLK 1000000
#define CONFIG_FSL_PMIC_MODE (SPI_MODE_2 | SPI_CS_HIGH)
#define CONFIG_RTC_MC13783 1
/* MC13783 connected to CSPI2 and SS0 */
#define CONFIG_MC13783_SPI_BUS 1
#define CONFIG_MC13783_SPI_CS 0
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
@ -89,6 +92,7 @@
#define CONFIG_CMD_PING
#define CONFIG_CMD_SPI
#define CONFIG_CMD_DATE
#define CONFIG_CMD_NAND
#define CONFIG_BOOTDELAY 3
@ -174,4 +178,13 @@
#undef CONFIG_CMD_MTDPARTS
#define CONFIG_JFFS2_DEV "nor0"
/*
* NAND flash
*/
#define CONFIG_NAND_MXC
#define CONFIG_MXC_NAND_REGS_BASE NFC_BASE_ADDR
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR
#define CONFIG_MXC_NAND_HWECC
#endif /* __CONFIG_H */

View File

@ -65,10 +65,12 @@
#define CONFIG_DEFAULT_SPI_BUS 1
#define CONFIG_DEFAULT_SPI_MODE (SPI_MODE_2 | SPI_CS_HIGH)
#define CONFIG_FSL_PMIC
#define CONFIG_FSL_PMIC_BUS 1
#define CONFIG_FSL_PMIC_CS 0
#define CONFIG_FSL_PMIC_CLK 1000000
#define CONFIG_FSL_PMIC_MODE (SPI_MODE_2 | SPI_CS_HIGH)
#define CONFIG_RTC_MC13783 1
/* MC13783 connected to CSPI2 and SS0 */
#define CONFIG_MC13783_SPI_BUS 1
#define CONFIG_MC13783_SPI_CS 0
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE

View File

@ -69,12 +69,13 @@
#define CONFIG_DEFAULT_SPI_BUS 1
#define CONFIG_DEFAULT_SPI_MODE (SPI_MODE_2 | SPI_CS_HIGH)
#define CONFIG_FSL_PMIC
#define CONFIG_FSL_PMIC_BUS 1
#define CONFIG_FSL_PMIC_CS 2
#define CONFIG_FSL_PMIC_CLK 1000000
#define CONFIG_FSL_PMIC_MODE (SPI_MODE_2 | SPI_CS_HIGH)
#define CONFIG_RTC_MC13783 1
/* MC13783 connected to CSPI2 and SS2 */
#define CONFIG_MC13783_SPI_BUS 1
#define CONFIG_MC13783_SPI_CS 2
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#define CONFIG_CONS_INDEX 1

View File

@ -54,12 +54,27 @@
/* size in bytes reserved for initial data */
#define CONFIG_SYS_GBL_DATA_SIZE 128
#define BOARD_LATE_INIT
/*
* Hardware drivers
*/
#define CONFIG_MXC_UART
#define CONFIG_SYS_MX51_UART1
/*
* SPI Configs
* */
#define CONFIG_CMD_SPI
#define CONFIG_MXC_SPI
#define CONFIG_FSL_PMIC
#define CONFIG_FSL_PMIC_BUS 0
#define CONFIG_FSL_PMIC_CS 0
#define CONFIG_FSL_PMIC_CLK 2500000
#define CONFIG_FSL_PMIC_MODE (SPI_CPOL | SPI_CS_HIGH)
/*
* MMC Configs
* */

View File

@ -54,6 +54,17 @@
#define CONFIG_MX31_GPIO
#define CONFIG_MXC_SPI
#define CONFIG_DEFAULT_SPI_BUS 1
#define CONFIG_DEFAULT_SPI_MODE (SPI_MODE_2 | SPI_CS_HIGH)
#define CONFIG_RTC_MC13783
#define CONFIG_FSL_PMIC
#define CONFIG_FSL_PMIC_BUS 1
#define CONFIG_FSL_PMIC_CS 0
#define CONFIG_FSL_PMIC_CLK 100000
#define CONFIG_FSL_PMIC_MODE (SPI_MODE_2 | SPI_CS_HIGH)
/* FPGA */
#define CONFIG_QONG_FPGA 1
#define CONFIG_FPGA_BASE (CS1_BASE)
@ -73,7 +84,7 @@
#define CONFIG_SPLASH_SCREEN
#define CONFIG_CMD_BMP
#define CONFIG_BMP_16BPP
#define CONFIG_DISPLAY_VBEST_VGG322403
#define CONFIG_DISPLAY_COM57H5M10XRC
/*
* Reducing the ARP timeout from default 5 seconds to 200ms we speed up the
@ -98,6 +109,9 @@
#define CONFIG_CMD_NET
#define CONFIG_CMD_MII
#define CONFIG_CMD_NAND
#define CONFIG_CMD_SPI
#define CONFIG_CMD_DATE
#define BOARD_LATE_INIT
/*
* You can compile in a MAC address and your custom net settings by using

128
include/fsl_pmic.h Normal file
View File

@ -0,0 +1,128 @@
/*
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de.
*
* (C) Copyright 2009 Freescale Semiconductor, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef __FSL_PMIC_H__
#define __FSL_PMIC_H__
/*
* The registers of different PMIC has the same meaning
* but the bit positions of the fields can differ or
* some fields has a meaning only on some devices.
* You have to check with the internal SPI bitmap
* (see Freescale Documentation) to set the registers
* for the device you are using
*/
enum {
REG_INT_STATUS0 = 0,
REG_INT_MASK0,
REG_INT_SENSE0,
REG_INT_STATUS1,
REG_INT_MASK1,
REG_INT_SENSE1,
REG_PU_MODE_S,
REG_IDENTIFICATION,
REG_UNUSED0,
REG_ACC0,
REG_ACC1, /*10 */
REG_UNUSED1,
REG_UNUSED2,
REG_POWER_CTL0,
REG_POWER_CTL1,
REG_POWER_CTL2,
REG_REGEN_ASSIGN,
REG_UNUSED3,
REG_MEM_A,
REG_MEM_B,
REG_RTC_TIME, /*20 */
REG_RTC_ALARM,
REG_RTC_DAY,
REG_RTC_DAY_ALARM,
REG_SW_0,
REG_SW_1,
REG_SW_2,
REG_SW_3,
REG_SW_4,
REG_SW_5,
REG_SETTING_0, /*30 */
REG_SETTING_1,
REG_MODE_0,
REG_MODE_1,
REG_POWER_MISC,
REG_UNUSED4,
REG_UNUSED5,
REG_UNUSED6,
REG_UNUSED7,
REG_UNUSED8,
REG_UNUSED9, /*40 */
REG_UNUSED10,
REG_UNUSED11,
REG_ADC0,
REG_ADC1,
REG_ADC2,
REG_ADC3,
REG_ADC4,
REG_CHARGE,
REG_USB0,
REG_USB1, /*50 */
REG_LED_CTL0,
REG_LED_CTL1,
REG_LED_CTL2,
REG_LED_CTL3,
REG_UNUSED12,
REG_UNUSED13,
REG_TRIM0,
REG_TRIM1,
REG_TEST0,
REG_TEST1, /*60 */
REG_TEST2,
REG_TEST3,
REG_TEST4,
};
/* REG_POWER_MISC */
#define GPO1EN (1 << 6)
#define GPO1STBY (1 << 7)
#define GPO2EN (1 << 8)
#define GPO2STBY (1 << 9)
#define GPO3EN (1 << 10)
#define GPO3STBY (1 << 11)
#define GPO4EN (1 << 12)
#define GPO4STBY (1 << 13)
#define PWGT1SPIEN (1 << 15)
#define PWGT2SPIEN (1 << 16)
#define PWUP (1 << 21)
/* Power Control 0 */
#define COINCHEN (1 << 23)
#define BATTDETEN (1 << 19)
/* Interrupt status 1 */
#define RTCRSTI (1 << 7)
void pmic_show_pmic_info(void);
void pmic_reg_write(u32 reg, u32 value);
u32 pmic_reg_read(u32 reg);
#endif

160
include/mc13892.h Normal file
View File

@ -0,0 +1,160 @@
/*
* (C) Copyright 2010
* Stefano Babic, DENX Software Engineering, sbabic@denx.de.
*
* (C) Copyright 2009 Freescale Semiconductor, Inc.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef __MC13892_H__
#define __MC13892_H__
/* REG_CHARGE */
#define VCHRG0 0
#define VCHRG1 (1 << 1)
#define VCHRG2 (1 << 2)
#define ICHRG0 (1 << 3)
#define ICHRG1 (1 << 4)
#define ICHRG2 (1 << 5)
#define ICHRG3 (1 << 6)
#define ICHRGTR0 (1 << 7)
#define ICHRGTR1 (1 << 8)
#define ICHRGTR2 (1 << 9)
#define FETOVRD (1 << 10)
#define FETCTRL (1 << 11)
#define RVRSMODE (1 << 13)
#define OVCTRL0 (1 << 15)
#define OVCTRL1 (1 << 16)
#define UCHEN (1 << 17)
#define CHRGLEDEN (1 << 18)
#define CHRGRAWPDEN (1 << 19)
#define CHGRESTART (1 << 20)
#define CHGAUTOB (1 << 21)
#define CYCLB (1 << 22)
#define CHGAUTOVIB (1 << 23)
/* REG_SETTING_0/1 */
#define VO_1_20V 0
#define VO_1_30V 1
#define VO_1_50V 2
#define VO_1_80V 3
#define VO_1_10V 4
#define VO_2_00V 5
#define VO_2_77V 6
#define VO_2_40V 7
#define VIOL 2
#define VDIG 4
#define VGEN 6
/* SWxMode for Normal/Standby Mode */
#define SWMODE_OFF_OFF 0
#define SWMODE_PWM_OFF 1
#define SWMODE_PWMPS_OFF 2
#define SWMODE_PFM_OFF 3
#define SWMODE_AUTO_OFF 4
#define SWMODE_PWM_PWM 5
#define SWMODE_PWM_AUTO 6
#define SWMODE_AUTO_AUTO 8
#define SWMODE_PWM_PWMPS 9
#define SWMODE_PWMS_PWMPS 10
#define SWMODE_PWMS_AUTO 11
#define SWMODE_AUTO_PFM 12
#define SWMODE_PWM_PFM 13
#define SWMODE_PWMS_PFM 14
#define SWMODE_PFM_PFM 15
#define SWMODE_MASK 0x0F
#define SWMODE1_SHIFT 0
#define SWMODE2_SHIFT 10
#define SWMODE3_SHIFT 0
#define SWMODE4_SHIFT 8
/* Fields in REG_SETTING_1 */
#define VVIDEO_2_7 (0 << 2)
#define VVIDEO_2_775 (1 << 2)
#define VVIDEO_2_5 (2 << 2)
#define VVIDEO_2_6 (3 << 2)
#define VVIDEO_MASK (3 << 2)
#define VAUDIO_2_3 (0 << 4)
#define VAUDIO_2_5 (1 << 4)
#define VAUDIO_2_775 (2 << 4)
#define VAUDIO_3_0 (3 << 4)
#define VAUDIO_MASK (3 << 4)
#define VSD_1_8 (0 << 6)
#define VSD_2_0 (1 << 6)
#define VSD_2_6 (2 << 6)
#define VSD_2_7 (3 << 6)
#define VSD_2_8 (4 << 6)
#define VSD_2_9 (5 << 6)
#define VSD_3_0 (6 << 6)
#define VSD_3_15 (7 << 6)
#define VSD_MASK (7 << 6)
#define VGEN1_1_2 0
#define VGEN1_1_5 1
#define VGEN1_2_775 2
#define VGEN1_3_15 3
#define VGEN1_MASK 3
#define VGEN2_1_2 (0 << 6)
#define VGEN2_1_5 (1 << 6)
#define VGEN2_1_6 (2 << 6)
#define VGEN2_1_8 (3 << 6)
#define VGEN2_2_7 (4 << 6)
#define VGEN2_2_8 (5 << 6)
#define VGEN2_3_0 (6 << 6)
#define VGEN2_3_15 (7 << 6)
#define VGEN2_MASK (7 << 6)
/* Fields in REG_SETTING_1 */
#define VGEN3_1_8 (0 << 14)
#define VGEN3_2_9 (1 << 14)
#define VGEN3_MASK (1 << 14)
#define VDIG_1_05 (0 << 4)
#define VDIG_1_25 (1 << 4)
#define VDIG_1_65 (2 << 4)
#define VDIG_1_8 (3 << 4)
#define VDIG_MASK (3 << 4)
#define VCAM_2_5 (0 << 16)
#define VCAM_2_6 (1 << 16)
#define VCAM_2_75 (2 << 16)
#define VCAM_3_0 (3 << 16)
#define VCAM_MASK (3 << 16)
/* Reg Mode 1 */
#define VGEN3EN (1 << 0)
#define VGEN3STBY (1 << 1)
#define VGEN3MODE (1 << 2)
#define VGEN3CONFIG (1 << 3)
#define VCAMEN (1 << 6)
#define VCAMSTBY (1 << 7)
#define VCAMMODE (1 << 8)
#define VCAMCONFIG (1 << 9)
#define VVIDEOEN (1 << 12)
#define VIDEOSTBY (1 << 13)
#define VVIDEOMODE (1 << 14)
#define VAUDIOEN (1 << 15)
#define VAUDIOSTBY (1 << 16)
#define VSDEN (1 << 18)
#define VSDSTBY (1 << 19)
#define VSDMODE (1 << 20)
#endif