[U-Boot] MX51 Support in u-boot

Hi all,
the next patchset adds support for the Freescale MX51 processor. Fred Fan has already sent a patchset sometimes ago.
In agreement with Fred, I rearranged the patches after the first review, adding support for network (FEC) and SD controller. In the meantime, Freescale has published documentation on this board and has renamed it mx51evk (mx51 Evaluation Kit).
Stefano
[PATCH 1/9] mkimage: Add Freescale imx Boot Image support (imximage) [PATCH 2/9] MX51: Add initial support for the Freescale MX51 [PATCH 3/9] MX51: Add register definitions [PATCH 4/9] MX51: Add pin and multiplexer definitions. [PATCH 5/9] serial_mxc: add support for MX51 processor [PATCH 6/9] fec_mxc: add support for MX51 processor [PATCH 7/9] fsl_esdhc: add support for mx51 processor [PATCH 8/9] mmc: check correctness of the voltage mask in ocr [PATCH 9/9] Add initial support for Freescale mx51evk board

This patch adds support for "imximage" (MX Boot Image) to the mkimage utility. The imximage is used on the Freescales's MX.51 processors.
Further details under doc/README.imximage.
This patch was tested on a Freescale mx51evk board.
Signed-off-by: Stefano Babic sbabic@denx.de --- common/image.c | 1 + doc/README.imximage | 73 +++++++++++++ include/image.h | 1 + tools/Makefile | 2 + tools/imximage.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++++++ tools/imximage.h | 107 +++++++++++++++++++ tools/mkimage.c | 2 + tools/mkimage.h | 1 + 8 files changed, 476 insertions(+), 0 deletions(-) create mode 100644 doc/README.imximage create mode 100644 tools/imximage.c create mode 100644 tools/imximage.h
diff --git a/common/image.c b/common/image.c index 82e7aa4..9e49713 100644 --- a/common/image.c +++ b/common/image.c @@ -140,6 +140,7 @@ static table_entry_t uimage_type[] = { { IH_TYPE_STANDALONE, "standalone", "Standalone Program", }, { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, { IH_TYPE_KWBIMAGE, "kwbimage", "Kirkwood Boot Image",}, + { IH_TYPE_IMXIMAGE, "imximage", "Freescale i.MX Boot Image",}, { -1, "", "", }, };
diff --git a/doc/README.imximage b/doc/README.imximage new file mode 100644 index 0000000..db765d2 --- /dev/null +++ b/doc/README.imximage @@ -0,0 +1,73 @@ +--------------------------------------------- +Imximage Boot Image generation using mkimage +--------------------------------------------- + +This document describes how to set up a U-Boot image +that can be booted by the Freescale i.MX51 processor. + +The i.MX51 can boot directly from NAND, SPI flash and SD card flash +using its internal boot ROM support. It can boot from an internal +UART, if booting from device media fails. +Booting from NOR flash does not require to use this image type. + +For more details refer Chapter 2 - System Boot and section 2.14 +(flash header description) of the processor's manual. + +This implementation does not use at the moment the secure boot feature +of the processor. The image is generated disabling all security fields. + +Command syntax: +-------------- +./tools/mkimage -l <mx u-boot_file> + to list the imx image file details + +./tools/mkimage -T imximage \ + -n <board specific configuration file> \ + -e <execution address> -d <u-boot binary> <output image file> + +for example, for the mx51evk board: +./tools/mkimage -n ./board/freescale/mx51evk/imximage.cfg \ + -T imximage -e 0x97800000 \ + -d u-boot.bin u-boot.imx + +The output image can be flashed on the board SPI flash or on a SD card. +In both cases, you have to copy the image at the offset required for the +chosen media devices (0x400 for both SPI flash or SD card). + +Please check Freescale documentation for further details. + +Board specific configuration file specifications: +------------------------------------------------ +1. This file must present in the $(BOARDDIR) and the name should be + imximage.cfg (since this is used in Makefile). +2. This file can have empty lines and lines starting with "#" as first + character to put comments. +3. This file can have configuration command lines as mentioned below, + any other information in this file is treated as invalid. + +Configuration command line syntax: +--------------------------------- +1. Each command line is must have two strings, first one command or address + and second one data string +2. Following are the valid command strings and associated data strings:- + Command string data string + -------------- ----------- + BOOT_FROM nand/spi/sd/onenand + Example: + BOOT_FROM spi + DATA type address value + + type: word=4, halfword=2, byte=1 + address: physycal register address + value: value to be set in register + All values are in in hexadecimal. + Example (write to IOMUXC): + DATA 4 0x73FA88a0 0x200 + +The processor support up to 60 register programming commands. An error +is generated if more commands are found in the configuration file. + +3. All commands are optional to program. + +------------------------------------------------ +Author: Stefano babic sbabic@denx.de diff --git a/include/image.h b/include/image.h index d2e78fe..3e959de 100644 --- a/include/image.h +++ b/include/image.h @@ -156,6 +156,7 @@ #define IH_TYPE_FILESYSTEM 7 /* Filesystem Image (any type) */ #define IH_TYPE_FLATDT 8 /* Binary Flat Device Tree Blob */ #define IH_TYPE_KWBIMAGE 9 /* Kirkwood Boot Image */ +#define IH_TYPE_IMXIMAGE 10 /* Freescale IMXBoot Image */
/* * Compression Types diff --git a/tools/Makefile b/tools/Makefile index 5b8c3c3..afc1d44 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -73,6 +73,7 @@ OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o OBJ_FILES-$(CONFIG_CMD_LOADS) += img2srec.o OBJ_FILES-$(CONFIG_INCA_IP) += inca-swap-bytes.o NOPED_OBJ_FILES-y += kwbimage.o +NOPED_OBJ_FILES-y += imximage.o NOPED_OBJ_FILES-y += mkimage.o OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o NOPED_OBJ_FILES-y += os_support.o @@ -159,6 +160,7 @@ $(obj)mkimage$(SFX): $(obj)crc32.o \ $(obj)fit_image.o \ $(obj)image.o \ $(obj)kwbimage.o \ + $(obj)imximage.o \ $(obj)md5.o \ $(obj)mkimage.o \ $(obj)os_support.o \ diff --git a/tools/imximage.c b/tools/imximage.c new file mode 100644 index 0000000..b40a23b --- /dev/null +++ b/tools/imximage.c @@ -0,0 +1,289 @@ +/* + * (C) Copyright 2009 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * (C) Copyright 2008 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar prafulla@marvell.com + * + * 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 "mkimage.h" +#include <image.h> +#include "imximage.h" + +/* + * Supported commands for configuration file + */ +static table_entry_t imximage_cmds[] = { + {CMD_BOOT_FROM, "BOOT_FROM", "boot comand", }, + {CMD_DATA, "DATA", "Reg Write Data", }, + {-1, "", "", }, +}; + +/* + * Supported Boot options for configuration file + * this is needed to set the correct flash offset + */ +static table_entry_t imximage_bootops[] = { + {FLASH_OFFSET_SPI, "spi", "SPI Flash", }, + {FLASH_OFFSET_NAND, "nand", "NAND Flash", }, + {FLASH_OFFSET_SD, "sd", "SD Card", }, + {FLASH_OFFSET_ONENAND, "onenand", "OneNAND Flash",}, + {-1, "", "Invalid", }, +}; + + +static struct imx_header imximage_header; + +static uint32_t get_cfg_value(char *token, char *name, int linenr) +{ + char *endptr; + uint32_t value; + + errno = 0; + value = strtoul(token, &endptr, 16); + if (errno || (token == endptr)) { + printf ("Error: %s[%d] - Invalid hex data(%s)\n", + name, linenr, token); + exit (EXIT_FAILURE); + } + return value; +} + +static int imximage_check_image_types (uint8_t type) +{ + if (type == IH_TYPE_IMXIMAGE) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +static int imximage_verify_header (unsigned char *ptr, int image_size, + struct mkimage_params *params) +{ + + struct imx_header *imx_hdr = (struct imx_header *) ptr; + flash_header_t *hdr = &imx_hdr->fhdr; + + /* Only a few checks can be done: search for magic numbers */ + if (hdr->app_code_barker != APP_CODE_BARKER) + return -FDT_ERR_BADSTRUCTURE; + + if (imx_hdr->dcd_table.preamble.barker != DCD_BARKER) + return -FDT_ERR_BADSTRUCTURE; + + return 0; +} + +static void imximage_print_header (const void *ptr) +{ + struct imx_header *imx_hdr = (struct imx_header *) ptr; + flash_header_t *hdr = &imx_hdr->fhdr; + uint32_t size; + flash_cfg_parms_t *ext_header; + + size = imx_hdr->dcd_table.preamble.length; + if (size > (MAX_HW_CFG_SIZE * sizeof(dcd_type_addr_data_t))) { + printf ("Image corrupt: DCD size %d exceed maximum %d\n", + size / sizeof(dcd_type_addr_data_t), MAX_HW_CFG_SIZE); + exit (EXIT_FAILURE); + } + + ext_header = (flash_cfg_parms_t *) ((uint32_t)&imx_hdr->dcd_table + sizeof (dcd_preamble_t) + + size); + + printf ("Image Type: Freescale IMX Boot Image\n"); + printf ("Data Size: "); + genimg_print_size (ext_header->length); + printf ("Load Address: %08x\n", (unsigned int)hdr->app_dest_ptr); + printf ("Entry Point: %08x\n", (unsigned int)hdr->app_code_jump_vector); +} + +static uint32_t imximage_parse_cfg_file (struct imx_header *imxhdr, char* name) +{ + FILE *fd = NULL; + char *line = NULL; + char * token, *saveptr1, *saveptr2; + int lineno = 0; + int fld, value; + uint32_t len; + int dcd_len = 0; + dcd_t *dcd = &imxhdr->dcd_table; + int32_t cmd; + + if ((fd = fopen (name, "r")) == 0) { + printf ("Error:%s - Can't open DCD file\n", name); + exit (EXIT_FAILURE); + } + + /* Very simple parsing, line starting with # are comments and are dropped */ + while ((getline (&line, &len, fd)) > 0) { + lineno++; + + token = strtok_r (line, "\r\n", &saveptr1); + if (token == NULL) + continue; + + /* Check inside the single line */ + for (fld = CFG_COMMAND, cmd = CMD_INVALID, line = token; ; line = NULL, fld++) { + token = strtok_r (line, " \t", &saveptr2); + if (token == NULL) + break; + + /* Drop all text starting with '#' as comments */ + if (token[0] == '#') + break; + + /* parse all fields in a single line */ + switch (fld) { + case CFG_COMMAND: + cmd = get_table_entry_id (imximage_cmds, + "imximage commands", token); + if (cmd < 0) { + printf ("Error: %s[%d] - Invalid command (%s)\n", + name, lineno, token); + exit (EXIT_FAILURE); + } + break; + case CFG_REG_SIZE: + switch (cmd) { + case CMD_BOOT_FROM: + /* Get flash header offset */ + imxhdr->flash_offset = get_table_entry_id (imximage_bootops, + "imximage boot option", token); + if (imxhdr->flash_offset == -1) { + printf ("Error: %s[%d] - Invalid boot device (%s)\n", + name, lineno, token); + exit (EXIT_FAILURE); + } + break; + case CMD_DATA: + value = get_cfg_value(token, name, lineno); + + /* Byte, halfword, word */ + if ((value != 1) && (value != 2) && (value != 4)) { + printf ("Error:%s[%d] - Invalid register size %d\n", + name, lineno, value); + exit (EXIT_FAILURE); + } + dcd->addr_data[dcd_len].type = value; + break; + } + + case CFG_REG_ADDRESS: + if (cmd == CMD_DATA) { + dcd->addr_data[dcd_len].addr = get_cfg_value(token, name, lineno); + } + break; + case CFG_REG_VALUE: + if (cmd == CMD_DATA) { + dcd->addr_data[dcd_len].value = get_cfg_value(token, name, lineno); + dcd_len++; + } + break; + } + } + + if (dcd_len > MAX_HW_CFG_SIZE) { + printf ("Error:%s[%d] - DCD table exceeds maximum size(%d)\n", + name, lineno, MAX_HW_CFG_SIZE); + } + } + dcd->preamble.barker = DCD_BARKER; + dcd->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t); + fclose (fd); + + return dcd->preamble.length; +} + +static void imximage_set_header (void *ptr, struct stat *sbuf, int ifd, + struct mkimage_params *params) +{ + struct imx_header *hdr = (struct imx_header *)ptr; + flash_header_t *fhdr = &hdr->fhdr; + int dcd_len; + flash_cfg_parms_t *ext_header; + uint32_t base_offset; + + /* Set default offset */ + hdr->flash_offset = FLASH_OFFSET_STANDARD; + + /* Set magic number */ + fhdr->app_code_barker = APP_CODE_BARKER; + + /* Parse dcd configuration file */ + dcd_len = imximage_parse_cfg_file (hdr, params->imagename); + + fhdr->app_dest_ptr = params->addr; + fhdr->app_dest_ptr = params->ep - hdr->flash_offset - sizeof(struct imx_header); + fhdr->app_code_jump_vector = params->ep; + + base_offset = fhdr->app_dest_ptr + hdr->flash_offset ; + fhdr->dcd_ptr_ptr = (uint32_t) ((uint32_t)&fhdr->dcd_ptr - + (uint32_t)&fhdr->app_code_jump_vector) + base_offset ; + + fhdr->dcd_ptr = base_offset + ((uint32_t)&hdr->dcd_table - (uint32_t)&hdr->fhdr); + + /* The external flash header must be at the end of the DCD table */ + ext_header = (flash_cfg_parms_t *) ((uint32_t)&hdr->dcd_table + dcd_len + + sizeof(dcd_preamble_t)); + ext_header->length = sbuf->st_size + hdr->flash_offset + sizeof(struct imx_header); + + /* Security feature are not supported */ + fhdr->app_code_csf = 0; + fhdr->super_root_key = NULL; + +} + +int imximage_check_params (struct mkimage_params *params) +{ + if (!params) + return CFG_INVALID; + if (!strlen (params->imagename)) { + printf ("Error:%s - Configuration file not specified, " + "it is needed for imximage generation\n", + params->cmdname); + return CFG_INVALID; + } + return ((params->dflag && (params->fflag || params->lflag)) || + (params->fflag && (params->dflag || params->lflag)) || + (params->lflag && (params->dflag || params->fflag)) || + (params->xflag) || !(strlen (params->imagename))); +} + +/* + * imximage parameters + */ +static struct image_type_params imximage_params = { + .name = "Freescale i.MX 51 Boot Image support", + .header_size = sizeof(struct imx_header), + .hdr = (void*)&imximage_header, + .check_image_type = imximage_check_image_types, + .verify_header = imximage_verify_header, + .print_header = imximage_print_header, + .set_header = imximage_set_header, + .check_params = imximage_check_params, +}; + +void init_imx_image_type (void) +{ + mkimage_register (&imximage_params); +} diff --git a/tools/imximage.h b/tools/imximage.h new file mode 100644 index 0000000..b311738 --- /dev/null +++ b/tools/imximage.h @@ -0,0 +1,107 @@ +/* + * (C) Copyright 2009 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * 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 _IMXIMAGE_H_ +#define _IMXIMAGE_H_ + +#define MAX_HW_CFG_SIZE 60 /* Max number of registers that imx.51 can set */ +#define MAX_EXP_SIZE 4 +#define APP_CODE_BARKER 0xB1 +#define DCD_BARKER 0xB17219E9 +#define HEADER_OFFSET 0x400 + + +#define CMD_DATA_STR "DATA" +#define FLASH_OFFSET_STANDARD 0x400 +#define FLASH_OFFSET_NAND FLASH_OFFSET_STANDARD +#define FLASH_OFFSET_SD FLASH_OFFSET_STANDARD +#define FLASH_OFFSET_SPI FLASH_OFFSET_STANDARD +#define FLASH_OFFSET_ONENAND 0x100 + +enum imximage_cmd { + CMD_INVALID, + CMD_BOOT_FROM, + CMD_DATA +}; + +enum imximage_fld_types { + CFG_INVALID = -1, + CFG_COMMAND, + CFG_REG_SIZE, + CFG_REG_ADDRESS, + CFG_REG_VALUE +}; + +typedef struct { + uint8_t rsa_exponent[MAX_EXP_SIZE]; /* RSA public exponent */ + uint8_t *rsa_modulus; /* RSA modulus pointer */ + uint16_t exponent_size; /* Exponent size (bytes) */ + uint16_t modulus_size; /* Modulus size (bytes) */ + uint8_t init_flag; /* Indicates if key initialized */ +} hab_rsa_public_key; + +typedef struct +{ + uint32_t type; /* Type of pointer (byte, halfword, word, wait/read) */ + uint32_t addr; /* Address to write to */ + uint32_t value; /* Data to write */ +} dcd_type_addr_data_t; + +typedef struct +{ + uint32_t barker; /* Barker for sanity check */ + uint32_t length; /* Device configuration structure length (not including preamble) */ +} dcd_preamble_t; + +typedef struct { + dcd_preamble_t preamble; + dcd_type_addr_data_t addr_data[MAX_HW_CFG_SIZE]; +} dcd_t; + +typedef struct { + uint32_t app_code_jump_vector; + uint32_t app_code_barker; + uint32_t app_code_csf; + uint32_t dcd_ptr_ptr; + hab_rsa_public_key *super_root_key; + uint32_t dcd_ptr; + uint32_t app_dest_ptr; +} flash_header_t; + +typedef struct { + uint32_t length; /* Length of data to be read from flash */ +} flash_cfg_parms_t; + +struct imx_header { + flash_header_t fhdr; + dcd_t dcd_table; + flash_cfg_parms_t ext_header; + uint32_t flash_offset; +}; + +struct reg_config { + uint32_t raddr; + uint32_t rdata; +}; + +#endif /* _IMXIMAGE_H_ */ diff --git a/tools/mkimage.c b/tools/mkimage.c index 1bed933..8b5d7f5 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -150,6 +150,8 @@ main (int argc, char **argv)
/* Init Kirkwood Boot image generation/list support */ init_kwb_image_type (); + /* Init Freescale imx.51 Boot image generation/list support */ + init_imx_image_type (); /* Init FIT image generation/list support */ init_fit_image_type (); /* Init Default image generation/list support */ diff --git a/tools/mkimage.h b/tools/mkimage.h index ec67336..9033a7d 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -140,6 +140,7 @@ void mkimage_register (struct image_type_params *tparams); * Supported image types init functions */ void init_kwb_image_type (void); +void init_imx_image_type (void); void init_default_image_type (void); void init_fit_image_type (void);

The patch add initial support for the Freescale i.MX51 processor (family arm cortex_a8).
Signed-off-by: Fred Fan fanyefeng@gmail.com Signed-off-by: Stefano Babic sbabic@denx.de --- cpu/arm_cortexa8/mx51/Makefile | 48 +++++ cpu/arm_cortexa8/mx51/clock.c | 282 +++++++++++++++++++++++++++++ cpu/arm_cortexa8/mx51/iomux.c | 205 +++++++++++++++++++++ cpu/arm_cortexa8/mx51/lowlevel_init.S | 320 +++++++++++++++++++++++++++++++++ cpu/arm_cortexa8/mx51/soc.c | 78 ++++++++ cpu/arm_cortexa8/mx51/timer.c | 122 +++++++++++++ cpu/arm_cortexa8/mx51/u-boot.lds | 61 +++++++ 7 files changed, 1116 insertions(+), 0 deletions(-) create mode 100644 cpu/arm_cortexa8/mx51/Makefile create mode 100644 cpu/arm_cortexa8/mx51/clock.c create mode 100644 cpu/arm_cortexa8/mx51/iomux.c create mode 100644 cpu/arm_cortexa8/mx51/lowlevel_init.S create mode 100644 cpu/arm_cortexa8/mx51/soc.c create mode 100644 cpu/arm_cortexa8/mx51/timer.c create mode 100644 cpu/arm_cortexa8/mx51/u-boot.lds
diff --git a/cpu/arm_cortexa8/mx51/Makefile b/cpu/arm_cortexa8/mx51/Makefile new file mode 100644 index 0000000..4d82293 --- /dev/null +++ b/cpu/arm_cortexa8/mx51/Makefile @@ -0,0 +1,48 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@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 +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).a + +COBJS = soc.o clock.o iomux.o timer.o +SOBJS = lowlevel_init.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/cpu/arm_cortexa8/mx51/clock.c b/cpu/arm_cortexa8/mx51/clock.c new file mode 100644 index 0000000..763c994 --- /dev/null +++ b/cpu/arm_cortexa8/mx51/clock.c @@ -0,0 +1,282 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (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 + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/crm_regs.h> + +enum pll_clocks { + PLL1_CLOCK = 0, + PLL2_CLOCK, + PLL3_CLOCK, + PLL_CLOCKS, +}; + +struct mxc_pll_reg *mxc_plls[PLL_CLOCKS] = { + [PLL1_CLOCK] = (struct mxc_pll_reg *)PLL1_BASE_ADDR, + [PLL2_CLOCK] = (struct mxc_pll_reg *)PLL2_BASE_ADDR, + [PLL3_CLOCK] = (struct mxc_pll_reg *)PLL3_BASE_ADDR, +}; + +struct mxc_ccm_reg *mxc_ccm = MXC_CCM_BASE; + +/* + * Calculate the frequence of this pll. + */ +static u32 decode_pll(struct mxc_pll_reg *pll, u32 infreq) +{ + u32 mfi, mfn, mfd, pd; + + mfn = __raw_readl(&pll->mfn); + mfd = __raw_readl(&pll->mfd) + 1; + mfi = __raw_readl(&pll->op); + pd = (mfi & 0xF) + 1; + mfi = (mfi >> 4) & 0xF; + mfi = (mfi >= 5) ? mfi : 5; + + return ((4 * (infreq / 1000) * (mfi * mfd + mfn)) / (mfd * pd)) * 1000; +} + +/* + * Get mcu main rate + */ +u32 get_mcu_main_clk(void) +{ + u32 reg, freq; + + reg = (__raw_readl(&mxc_ccm->cacrr) & MXC_CCM_CACRR_ARM_PODF_MASK) >> + MXC_CCM_CACRR_ARM_PODF_OFFSET; + freq = decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_MX51_HCLK_FREQ); + return freq / (reg + 1); +} + +/* + * Get the rate of peripheral's root clock. + */ +static u32 get_periph_clk(void) +{ + u32 reg; + + reg = __raw_readl(&mxc_ccm->cbcdr); + if (!(reg & MXC_CCM_CBCDR_PERIPH_CLK_SEL)) + return decode_pll(mxc_plls[PLL2_CLOCK], CONFIG_MX51_HCLK_FREQ); + reg = __raw_readl(&mxc_ccm->cbcmr); + switch ((reg & MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK) >> + MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET) { + case 0: + return decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_MX51_HCLK_FREQ); + case 1: + return decode_pll(mxc_plls[PLL3_CLOCK], CONFIG_MX51_HCLK_FREQ); + default: + return 0; + } + /* NOTREACHED */ +} + +/* + * Get the rate of ipg clock. + */ +static u32 get_ipg_clk(void) +{ + u32 ahb_podf, ipg_podf; + + ahb_podf = __raw_readl(&mxc_ccm->cbcdr); + ipg_podf = (ahb_podf & MXC_CCM_CBCDR_IPG_PODF_MASK) >> + MXC_CCM_CBCDR_IPG_PODF_OFFSET; + ahb_podf = (ahb_podf & MXC_CCM_CBCDR_AHB_PODF_MASK) >> + MXC_CCM_CBCDR_AHB_PODF_OFFSET; + return get_periph_clk() / ((ahb_podf + 1) * (ipg_podf + 1)); +} + +/* + * Get the rate of ipg_per clock. + */ +static u32 get_ipg_per_clk(void) +{ + u32 pred1, pred2, podf; + + if (__raw_readl(&mxc_ccm->cbcmr) & MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL) + return get_ipg_clk(); + /* Fixme: not handle what about lpm*/ + podf = __raw_readl(&mxc_ccm->cbcdr); + pred1 = (podf & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >> + MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET; + pred2 = (podf & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >> + MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET; + podf = (podf & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >> + MXC_CCM_CBCDR_PERCLK_PODF_OFFSET; + + return get_periph_clk() / ((pred1 + 1) * (pred2 + 1) * (podf + 1)); +} + +/* + * Get the rate of uart clk. + */ +static u32 get_uart_clk(void) +{ + unsigned int freq, reg, pred, podf; + + reg = __raw_readl(&mxc_ccm->cscmr1); + switch ((reg & MXC_CCM_CSCMR1_UART_CLK_SEL_MASK) >> + MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET) { + case 0x0: + freq = decode_pll(mxc_plls[PLL1_CLOCK], + CONFIG_MX51_HCLK_FREQ); + break; + case 0x1: + freq = decode_pll(mxc_plls[PLL2_CLOCK], + CONFIG_MX51_HCLK_FREQ); + break; + case 0x2: + freq = decode_pll(mxc_plls[PLL3_CLOCK], + CONFIG_MX51_HCLK_FREQ); + break; + default: + return 66500000; + } + + reg = __raw_readl(&mxc_ccm->cscdr1); + + pred = (reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >> + MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET; + + podf = (reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >> + MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET; + freq /= (pred + 1) * (podf + 1); + + return freq; +} + +/* + * This function returns the low power audio clock. + */ +u32 get_lp_apm(void) +{ + u32 ret_val = 0; + u32 ccsr = __raw_readl(&mxc_ccm->ccsr); + + if (((ccsr >> 9) & 1) == 0) + ret_val = CONFIG_MX51_HCLK_FREQ; + else + ret_val = ((32768 * 1024)); + + return ret_val; +} + +/* + * get cspi clock rate. + */ +static u32 get_cspi_clk(void) +{ + u32 ret_val = 0, pdf, pre_pdf, clk_sel; + u32 cscmr1 = __raw_readl(&mxc_ccm->cscmr1); + u32 cscdr2 = __raw_readl(&mxc_ccm->cscdr2); + + pre_pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) \ + >> MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET; + pdf = (cscdr2 & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) \ + >> MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET; + clk_sel = (cscmr1 & MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK) \ + >> MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET; + + switch (clk_sel) { + case 0: + ret_val = decode_pll(mxc_plls[PLL1_CLOCK], + CONFIG_MX51_HCLK_FREQ) / + ((pre_pdf + 1) * (pdf + 1)); + break; + case 1: + ret_val = decode_pll(mxc_plls[PLL2_CLOCK], + CONFIG_MX51_HCLK_FREQ) / + ((pre_pdf + 1) * (pdf + 1)); + break; + case 2: + ret_val = decode_pll(mxc_plls[PLL3_CLOCK], + CONFIG_MX51_HCLK_FREQ) / + ((pre_pdf + 1) * (pdf + 1)); + break; + default: + ret_val = get_lp_apm() / ((pre_pdf + 1) * (pdf + 1)); + break; + } + + return ret_val; +} + +/* + * The API of get mxc clockes. + */ +unsigned int mxc_get_clock(enum mxc_clock clk) +{ + switch (clk) { + case MXC_ARM_CLK: + return get_mcu_main_clk(); + case MXC_AHB_CLK: + break; + case MXC_IPG_CLK: + return get_ipg_clk(); + case MXC_IPG_PERCLK: + return get_ipg_per_clk(); + case MXC_UART_CLK: + return get_uart_clk(); + case MXC_CSPI_CLK: + return get_cspi_clk(); + case MXC_FEC_CLK: + return decode_pll(mxc_plls[PLL1_CLOCK], + CONFIG_MX51_HCLK_FREQ); + default: + break; + } + return -1; +} + +/* + * Dump some core clockes. + */ +int do_mx51_showclocks (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + u32 freq; + + freq = decode_pll(mxc_plls[PLL1_CLOCK], CONFIG_MX51_HCLK_FREQ); + printf("mx51 pll1: %dMHz\n", freq / 1000000); + freq = decode_pll(mxc_plls[PLL2_CLOCK], CONFIG_MX51_HCLK_FREQ); + printf("mx51 pll2: %dMHz\n", freq / 1000000); + freq = decode_pll(mxc_plls[PLL3_CLOCK], CONFIG_MX51_HCLK_FREQ); + printf("mx51 pll3: %dMHz\n", freq / 1000000); + printf("ipg clock : %dHz\n", mxc_get_clock(MXC_IPG_CLK)); + printf("ipg per clock : %dHz\n", mxc_get_clock(MXC_IPG_PERCLK)); + + return 0; +} + +/***************************************************/ + +U_BOOT_CMD( + mx51clocks, CONFIG_SYS_MAXARGS, 1, do_mx51_showclocks, + "display mx51 clocks\n", + "" +); diff --git a/cpu/arm_cortexa8/mx51/iomux.c b/cpu/arm_cortexa8/mx51/iomux.c new file mode 100644 index 0000000..a42ec3a --- /dev/null +++ b/cpu/arm_cortexa8/mx51/iomux.c @@ -0,0 +1,205 @@ +/* + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/*! + * @defgroup GPIO_MX51 Board GPIO and Muxing Setup + * @ingroup MSL_MX51 + */ +/*! + * @file mach-mx51/iomux.c + * + * @brief I/O Muxing control functions + * + * @ingroup GPIO_MX51 + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/mx51_pins.h> +#include <asm/arch/iomux.h> + +/*! + * IOMUX register (base) addresses + */ +enum iomux_reg_addr { + IOMUXGPR0 = IOMUXC_BASE_ADDR, + IOMUXGPR1 = IOMUXC_BASE_ADDR + 0x004, + IOMUXSW_MUX_CTL = IOMUXC_BASE_ADDR, + IOMUXSW_MUX_END = IOMUXC_BASE_ADDR + MUX_I_END, + IOMUXSW_PAD_CTL = IOMUXC_BASE_ADDR + PAD_I_START, + IOMUXSW_INPUT_CTL = IOMUXC_BASE_ADDR, +}; + +#define MUX_PIN_NUM_MAX (((MUX_I_END - MUX_I_START) >> 2) + 1) + +/* Get the iomux register address of this pin */ +static inline u32 get_mux_reg(iomux_pin_name_t pin) +{ + u32 mux_reg = PIN_TO_IOMUX_MUX(pin); + + if (is_soc_rev(CHIP_REV_2_0) < 0) { + /* + * Fixup register address: + * i.MX51 TO1 has offset with the register + * which is define as TO2. + */ + if ((pin == MX51_PIN_NANDF_RB5) || + (pin == MX51_PIN_NANDF_RB6) || + (pin == MX51_PIN_NANDF_RB7)) + ; /* Do nothing */ + else if (mux_reg >= 0x2FC) + mux_reg += 8; + else if (mux_reg >= 0x130) + mux_reg += 0xC; + } + mux_reg += IOMUXSW_MUX_CTL; + return mux_reg; +} + +/* Get the pad register address of this pin */ +static inline u32 get_pad_reg(iomux_pin_name_t pin) +{ + u32 pad_reg = PIN_TO_IOMUX_PAD(pin); + + if (is_soc_rev(CHIP_REV_2_0) < 0) { + /* + * Fixup register address: + * i.MX51 TO1 has offset with the register + * which is define as TO2. + */ + if ((pin == MX51_PIN_NANDF_RB5) || + (pin == MX51_PIN_NANDF_RB6) || + (pin == MX51_PIN_NANDF_RB7)) + ; /* Do nothing */ + else if (pad_reg == 0x4D0 - PAD_I_START) + pad_reg += 0x4C; + else if (pad_reg == 0x860 - PAD_I_START) + pad_reg += 0x9C; + else if (pad_reg >= 0x804 - PAD_I_START) + pad_reg += 0xB0; + else if (pad_reg >= 0x7FC - PAD_I_START) + pad_reg += 0xB4; + else if (pad_reg >= 0x4E4 - PAD_I_START) + pad_reg += 0xCC; + else + pad_reg += 8; + } + pad_reg += IOMUXSW_PAD_CTL; + return pad_reg; +} + +/* Get the last iomux register address */ +static inline u32 get_mux_end(void) +{ + if (is_soc_rev(CHIP_REV_2_0) < 0) + return IOMUXC_BASE_ADDR + (0x3F8 - 4); + else + return IOMUXC_BASE_ADDR + (0x3F0 - 4); +} + +/*! + * This function is used to configure a pin through the IOMUX module. + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param cfg an output function as defined in \b #iomux_pin_cfg_t + * + * @return 0 if successful; Non-zero otherwise + */ +static void iomux_config_mux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) +{ + u32 mux_reg = get_mux_reg(pin); + + if ((mux_reg > get_mux_end()) || (mux_reg < IOMUXSW_MUX_CTL)) + return ; + if (cfg == IOMUX_CONFIG_GPIO) + writel(PIN_TO_ALT_GPIO(pin), mux_reg); + else + writel(cfg, mux_reg); +} + +/*! + * Request ownership for an IO pin. This function has to be the first one + * being called before that pin is used. The caller has to check the + * return value to make sure it returns 0. + * + * @param pin a name defined by \b iomux_pin_name_t + * @param cfg an input function as defined in \b #iomux_pin_cfg_t + * + */ +void mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) +{ + iomux_config_mux(pin, cfg); +} + +/*! + * Release ownership for an IO pin + * + * @param pin a name defined by \b iomux_pin_name_t + * @param cfg an input function as defined in \b #iomux_pin_cfg_t + */ +void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t cfg) +{ +} + +/*! + * This function configures the pad value for a IOMUX pin. + * + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param config the ORed value of elements defined in \b #iomux_pad_config_t + */ +void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config) +{ + u32 pad_reg = get_pad_reg(pin); + writel(config, pad_reg); +} + +unsigned int mxc_iomux_get_pad(iomux_pin_name_t pin) +{ + u32 pad_reg = get_pad_reg(pin); + return readl(pad_reg); +} +/*! + * This function configures input path. + * + * @param input index of input select register as defined in \b + * #iomux_input_select_t + * @param config the binary value of elements defined in \b + * #iomux_input_config_t + */ +void mxc_iomux_set_input(iomux_input_select_t input, u32 config) +{ + u32 reg; + + if (is_soc_rev(CHIP_REV_2_0) < 0) { + if (input == MUX_IN_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT) + input -= 4; + else if (input == + MUX_IN_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT) + input -= 3; + else if (input >= MUX_IN_KPP_IPP_IND_COL_6_SELECT_INPUT) + input -= 2; + else if (input >= + MUX_IN_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT) + input -= 5; + else if (input >= + MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS1_DATA_EN_SELECT_INPUT) + input -= 3; + else if (input >= MUX_IN_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT) + input -= 2; + else if (input >= MUX_IN_CCM_PLL1_BYPASS_CLK_SELECT_INPUT) + input -= 1; + reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START_TO1; + } else + reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START; + + writel(config, reg); +} diff --git a/cpu/arm_cortexa8/mx51/lowlevel_init.S b/cpu/arm_cortexa8/mx51/lowlevel_init.S new file mode 100644 index 0000000..843a7b8 --- /dev/null +++ b/cpu/arm_cortexa8/mx51/lowlevel_init.S @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2007, Guennadi Liakhovetski lg@denx.de + * + * (C) Copyright 2009 Freescale Semiconductor, Inc. + * + * 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 <asm/arch/imx-regs.h> + +/* + * return soc version + * 0x10: TO1 + * 0x20: TO2 + * 0x30: TO3 + */ +.macro check_soc_version ret, tmp +.endm + +/* + * L2CC Cache setup/invalidation/disable + */ +.macro init_l2cc + /* explicitly disable L2 cache */ + mrc 15, 0, r0, c1, c0, 1 + bic r0, r0, #0x2 + mcr 15, 0, r0, c1, c0, 1 + + /* reconfigure L2 cache aux control reg */ + mov r0, #0xC0 /* tag RAM */ + add r0, r0, #0x4 /* data RAM */ + orr r0, r0, #(1 << 24) /* disable write allocate delay */ + orr r0, r0, #(1 << 23) /* disable write allocate combine */ + orr r0, r0, #(1 << 22) /* disable write allocate */ + + cmp r3, #0x10 /* r3 contains the silicon rev */ + orrls r0, r0, #(1 << 25) /* disable write combine for TO 2 and lower revs */ + + mcr 15, 1, r0, c9, c0, 2 +.endm /* init_l2cc */ + +/* AIPS setup - Only setup MPROTx registers. + * The PACR default values are good.*/ +.macro init_aips + /* + * Set all MPROTx to be non-bufferable, trusted for R/W, + * not forced to user-mode. + */ + ldr r0, =AIPS1_BASE_ADDR + ldr r1, =0x77777777 + str r1, [r0, #0x0] + str r1, [r0, #0x4] + ldr r0, =AIPS2_BASE_ADDR + str r1, [r0, #0x0] + str r1, [r0, #0x4] + /* + * Clear the on and off peripheral modules Supervisor Protect bit + * for SDMA to access them. Did not change the AIPS control registers + * (offset 0x20) access type + */ +.endm /* init_aips */ + +/* MAX (Multi-Layer AHB Crossbar Switch) setup */ +.macro init_max +.endm /* init_max */ + +/* M4IF setup */ +.macro init_m4if + /* VPU and IPU given higher priority (0x4) + * IPU accesses with ID=0x1 given highest priority (=0xA) + */ + ldr r0, =M4IF_BASE_ADDR + + ldr r1, =0x00000203 + str r1, [r0, #0x40] + + ldr r1, =0x0 + str r1, [r0, #0x44] + + ldr r1, =0x00120125 + str r1, [r0, #0x9C] + + ldr r1, =0x001901A3 + str r1, [r0, #0x48] + +/* + ldr r1, =0x00000a01 + str r1, [r0, #0x48] + ldr r1, =0x00000404 + str r1, [r0, #0x40] +*/ +.endm /* init_m4if */ + +/* To support 133MHz DDR */ +.macro init_drive_strength +.endm /* init_drive_strength */ + +/* CPLD on CS5 setup */ +.macro init_debug_board +.endm /* init_debug_board */ + +.macro setup_pll pll, freq + ldr r2, =\pll + ldr r1, =0x00001232 + str r1, [r2, #PLL_DP_CTL] /* Set DPLL ON (set UPEN bit): BRMO=1 */ + mov r1, #0x2 + str r1, [r2, #PLL_DP_CONFIG] /* Enable auto-restart AREN bit */ + + str r3, [r2, #PLL_DP_OP] + str r3, [r2, #PLL_DP_HFS_OP] + + str r4, [r2, #PLL_DP_MFD] + str r4, [r2, #PLL_DP_HFS_MFD] + + str r5, [r2, #PLL_DP_MFN] + str r5, [r2, #PLL_DP_HFS_MFN] + + ldr r1, =0x00001232 + str r1, [r2, #PLL_DP_CTL] +1: ldr r1, [r2, #PLL_DP_CTL] + ands r1, r1, #0x1 + beq 1b +.endm + +.macro init_clock + ldr r0, =CCM_BASE_ADDR + + /* Gate of clocks to the peripherals first */ + ldr r1, =0x3FFFFFFF + str r1, [r0, #CLKCTL_CCGR0] + ldr r1, =0x0 + str r1, [r0, #CLKCTL_CCGR1] + str r1, [r0, #CLKCTL_CCGR2] + str r1, [r0, #CLKCTL_CCGR3] + + ldr r1, =0x00030000 + str r1, [r0, #CLKCTL_CCGR4] + ldr r1, =0x00FFF030 + str r1, [r0, #CLKCTL_CCGR5] + ldr r1, =0x00000300 + str r1, [r0, #CLKCTL_CCGR6] + + /* Disable IPU and HSC dividers */ + mov r1, #0x60000 + str r1, [r0, #CLKCTL_CCDR] + + /* Make sure to switch the DDR away from PLL 1 */ + ldr r1, =0x19239145 + str r1, [r0, #CLKCTL_CBCDR] + /* make sure divider effective */ +1: ldr r1, [r0, #CLKCTL_CDHIPR] + cmp r1, #0x0 + bne 1b + + /* Switch ARM to step clock */ + mov r1, #0x4 + str r1, [r0, #CLKCTL_CCSR] + mov r3, #DP_OP_800 + mov r4, #DP_MFD_800 + mov r5, #DP_MFN_800 + setup_pll PLL1_BASE_ADDR + + mov r3, #DP_OP_665 + mov r4, #DP_MFD_665 + mov r5, #DP_MFN_665 + setup_pll PLL3_BASE_ADDR + + /* Switch peripheral to PLL 3 */ + ldr r0, =CCM_BASE_ADDR + ldr r1, =0x000010C0 + str r1, [r0, #CLKCTL_CBCMR] + ldr r1, =0x13239145 + str r1, [r0, #CLKCTL_CBCDR] + mov r3, #DP_OP_665 + mov r4, #DP_MFD_665 + mov r5, #DP_MFN_665 + setup_pll PLL2_BASE_ADDR + + /* Switch peripheral to PLL2 */ + ldr r0, =CCM_BASE_ADDR + ldr r1, =0x19239145 + str r1, [r0, #CLKCTL_CBCDR] + ldr r1, =0x000020C0 + str r1, [r0, #CLKCTL_CBCMR] + + mov r3, #DP_OP_216 + mov r4, #DP_MFD_216 + mov r5, #DP_MFN_216 + setup_pll PLL3_BASE_ADDR + + + /* Set the platform clock dividers */ + ldr r0, =ARM_BASE_ADDR + ldr r1, =0x00000725 + str r1, [r0, #0x14] + + ldr r0, =CCM_BASE_ADDR + /* Run TO 3.0 at Full speed, for other TO's wait till we increase VDDGP */ + ldr r1, =0x0 + ldr r3, [r1, #ROM_SI_REV] + cmp r3, #0x10 + movls r1, #0x1 + movhi r1, #0 + str r1, [r0, #CLKCTL_CACRR] + + /* Switch ARM back to PLL 1 */ + mov r1, #0 + str r1, [r0, #CLKCTL_CCSR] + + /* setup the rest */ + /* Use lp_apm (24MHz) source for perclk */ + ldr r1, =0x000020C2 + str r1, [r0, #CLKCTL_CBCMR] + /* ddr clock from PLL 1, all perclk dividers are 1 since using 24MHz */ + ldr r1, =0x59E35100 + str r1, [r0, #CLKCTL_CBCDR] + + /* Restore the default values in the Gate registers */ + ldr r1, =0xFFFFFFFF + str r1, [r0, #CLKCTL_CCGR0] + str r1, [r0, #CLKCTL_CCGR1] + str r1, [r0, #CLKCTL_CCGR2] + str r1, [r0, #CLKCTL_CCGR3] + str r1, [r0, #CLKCTL_CCGR4] + str r1, [r0, #CLKCTL_CCGR5] + str r1, [r0, #CLKCTL_CCGR6] + + /* Use PLL 2 for UART's, get 66.5MHz from it */ + ldr r1, =0xA5A2A020 + str r1, [r0, #CLKCTL_CSCMR1] + ldr r1, =0x00C30321 + str r1, [r0, #CLKCTL_CSCDR1] + + /* make sure divider effective */ +1: ldr r1, [r0, #CLKCTL_CDHIPR] + cmp r1, #0x0 + bne 1b + + mov r1, #0x0 + str r1, [r0, #CLKCTL_CCDR] + + /* for cko - for ARM div by 8 */ + mov r1, #0x000A0000 + add r1, r1, #0x00000F0 + str r1, [r0, #CLKCTL_CCOSR] +.endm + +.macro setup_wdog + ldr r0, =WDOG1_BASE_ADDR + mov r1, #0x30 + strh r1, [r0] +.endm + +.section ".text.init", "x" + +.globl lowlevel_init +lowlevel_init: + ldr r0, =GPIO1_BASE_ADDR + ldr r1, [r0, #0x0] + orr r1, r1, #(1 << 23) + str r1, [r0, #0x0] + ldr r1, [r0, #0x4] + orr r1, r1, #(1 << 23) + str r1, [r0, #0x4] + +#ifdef ENABLE_IMPRECISE_ABORT + mrs r1, spsr /* save old spsr */ + mrs r0, cpsr /* read out the cpsr */ + bic r0, r0, #0x100 /* clear the A bit */ + msr spsr, r0 /* update spsr */ + add lr, pc, #0x8 /* update lr */ + movs pc, lr /* update cpsr */ + nop + nop + nop + nop + msr spsr, r1 /* restore old spsr */ +#endif + + init_l2cc + + init_aips + + init_max + + init_m4if + + init_drive_strength + + init_clock + + init_debug_board + + /* return from mxc_nand_load */ + /* r12 saved upper lr*/ + mov pc,lr + +/* b mxc_nand_load */ + +/* Board level setting value */ +DDR_PERCHARGE_CMD: .word 0x04008008 +DDR_REFRESH_CMD: .word 0x00008010 +DDR_LMR1_W: .word 0x00338018 +DDR_LMR_CMD: .word 0xB2220000 +DDR_TIMING_W: .word 0xB02567A9 +DDR_MISC_W: .word 0x000A0104 diff --git a/cpu/arm_cortexa8/mx51/soc.c b/cpu/arm_cortexa8/mx51/soc.c new file mode 100644 index 0000000..e91e72a --- /dev/null +++ b/cpu/arm_cortexa8/mx51/soc.c @@ -0,0 +1,78 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (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 + */ + +#include <common.h> +#include <asm/arch/imx-regs.h> +#include <asm/errno.h> +#include <asm/io.h> + +#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{ + printf("CPU: Freescale i.MX51 family %d.%dV at %d MHz\n", + (get_board_rev() & 0xFF) >> 4, + (get_board_rev() & 0xF), + get_mcu_main_clk() / 1000000); + return 0; +} +#endif + +/* + * Initializes on-chip ethernet controllers. + * to override, implement board_eth_init() + */ +#if defined(CONFIG_MXC_FEC) +extern int mxc_fec_initialize(bd_t *bis); +#endif + +int cpu_eth_init(bd_t *bis) +{ + int rc = -ENODEV; + +#if defined(CONFIG_MXC_FEC) + rc = mxc_fec_initialize(bis); +#endif + + return rc; +} + +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ +#ifdef CONFIG_FSL_ESDHC + return fsl_esdhc_mmc_init(bis); +#else + return 0; +#endif +} + + +void reset_cpu(ulong addr) +{ + __raw_writew(4, WDOG1_BASE_ADDR); +} diff --git a/cpu/arm_cortexa8/mx51/timer.c b/cpu/arm_cortexa8/mx51/timer.c new file mode 100644 index 0000000..0937998 --- /dev/null +++ b/cpu/arm_cortexa8/mx51/timer.c @@ -0,0 +1,122 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (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 + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +/* General purpose timers registers */ +struct mxc_gpt { + unsigned int control; + unsigned int prescaler; + unsigned int status; + unsigned int nouse[6]; + unsigned int counter; +}; + +static struct mxc_gpt *cur_gpt = (struct mxc_gpt *)GPT1_BASE_ADDR; + +/* General purpose timers bitfields */ +#define GPTCR_SWR (1<<15) /* Software reset */ +#define GPTCR_FRR (1<<9) /* Freerun / restart */ +#define GPTCR_CLKSOURCE_32 (4<<6) /* Clock source */ +#define GPTCR_TEN (1) /* Timer enable */ + +static ulong timestamp; +static ulong lastinc; + +int timer_init(void) +{ + int i; + + /* setup GP Timer 1 */ + __raw_writel(GPTCR_SWR, &cur_gpt->control); + + /* We have no udelay by now */ + for (i = 0; i < 100; i++) + __raw_writel(0, &cur_gpt->control); + + __raw_writel(0, &cur_gpt->prescaler); /* 32Khz */ + + /* Freerun Mode, PERCLK1 input */ + i = __raw_readl(&cur_gpt->control); + __raw_writel(i | GPTCR_CLKSOURCE_32 | GPTCR_TEN, &cur_gpt->control); + reset_timer_masked(); + return 0; +} + +void reset_timer(void) +{ + reset_timer_masked(); +} + +void reset_timer_masked(void) +{ + ulong val = __raw_readl(&cur_gpt->counter); + lastinc = val / (CONFIG_MX51_CLK32 / CONFIG_SYS_HZ); + timestamp = 0; +} + +ulong get_timer_masked(void) +{ + ulong val = __raw_readl(&cur_gpt->counter); + val /= (CONFIG_MX51_CLK32 / CONFIG_SYS_HZ); + if (val >= lastinc) + timestamp += (val - lastinc); + else + timestamp += ((0xFFFFFFFF / (CONFIG_MX51_CLK32 / CONFIG_SYS_HZ)) + - lastinc) + val; + lastinc = val; + return val; +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +void set_timer(ulong t) +{ + timestamp = t; +} + +/* delay x useconds AND perserve advance timstamp value */ +void __udelay(unsigned long usec) +{ + unsigned long now, last = readl(&cur_gpt->counter); + long tmo = usec * (CONFIG_MX51_CLK32 / 1000) / 1000; + + if (!tmo) + tmo = 1; + + while (tmo > 0) { + now = readl(&cur_gpt->counter); + if (last > now) + tmo -= 0xFFFFFFFF - last + now; + else + tmo -= now - last; + last = now; + } +} diff --git a/cpu/arm_cortexa8/mx51/u-boot.lds b/cpu/arm_cortexa8/mx51/u-boot.lds new file mode 100644 index 0000000..84c173a --- /dev/null +++ b/cpu/arm_cortexa8/mx51/u-boot.lds @@ -0,0 +1,61 @@ +/* + * January 2004 - Changed to support H4 device + * Copyright (c) 2004 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, gj@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 + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/arm_cortexa8/start.o + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + __bss_start = .; + .bss : { *(.bss) } + _end = .; +}

The patch add header files to support the Freescale i.MX51 processor, setting definitions for internal registers.
Signed-off-by: Stefano Babic sbabic@denx.de Signed-off-by: Fred Fan fanyefeng@gmail.com --- include/asm-arm/arch-mx51/crm_regs.h | 182 +++++++++++++++++++++ include/asm-arm/arch-mx51/imx-regs.h | 298 ++++++++++++++++++++++++++++++++++ 2 files changed, 480 insertions(+), 0 deletions(-) create mode 100644 include/asm-arm/arch-mx51/crm_regs.h create mode 100644 include/asm-arm/arch-mx51/imx-regs.h
diff --git a/include/asm-arm/arch-mx51/crm_regs.h b/include/asm-arm/arch-mx51/crm_regs.h new file mode 100644 index 0000000..92da560 --- /dev/null +++ b/include/asm-arm/arch-mx51/crm_regs.h @@ -0,0 +1,182 @@ +/* + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__ +#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__ + +#define MXC_CCM_BASE CCM_BASE_ADDR + +/* DPLL register mapping structure */ +struct mxc_pll_reg { + unsigned int ctrl; + unsigned int config; + unsigned int op; + unsigned int mfd; + unsigned int mfn; + unsigned int mfn_minus; + unsigned int mfn_plus; + unsigned int hfs_op; + unsigned int hfs_mfd; + unsigned int hfs_mfn; + unsigned int mfn_togc; + unsigned int destat; +}; + +/* Register maping of CCM*/ +struct mxc_ccm_reg { + unsigned int ccr; /* 0x0000 */ + unsigned int ccdr; + unsigned int csr; + unsigned int ccsr; + unsigned int cacrr; /* 0x0010*/ + unsigned int cbcdr; + unsigned int cbcmr; + unsigned int cscmr1; + unsigned int cscmr2; /* 0x0020 */ + unsigned int cscdr1; + unsigned int cs1cdr; + unsigned int cs2cdr; + unsigned int cdcdr; /* 0x0030 */ + unsigned int chscdr; + unsigned int cscdr2; + unsigned int cscdr3; + unsigned int cscdr4; /* 0x0040 */ + unsigned int cwdr; + unsigned int cdhipr; + unsigned int cdcr; + unsigned int ctor; /* 0x0050 */ + unsigned int clpcr; + unsigned int cisr; + unsigned int cimr; + unsigned int ccosr; /* 0x0060 */ + unsigned int cgpr; + unsigned int CCGR0; + unsigned int CCGR1; + unsigned int CCGR2; /* 0x0070 */ + unsigned int CCGR3; + unsigned int CCGR4; + unsigned int CCGR5; + unsigned int CCGR6; /* 0x0080 */ + unsigned int cmeor; +}; + +/* Define the bits in register CACRR */ +#define MXC_CCM_CACRR_ARM_PODF_OFFSET (0) +#define MXC_CCM_CACRR_ARM_PODF_MASK (0x7) + +/* Define the bits in register CBCDR */ +#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26) +#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25) +#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22) +#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22) +#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19) +#define MXC_CCM_CBCDR_AXI_B_PODF_MASK (0x7 << 19) +#define MXC_CCM_CBCDR_AXI_A_PODF_OFFSET (16) +#define MXC_CCM_CBCDR_AXI_A_PODF_MASK (0x7 << 16) +#define MXC_CCM_CBCDR_NFC_PODF_OFFSET (13) +#define MXC_CCM_CBCDR_NFC_PODF_MASK (0x7 << 13) +#define MXC_CCM_CBCDR_AHB_PODF_OFFSET (10) +#define MXC_CCM_CBCDR_AHB_PODF_MASK (0x7 << 10) +#define MXC_CCM_CBCDR_IPG_PODF_OFFSET (8) +#define MXC_CCM_CBCDR_IPG_PODF_MASK (0x3 << 8) +#define MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET (6) +#define MXC_CCM_CBCDR_PERCLK_PRED1_MASK (0x3 << 6) +#define MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET (3) +#define MXC_CCM_CBCDR_PERCLK_PRED2_MASK (0x7 << 3) +#define MXC_CCM_CBCDR_PERCLK_PODF_OFFSET (0) +#define MXC_CCM_CBCDR_PERCLK_PODF_MASK (0x7) + +/* Define the bits in register CSCMR1 */ +#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30) +#define MXC_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30) +#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28) +#define MXC_CCM_CSCMR1_SSI_EXT1_CLK_SEL_MASK (0x3 << 28) +#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET (26) +#define MXC_CCM_CSCMR1_USB_PHY_CLK_SEL (0x1 << 26) +#define MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET (24) +#define MXC_CCM_CSCMR1_UART_CLK_SEL_MASK (0x3 << 24) +#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET (22) +#define MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK (0x3 << 22) +#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET (20) +#define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK (0x3 << 20) +#define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL (0x1 << 19) +#define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL (0x1 << 18) +#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET (16) +#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK (0x3 << 16) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET (14) +#define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET (12) +#define MXC_CCM_CSCMR1_SSI2_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CSCMR1_SSI3_CLK_SEL (0x1 << 11) +#define MXC_CCM_CSCMR1_VPU_RCLK_SEL (0x1 << 10) +#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_OFFSET (8) +#define MXC_CCM_CSCMR1_SSI_APM_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CSCMR1_TVE_CLK_SEL (0x1 << 7) +#define MXC_CCM_CSCMR1_TVE_EXT_CLK_SEL (0x1 << 6) +#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET (4) +#define MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_OFFSET (2) +#define MXC_CCM_CSCMR1_SPDIF_CLK_SEL_MASK (0x3 << 2) +#define MXC_CCM_CSCMR1_SSI_EXT2_COM_CLK_SEL (0x1 << 1) +#define MXC_CCM_CSCMR1_SSI_EXT1_COM_CLK_SEL (0x1) + +/* Define the bits in register CSCDR2 */ +#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET (25) +#define MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK (0x7 << 25) +#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK (0x3F << 19) +#define MXC_CCM_CSCDR2_SIM_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR2_SIM_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR2_SIM_CLK_PODF_OFFSET (9) +#define MXC_CCM_CSCDR2_SIM_CLK_PODF_MASK (0x3F << 9) +#define MXC_CCM_CSCDR2_SLIMBUS_CLK_PRED_OFFSET (6) +#define MXC_CCM_CSCDR2_SLIMBUS_PRED_MASK (0x7 << 6) +#define MXC_CCM_CSCDR2_SLIMBUS_PODF_OFFSET (0) +#define MXC_CCM_CSCDR2_SLIMBUS_PODF_MASK (0x3F) + +/* Define the bits in register CBCMR */ +#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_OFFSET (14) +#define MXC_CCM_CBCMR_VPU_AXI_CLK_SEL_MASK (0x3 << 14) +#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET (12) +#define MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK (0x3 << 12) +#define MXC_CCM_CBCMR_DDR_CLK_SEL_OFFSET (10) +#define MXC_CCM_CBCMR_DDR_CLK_SEL_MASK (0x3 << 10) +#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_OFFSET (8) +#define MXC_CCM_CBCMR_ARM_AXI_CLK_SEL_MASK (0x3 << 8) +#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_OFFSET (6) +#define MXC_CCM_CBCMR_IPU_HSP_CLK_SEL_MASK (0x3 << 6) +#define MXC_CCM_CBCMR_GPU_CLK_SEL_OFFSET (4) +#define MXC_CCM_CBCMR_GPU_CLK_SEL_MASK (0x3 << 4) +#define MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL (0x1 << 1) +#define MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0) + +/* Define the bits in register CSCDR1 */ +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19) +#define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK (0x7 << 19) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET (16) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK (0x7 << 16) +#define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET (14) +#define MXC_CCM_CSCDR1_PGC_CLK_PODF_MASK (0x3 << 14) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET (11) +#define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK (0x7 << 11) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET (8) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK (0x7 << 8) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET (6) +#define MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK (0x3 << 6) +#define MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET (3) +#define MXC_CCM_CSCDR1_UART_CLK_PRED_MASK (0x7 << 3) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET (0) +#define MXC_CCM_CSCDR1_UART_CLK_PODF_MASK (0x7) + +#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */ diff --git a/include/asm-arm/arch-mx51/imx-regs.h b/include/asm-arm/arch-mx51/imx-regs.h new file mode 100644 index 0000000..e09afd5 --- /dev/null +++ b/include/asm-arm/arch-mx51/imx-regs.h @@ -0,0 +1,298 @@ +/* + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef __ASM_ARCH_MXC_MX51_H__ +#define __ASM_ARCH_MXC_MX51_H__ + +#define __REG(x) (*((volatile u32 *)(x))) +#define __REG16(x) (*((volatile u16 *)(x))) +#define __REG8(x) (*((volatile u8 *)(x))) +/* + * IRAM + */ +#define IRAM_BASE_ADDR 0x1FFE8000 /* internal ram */ +/* + * Graphics Memory of GPU + */ +#define GPU_BASE_ADDR 0x20000000 +#define GPU_CTRL_BASE_ADDR 0x30000000 +#define IPU_CTRL_BASE_ADDR 0x40000000 +/* + * Debug + */ +#define DEBUG_BASE_ADDR 0x60000000 +#define ETB_BASE_ADDR (DEBUG_BASE_ADDR + 0x00001000) +#define ETM_BASE_ADDR (DEBUG_BASE_ADDR + 0x00002000) +#define TPIU_BASE_ADDR (DEBUG_BASE_ADDR + 0x00003000) +#define CTI0_BASE_ADDR (DEBUG_BASE_ADDR + 0x00004000) +#define CTI1_BASE_ADDR (DEBUG_BASE_ADDR + 0x00005000) +#define CTI2_BASE_ADDR (DEBUG_BASE_ADDR + 0x00006000) +#define CTI3_BASE_ADDR (DEBUG_BASE_ADDR + 0x00007000) +#define CORTEX_DBG_BASE_ADDR (DEBUG_BASE_ADDR + 0x00008000) + +/* + * SPBA global module enabled #0 + */ +#define SPBA0_BASE_ADDR 0x70000000 + +#define MMC_SDHC1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00004000) +#define MMC_SDHC2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00008000) +#define UART3_BASE_ADDR (SPBA0_BASE_ADDR + 0x0000C000) +#define CSPI1_BASE_ADDR (SPBA0_BASE_ADDR + 0x00010000) +#define SSI2_BASE_ADDR (SPBA0_BASE_ADDR + 0x00014000) +#define MMC_SDHC3_BASE_ADDR (SPBA0_BASE_ADDR + 0x00020000) +#define MMC_SDHC4_BASE_ADDR (SPBA0_BASE_ADDR + 0x00024000) +#define SPDIF_BASE_ADDR (SPBA0_BASE_ADDR + 0x00028000) +#define ATA_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00030000) +#define SLIM_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00034000) +#define HSI2C_DMA_BASE_ADDR (SPBA0_BASE_ADDR + 0x00038000) +#define SPBA_CTRL_BASE_ADDR (SPBA0_BASE_ADDR + 0x0003C000) + +/* + * AIPS 1 + */ +#define AIPS1_BASE_ADDR 0x73F00000 + +#define OTG_BASE_ADDR (AIPS1_BASE_ADDR + 0x00080000) +#define GPIO1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00084000) +#define GPIO2_BASE_ADDR (AIPS1_BASE_ADDR + 0x00088000) +#define GPIO3_BASE_ADDR (AIPS1_BASE_ADDR + 0x0008C000) +#define GPIO4_BASE_ADDR (AIPS1_BASE_ADDR + 0x00090000) +#define KPP_BASE_ADDR (AIPS1_BASE_ADDR + 0x00094000) +#define WDOG1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00098000) +#define WDOG2_BASE_ADDR (AIPS1_BASE_ADDR + 0x0009C000) +#define GPT1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A0000) +#define SRTC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A4000) +#define IOMUXC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000A8000) +#define EPIT1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000AC000) +#define EPIT2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B0000) +#define PWM1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B4000) +#define PWM2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000B8000) +#define UART1_BASE_ADDR (AIPS1_BASE_ADDR + 0x000BC000) +#define UART2_BASE_ADDR (AIPS1_BASE_ADDR + 0x000C0000) +#define SRC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D0000) +#define CCM_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D4000) +#define GPC_BASE_ADDR (AIPS1_BASE_ADDR + 0x000D8000) + +/* + * AIPS 2 + */ +#define AIPS2_BASE_ADDR 0x83F00000 + +#define PLL1_BASE_ADDR (AIPS2_BASE_ADDR + 0x00080000) +#define PLL2_BASE_ADDR (AIPS2_BASE_ADDR + 0x00084000) +#define PLL3_BASE_ADDR (AIPS2_BASE_ADDR + 0x00088000) +#define AHBMAX_BASE_ADDR (AIPS2_BASE_ADDR + 0x00094000) +#define IIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x00098000) +#define CSU_BASE_ADDR (AIPS2_BASE_ADDR + 0x0009C000) +#define ARM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A0000) +#define OWIRE_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A4000) +#define FIRI_BASE_ADDR (AIPS2_BASE_ADDR + 0x000A8000) +#define CSPI2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000AC000) +#define SDMA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B0000) +#define SCC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B4000) +#define ROMCP_BASE_ADDR (AIPS2_BASE_ADDR + 0x000B8000) +#define RTIC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000BC000) +#define CSPI3_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C0000) +#define I2C2_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C4000) +#define I2C1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000C8000) +#define SSI1_BASE_ADDR (AIPS2_BASE_ADDR + 0x000CC000) +#define AUDMUX_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D0000) +#define M4IF_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D8000) +#define ESDCTL_BASE_ADDR (AIPS2_BASE_ADDR + 0x000D9000) +#define WEIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DA000) +#define NFC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DB000) +#define EMI_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DBF00) +#define MIPI_HSC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000DC000) +#define ATA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E0000) +#define SIM_BASE_ADDR (AIPS2_BASE_ADDR + 0x000E4000) +#define SSI3BASE_ADDR (AIPS2_BASE_ADDR + 0x000E8000) +#define FEC_BASE_ADDR (AIPS2_BASE_ADDR + 0x000EC000) +#define TVE_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F0000) +#define VPU_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F4000) +#define SAHARA_BASE_ADDR (AIPS2_BASE_ADDR + 0x000F8000) + +#define TZIC_BASE_ADDR 0x8FFFC000 + +/* + * Memory regions and CS + */ +#define CSD0_BASE_ADDR 0x90000000 +#define CSD1_BASE_ADDR 0xA0000000 +#define CS0_BASE_ADDR 0xB0000000 +#define CS1_BASE_ADDR 0xB8000000 +#define CS2_BASE_ADDR 0xC0000000 +#define CS3_BASE_ADDR 0xC8000000 +#define CS4_BASE_ADDR 0xCC000000 +#define CS5_BASE_ADDR 0xCE000000 + +/* + * NFC + */ +#define NFC_BASE_ADDR_AXI 0xCFFF0000 /* NAND flash AXI */ + +/*! + * Number of GPIO port as defined in the IC Spec + */ +#define GPIO_PORT_NUM 4 +/*! + * Number of GPIO pins per port + */ +#define GPIO_NUM_PIN 32 + +#define IIM_SREV 0x24 +#define ROM_SI_REV 0x48 + +#define NFC_BUF_SIZE 0x1000 + +/* WEIM registers */ +#define CSGCR1 0x00 +#define CSGCR2 0x04 +#define CSRCR1 0x08 +#define CSRCR2 0x0C +#define CSWCR1 0x10 + +/* M4IF */ +#define M4IF_FBPM0 0x40 +#define M4IF_FIDBP 0x48 + +/* ESDCTL */ +#define ESDCTL_ESDCTL0 0x00 +#define ESDCTL_ESDCFG0 0x04 +#define ESDCTL_ESDCTL1 0x08 +#define ESDCTL_ESDCFG1 0x0C +#define ESDCTL_ESDMISC 0x10 +#define ESDCTL_ESDSCR 0x14 +#define ESDCTL_ESDCDLY1 0x20 +#define ESDCTL_ESDCDLY2 0x24 +#define ESDCTL_ESDCDLY3 0x28 +#define ESDCTL_ESDCDLY4 0x2C +#define ESDCTL_ESDCDLY5 0x30 +#define ESDCTL_ESDCDLYGD 0x34 + +/* CCM */ +#define CLKCTL_CCR 0x00 +#define CLKCTL_CCDR 0x04 +#define CLKCTL_CSR 0x08 +#define CLKCTL_CCSR 0x0C +#define CLKCTL_CACRR 0x10 +#define CLKCTL_CBCDR 0x14 +#define CLKCTL_CBCMR 0x18 +#define CLKCTL_CSCMR1 0x1C +#define CLKCTL_CSCMR2 0x20 +#define CLKCTL_CSCDR1 0x24 +#define CLKCTL_CS1CDR 0x28 +#define CLKCTL_CS2CDR 0x2C +#define CLKCTL_CDCDR 0x30 +#define CLKCTL_CHSCCDR 0x34 +#define CLKCTL_CSCDR2 0x38 +#define CLKCTL_CSCDR3 0x3C +#define CLKCTL_CSCDR4 0x40 +#define CLKCTL_CWDR 0x44 +#define CLKCTL_CDHIPR 0x48 +#define CLKCTL_CDCR 0x4C +#define CLKCTL_CTOR 0x50 +#define CLKCTL_CLPCR 0x54 +#define CLKCTL_CISR 0x58 +#define CLKCTL_CIMR 0x5C +#define CLKCTL_CCOSR 0x60 +#define CLKCTL_CGPR 0x64 +#define CLKCTL_CCGR0 0x68 +#define CLKCTL_CCGR1 0x6C +#define CLKCTL_CCGR2 0x70 +#define CLKCTL_CCGR3 0x74 +#define CLKCTL_CCGR4 0x78 +#define CLKCTL_CCGR5 0x7C +#define CLKCTL_CCGR6 0x80 +#define CLKCTL_CMEOR 0x84 + +/* DPLL */ +#define PLL_DP_CTL 0x00 +#define PLL_DP_CONFIG 0x04 +#define PLL_DP_OP 0x08 +#define PLL_DP_MFD 0x0C +#define PLL_DP_MFN 0x10 +#define PLL_DP_MFNMINUS 0x14 +#define PLL_DP_MFNPLUS 0x18 +#define PLL_DP_HFS_OP 0x1C +#define PLL_DP_HFS_MFD 0x20 +#define PLL_DP_HFS_MFN 0x24 +#define PLL_DP_TOGC 0x28 +#define PLL_DP_DESTAT 0x2C + +/* Assuming 24MHz input clock with doubler ON */ +/* MFI PDF */ +#define DP_OP_850 ((8 << 4) + ((1 - 1) << 0)) +#define DP_MFD_850 (48 - 1) +#define DP_MFN_850 41 + +#define DP_OP_800 ((8 << 4) + ((1 - 1) << 0)) +#define DP_MFD_800 (3 - 1) +#define DP_MFN_800 1 + +#define DP_OP_700 ((7 << 4) + ((1 - 1) << 0)) +#define DP_MFD_700 (24 - 1) +#define DP_MFN_700 7 + +#define DP_OP_665 ((6 << 4) + ((1 - 1) << 0)) +#define DP_MFD_665 (96 - 1) +#define DP_MFN_665 89 + +#define DP_OP_532 ((5 << 4) + ((1 - 1) << 0)) +#define DP_MFD_532 (24 - 1) +#define DP_MFN_532 13 + +#define DP_OP_400 ((8 << 4) + ((2 - 1) << 0)) +#define DP_MFD_400 (3 - 1) +#define DP_MFN_400 1 + +#define DP_OP_216 ((6 << 4) + ((3 - 1) << 0)) +#define DP_MFD_216 (4 - 1) +#define DP_MFN_216 3 + +#define CHIP_REV_1_0 0x10 +#define CHIP_REV_1_1 0x11 +#define CHIP_REV_2_0 0x20 +#define CHIP_REV_2_5 0x25 +#define CHIP_REV_3_0 0x30 + +#define BOARD_REV_1_0 0x0 +#define BOARD_REV_2_0 0x1 + +#ifndef __ASSEMBLER__ + +enum mxc_clock { + MXC_ARM_CLK = 0, + MXC_AHB_CLK, + MXC_IPG_CLK, + MXC_IPG_PERCLK, + MXC_UART_CLK, + MXC_CSPI_CLK, + MXC_FEC_CLK, +}; + +/*! + * NFMS bit in RCSR register for pagesize of nandflash + */ +#define NFMS (*((volatile u32 *)(CCM_BASE_ADDR+0x18))) +#define NFMS_BIT 8 +#define NFMS_NF_DWIDTH 14 +#define NFMS_NF_PG_SZ 8 + +extern unsigned int mxc_get_clock(enum mxc_clock clk); +extern unsigned int get_board_rev(void); +extern int is_soc_rev(int rev); + +#endif /* __ASSEMBLER__*/ + +#endif /* __ASM_ARCH_MXC_MX51_H__ */

The patch add header files to support the pin multiplexer of the the Freescale i.MX51 processor.
Signed-off-by: Stefano Babic sbabic@denx.de Signed-off-by: Fred Fan fanyefeng@gmail.com --- include/asm-arm/arch-mx51/iomux.h | 240 ++++++++++++++++++++++ include/asm-arm/arch-mx51/mx51_pins.h | 365 +++++++++++++++++++++++++++++++++ 2 files changed, 605 insertions(+), 0 deletions(-) create mode 100644 include/asm-arm/arch-mx51/iomux.h create mode 100644 include/asm-arm/arch-mx51/mx51_pins.h
diff --git a/include/asm-arm/arch-mx51/iomux.h b/include/asm-arm/arch-mx51/iomux.h new file mode 100644 index 0000000..3724bb8 --- /dev/null +++ b/include/asm-arm/arch-mx51/iomux.h @@ -0,0 +1,240 @@ +/* + * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __MACH_MX51_IOMUX_H__ +#define __MACH_MX51_IOMUX_H__ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/mx51_pins.h> + +/*! + * @file iomux.h + * + * @brief I/O Muxing control definitions and functions + * + * @ingroup GPIO_MX51 + */ + +typedef unsigned int iomux_pin_name_t; + +/*! + * various IOMUX output functions + */ +typedef enum iomux_config { + IOMUX_CONFIG_ALT0, /*!< used as alternate function 0 */ + IOMUX_CONFIG_ALT1, /*!< used as alternate function 1 */ + IOMUX_CONFIG_ALT2, /*!< used as alternate function 2 */ + IOMUX_CONFIG_ALT3, /*!< used as alternate function 3 */ + IOMUX_CONFIG_ALT4, /*!< used as alternate function 4 */ + IOMUX_CONFIG_ALT5, /*!< used as alternate function 5 */ + IOMUX_CONFIG_ALT6, /*!< used as alternate function 6 */ + IOMUX_CONFIG_ALT7, /*!< used as alternate function 7 */ + IOMUX_CONFIG_GPIO, /*!< added to help user use GPIO mode */ + IOMUX_CONFIG_SION = 0x1 << 4, /*!< used as LOOPBACK:MUX SION bit */ +} iomux_pin_cfg_t; + +/*! + * various IOMUX pad functions + */ +typedef enum iomux_pad_config { + PAD_CTL_SRE_SLOW = 0x0 << 0, + PAD_CTL_SRE_FAST = 0x1 << 0, + PAD_CTL_DRV_LOW = 0x0 << 1, + PAD_CTL_DRV_MEDIUM = 0x1 << 1, + PAD_CTL_DRV_HIGH = 0x2 << 1, + PAD_CTL_DRV_MAX = 0x3 << 1, + PAD_CTL_ODE_OPENDRAIN_NONE = 0x0 << 3, + PAD_CTL_ODE_OPENDRAIN_ENABLE = 0x1 << 3, + PAD_CTL_100K_PD = 0x0 << 4, + PAD_CTL_47K_PU = 0x1 << 4, + PAD_CTL_100K_PU = 0x2 << 4, + PAD_CTL_22K_PU = 0x3 << 4, + PAD_CTL_PUE_KEEPER = 0x0 << 6, + PAD_CTL_PUE_PULL = 0x1 << 6, + PAD_CTL_PKE_NONE = 0x0 << 7, + PAD_CTL_PKE_ENABLE = 0x1 << 7, + PAD_CTL_HYS_NONE = 0x0 << 8, + PAD_CTL_HYS_ENABLE = 0x1 << 8, + PAD_CTL_DDR_INPUT_CMOS = 0x0 << 9, + PAD_CTL_DDR_INPUT_DDR = 0x1 << 9, + PAD_CTL_DRV_VOT_LOW = 0x0 << 13, + PAD_CTL_DRV_VOT_HIGH = 0x1 << 13, +} iomux_pad_config_t; + +/*! + * various IOMUX input select register index + */ +typedef enum iomux_input_select { + MUX_IN_AUDMUX_P4_INPUT_DA_AMX_SELECT_I = 0, + MUX_IN_AUDMUX_P4_INPUT_DB_AMX_SELECT_I, + MUX_IN_AUDMUX_P4_INPUT_TXCLK_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P4_INPUT_TXFS_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P5_INPUT_DA_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P5_INPUT_DB_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P5_INPUT_RXCLK_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P5_INPUT_RXFS_AMX_SELECT, + MUX_IN_AUDMUX_P5_INPUT_TXCLK_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P5_INPUT_TXFS_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_DA_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_DB_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_RXCLK_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_RXFS_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_TXCLK_AMX_SELECT_INPUT, + MUX_IN_AUDMUX_P6_INPUT_TXFS_AMX_SELECT_INPUT, + MUX_IN_CCM_IPP_DI_CLK_SELECT_INPUT, + /* TO2 */ + MUX_IN_CCM_IPP_DI1_CLK_SELECT_INPUT, + MUX_IN_CCM_PLL1_BYPASS_CLK_SELECT_INPUT, + MUX_IN_CCM_PLL2_BYPASS_CLK_SELECT_INPUT, + MUX_IN_CSPI_IPP_CSPI_CLK_IN_SELECT_INPUT, + MUX_IN_CSPI_IPP_IND_MISO_SELECT_INPUT, + MUX_IN_CSPI_IPP_IND_MOSI_SELECT_INPUT, + MUX_IN_CSPI_IPP_IND_SS_B_1_SELECT_INPUT, + MUX_IN_CSPI_IPP_IND_SS_B_2_SELECT_INPUT, + MUX_IN_CSPI_IPP_IND_SS_B_3_SELECT_INPUT, + MUX_IN_DPLLIP1_L1T_TOG_EN_SELECT_INPUT, + /* TO2 */ + MUX_IN_ECSPI2_IPP_IND_SS_B_1_SELECT_INPUT, + MUX_IN_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT, + MUX_IN_EMI_IPP_IND_RDY_INT_SELECT_INPUT, + MUX_IN_ESDHC3_IPP_DAT0_IN_SELECT_INPUT, + MUX_IN_ESDHC3_IPP_DAT1_IN_SELECT_INPUT, + MUX_IN_ESDHC3_IPP_DAT2_IN_SELECT_INPUT, + MUX_IN_ESDHC3_IPP_DAT3_IN_SELECT_INPUT, + MUX_IN_FEC_FEC_COL_SELECT_INPUT, + MUX_IN_FEC_FEC_CRS_SELECT_INPUT, + MUX_IN_FEC_FEC_MDI_SELECT_INPUT, + MUX_IN_FEC_FEC_RDATA_0_SELECT_INPUT, + MUX_IN_FEC_FEC_RDATA_1_SELECT_INPUT, + MUX_IN_FEC_FEC_RDATA_2_SELECT_INPUT, + MUX_IN_FEC_FEC_RDATA_3_SELECT_INPUT, + MUX_IN_FEC_FEC_RX_CLK_SELECT_INPUT, + MUX_IN_FEC_FEC_RX_DV_SELECT_INPUT, + MUX_IN_FEC_FEC_RX_ER_SELECT_INPUT, + MUX_IN_FEC_FEC_TX_CLK_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_1_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_2_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_3_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_4_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_5_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_6_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_7_SELECT_INPUT, + MUX_IN_GPIO3_IPP_IND_G_IN_8_SELECT_INPUT, + /* TO2 */ + MUX_IN_GPIO3_IPP_IND_G_IN_12_SELECT_INPUT, + MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS1_DATA_EN_SELECT_INPUT, + MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS2_DATA_EN_SELECT_INPUT, + /* TO2 */ + MUX_IN_HSC_MIPI_MIX_PAR_VSYNC_SELECT_INPUT, + /* TO2 */ + MUX_IN_HSC_MIPI_MIX_PAR_DI_WAIT_SELECT_INPUT, + MUX_IN_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT, + MUX_IN_I2C1_IPP_SCL_IN_SELECT_INPUT, + MUX_IN_I2C1_IPP_SDA_IN_SELECT_INPUT, + MUX_IN_I2C2_IPP_SCL_IN_SELECT_INPUT, + MUX_IN_I2C2_IPP_SDA_IN_SELECT_INPUT, + + MUX_IN_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT, + + MUX_IN_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT, + + MUX_IN_KPP_IPP_IND_COL_6_SELECT_INPUT, + MUX_IN_KPP_IPP_IND_COL_7_SELECT_INPUT, + MUX_IN_KPP_IPP_IND_ROW_4_SELECT_INPUT, + MUX_IN_KPP_IPP_IND_ROW_5_SELECT_INPUT, + MUX_IN_KPP_IPP_IND_ROW_6_SELECT_INPUT, + MUX_IN_KPP_IPP_IND_ROW_7_SELECT_INPUT, + MUX_IN_UART1_IPP_UART_RTS_B_SELECT_INPUT, + MUX_IN_UART1_IPP_UART_RXD_MUX_SELECT_INPUT, + MUX_IN_UART2_IPP_UART_RTS_B_SELECT_INPUT, + MUX_IN_UART2_IPP_UART_RXD_MUX_SELECT_INPUT, + MUX_IN_UART3_IPP_UART_RTS_B_SELECT_INPUT, + MUX_IN_UART3_IPP_UART_RXD_MUX_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_CLK_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_0_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_1_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_2_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_3_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_4_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_5_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_6_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DATA_7_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_DIR_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_NXT_SELECT_INPUT, + MUX_IN_USBOH3_IPP_IND_UH3_STP_SELECT_INPUT, + MUX_INPUT_NUM_MUX, +} iomux_input_select_t; + +/*! + * various IOMUX input functions + */ +typedef enum iomux_input_config { + INPUT_CTL_PATH0 = 0x0, + INPUT_CTL_PATH1, + INPUT_CTL_PATH2, + INPUT_CTL_PATH3, + INPUT_CTL_PATH4, + INPUT_CTL_PATH5, + INPUT_CTL_PATH6, + INPUT_CTL_PATH7, +} iomux_input_config_t; + +/*! + * Request ownership for an IO pin. This function has to be the first one + * being called before that pin is used. The caller has to check the + * return value to make sure it returns 0. + * + * @param pin a name defined by \b iomux_pin_name_t + * @param config config as defined in \b #iomux_pin_ocfg_t + * + * @return 0 if successful; Non-zero otherwise + */ +void mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config); + +/*! + * Release ownership for an IO pin + * + * @param pin a name defined by \b iomux_pin_name_t + * @param config config as defined in \b #iomux_pin_ocfg_t + */ +void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config); + +/*! + * This function configures the pad value for a IOMUX pin. + * + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @param config the ORed value of elements defined in + * \b #iomux_pad_config_t + */ +void mxc_iomux_set_pad(iomux_pin_name_t pin, u32 config); + +/*! + * This function gets the current pad value for a IOMUX pin. + * + * @param pin a pin number as defined in \b #iomux_pin_name_t + * @return current pad value + */ +unsigned int mxc_iomux_get_pad(iomux_pin_name_t pin); + +/*! + * This function configures input path. + * + * @param input index of input select register as defined in + * \b #iomux_input_select_t + * @param config the binary value of elements defined in + * \b #iomux_input_config_t + */ +void mxc_iomux_set_input(iomux_input_select_t input, u32 config); + +#endif /* __MACH_MX51_IOMUX_H__ */ diff --git a/include/asm-arm/arch-mx51/mx51_pins.h b/include/asm-arm/arch-mx51/mx51_pins.h new file mode 100644 index 0000000..8816168 --- /dev/null +++ b/include/asm-arm/arch-mx51/mx51_pins.h @@ -0,0 +1,365 @@ +/* + * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ +#ifndef __ASM_ARCH_MXC_MX51_PINS_H__ +#define __ASM_ARCH_MXC_MX51_PINS_H__ + +#ifndef __ASSEMBLY__ + +/* + * In order to identify pins more effectively, each mux-controlled pin's + * enumerated value is constructed in the following way: + * + * ------------------------------------------------------------------- + * 31-29 | 28 - 24 | 23 - 21 | 20 - 10| 9 - 0 + * ------------------------------------------------------------------- + * IO_P | IO_I | GPIO_I | PAD_I | MUX_I + * ------------------------------------------------------------------- + * + * Bit 0 to 9 contains MUX_I used to identify the register + * offset (0-based. base is IOMUX_module_base) defined in the Section + * "sw_pad_ctl & sw_mux_ctl details" of the IC Spec. The + * similar field definitions are used for the pad control register. + * The IOMUX controller can be split in two parts. At the begeinning, + * there is the register definitions for the multiplexing each pin. + * Then there is a set of registers (PAD_I) to configure each pin + * (pullup, pulldown, etc). + * PAD_I defines the offset of the pad register for each pin. + * GPIO_I defines, if available, the number of gpio that can be connected to that pad + * IO_I defines the multiplexer mode required to set the pad in gpio mode + * IO_P defines the gpio structure (gpio1..gpio4) the pad belongs + * + * For example, the MX51_PIN_ETM_D0 is defined in the enumeration: + * ( (0x28 - MUX_I_START) << MUX_I)|( (0x250 - PAD_I_START) << PAD_I) + * It means the mux control register is at register offset 0x28. The pad control + * register offset is: 0x250 and also occupy the least significant bits + * within the register. + */ + +/*! + * Starting bit position within each entry of \b iomux_pins to represent the + * MUX control register offset + */ +#define MUX_I 0 +/*! + * Starting bit position within each entry of \b iomux_pins to represent the + * PAD control register offset + */ +#define PAD_I 10 +/*! + * Starting bit position within each entry of \b iomux_pins to represent which + * mux mode is for GPIO (0-based) + */ +#define GPIO_I 21 + +#define MUX_IO_P 29 +#define MUX_IO_I 24 +#define IOMUX_TO_GPIO(pin) ((((unsigned int)pin >> MUX_IO_P) * \ + GPIO_NUM_PIN) + ((pin >> MUX_IO_I) &\ + ((1 << (MUX_IO_P - MUX_IO_I)) - 1))) +#define IOMUX_TO_IRQ(pin) (MXC_GPIO_INT_BASE + IOMUX_TO_GPIO(pin)) +#define GPIO_TO_PORT(n) (n / GPIO_NUM_PIN) +#define GPIO_TO_INDEX(n) (n % GPIO_NUM_PIN) + +#define NON_GPIO_PORT 0x7 +#define PIN_TO_MUX_MASK ((1 << (PAD_I - MUX_I)) - 1) +#define PIN_TO_PAD_MASK ((1 << (GPIO_I - PAD_I)) - 1) +#define PIN_TO_ALT_GPIO_MASK ((1 << (MUX_IO_I - GPIO_I)) - 1) + +#define NON_MUX_I PIN_TO_MUX_MASK +#define MUX_I_START 0x001C +#define PAD_I_START 0x3F0 +#define INPUT_CTL_START 0x8C4 +#define INPUT_CTL_START_TO1 0x928 +#define MUX_I_END (PAD_I_START - 4) + +#define _MXC_BUILD_PIN(gp, gi, ga, mi, pi) \ + (((gp) << MUX_IO_P) | ((gi) << MUX_IO_I) | \ + ((mi) << MUX_I) | \ + ((pi - PAD_I_START) << PAD_I) | \ + ((ga) << GPIO_I)) + +#define _MXC_BUILD_GPIO_PIN(gp, gi, ga, mi, pi) \ + _MXC_BUILD_PIN(gp, gi, ga, mi, pi) + +#define _MXC_BUILD_NON_GPIO_PIN(mi, pi) \ + _MXC_BUILD_PIN(NON_GPIO_PORT, 0, 0, mi, pi) + +#define PIN_TO_IOMUX_MUX(pin) ((pin >> MUX_I) & PIN_TO_MUX_MASK) +#define PIN_TO_IOMUX_PAD(pin) ((pin >> PAD_I) & PIN_TO_PAD_MASK) +#define PIN_TO_ALT_GPIO(pin) ((pin >> GPIO_I) & PIN_TO_ALT_GPIO_MASK) +#define PIN_TO_IOMUX_INDEX(pin) (PIN_TO_IOMUX_MUX(pin) >> 2) + +/*! @} End IOMUX/PAD Bit field definitions */ + +/*! + * This enumeration is constructed based on the Section + * "sw_pad_ctl & sw_mux_ctl details" of the MX51 IC Spec. Each enumerated + * value is constructed based on the rules described above. + */ +enum iomux_pins { + MX51_PIN_EIM_DA0 = _MXC_BUILD_NON_GPIO_PIN(0x1C, 0x7A8), + MX51_PIN_EIM_DA1 = _MXC_BUILD_NON_GPIO_PIN(0x20, 0x7A8), + MX51_PIN_EIM_DA2 = _MXC_BUILD_NON_GPIO_PIN(0x24, 0x7A8), + MX51_PIN_EIM_DA3 = _MXC_BUILD_NON_GPIO_PIN(0x28, 0x7A8), + MX51_PIN_EIM_DA4 = _MXC_BUILD_NON_GPIO_PIN(0x2C, 0x7AC), + MX51_PIN_EIM_DA5 = _MXC_BUILD_NON_GPIO_PIN(0x30, 0x7AC), + MX51_PIN_EIM_DA6 = _MXC_BUILD_NON_GPIO_PIN(0x34, 0x7AC), + MX51_PIN_EIM_DA7 = _MXC_BUILD_NON_GPIO_PIN(0x38, 0x7AC), + MX51_PIN_EIM_DA8 = _MXC_BUILD_NON_GPIO_PIN(0x3C, 0x7B0), + MX51_PIN_EIM_DA9 = _MXC_BUILD_NON_GPIO_PIN(0x40, 0x7B0), + MX51_PIN_EIM_DA10 = _MXC_BUILD_NON_GPIO_PIN(0x44, 0x7B0), + MX51_PIN_EIM_DA11 = _MXC_BUILD_NON_GPIO_PIN(0x48, 0x7B0), + MX51_PIN_EIM_DA12 = _MXC_BUILD_NON_GPIO_PIN(0x4C, 0x7BC), + MX51_PIN_EIM_DA13 = _MXC_BUILD_NON_GPIO_PIN(0x50, 0x7BC), + MX51_PIN_EIM_DA14 = _MXC_BUILD_NON_GPIO_PIN(0x54, 0x7BC), + MX51_PIN_EIM_DA15 = _MXC_BUILD_NON_GPIO_PIN(0x58, 0x7BC), + MX51_PIN_EIM_D16 = _MXC_BUILD_GPIO_PIN(1, 0, 1, 0x5C, 0x3F0), + MX51_PIN_EIM_D17 = _MXC_BUILD_GPIO_PIN(1, 1, 1, 0x60, 0x3F4), + MX51_PIN_EIM_D18 = _MXC_BUILD_GPIO_PIN(1, 2, 1, 0x64, 0x3F8), + MX51_PIN_EIM_D19 = _MXC_BUILD_GPIO_PIN(1, 3, 1, 0x68, 0x3FC), + MX51_PIN_EIM_D20 = _MXC_BUILD_GPIO_PIN(1, 4, 1, 0x6C, 0x400), + MX51_PIN_EIM_D21 = _MXC_BUILD_GPIO_PIN(1, 5, 1, 0x70, 0x404), + MX51_PIN_EIM_D22 = _MXC_BUILD_GPIO_PIN(1, 6, 1, 0x74, 0x408), + MX51_PIN_EIM_D23 = _MXC_BUILD_GPIO_PIN(1, 7, 1, 0x78, 0x40C), + MX51_PIN_EIM_D24 = _MXC_BUILD_GPIO_PIN(1, 8, 1, 0x7C, 0x410), + MX51_PIN_EIM_D25 = _MXC_BUILD_NON_GPIO_PIN(0x80, 0x414), + MX51_PIN_EIM_D26 = _MXC_BUILD_NON_GPIO_PIN(0x84, 0x418), + MX51_PIN_EIM_D27 = _MXC_BUILD_GPIO_PIN(1, 9, 1, 0x88, 0x41C), + MX51_PIN_EIM_D28 = _MXC_BUILD_NON_GPIO_PIN(0x8C, 0x420), + MX51_PIN_EIM_D29 = _MXC_BUILD_NON_GPIO_PIN(0x90, 0x424), + MX51_PIN_EIM_D30 = _MXC_BUILD_NON_GPIO_PIN(0x94, 0x428), + MX51_PIN_EIM_D31 = _MXC_BUILD_NON_GPIO_PIN(0x98, 0x42C), + MX51_PIN_EIM_A16 = _MXC_BUILD_GPIO_PIN(1, 10, 1, 0x9C, 0x430), + MX51_PIN_EIM_A17 = _MXC_BUILD_GPIO_PIN(1, 11, 1, 0xA0, 0x434), + MX51_PIN_EIM_A18 = _MXC_BUILD_GPIO_PIN(1, 12, 1, 0xA4, 0x438), + MX51_PIN_EIM_A19 = _MXC_BUILD_GPIO_PIN(1, 13, 1, 0xA8, 0x43C), + MX51_PIN_EIM_A20 = _MXC_BUILD_GPIO_PIN(1, 14, 1, 0xAC, 0x440), + MX51_PIN_EIM_A21 = _MXC_BUILD_GPIO_PIN(1, 15, 1, 0xB0, 0x444), + MX51_PIN_EIM_A22 = _MXC_BUILD_GPIO_PIN(1, 16, 1, 0xB4, 0x448), + MX51_PIN_EIM_A23 = _MXC_BUILD_GPIO_PIN(1, 17, 1, 0xB8, 0x44C), + MX51_PIN_EIM_A24 = _MXC_BUILD_GPIO_PIN(1, 18, 1, 0xBC, 0x450), + MX51_PIN_EIM_A25 = _MXC_BUILD_GPIO_PIN(1, 19, 1, 0xC0, 0x454), + MX51_PIN_EIM_A26 = _MXC_BUILD_GPIO_PIN(1, 20, 1, 0xC4, 0x458), + MX51_PIN_EIM_A27 = _MXC_BUILD_GPIO_PIN(1, 21, 1, 0xC8, 0x45C), + MX51_PIN_EIM_EB0 = _MXC_BUILD_NON_GPIO_PIN(0xCC, 0x460), + MX51_PIN_EIM_EB1 = _MXC_BUILD_NON_GPIO_PIN(0xD0, 0x464), + MX51_PIN_EIM_EB2 = _MXC_BUILD_GPIO_PIN(1, 22, 1, 0xD4, 0x468), + MX51_PIN_EIM_EB3 = _MXC_BUILD_GPIO_PIN(1, 23, 1, 0xD8, 0x46C), + MX51_PIN_EIM_OE = _MXC_BUILD_GPIO_PIN(1, 24, 1, 0xDC, 0x470), + MX51_PIN_EIM_CS0 = _MXC_BUILD_GPIO_PIN(1, 25, 1, 0xE0, 0x474), + MX51_PIN_EIM_CS1 = _MXC_BUILD_GPIO_PIN(1, 26, 1, 0xE4, 0x478), + MX51_PIN_EIM_CS2 = _MXC_BUILD_GPIO_PIN(1, 27, 1, 0xE8, 0x47C), + MX51_PIN_EIM_CS3 = _MXC_BUILD_GPIO_PIN(1, 28, 1, 0xEC, 0x480), + MX51_PIN_EIM_CS4 = _MXC_BUILD_GPIO_PIN(1, 29, 1, 0xF0, 0x484), + MX51_PIN_EIM_CS5 = _MXC_BUILD_GPIO_PIN(1, 30, 1, 0xF4, 0x488), + MX51_PIN_EIM_DTACK = _MXC_BUILD_GPIO_PIN(1, 31, 1, 0xF8, 0x48C), + MX51_PIN_EIM_LBA = _MXC_BUILD_GPIO_PIN(2, 1, 1, 0xFC, 0x494), + MX51_PIN_EIM_CRE = _MXC_BUILD_GPIO_PIN(2, 2, 1, 0x100, 0x4A0), + MX51_PIN_DRAM_CS1 = _MXC_BUILD_NON_GPIO_PIN(0x104, 0x4D0), + MX51_PIN_NANDF_WE_B = _MXC_BUILD_GPIO_PIN(2, 3, 3, 0x108, 0x4E4), + MX51_PIN_NANDF_RE_B = _MXC_BUILD_GPIO_PIN(2, 4, 3, 0x10C, 0x4E8), + MX51_PIN_NANDF_ALE = _MXC_BUILD_GPIO_PIN(2, 5, 3, 0x110, 0x4EC), + MX51_PIN_NANDF_CLE = _MXC_BUILD_GPIO_PIN(2, 6, 3, 0x114, 0x4F0), + MX51_PIN_NANDF_WP_B = _MXC_BUILD_GPIO_PIN(2, 7, 3, 0x118, 0x4F4), + MX51_PIN_NANDF_RB0 = _MXC_BUILD_GPIO_PIN(2, 8, 3, 0x11C, 0x4F8), + MX51_PIN_NANDF_RB1 = _MXC_BUILD_GPIO_PIN(2, 9, 3, 0x120, 0x4FC), + MX51_PIN_NANDF_RB2 = _MXC_BUILD_GPIO_PIN(2, 10, 3, 0x124, 0x500), + MX51_PIN_NANDF_RB3 = _MXC_BUILD_GPIO_PIN(2, 11, 3, 0x128, 0x504), + MX51_PIN_GPIO_NAND = _MXC_BUILD_GPIO_PIN(2, 12, 3, 0x12C, 0x514), + MX51_PIN_NANDF_RB4 = MX51_PIN_GPIO_NAND, + MX51_PIN_NANDF_RB5 = _MXC_BUILD_GPIO_PIN(2, 13, 3, 0x130, 0x5D8), + MX51_PIN_NANDF_RB6 = _MXC_BUILD_GPIO_PIN(2, 14, 3, 0x134, 0x5DC), + MX51_PIN_NANDF_RB7 = _MXC_BUILD_GPIO_PIN(2, 15, 3, 0x138, 0x5E0), + MX51_PIN_NANDF_CS0 = _MXC_BUILD_GPIO_PIN(2, 16, 3, 0x130, 0x518), + MX51_PIN_NANDF_CS1 = _MXC_BUILD_GPIO_PIN(2, 17, 3, 0x134, 0x51C), + MX51_PIN_NANDF_CS2 = _MXC_BUILD_GPIO_PIN(2, 18, 3, 0x138, 0x520), + MX51_PIN_NANDF_CS3 = _MXC_BUILD_GPIO_PIN(2, 19, 3, 0x13C, 0x524), + MX51_PIN_NANDF_CS4 = _MXC_BUILD_GPIO_PIN(2, 20, 3, 0x140, 0x528), + MX51_PIN_NANDF_CS5 = _MXC_BUILD_GPIO_PIN(2, 21, 3, 0x144, 0x52C), + MX51_PIN_NANDF_CS6 = _MXC_BUILD_GPIO_PIN(2, 22, 3, 0x148, 0x530), + MX51_PIN_NANDF_CS7 = _MXC_BUILD_GPIO_PIN(2, 23, 3, 0x14C, 0x534), + MX51_PIN_NANDF_RDY_INT = _MXC_BUILD_GPIO_PIN(2, 24, 3, 0x150, 0x538), + MX51_PIN_NANDF_D15 = _MXC_BUILD_GPIO_PIN(2, 25, 3, 0x154, 0x53C), + MX51_PIN_NANDF_D14 = _MXC_BUILD_GPIO_PIN(2, 26, 3, 0x158, 0x540), + MX51_PIN_NANDF_D13 = _MXC_BUILD_GPIO_PIN(2, 27, 3, 0x15C, 0x544), + MX51_PIN_NANDF_D12 = _MXC_BUILD_GPIO_PIN(2, 28, 3, 0x160, 0x548), + MX51_PIN_NANDF_D11 = _MXC_BUILD_GPIO_PIN(2, 29, 3, 0x164, 0x54C), + MX51_PIN_NANDF_D10 = _MXC_BUILD_GPIO_PIN(2, 30, 3, 0x168, 0x550), + MX51_PIN_NANDF_D9 = _MXC_BUILD_GPIO_PIN(2, 31, 3, 0x16C, 0x554), + MX51_PIN_NANDF_D8 = _MXC_BUILD_GPIO_PIN(3, 0, 3, 0x170, 0x558), + MX51_PIN_NANDF_D7 = _MXC_BUILD_GPIO_PIN(3, 1, 3, 0x174, 0x55C), + MX51_PIN_NANDF_D6 = _MXC_BUILD_GPIO_PIN(3, 2, 3, 0x178, 0x560), + MX51_PIN_NANDF_D5 = _MXC_BUILD_GPIO_PIN(3, 3, 3, 0x17C, 0x564), + MX51_PIN_NANDF_D4 = _MXC_BUILD_GPIO_PIN(3, 4, 3, 0x180, 0x568), + MX51_PIN_NANDF_D3 = _MXC_BUILD_GPIO_PIN(3, 5, 3, 0x184, 0x56C), + MX51_PIN_NANDF_D2 = _MXC_BUILD_GPIO_PIN(3, 6, 3, 0x188, 0x570), + MX51_PIN_NANDF_D1 = _MXC_BUILD_GPIO_PIN(3, 7, 3, 0x18C, 0x574), + MX51_PIN_NANDF_D0 = _MXC_BUILD_GPIO_PIN(3, 8, 3, 0x190, 0x578), + MX51_PIN_CSI1_D8 = _MXC_BUILD_GPIO_PIN(2, 12, 3, 0x194, 0x57C), + MX51_PIN_CSI1_D9 = _MXC_BUILD_GPIO_PIN(2, 13, 3, 0x198, 0x580), + MX51_PIN_CSI1_D10 = _MXC_BUILD_NON_GPIO_PIN(0x19C, 0x584), + MX51_PIN_CSI1_D11 = _MXC_BUILD_NON_GPIO_PIN(0x1A0, 0x588), + MX51_PIN_CSI1_D12 = _MXC_BUILD_NON_GPIO_PIN(0x1A4, 0x58C), + MX51_PIN_CSI1_D13 = _MXC_BUILD_NON_GPIO_PIN(0x1A8, 0x590), + MX51_PIN_CSI1_D14 = _MXC_BUILD_NON_GPIO_PIN(0x1AC, 0x594), + MX51_PIN_CSI1_D15 = _MXC_BUILD_NON_GPIO_PIN(0x1B0, 0x598), + MX51_PIN_CSI1_D16 = _MXC_BUILD_NON_GPIO_PIN(0x1B4, 0x59C), + MX51_PIN_CSI1_D17 = _MXC_BUILD_NON_GPIO_PIN(0x1B8, 0x5A0), + MX51_PIN_CSI1_D18 = _MXC_BUILD_NON_GPIO_PIN(0x1BC, 0x5A4), + MX51_PIN_CSI1_D19 = _MXC_BUILD_NON_GPIO_PIN(0x1C0, 0x5A8), + MX51_PIN_CSI1_VSYNC = _MXC_BUILD_NON_GPIO_PIN(0x1C4, 0x5AC), + MX51_PIN_CSI1_HSYNC = _MXC_BUILD_NON_GPIO_PIN(0x1C8, 0x5B0), + MX51_PIN_CSI1_PIXCLK = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x5B4), + MX51_PIN_CSI1_MCLK = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x5B8), + MX51_PIN_CSI1_PKE0 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x860), + MX51_PIN_CSI2_D12 = _MXC_BUILD_GPIO_PIN(3, 9, 3, 0x1CC, 0x5BC), + MX51_PIN_CSI2_D13 = _MXC_BUILD_GPIO_PIN(3, 10, 3, 0x1D0, 0x5C0), + MX51_PIN_CSI2_D14 = _MXC_BUILD_GPIO_PIN(3, 11, 3, 0x1D4, 0x5C4), + MX51_PIN_CSI2_D15 = _MXC_BUILD_GPIO_PIN(3, 12, 3, 0x1D8, 0x5C8), + MX51_PIN_CSI2_D16 = _MXC_BUILD_GPIO_PIN(3, 11, 3, 0x1DC, 0x5CC), + MX51_PIN_CSI2_D17 = _MXC_BUILD_GPIO_PIN(3, 12, 3, 0x1E0, 0x5D0), + MX51_PIN_CSI2_D18 = _MXC_BUILD_GPIO_PIN(3, 11, 3, 0x1E4, 0x5D4), + MX51_PIN_CSI2_D19 = _MXC_BUILD_GPIO_PIN(3, 12, 3, 0x1E8, 0x5D8), + MX51_PIN_CSI2_VSYNC = _MXC_BUILD_GPIO_PIN(3, 13, 3, 0x1EC, 0x5DC), + MX51_PIN_CSI2_HSYNC = _MXC_BUILD_GPIO_PIN(3, 14, 3, 0x1F0, 0x5E0), + MX51_PIN_CSI2_PIXCLK = _MXC_BUILD_GPIO_PIN(3, 15, 3, 0x1F4, 0x5E4), + MX51_PIN_CSI2_PKE0 = _MXC_BUILD_NON_GPIO_PIN(NON_MUX_I, 0x81C), + MX51_PIN_I2C1_CLK = _MXC_BUILD_GPIO_PIN(3, 16, 3, 0x1F8, 0x5E8), + MX51_PIN_I2C1_DAT = _MXC_BUILD_GPIO_PIN(3, 17, 3, 0x1FC, 0x5EC), + MX51_PIN_AUD3_BB_TXD = _MXC_BUILD_GPIO_PIN(3, 18, 3, 0x200, 0x5F0), + MX51_PIN_AUD3_BB_RXD = _MXC_BUILD_GPIO_PIN(3, 19, 3, 0x204, 0x5F4), + MX51_PIN_AUD3_BB_CK = _MXC_BUILD_GPIO_PIN(3, 20, 3, 0x208, 0x5F8), + MX51_PIN_AUD3_BB_FS = _MXC_BUILD_GPIO_PIN(3, 21, 3, 0x20C, 0x5FC), + MX51_PIN_CSPI1_MOSI = _MXC_BUILD_GPIO_PIN(3, 22, 3, 0x210, 0x600), + MX51_PIN_CSPI1_MISO = _MXC_BUILD_GPIO_PIN(3, 23, 3, 0x214, 0x604), + MX51_PIN_CSPI1_SS0 = _MXC_BUILD_GPIO_PIN(3, 24, 3, 0x218, 0x608), + MX51_PIN_CSPI1_SS1 = _MXC_BUILD_GPIO_PIN(3, 25, 3, 0x21C, 0x60C), + MX51_PIN_CSPI1_RDY = _MXC_BUILD_GPIO_PIN(3, 26, 3, 0x220, 0x610), + MX51_PIN_CSPI1_SCLK = _MXC_BUILD_GPIO_PIN(3, 27, 3, 0x224, 0x614), + MX51_PIN_UART1_RXD = _MXC_BUILD_GPIO_PIN(3, 28, 3, 0x228, 0x618), + MX51_PIN_UART1_TXD = _MXC_BUILD_GPIO_PIN(3, 29, 3, 0x22C, 0x61C), + MX51_PIN_UART1_RTS = _MXC_BUILD_GPIO_PIN(3, 30, 3, 0x230, 0x620), + MX51_PIN_UART1_CTS = _MXC_BUILD_GPIO_PIN(3, 31, 3, 0x234, 0x624), + MX51_PIN_UART2_RXD = _MXC_BUILD_GPIO_PIN(0, 20, 3, 0x238, 0x628), + MX51_PIN_UART2_TXD = _MXC_BUILD_GPIO_PIN(0, 21, 3, 0x23C, 0x62C), + MX51_PIN_UART3_RXD = _MXC_BUILD_GPIO_PIN(0, 22, 3, 0x240, 0x630), + MX51_PIN_UART3_TXD = _MXC_BUILD_GPIO_PIN(0, 23, 3, 0x244, 0x634), + MX51_PIN_OWIRE_LINE = _MXC_BUILD_GPIO_PIN(0, 24, 3, 0x248, 0x638), + MX51_PIN_KEY_ROW0 = _MXC_BUILD_NON_GPIO_PIN(0x24C, 0x63C), + MX51_PIN_KEY_ROW1 = _MXC_BUILD_NON_GPIO_PIN(0x250, 0x640), + MX51_PIN_KEY_ROW2 = _MXC_BUILD_NON_GPIO_PIN(0x254, 0x644), + MX51_PIN_KEY_ROW3 = _MXC_BUILD_NON_GPIO_PIN(0x258, 0x648), + MX51_PIN_KEY_COL0 = _MXC_BUILD_NON_GPIO_PIN(0x25C, 0x64C), + MX51_PIN_KEY_COL1 = _MXC_BUILD_NON_GPIO_PIN(0x260, 0x650), + MX51_PIN_KEY_COL2 = _MXC_BUILD_NON_GPIO_PIN(0x264, 0x654), + MX51_PIN_KEY_COL3 = _MXC_BUILD_NON_GPIO_PIN(0x268, 0x658), + MX51_PIN_KEY_COL4 = _MXC_BUILD_NON_GPIO_PIN(0x26C, 0x65C), + MX51_PIN_KEY_COL5 = _MXC_BUILD_NON_GPIO_PIN(0x270, 0x660), + MX51_PIN_USBH1_CLK = _MXC_BUILD_GPIO_PIN(0, 25, 2, 0x278, 0x678), + MX51_PIN_USBH1_DIR = _MXC_BUILD_GPIO_PIN(0, 26, 2, 0x27C, 0x67C), + MX51_PIN_USBH1_STP = _MXC_BUILD_GPIO_PIN(0, 27, 2, 0x280, 0x680), + MX51_PIN_USBH1_NXT = _MXC_BUILD_GPIO_PIN(0, 28, 2, 0x284, 0x684), + MX51_PIN_USBH1_DATA0 = _MXC_BUILD_GPIO_PIN(0, 11, 2, 0x288, 0x688), + MX51_PIN_USBH1_DATA1 = _MXC_BUILD_GPIO_PIN(0, 12, 2, 0x28C, 0x68C), + MX51_PIN_USBH1_DATA2 = _MXC_BUILD_GPIO_PIN(0, 13, 2, 0x290, 0x690), + MX51_PIN_USBH1_DATA3 = _MXC_BUILD_GPIO_PIN(0, 14, 2, 0x294, 0x694), + MX51_PIN_USBH1_DATA4 = _MXC_BUILD_GPIO_PIN(0, 15, 2, 0x298, 0x698), + MX51_PIN_USBH1_DATA5 = _MXC_BUILD_GPIO_PIN(0, 16, 2, 0x29C, 0x69C), + MX51_PIN_USBH1_DATA6 = _MXC_BUILD_GPIO_PIN(0, 17, 2, 0x2A0, 0x6A0), + MX51_PIN_USBH1_DATA7 = _MXC_BUILD_GPIO_PIN(0, 18, 2, 0x2A4, 0x6A4), + MX51_PIN_DI1_PIN11 = _MXC_BUILD_GPIO_PIN(2, 0, 4, 0x2A8, 0x6A8), + MX51_PIN_DI1_PIN12 = _MXC_BUILD_GPIO_PIN(2, 1, 4, 0x2AC, 0x6AC), + MX51_PIN_DI1_PIN13 = _MXC_BUILD_GPIO_PIN(2, 2, 4, 0x2B0, 0x6B0), + MX51_PIN_DI1_D0_CS = _MXC_BUILD_GPIO_PIN(2, 3, 4, 0x2B4, 0x6B4), + MX51_PIN_DI1_D1_CS = _MXC_BUILD_GPIO_PIN(2, 4, 4, 0x2B8, 0x6B8), + MX51_PIN_DISPB2_SER_DIN = _MXC_BUILD_GPIO_PIN(2, 5, 4, 0x2BC, 0x6BC), + MX51_PIN_DISPB2_SER_DIO = _MXC_BUILD_GPIO_PIN(2, 6, 4, 0x2C0, 0x6C0), + MX51_PIN_DISPB2_SER_CLK = _MXC_BUILD_GPIO_PIN(2, 7, 4, 0x2C4, 0x6C4), + MX51_PIN_DISPB2_SER_RS = _MXC_BUILD_GPIO_PIN(2, 8, 4, 0x2C8, 0x6C8), + MX51_PIN_DISP1_DAT0 = _MXC_BUILD_NON_GPIO_PIN(0x2CC, 0x6CC), + MX51_PIN_DISP1_DAT1 = _MXC_BUILD_NON_GPIO_PIN(0x2D0, 0x6D0), + MX51_PIN_DISP1_DAT2 = _MXC_BUILD_NON_GPIO_PIN(0x2D4, 0x6D4), + MX51_PIN_DISP1_DAT3 = _MXC_BUILD_NON_GPIO_PIN(0x2D8, 0x6D8), + MX51_PIN_DISP1_DAT4 = _MXC_BUILD_NON_GPIO_PIN(0x2DC, 0x6DC), + MX51_PIN_DISP1_DAT5 = _MXC_BUILD_NON_GPIO_PIN(0x2E0, 0x6E0), + MX51_PIN_DISP1_DAT6 = _MXC_BUILD_NON_GPIO_PIN(0x2E4, 0x6E4), + MX51_PIN_DISP1_DAT7 = _MXC_BUILD_NON_GPIO_PIN(0x2E8, 0x6E8), + MX51_PIN_DISP1_DAT8 = _MXC_BUILD_NON_GPIO_PIN(0x2EC, 0x6EC), + MX51_PIN_DISP1_DAT9 = _MXC_BUILD_NON_GPIO_PIN(0x2F0, 0x6F0), + MX51_PIN_DISP1_DAT10 = _MXC_BUILD_NON_GPIO_PIN(0x2F4, 0x6F4), + MX51_PIN_DISP1_DAT11 = _MXC_BUILD_NON_GPIO_PIN(0x2F8, 0x6F8), + MX51_PIN_DISP1_DAT12 = _MXC_BUILD_NON_GPIO_PIN(0x2FC, 0x6FC), + MX51_PIN_DISP1_DAT13 = _MXC_BUILD_NON_GPIO_PIN(0x300, 0x700), + MX51_PIN_DISP1_DAT14 = _MXC_BUILD_NON_GPIO_PIN(0x304, 0x704), + MX51_PIN_DISP1_DAT15 = _MXC_BUILD_NON_GPIO_PIN(0x308, 0x708), + MX51_PIN_DISP1_DAT16 = _MXC_BUILD_NON_GPIO_PIN(0x30C, 0x70C), + MX51_PIN_DISP1_DAT17 = _MXC_BUILD_NON_GPIO_PIN(0x310, 0x710), + MX51_PIN_DISP1_DAT18 = _MXC_BUILD_NON_GPIO_PIN(0x314, 0x714), + MX51_PIN_DISP1_DAT19 = _MXC_BUILD_NON_GPIO_PIN(0x318, 0x718), + MX51_PIN_DISP1_DAT20 = _MXC_BUILD_NON_GPIO_PIN(0x31C, 0x71C), + MX51_PIN_DISP1_DAT21 = _MXC_BUILD_NON_GPIO_PIN(0x320, 0x720), + MX51_PIN_DISP1_DAT22 = _MXC_BUILD_NON_GPIO_PIN(0x324, 0x724), + MX51_PIN_DISP1_DAT23 = _MXC_BUILD_NON_GPIO_PIN(0x328, 0x728), + MX51_PIN_DI1_PIN3 = _MXC_BUILD_NON_GPIO_PIN(0x32C, 0x72C), + MX51_PIN_DI1_PIN2 = _MXC_BUILD_NON_GPIO_PIN(0x330, 0x734), + MX51_PIN_DI_GP1 = _MXC_BUILD_NON_GPIO_PIN(0x334, 0x73C), + MX51_PIN_DI_GP2 = _MXC_BUILD_NON_GPIO_PIN(0x338, 0x740), + MX51_PIN_DI_GP3 = _MXC_BUILD_NON_GPIO_PIN(0x33C, 0x744), + MX51_PIN_DI2_PIN4 = _MXC_BUILD_NON_GPIO_PIN(0x340, 0x748), + MX51_PIN_DI2_PIN2 = _MXC_BUILD_NON_GPIO_PIN(0x344, 0x74C), + MX51_PIN_DI2_PIN3 = _MXC_BUILD_NON_GPIO_PIN(0x348, 0x750), + MX51_PIN_DI2_DISP_CLK = _MXC_BUILD_NON_GPIO_PIN(0x34C, 0x754), + MX51_PIN_DI_GP4 = _MXC_BUILD_NON_GPIO_PIN(0x350, 0x758), + MX51_PIN_DISP2_DAT0 = _MXC_BUILD_NON_GPIO_PIN(0x354, 0x75C), + MX51_PIN_DISP2_DAT1 = _MXC_BUILD_NON_GPIO_PIN(0x358, 0x760), + MX51_PIN_DISP2_DAT2 = _MXC_BUILD_NON_GPIO_PIN(0x35C, 0x764), + MX51_PIN_DISP2_DAT3 = _MXC_BUILD_NON_GPIO_PIN(0x360, 0x768), + MX51_PIN_DISP2_DAT4 = _MXC_BUILD_NON_GPIO_PIN(0x364, 0x76C), + MX51_PIN_DISP2_DAT5 = _MXC_BUILD_NON_GPIO_PIN(0x368, 0x770), + MX51_PIN_DISP2_DAT6 = _MXC_BUILD_GPIO_PIN(0, 19, 5, 0x36C, 0x774), + MX51_PIN_DISP2_DAT7 = _MXC_BUILD_GPIO_PIN(0, 29, 5, 0x370, 0x778), + MX51_PIN_DISP2_DAT8 = _MXC_BUILD_GPIO_PIN(0, 30, 5, 0x374, 0x77C), + MX51_PIN_DISP2_DAT9 = _MXC_BUILD_GPIO_PIN(0, 31, 5, 0x378, 0x780), + MX51_PIN_DISP2_DAT10 = _MXC_BUILD_NON_GPIO_PIN(0x37C, 0x784), + MX51_PIN_DISP2_DAT11 = _MXC_BUILD_NON_GPIO_PIN(0x380, 0x788), + MX51_PIN_DISP2_DAT12 = _MXC_BUILD_NON_GPIO_PIN(0x384, 0x78C), + MX51_PIN_DISP2_DAT13 = _MXC_BUILD_NON_GPIO_PIN(0x388, 0x790), + MX51_PIN_DISP2_DAT14 = _MXC_BUILD_NON_GPIO_PIN(0x38C, 0x794), + MX51_PIN_DISP2_DAT15 = _MXC_BUILD_NON_GPIO_PIN(0x390, 0x798), + MX51_PIN_SD1_CMD = _MXC_BUILD_NON_GPIO_PIN(0x394, 0x79C), + MX51_PIN_SD1_CLK = _MXC_BUILD_NON_GPIO_PIN(0x398, 0x7A0), + MX51_PIN_SD1_DATA0 = _MXC_BUILD_NON_GPIO_PIN(0x39C, 0x7A4), + MX51_PIN_SD1_DATA1 = _MXC_BUILD_NON_GPIO_PIN(0x3A0, 0x7A8), + MX51_PIN_SD1_DATA2 = _MXC_BUILD_NON_GPIO_PIN(0x3A4, 0x7AC), + MX51_PIN_SD1_DATA3 = _MXC_BUILD_NON_GPIO_PIN(0x3A8, 0x7B0), + MX51_PIN_GPIO1_0 = _MXC_BUILD_GPIO_PIN(0, 0, 1, 0x3AC, 0x7B4), + MX51_PIN_GPIO1_1 = _MXC_BUILD_GPIO_PIN(0, 1, 1, 0x3B0, 0x7B8), + MX51_PIN_SD2_CMD = _MXC_BUILD_NON_GPIO_PIN(0x3B4, 0x7BC), + MX51_PIN_SD2_CLK = _MXC_BUILD_NON_GPIO_PIN(0x3B8, 0x7C0), + MX51_PIN_SD2_DATA0 = _MXC_BUILD_NON_GPIO_PIN(0x3BC, 0x7C4), + MX51_PIN_SD2_DATA1 = _MXC_BUILD_NON_GPIO_PIN(0x3C0, 0x7C8), + MX51_PIN_SD2_DATA2 = _MXC_BUILD_NON_GPIO_PIN(0x3C4, 0x7CC), + MX51_PIN_SD2_DATA3 = _MXC_BUILD_NON_GPIO_PIN(0x3C8, 0x7D0), + MX51_PIN_GPIO1_2 = _MXC_BUILD_GPIO_PIN(0, 2, 0, 0x3CC, 0x7D4), + MX51_PIN_GPIO1_3 = _MXC_BUILD_GPIO_PIN(0, 3, 0, 0x3D0, 0x7D8), + MX51_PIN_PMIC_INT_REQ = _MXC_BUILD_NON_GPIO_PIN(0x3D4, 0x7FC), + MX51_PIN_GPIO1_4 = _MXC_BUILD_GPIO_PIN(0, 4, 0, 0x3D8, 0x804), + MX51_PIN_GPIO1_5 = _MXC_BUILD_GPIO_PIN(0, 5, 0, 0x3DC, 0x808), + MX51_PIN_GPIO1_6 = _MXC_BUILD_GPIO_PIN(0, 6, 0, 0x3E0, 0x80C), + MX51_PIN_GPIO1_7 = _MXC_BUILD_GPIO_PIN(0, 7, 0, 0x3E4, 0x810), + MX51_PIN_GPIO1_8 = _MXC_BUILD_GPIO_PIN(0, 8, 0, 0x3E8, 0x814), + MX51_PIN_GPIO1_9 = _MXC_BUILD_GPIO_PIN(0, 9, 0, 0x3EC, 0x818), +}; + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_ARCH_MXC_MX51_PINS_H__ */

The patch adds support for the Freescale mx51 processor.
Signed-off-by: Stefano Babic sbabic@denx.de Signed-off-by: Fred Fan fanyefeng@gmail.com --- drivers/serial/serial_mxc.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-)
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c index acc5b7d..e34733b 100644 --- a/drivers/serial/serial_mxc.c +++ b/drivers/serial/serial_mxc.c @@ -20,6 +20,8 @@ #include <common.h> #ifdef CONFIG_MX31 #include <asm/arch/mx31.h> +#elif defined(CONFIG_MX51) +#include <asm/arch/imx-regs.h> #else #include <asm/arch/imx-regs.h> #include <asm/arch/clock.h> @@ -49,8 +51,14 @@ #define UART_PHYS 0x1001b000 #elif defined(CONFIG_SYS_MX27_UART6) #define UART_PHYS 0x1001c000 +#elif defined(CONFIG_SYS_MX51_UART1) +#define UART_PHYS UART1_BASE_ADDR +#elif defined(CONFIG_SYS_MX51_UART2) +#define UART_PHYS UART2_BASE_ADDR +#elif defined(CONFIG_SYS_MX51_UART3) +#define UART_PHYS UART3_BASE_ADDR #else -#error "define CONFIG_SYS_MX31_UARTx to use the mx31 UART driver" +#error "define CONFIG_SYS_MXxx_UARTx to use the mxxx UART driver" #endif
/* Register definitions */ @@ -168,6 +176,8 @@ void serial_setbrg (void) { #ifdef CONFIG_MX31 u32 clk = mx31_get_ipg_clk(); +#elif defined(CONFIG_MX51) + u32 clk = mxc_get_clock(MXC_UART_CLK); #else u32 clk = imx_get_perclk1(); #endif

The patch add support for the Freescale mx51 processor to the FEC ethernet driver.
Signed-off-by: Stefano Babic sbabic@denx.de --- drivers/net/fec_mxc.c | 57 ++++++++++++++++++++++++++++++------------------- 1 files changed, 35 insertions(+), 22 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 19116f2..203832e 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -27,8 +27,10 @@ #include <miiphy.h> #include "fec_mxc.h"
-#include <asm/arch/clock.h> #include <asm/arch/imx-regs.h> +#ifndef CONFIG_MX51 +#include <asm/arch/clock.h> +#endif #include <asm/io.h> #include <asm/errno.h>
@@ -108,6 +110,23 @@ static int fec_miiphy_read(char *dev, uint8_t phyAddr, uint8_t regAddr, return 0; }
+static void fec_mii_setspeed(struct fec_priv *fec) +{ +#ifdef CONFIG_MX51 + writel((((mxc_get_clock(MXC_IPG_CLK) + 499999) / 5000000) << 1), + &fec->eth->mii_speed); +#else + /* + * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock + * and do not drop the Preamble. + */ + writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1, + &fec->eth->mii_speed); + debug("fec_init: mii_speed %#lx\n", + (((imx_get_ahbclk() / 1000000) + 2) / 5) << 1); +#endif + +} static int fec_miiphy_write(char *dev, uint8_t phyAddr, uint8_t regAddr, uint16_t data) { @@ -236,7 +255,7 @@ static int fec_rbd_init(struct fec_priv *fec, int count, int size) fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT); p = (uint32_t)fec->rdb_ptr; if (!p) { - puts("fec_imx27: not enough malloc memory!\n"); + puts("fec_mxc: not enough malloc memory!\n"); return -ENOMEM; } memset((void *)p, 0, size * count + DB_DATA_ALIGNMENT); @@ -299,6 +318,7 @@ static void fec_rbd_clean(int last, struct fec_bd *pRbd)
static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac) { +#ifndef CONFIG_MX51 struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; int i;
@@ -306,6 +326,9 @@ static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac) mac[6-1-i] = readl(&iim->iim_bank_area0[IIM0_MAC + i]);
return is_valid_ether_addr(mac); +#else + return -1; +#endif }
static int fec_set_hwaddr(struct eth_device *dev, unsigned char *mac) @@ -373,7 +396,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd) sizeof(struct fec_bd) + DB_ALIGNMENT); base = (uint32_t)fec->base_ptr; if (!base) { - puts("fec_imx27: not enough malloc memory!\n"); + puts("fec_mxc: not enough malloc memory!\n"); return -ENOMEM; } memset((void *)base, 0, (2 + FEC_RBD_NUM) * @@ -411,14 +434,8 @@ static int fec_init(struct eth_device *dev, bd_t* bd) * Frame length=1518; MII mode; */ writel(0x05ee0024, &fec->eth->r_cntrl); /* FIXME 0x05ee0004 */ - /* - * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock - * and do not drop the Preamble. - */ - writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1, - &fec->eth->mii_speed); - debug("fec_init: mii_speed %#lx\n", - (((imx_get_ahbclk() / 1000000) + 2) / 5) << 1); + + fec_mii_setspeed(fec); } /* * Set Opcode/Pause Duration Register @@ -651,22 +668,24 @@ static int fec_recv(struct eth_device *dev)
static int fec_probe(bd_t *bd) { - struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; struct eth_device *edev; struct fec_priv *fec = &gfec; unsigned char ethaddr_str[20]; unsigned char ethaddr[6]; - char *tmp = getenv("ethaddr"); + char *tmp; char *end; +#ifndef CONFIG_MX51 + struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
/* enable FEC clock */ writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0); +#endif
/* create and fill edev struct */ edev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!edev) { - puts("fec_imx27: not enough malloc memory!\n"); + puts("fec_mxc: not enough malloc memory!\n"); return -ENOMEM; } edev->priv = fec; @@ -702,14 +721,7 @@ static int fec_probe(bd_t *bd) * Frame length=1518; MII mode; */ writel(0x05ee0024, &fec->eth->r_cntrl); /* FIXME 0x05ee0004 */ - /* - * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock - * and do not drop the Preamble. - */ - writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1, - &fec->eth->mii_speed); - debug("fec_init: mii_speed %#lx\n", - (((imx_get_ahbclk() / 1000000) + 2) / 5) << 1); + fec_mii_setspeed(fec);
sprintf(edev->name, "FEC_MXC");
@@ -717,6 +729,7 @@ static int fec_probe(bd_t *bd)
eth_register(edev);
+ tmp = getenv("ethaddr"); if ((NULL != tmp) && (12 <= strlen(tmp))) { int i; /* convert MAC from string to int */

The esdhc controller in the mx51 processor is quite the same as the one in some powerpc processors (MPC83xx, MPC85xx). This patches adapts the driver to support the arm mx51.
Signed-off-by: Stefano Babic sbabic@denx.de --- drivers/mmc/fsl_esdhc.c | 72 +++++++++++++++++++++++++++++++++++++++------- include/asm-arm/io.h | 21 +++++++++++++ include/fsl_esdhc.h | 6 +++- include/mmc.h | 1 + 4 files changed, 88 insertions(+), 12 deletions(-)
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index c6e9e6e..5dcf6a8 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -37,6 +37,10 @@ #include <fdt_support.h> #include <asm/io.h>
+#ifndef CONFIG_PPC +#define out_be32(a,v) writel(v,a) +#define in_be32(a) __raw_readl(a) +#endif
DECLARE_GLOBAL_DATA_PTR;
@@ -129,7 +133,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) out_be32(®s->blkattr, data->blocks << 16 | data->blocksize);
/* Calculate the timeout period for data transactions */ - timeout = __ilog2(mmc->tran_speed/10); + timeout = fls(mmc->tran_speed/10) - 1; timeout -= 13;
if (timeout > 14) @@ -236,11 +240,18 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
void set_sysctl(struct mmc *mmc, uint clock) { +#ifdef CONFIG_PPC int sdhc_clk = gd->sdhc_clk; +#else + int sdhc_clk = mxc_get_clock(MXC_IPG_PERCLK); +#endif int div, pre_div; volatile struct fsl_esdhc *regs = mmc->priv; uint clk;
+ if (clock < mmc->f_min) + clock = mmc->f_min; + if (sdhc_clk / 16 > clock) { for (pre_div = 2; pre_div < 256; pre_div *= 2) if ((sdhc_clk / pre_div) <= (clock * 16)) @@ -257,11 +268,14 @@ void set_sysctl(struct mmc *mmc, uint clock)
clk = (pre_div << 8) | (div << 4);
+ /* On imx the clock must be stopped before changing frequency */ + clrbits_be32(®s->sysctl, SYSCTL_CKEN); + clrsetbits_be32(®s->sysctl, SYSCTL_CLOCK_MASK, clk);
udelay(10000);
- setbits_be32(®s->sysctl, SYSCTL_PEREN); + setbits_be32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); }
static void esdhc_set_ios(struct mmc *mmc) @@ -278,15 +292,26 @@ static void esdhc_set_ios(struct mmc *mmc) setbits_be32(®s->proctl, PROCTL_DTW_4); else if (mmc->bus_width == 8) setbits_be32(®s->proctl, PROCTL_DTW_8); + }
static int esdhc_init(struct mmc *mmc) { struct fsl_esdhc *regs = mmc->priv; int timeout = 1000; + int ret = 0;
+#ifdef CONFIG_PPC /* Enable cache snooping */ out_be32(®s->scr, 0x00000040); +#endif + + /* Reset the entire host controller */ + out_be32(®s->sysctl, SYSCTL_RSTA); + + /* Wait until the controller is available */ + while ((in_be32(®s->sysctl) & SYSCTL_RSTA) && --timeout) + udelay(1000);
out_be32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
@@ -299,24 +324,44 @@ static int esdhc_init(struct mmc *mmc) /* Put the PROCTL reg back to the default */ out_be32(®s->proctl, PROCTL_INIT);
- while (!(in_be32(®s->prsstat) & PRSSTAT_CINS) && --timeout) - udelay(1000); + /* Set timout to the maximum value */ + clrsetbits_be32(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
- if (timeout <= 0) - return NO_CARD_ERR; + /* Check if there is a callback for detecting the card */ + if (!mmc->getcd) { + timeout = 1000; + while (!(in_be32(®s->prsstat) & PRSSTAT_CINS) && --timeout) + udelay(1000);
- return 0; + if (timeout <= 0) + ret = NO_CARD_ERR; + } else { + if (mmc->getcd(mmc)) + ret = NO_CARD_ERR; + } + + return ret; }
-static int esdhc_initialize(bd_t *bis) +int fsl_esdhc_initialize(bd_t *bis, uint32_t esdhc_addr, int (*getcd)(struct mmc *mmc)) { - struct fsl_esdhc *regs = (struct fsl_esdhc *)CONFIG_SYS_FSL_ESDHC_ADDR; +#ifdef CONFIG_PPC + int sdhc_clk = gd->sdhc_clk; +#else + int sdhc_clk = mxc_get_clock(MXC_IPG_PERCLK); +#endif + struct fsl_esdhc *regs; struct mmc *mmc; u32 caps;
mmc = malloc(sizeof(struct mmc));
sprintf(mmc->name, "FSL_ESDHC"); + if (!esdhc_addr) { + regs = (struct fsl_esdhc *)CONFIG_SYS_FSL_ESDHC_ADDR; + } else { + regs = (struct fsl_esdhc *)esdhc_addr; + } mmc->priv = regs; mmc->send_cmd = esdhc_send_cmd; mmc->set_ios = esdhc_set_ios; @@ -337,7 +382,10 @@ static int esdhc_initialize(bd_t *bis) mmc->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
mmc->f_min = 400000; - mmc->f_max = MIN(gd->sdhc_clk, 50000000); + mmc->f_max = MIN(sdhc_clk, 50000000); + + if(getcd) + mmc->getcd = getcd;
mmc_register(mmc);
@@ -346,9 +394,10 @@ static int esdhc_initialize(bd_t *bis)
int fsl_esdhc_mmc_init(bd_t *bis) { - return esdhc_initialize(bis); + return fsl_esdhc_initialize(bis, 0, NULL); }
+#ifdef CONFIG_PPC void fdt_fixup_esdhc(void *blob, bd_t *bd) { const char *compat = "fsl,esdhc"; @@ -365,3 +414,4 @@ out: do_fixup_by_compat(blob, compat, "status", status, strlen(status) + 1, 1); } +#endif diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h index fec3a7e..fb104aa 100644 --- a/include/asm-arm/io.h +++ b/include/asm-arm/io.h @@ -33,6 +33,27 @@ static inline void sync(void) { }
+/* Clear and set bits in one shot. These macros can be used to clear and + * set multiple bits in a register using a single call. These macros can + * also be used to set a multiple-bit bit pattern using a mask, by + * specifying the mask in the 'clear' parameter and the new bit pattern + * in the 'set' parameter. + */ + +#define clrbits(type, addr, clear) \ + write##type(__raw_read##type(addr) & ~(clear), (addr)) + +#define setbits(type, addr, set) \ + write##type(__raw_read##type(addr) | (set), (addr)) + +#define clrsetbits(type, addr, clear, set) \ + write##type((__raw_read##type(addr) & ~(clear)) | (set), (addr)) + +#define clrbits_be32(addr, clear) clrbits(l, addr, clear) +#define setbits_be32(addr, set) setbits(l, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(l, addr, clear, set) + + /* * Given a physical address and a length, return a virtual address * that can be used to access the memory range with the caching diff --git a/include/fsl_esdhc.h b/include/fsl_esdhc.h index 89b8304..605e065 100644 --- a/include/fsl_esdhc.h +++ b/include/fsl_esdhc.h @@ -32,7 +32,9 @@ #define SYSCTL 0x0002e02c #define SYSCTL_INITA 0x08000000 #define SYSCTL_TIMEOUT_MASK 0x000f0000 -#define SYSCTL_CLOCK_MASK 0x00000fff +#define SYSCTL_CLOCK_MASK 0x0000ffff +#define SYSCTL_RSTA 0x01000000 +#define SYSCTL_CKEN 0x00000008 #define SYSCTL_PEREN 0x00000004 #define SYSCTL_HCKEN 0x00000002 #define SYSCTL_IPGEN 0x00000001 @@ -144,6 +146,8 @@
#ifdef CONFIG_FSL_ESDHC int fsl_esdhc_mmc_init(bd_t *bis); +int fsl_esdhc_initialize(bd_t *bis, uint32_t esdhc_addr, + int (*getcd)(struct mmc *mmc)); void fdt_fixup_esdhc(void *blob, bd_t *bd); #else static inline int fsl_esdhc_mmc_init(bd_t *bis) { return -ENOSYS; } diff --git a/include/mmc.h b/include/mmc.h index 2dc69ab..bc29953 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -264,6 +264,7 @@ struct mmc { struct mmc_cmd *cmd, struct mmc_data *data); void (*set_ios)(struct mmc *mmc); int (*init)(struct mmc *mmc); + int (*getcd)(struct mmc *mmc); };
int mmc_register(struct mmc *mmc);

Most cards do not answer if some reserved bits in the ocr are set. However, some controllers can set bit 7 (reserved for low voltages), but how to manage low voltages SD card is not yet specified.
Signed-off-by: Stefano Babic sbabic@denx.de --- drivers/mmc/mmc.c | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index b69ce15..d91b9b7 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -273,7 +273,15 @@ sd_send_op_cond(struct mmc *mmc)
cmd.cmdidx = SD_CMD_APP_SEND_OP_COND; cmd.resp_type = MMC_RSP_R3; - cmd.cmdarg = mmc->voltages; + + /* + * Most cards do not answer if some reserved bits + * in the ocr are set. However, Some controller + * can set bit 7 (reserved for low voltages), but + * how to manage low voltages SD card is not yet + * specified. + */ + cmd.cmdarg = mmc->voltages & 0xff8000;
if (mmc->version == SD_VERSION_2) cmd.cmdarg |= OCR_HCS;

The patch adds initial support for the Freescale mx51evk board. Network (FEC) and SD controller (fsl_esdhc) are supported.
Signed-off-by: Stefano Babic sbabic@denx.de Signed-off-by: Fred Fan fanyefeng@gmail.com --- MAINTAINERS | 4 + MAKEALL | 1 + Makefile | 8 + board/freescale/mx51evk/Makefile | 48 ++++ board/freescale/mx51evk/config.mk | 15 ++ board/freescale/mx51evk/imximage.cfg | 119 ++++++++++ board/freescale/mx51evk/mx51evk.c | 418 ++++++++++++++++++++++++++++++++++ board/freescale/mx51evk/mx51evk.h | 49 ++++ include/configs/mx51evk.h | 185 +++++++++++++++ 9 files changed, 847 insertions(+), 0 deletions(-) create mode 100644 board/freescale/mx51evk/Makefile create mode 100644 board/freescale/mx51evk/config.mk create mode 100644 board/freescale/mx51evk/imximage.cfg create mode 100644 board/freescale/mx51evk/mx51evk.c create mode 100644 board/freescale/mx51evk/mx51evk.h create mode 100644 include/configs/mx51evk.h
diff --git a/MAINTAINERS b/MAINTAINERS index 9734b1d..8637550 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -151,6 +151,10 @@ Dave Ellis DGE@sixnetio.com
SXNI855T MPC8xx
+Fred Fan fanyefeng@gmail.com + + mx51evk i.MX51 + Thomas Frieden ThomasF@hyperion-entertainment.com
AmigaOneG3SE MPC7xx diff --git a/MAKEALL b/MAKEALL index ab1bb6f..485107a 100755 --- a/MAKEALL +++ b/MAKEALL @@ -617,6 +617,7 @@ LIST_ARM11=" \ ######################################################################### LIST_ARM_CORTEX_A8=" \ devkit8000 \ + mx51evk \ omap3_beagle \ omap3_overo \ omap3_evm \ diff --git a/Makefile b/Makefile index ed6156f..01bf9a2 100644 --- a/Makefile +++ b/Makefile @@ -324,6 +324,10 @@ $(obj)u-boot.img: $(obj)u-boot.bin sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \ -d $< $@
+$(obj)u-boot.imx: $(obj)u-boot.bin + $(obj)tools/mkimage -n $(IMX_CONFIG) -T imximage \ + -e $(TEXT_BASE) -d $< $@ + $(obj)u-boot.kwb: $(obj)u-boot.bin $(obj)tools/mkimage -n $(KWD_CONFIG) -T kwbimage \ -a $(TEXT_BASE) -e $(TEXT_BASE) -d $< $@ @@ -3263,6 +3267,9 @@ mx31pdk_nand_config : unconfig fi @$(MKCONFIG) -a mx31pdk arm arm1136 mx31pdk freescale mx31
+mx51evk_config : unconfig + @$(MKCONFIG) $(@:_config=) arm arm_cortexa8 mx51evk freescale mx51 + omap2420h4_config : unconfig @$(MKCONFIG) $(@:_config=) arm arm1136 omap2420h4 ti omap24xx
@@ -3729,6 +3736,7 @@ clobber: clean $(obj)cscope.* $(obj)*.*~ @rm -f $(obj)u-boot $(obj)u-boot.map $(obj)u-boot.hex $(ALL) @rm -f $(obj)u-boot.kwb + @rm -f $(obj)u-boot.imx @rm -f $(obj)tools/{env/crc32.c,inca-swap-bytes} @rm -f $(obj)cpu/mpc824x/bedbug_603e.c @rm -f $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm diff --git a/board/freescale/mx51evk/Makefile b/board/freescale/mx51evk/Makefile new file mode 100644 index 0000000..eb12fc5 --- /dev/null +++ b/board/freescale/mx51evk/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2007, Guennadi Liakhovetski lg@denx.de +# +# (C) Copyright 2009 Freescale Semiconductor, Inc. +# +# 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).a + +COBJS := mx51evk.o + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +SOBJS := $(addprefix $(obj),$(SOBJS)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/freescale/mx51evk/config.mk b/board/freescale/mx51evk/config.mk new file mode 100644 index 0000000..fecfd5e --- /dev/null +++ b/board/freescale/mx51evk/config.mk @@ -0,0 +1,15 @@ +# +# Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. +# + +# +# The code contained herein is licensed under the GNU General Public +# License. You may obtain a copy of the GNU General Public License +# Version 2 or later at the following locations: +# +# http://www.opensource.org/licenses/gpl-license.html +# http://www.gnu.org/copyleft/gpl.html +# +LDSCRIPT = cpu/$(CPU)/$(SOC)/u-boot.lds +TEXT_BASE = 0x97800000 +IMX_CONFIG = $(SRCTREE)/board/$(BOARDDIR)/imximage.cfg diff --git a/board/freescale/mx51evk/imximage.cfg b/board/freescale/mx51evk/imximage.cfg new file mode 100644 index 0000000..8d13567 --- /dev/null +++ b/board/freescale/mx51evk/imximage.cfg @@ -0,0 +1,119 @@ +# +# (C Copyright 2009 +# Stefano Babic DENX Software Engineering sbabic@denx.de. +# +# 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. 51 Franklin Street Fifth Floor Boston, +# MA 02110-1301 USA +# +# Refer docs/README.imxmage for more details about how-to configure +# and create imximage boot image +# +# The syntax is taken as close as possible with the kwbimage + +# Boot Device : one of +# spi_flash, nand, onenand, sd_card + +BOOT_FROM spi + +# Device Configuration Data (DCD) +# +# Each entry must have the format: +# Addr-type Address Value +# +# where: +# Addr-type register length (1,2 or 4 bytes) +# Address absolute address of the register +# value value to be stored in the register + +# Setting IOMUXC +DATA 4 0x73FA88a0 0x200 +DATA 4 0x73FA850c 0x20c5 +DATA 4 0x73FA8510 0x20c5 +DATA 4 0x73FA883c 0x2 +DATA 4 0x73FA8848 0x2 +DATA 4 0x73FA84b8 0xe7 +DATA 4 0x73FA84bc 0x45 +DATA 4 0x73FA84c0 0x45 +DATA 4 0x73FA84c4 0x45 +DATA 4 0x73FA84c8 0x45 +DATA 4 0x73FA8820 0x0 +DATA 4 0x73FA84a4 0x3 +DATA 4 0x73FA84a8 0x3 +DATA 4 0x73FA84ac 0xe3 +DATA 4 0x73FA84b0 0xe3 +DATA 4 0x73FA84b4 0xe3 +DATA 4 0x73FA84cc 0xe3 +DATA 4 0x73FA84d0 0xe2 + +DATA 4 0x73FA882c 0x6 +DATA 4 0x73FA88a4 0x6 +DATA 4 0x73FA88ac 0x6 +DATA 4 0x73FA88b8 0x6 + +# Setting DDR for micron +# 13 Rows, 10 Cols, 32 bit, SREF=4 Micron Model +# CAS=3 BL=4 +# ESDCTL_ESDCTL0 +DATA 4 0x83FD9000 0x82a20000 +# ESDCTL_ESDCTL1 +DATA 4 0x83FD9008 0x82a20000 +# ESDCTL_ESDMISC +DATA 4 0x83FD9010 0x000ad0d0 +# ESDCTL_ESDCFG0 +DATA 4 0x83FD9004 0x333574aa +# ESDCTL_ESDCFG1 +DATA 4 0x83FD900C 0x333574aa + +# Init DRAM on CS0 +# ESDCTL_ESDSCR +DATA 4 0x83FD9014 0x04008008 +DATA 4 0x83FD9014 0x0000801a +DATA 4 0x83FD9014 0x0000801b +DATA 4 0x83FD9014 0x00448019 +DATA 4 0x83FD9014 0x07328018 +DATA 4 0x83FD9014 0x04008008 +DATA 4 0x83FD9014 0x00008010 +DATA 4 0x83FD9014 0x00008010 +DATA 4 0x83FD9014 0x06328018 +DATA 4 0x83FD9014 0x03808019 +DATA 4 0x83FD9014 0x00408019 +DATA 4 0x83FD9014 0x00008000 + +# Init DRAM on CS1 +DATA 4 0x83FD9014 0x0400800c +DATA 4 0x83FD9014 0x0000801e +DATA 4 0x83FD9014 0x0000801f +DATA 4 0x83FD9014 0x0000801d +DATA 4 0x83FD9014 0x0732801c +DATA 4 0x83FD9014 0x0400800c +DATA 4 0x83FD9014 0x00008014 +DATA 4 0x83FD9014 0x00008014 +DATA 4 0x83FD9014 0x0632801c +DATA 4 0x83FD9014 0x0380801d +DATA 4 0x83FD9014 0x0040801d +DATA 4 0x83FD9014 0x00008004 + +# Write to CTL0 +DATA 4 0x83FD9000 0xb2a20000 +# Write to CTL1 +DATA 4 0x83FD9008 0xb2a20000 +# ESDMISC +DATA 4 0x83FD9010 0x000ad6d0 +#ESDCTL_ESDCDLYGD +DATA 4 0x83FD9034 0x90000000 +DATA 4 0x83FD9014 0x00000000 diff --git a/board/freescale/mx51evk/mx51evk.c b/board/freescale/mx51evk/mx51evk.c new file mode 100644 index 0000000..dbf959d --- /dev/null +++ b/board/freescale/mx51evk/mx51evk.c @@ -0,0 +1,418 @@ +/* + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/mx51_pins.h> +#include <asm/arch/iomux.h> +#include <asm/errno.h> +#include <i2c.h> +#include <mmc.h> +#include <fsl_esdhc.h> +#include "mx51evk.h" + +DECLARE_GLOBAL_DATA_PTR; + +static u32 system_rev; +struct io_board_ctrl *mx51_io_board; + +u32 get_board_rev(void) +{ + return system_rev; +} + +static inline void setup_soc_rev(void) +{ + int reg; + + reg = __raw_readl(ROM_SI_REV); + switch (reg) { + case 0x02: + system_rev = 0x51000 | CHIP_REV_1_1; + break; + case 0x10: + if ((__raw_readl(GPIO1_BASE_ADDR + 0x0) & (0x1 << 22)) == 0) + system_rev = 0x51000 | CHIP_REV_2_5; + else + system_rev = 0x51000 | CHIP_REV_2_0; + break; + default: + system_rev = 0x51000 | CHIP_REV_1_0; + break; + } +} + +static inline void set_board_rev(int rev) +{ + system_rev |= (rev & 0xF) << 8; +} + +inline int is_soc_rev(int rev) +{ + return (system_rev & 0xFF) - rev; +} + +int dram_init(void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE); + return 0; +} + +static void setup_uart(void) +{ + unsigned int pad = PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE | + PAD_CTL_PUE_PULL | PAD_CTL_DRV_HIGH; + + mxc_request_iomux(MX51_PIN_UART1_RXD, IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_UART1_RXD, pad | PAD_CTL_SRE_FAST); + mxc_request_iomux(MX51_PIN_UART1_TXD, IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_UART1_TXD, pad | PAD_CTL_SRE_FAST); + mxc_request_iomux(MX51_PIN_UART1_RTS, IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_UART1_RTS, pad); + mxc_request_iomux(MX51_PIN_UART1_CTS, IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_UART1_CTS, pad); +} + +static void setup_expio(void) +{ + u32 reg; + + /* CS5 setup */ + mxc_request_iomux(MX51_PIN_EIM_CS5, IOMUX_CONFIG_ALT0); + writel(0x00410089, WEIM_BASE_ADDR + 0x78 + CSGCR1); + writel(0x00000002, WEIM_BASE_ADDR + 0x78 + CSGCR2); + /* RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0 */ + writel(0x32260000, WEIM_BASE_ADDR + 0x78 + CSRCR1); + /* APR = 0 */ + writel(0x00000000, WEIM_BASE_ADDR + 0x78 + CSRCR2); + /* + * WAL=0, WBED=1, WWSC=50, WADVA=2, WADVN=6, WEA=0, WEN=0, + * WCSA=0, WCSN=0 + */ + writel(0x72080F00, WEIM_BASE_ADDR + 0x78 + CSWCR1); + + mx51_io_board = (struct io_board_ctrl *)(CS5_BASE_ADDR + + IO_BOARD_OFFSET); + if ((readw(&mx51_io_board->id1) == 0xAAAA) && + (readw(&mx51_io_board->id2) == 0x5555)) { + if (is_soc_rev(CHIP_REV_2_0) < 0) { + reg = readl(CCM_BASE_ADDR + CLKCTL_CBCDR); + reg = (reg & (~0x70000)) | 0x30000; + writel(reg, CCM_BASE_ADDR + CLKCTL_CBCDR); + /* make sure divider effective */ + while (readl(CCM_BASE_ADDR + CLKCTL_CDHIPR) != 0) + ; + writel(0x0, CCM_BASE_ADDR + CLKCTL_CCDR); + } + } else { + /* CS1 */ + writel(0x00410089, WEIM_BASE_ADDR + 0x18 + CSGCR1); + writel(0x00000002, WEIM_BASE_ADDR + 0x18 + CSGCR2); + /* RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0 */ + writel(0x32260000, WEIM_BASE_ADDR + 0x18 + CSRCR1); + /* APR=0 */ + writel(0x00000000, WEIM_BASE_ADDR + 0x18 + CSRCR2); + /* WAL=0, WBED=1, WWSC=50, WADVA=2, WADVN=6, WEA=0, + * WEN=0, WCSA=0, WCSN=0 + */ + writel(0x72080F00, WEIM_BASE_ADDR + 0x18 + CSWCR1); + mx51_io_board = (struct io_board_ctrl *)(CS1_BASE_ADDR + + IO_BOARD_OFFSET); + } + + /* Reset interrupt status reg */ + writew(0x1F, &(mx51_io_board->int_rest)); + writew(0x00, &(mx51_io_board->int_rest)); + writew(0xFFFF, &(mx51_io_board->int_mask)); + + /* Reset the XUART and Ethernet controllers */ + reg = readw(&(mx51_io_board->sw_reset)); + reg |= 0x9; + writew(reg, &(mx51_io_board->sw_reset)); + reg &= ~0x9; + writew(reg, &(mx51_io_board->sw_reset)); +} + +static void setup_fec(void) +{ + /*FEC_MDIO*/ + mxc_request_iomux(MX51_PIN_EIM_EB2 , IOMUX_CONFIG_ALT3); + mxc_iomux_set_pad(MX51_PIN_EIM_EB2 , 0x1FD); + + /*FEC_MDC*/ + mxc_request_iomux(MX51_PIN_NANDF_CS3, IOMUX_CONFIG_ALT2); + mxc_iomux_set_pad(MX51_PIN_NANDF_CS3, 0x2004); + + /* FEC RDATA[3] */ + mxc_request_iomux(MX51_PIN_EIM_CS3, IOMUX_CONFIG_ALT3); + mxc_iomux_set_pad(MX51_PIN_EIM_CS3, 0x180); + + /* FEC RDATA[2] */ + mxc_request_iomux(MX51_PIN_EIM_CS2, IOMUX_CONFIG_ALT3); + mxc_iomux_set_pad(MX51_PIN_EIM_CS2, 0x180); + + /* FEC RDATA[1] */ + mxc_request_iomux(MX51_PIN_EIM_EB3, IOMUX_CONFIG_ALT3); + mxc_iomux_set_pad(MX51_PIN_EIM_EB3, 0x180); + + /* FEC RDATA[0] */ + mxc_request_iomux(MX51_PIN_NANDF_D9, IOMUX_CONFIG_ALT2); + mxc_iomux_set_pad(MX51_PIN_NANDF_D9, 0x2180); + + /* FEC TDATA[3] */ + mxc_request_iomux(MX51_PIN_NANDF_CS6, IOMUX_CONFIG_ALT2); + mxc_iomux_set_pad(MX51_PIN_NANDF_CS6, 0x2004); + + /* FEC TDATA[2] */ + mxc_request_iomux(MX51_PIN_NANDF_CS5, IOMUX_CONFIG_ALT2); + mxc_iomux_set_pad(MX51_PIN_NANDF_CS5, 0x2004); + + /* FEC TDATA[1] */ + mxc_request_iomux(MX51_PIN_NANDF_CS4, IOMUX_CONFIG_ALT2); + mxc_iomux_set_pad(MX51_PIN_NANDF_CS4, 0x2004); + + /* FEC TDATA[0] */ + mxc_request_iomux(MX51_PIN_NANDF_D8, IOMUX_CONFIG_ALT2); + mxc_iomux_set_pad(MX51_PIN_NANDF_D8, 0x2004); + + /* FEC TX_EN */ + mxc_request_iomux(MX51_PIN_NANDF_CS7, IOMUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX51_PIN_NANDF_CS7, 0x2004); + + /* FEC TX_ER */ + mxc_request_iomux(MX51_PIN_NANDF_CS2, IOMUX_CONFIG_ALT2); + mxc_iomux_set_pad(MX51_PIN_NANDF_CS2, 0x2004); + + /* FEC TX_CLK */ + mxc_request_iomux(MX51_PIN_NANDF_RDY_INT, IOMUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX51_PIN_NANDF_RDY_INT, 0x2180); + + /* FEC TX_COL */ + mxc_request_iomux(MX51_PIN_NANDF_RB2, IOMUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX51_PIN_NANDF_RB2, 0x2180); + + /* FEC RX_CLK */ + mxc_request_iomux(MX51_PIN_NANDF_RB3, IOMUX_CONFIG_ALT1); + mxc_iomux_set_pad(MX51_PIN_NANDF_RB3, 0x2180); + + /* FEC RX_CRS */ + mxc_request_iomux(MX51_PIN_EIM_CS5, IOMUX_CONFIG_ALT3); + mxc_iomux_set_pad(MX51_PIN_EIM_CS5, 0x180); + + /* FEC RX_ER */ + mxc_request_iomux(MX51_PIN_EIM_CS4, IOMUX_CONFIG_ALT3); + mxc_iomux_set_pad(MX51_PIN_EIM_CS4, 0x180); + + /* FEC RX_DV */ + mxc_request_iomux(MX51_PIN_NANDF_D11, IOMUX_CONFIG_ALT2); + mxc_iomux_set_pad(MX51_PIN_NANDF_D11, 0x2180); +} + +#ifdef CONFIG_NET_MULTI +int board_eth_init(bd_t *bis) +{ + int rc = -ENODEV; + +#ifdef CONFIG_FEC_MXC + rc = fecmxc_initialize(bis); +#endif + return rc; +} +#endif + +#ifdef CONFIG_FSL_ESDHC +int get_mmc_cd(struct mmc *mmc) +{ + uint32_t reg_base = (uint32_t)mmc->priv; + int ret; + + if (reg_base == MMC_SDHC1_BASE_ADDR) { + ret = readl(GPIO1_BASE_ADDR) & 0x01; + } else { + ret = readl(GPIO1_BASE_ADDR) & 0x40; + } + + return ret; +} + +int board_mmc_init(bd_t *bis) +{ + u32 interface_esdhc = 0; + s32 status = 0; + u32 esdhc_base_pointer; + + for (interface_esdhc = 0; interface_esdhc < CONFIG_SYS_FSL_ESDHC_NUM; interface_esdhc++) { + switch (interface_esdhc) { + case 0: + esdhc_base_pointer = MMC_SDHC1_BASE_ADDR; + + mxc_request_iomux(MX51_PIN_SD1_CMD, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_request_iomux(MX51_PIN_SD1_CLK, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_request_iomux(MX51_PIN_SD1_DATA0, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_request_iomux(MX51_PIN_SD1_DATA1, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_request_iomux(MX51_PIN_SD1_DATA2, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_request_iomux(MX51_PIN_SD1_DATA3, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_iomux_set_pad(MX51_PIN_SD1_CMD, + PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | + PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | + PAD_CTL_PUE_PULL | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + mxc_iomux_set_pad(MX51_PIN_SD1_CLK, + PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | + PAD_CTL_HYS_NONE | PAD_CTL_47K_PU | + PAD_CTL_PUE_PULL | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + mxc_iomux_set_pad(MX51_PIN_SD1_DATA0, + PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | + PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | + PAD_CTL_PUE_PULL | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + mxc_iomux_set_pad(MX51_PIN_SD1_DATA1, + PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | + PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | + PAD_CTL_PUE_PULL | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + mxc_iomux_set_pad(MX51_PIN_SD1_DATA2, + PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | + PAD_CTL_HYS_ENABLE | PAD_CTL_47K_PU | + PAD_CTL_PUE_PULL | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + mxc_iomux_set_pad(MX51_PIN_SD1_DATA3, + PAD_CTL_DRV_MAX | PAD_CTL_DRV_VOT_HIGH | + PAD_CTL_HYS_ENABLE | PAD_CTL_100K_PD | + PAD_CTL_PUE_PULL | + PAD_CTL_PKE_ENABLE | PAD_CTL_SRE_FAST); + mxc_request_iomux(MX51_PIN_GPIO1_0, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_iomux_set_pad(MX51_PIN_GPIO1_0, + PAD_CTL_HYS_ENABLE); + mxc_request_iomux(MX51_PIN_GPIO1_1, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_iomux_set_pad(MX51_PIN_GPIO1_1, + PAD_CTL_HYS_ENABLE); + break; + case 1: + esdhc_base_pointer = MMC_SDHC2_BASE_ADDR; + + mxc_request_iomux(MX51_PIN_SD2_CMD, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_request_iomux(MX51_PIN_SD2_CLK, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_request_iomux(MX51_PIN_SD2_DATA0, + IOMUX_CONFIG_ALT0); + mxc_request_iomux(MX51_PIN_SD2_DATA1, + IOMUX_CONFIG_ALT0); + mxc_request_iomux(MX51_PIN_SD2_DATA2, + IOMUX_CONFIG_ALT0); + mxc_request_iomux(MX51_PIN_SD2_DATA3, + IOMUX_CONFIG_ALT0); + mxc_iomux_set_pad(MX51_PIN_SD2_CMD, + PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | + PAD_CTL_SRE_FAST); + mxc_iomux_set_pad(MX51_PIN_SD2_CLK, + PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | + PAD_CTL_SRE_FAST); + mxc_iomux_set_pad(MX51_PIN_SD2_DATA0, + PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | + PAD_CTL_SRE_FAST); + mxc_iomux_set_pad(MX51_PIN_SD2_DATA1, + PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | + PAD_CTL_SRE_FAST); + mxc_iomux_set_pad(MX51_PIN_SD2_DATA2, + PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | + PAD_CTL_SRE_FAST); + mxc_iomux_set_pad(MX51_PIN_SD2_DATA3, + PAD_CTL_DRV_MAX | PAD_CTL_22K_PU | + PAD_CTL_SRE_FAST); + mxc_request_iomux(MX51_PIN_SD2_CMD, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_request_iomux(MX51_PIN_GPIO1_6, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_iomux_set_pad(MX51_PIN_GPIO1_6, + PAD_CTL_HYS_ENABLE); + mxc_request_iomux(MX51_PIN_GPIO1_5, + IOMUX_CONFIG_ALT0 | IOMUX_CONFIG_SION); + mxc_iomux_set_pad(MX51_PIN_GPIO1_5, + PAD_CTL_HYS_ENABLE); + break; + } + status |= fsl_esdhc_initialize(bis, esdhc_base_pointer, get_mmc_cd); + } + return status; +} + +#endif + +int board_init(void) +{ + setup_soc_rev(); + + gd->bd->bi_arch_number = MACH_TYPE_MX51_BABBAGE; /* board id for linux */ + /* address of boot parameters */ + gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100; + + setup_uart(); + setup_expio(); + setup_fec(); + return 0; +} + +int checkboard(void) +{ + puts("Board: MX51 BABBAGE "); + + switch (system_rev & 0xff) { + case CHIP_REV_3_0: + puts("3.0 ["); + break; + case CHIP_REV_2_5: + puts("2.5 ["); + break; + case CHIP_REV_2_0: + puts("2.0 ["); + break; + case CHIP_REV_1_1: + puts("1.1 ["); + break; + case CHIP_REV_1_0: + default: + puts("1.0 ["); + break; + } + + switch (__raw_readl(SRC_BASE_ADDR + 0x8)) { + case 0x0001: + puts("POR"); + break; + case 0x0009: + puts("RST"); + break; + case 0x0010: + case 0x0011: + puts("WDOG"); + break; + default: + puts("unknown"); + } + puts("]\n"); + return 0; +} + diff --git a/board/freescale/mx51evk/mx51evk.h b/board/freescale/mx51evk/mx51evk.h new file mode 100644 index 0000000..fec886d --- /dev/null +++ b/board/freescale/mx51evk/mx51evk.h @@ -0,0 +1,49 @@ +/* + * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. + */ + +/* + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#ifndef __BOARD_FREESCALE_BOARD_MX51_BABBAGE_H__ +#define __BOARD_FREESCALE_BOARD_MX51_BABBAGE_H__ + +#ifndef __ASSEMBLY__ +struct io_board_ctrl { + u16 led_ctrl; /* 0x00 */ + u16 resv1[0x03]; + u16 sb_stat; /* 0x08 */ + u16 resv2[0x03]; + u16 int_stat; /* 0x10 */ + u16 resv3[0x07]; + u16 int_rest; /* 0x20 */ + u16 resv4[0x0B]; + u16 int_mask; /* 0x38 */ + u16 resv5[0x03]; + u16 id1; /* 0x40 */ + u16 resv6[0x03]; + u16 id2; /* 0x48 */ + u16 resv7[0x03]; + u16 version; /* 0x50 */ + u16 resv8[0x03]; + u16 id3; /* 0x58 */ + u16 resv9[0x03]; + u16 sw_reset; /* 0x60 */ +}; +#endif + +/* CPLD offsets */ +#define IO_BOARD_OFFSET (0x20000) +#define PBC_ID_AAAA (0x20040) +#define PBC_ID_5555 (0x20048) +#define PBC_INT_REST (0x20020) +#define PBC_INT_MASK (0x20038) +#define PBC_SW_RESET (0x20060) + +#endif /* __BOARD_FREESCALE_BOARD_MX51_BABBAGE_H__ */ diff --git a/include/configs/mx51evk.h b/include/configs/mx51evk.h new file mode 100644 index 0000000..c8b2970 --- /dev/null +++ b/include/configs/mx51evk.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2007, Guennadi Liakhovetski lg@denx.de + * + * (C) Copyright 2009 Freescale Semiconductor, Inc. + * + * Configuration settings for the MX51-3Stack Freescale board. + * + * 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 __CONFIG_H +#define __CONFIG_H + +#include <asm/arch/imx-regs.h> + + /* High Level Configuration Options */ +#define CONFIG_SYS_APCS_GNU +#define CONFIG_L2_OFF + +#define CONFIG_MX51 /* in a mx51 */ + +#define CONFIG_SKIP_RELOCATE_UBOOT + +#define CONFIG_MX51_HCLK_FREQ 24000000 /* RedBoot says 26MHz */ +#define CONFIG_MX51_CLK32 32768 +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_DISPLAY_BOARDINFO + +/* + * Disabled for now due to build problems under Debian and a significant + * increase in the final file size: 144260 vs. 109536 Bytes. + */ + +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_REVISION_TAG 1 +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG 1 + +/* + * Size of malloc() pool + */ +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 2 * 1024 * 1024) +/* size in bytes reserved for initial data */ +#define CONFIG_SYS_GBL_DATA_SIZE 128 + +/* + * Hardware drivers + */ +#define CONFIG_MXC_UART +#define CONFIG_SYS_MX51_UART1 + +/* + * MMC Configs + * */ +#define CONFIG_FSL_ESDHC +#define CONFIG_SYS_FSL_ESDHC_ADDR MMC_SDHC1_BASE_ADDR +#define CONFIG_SYS_FSL_ESDHC_NUM 2 + +#define CONFIG_MMC + +#define CONFIG_CMD_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_CMD_FAT +#define CONFIG_DOS_PARTITION + +/* + * Eth Configs + */ +#define CONFIG_HAS_ETH1 +#define CONFIG_NET_MULTI +#define CONFIG_MII +#define CONFIG_DISCOVER_PHY + +#define CONFIG_FEC_MXC +#define IMX_FEC_BASE FEC_BASE_ADDR +#define CONFIG_FEC_MXC_PHYADDR 0x1F + +#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_MII +#define CONFIG_CMD_NET + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SYS_BAUDRATE_TABLE {9600, 19200, 38400, 57600, 115200} + +/*********************************************************** + * Command definition + ***********************************************************/ + +#include <config_cmd_default.h> + +#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#undef CONFIG_CMD_IMLS + +#define CONFIG_BOOTDELAY 3 + +#define CONFIG_PRIME "FEC0" + +#define CONFIG_LOADADDR 0x90800000 /* loadaddr env var */ + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "netdev=eth0\0" \ + "uboot_addr=0xa0000000\0" \ + "uboot=u-boot.bin\0" \ + "loadaddr=0x90800000\0" \ + "bootargs_base=setenv bootargs console= tty console=ttymxc0,${baudrate}\0"\ + "bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs "\ + "ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp\0"\ + "bootcmd=run bootcmd_net\0" \ + "bootcmd_net=run bootargs_base bootargs_nfs; " \ + "tftpboot ${loadaddr} ${kernel}; bootm\0" + +/* + * The MX51 3stack board seems to have a hardware "peculiarity" confirmed under + * U-Boot, RedBoot and Linux: the ethernet Rx signal is reaching the CS8900A + * controller inverted. The controller is capable of detecting and correcting + * this, but it needs 4 network packets for that. Which means, at startup, you + * will not receive answers to the first 4 packest, unless there have been some + * broadcasts on the network, or your board is on a hub. Reducing the ARP + * timeout from default 5 seconds to 200ms we speed up the initial TFTP + * transfer, should the user wish one, significantly. + */ +#define CONFIG_ARP_TIMEOUT 200UL + +/* + * Miscellaneous configurable options + */ +#define CONFIG_SYS_LONGHELP /* undef to save memory */ +#define CONFIG_SYS_PROMPT "BBG U-Boot > " +#define CONFIG_AUTO_COMPLETE +#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */ +/* Print Buffer Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_MAXARGS 16 /* max number of command args */ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */ + +#define CONFIG_SYS_MEMTEST_START CSD0_BASE_ADDR +#define CONFIG_SYS_MEMTEST_END 0x10000 + +#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR + +#define CONFIG_SYS_HZ 1000 +#define CONFIG_CMDLINE_EDITING + +/*----------------------------------------------------------------------- + * Stack sizes + * + * The stack sizes are set up in start.S using the settings below + */ +#define CONFIG_STACKSIZE (128 * 1024) /* regular stack */ + +/*----------------------------------------------------------------------- + * Physical Memory Map + */ +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM_1 CSD0_BASE_ADDR +#define PHYS_SDRAM_1_SIZE (512 * 1024 * 1024) + +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ +#define CONFIG_SYS_NO_FLASH + +#define CONFIG_ENV_SECT_SIZE (128 * 1024) +#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE +#define CONFIG_ENV_IS_NOWHERE + +#endif /* __CONFIG_H */

Hi Stefano,
--- On Mon, 1/11/10, Stefano Babic sbabic@denx.de wrote:
From: Stefano Babic sbabic@denx.de Subject: [U-Boot] [PATCH 9/9] Add initial support for Freescale mx51evk board To: u-boot@lists.denx.de Date: Monday, January 11, 2010, 10:26 AM The patch adds initial support for the Freescale mx51evk board. Network (FEC) and SD controller (fsl_esdhc) are supported.
Signed-off-by: Stefano Babic sbabic@denx.de Signed-off-by: Fred Fan fanyefeng@gmail.com +Â Â Â puts("Board: MX51 BABBAGE ");
We should use MX51EVK instead.
....
+#define CONFIG_CMD_PING +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_MII +#define CONFIG_CMD_NET
+/* allow to overwrite serial and ethaddr */
- The MX51 3stack board seems to have a hardware
"peculiarity" confirmed under
- U-Boot, RedBoot and Linux: the ethernet Rx signal is
reaching the CS8900A
- controller inverted. The controller is capable of
detecting and correcting
- this, but it needs 4 network packets for that. Which
means, at startup, you
- will not receive answers to the first 4 packest, unless
there have been some
- broadcasts on the network, or your board is on a hub.
Reducing the ARP
- timeout from default 5 seconds to 200ms we speed up the
initial TFTP
- transfer, should the user wish one, significantly.
These comments do not apply to MX51EVK as there is no CS8900 controller on this board. Please remove.
...
+#define CONFIG_SYS_LONGHELPÂ Â Â Â Â Â /* undef to save memory */ +#define CONFIG_SYS_PROMPTÂ Â Â Â Â Â "BBG U-Boot > "
'BBG' should be removed as we are no longer using the term Babbage.
I will also send you new optimized values for the DDR settings when I come back to the office.
Regards,
Fabio Estevam

Hi Stefano,
More comments below.
--- On Mon, 1/11/10, Stefano Babic sbabic@denx.de wrote:
From: Stefano Babic sbabic@denx.de Subject: [U-Boot] [PATCH 9/9] Add initial support for Freescale mx51evk board To: u-boot@lists.denx.de Date: Monday, January 11, 2010, 10:26 AM The patch adds initial support for the Freescale mx51evk board. Network (FEC) and SD controller (fsl_esdhc) are supported.
Signed-off-by: Stefano Babic sbabic@denx.de Signed-off-by: Fred Fan fanyefeng@gmail.com
....
+static inline void setup_soc_rev(void) +{ +Â Â Â int reg;
+Â Â Â reg = __raw_readl(ROM_SI_REV); +Â Â Â switch (reg) { +Â Â Â case 0x02: +Â Â Â Â Â Â system_rev = 0x51000 | CHIP_REV_1_1; +Â Â Â Â Â Â break; +Â Â Â case 0x10: +Â Â Â Â Â Â if ((__raw_readl(GPIO1_BASE_ADDR + 0x0) & (0x1 << 22)) == 0) +Â Â Â Â Â Â Â Â Â system_rev = 0x51000 | CHIP_REV_2_5; +Â Â Â Â Â Â else +Â Â Â Â Â Â Â Â Â system_rev = 0x51000 | CHIP_REV_2_0; +Â Â Â Â Â Â break; +Â Â Â default: +Â Â Â Â Â Â system_rev = 0x51000 | CHIP_REV_1_0; +Â Â Â Â Â Â break; +Â Â Â } +}
Looks like CHIP_REV_3_0 case is missing.
...
+/* CPLD offsets */ +#define IO_BOARD_OFFSETÂ Â Â Â Â Â (0x20000) +#define PBC_ID_AAAAÂ Â Â Â Â Â (0x20040) +#define PBC_ID_5555Â Â Â Â Â Â (0x20048) +#define PBC_INT_RESTÂ Â Â Â Â Â (0x20020) +#define PBC_INT_MASKÂ Â Â Â Â Â (0x20038) +#define PBC_SW_RESETÂ Â Â Â Â Â (0x20060)
+#endif
There is no CPLD on MX51EVK board. Please remove these defines.
/* __BOARD_FREESCALE_BOARD_MX51_BABBAGE_H__ */
Please remove Babbage references.
Regards,
Fabio Estevam

Dear Stefano Babic,
In message 1263212760-27272-10-git-send-email-sbabic@denx.de you wrote:
The patch adds initial support for the Freescale mx51evk board. Network (FEC) and SD controller (fsl_esdhc) are supported.
--- a/Makefile +++ b/Makefile @@ -324,6 +324,10 @@ $(obj)u-boot.img: $(obj)u-boot.bin sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \ -d $< $@
+$(obj)u-boot.imx: $(obj)u-boot.bin
$(obj)tools/mkimage -n $(IMX_CONFIG) -T imximage \
-e $(TEXT_BASE) -d $< $@
This actually belongs into the patch that adds the imx image format support.
+int dram_init(void) +{
- gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
- gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
Line too long. Please check globally.
- return 0;
+}
+static void setup_uart(void) +{
- unsigned int pad = PAD_CTL_HYS_ENABLE | PAD_CTL_PKE_ENABLE |
PAD_CTL_PUE_PULL | PAD_CTL_DRV_HIGH;
Indentation by TAB, please. Please check globally.
+static void setup_expio(void) +{
- u32 reg;
- /* CS5 setup */
- mxc_request_iomux(MX51_PIN_EIM_CS5, IOMUX_CONFIG_ALT0);
- writel(0x00410089, WEIM_BASE_ADDR + 0x78 + CSGCR1);
- writel(0x00000002, WEIM_BASE_ADDR + 0x78 + CSGCR2);
- /* RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0 */
- writel(0x32260000, WEIM_BASE_ADDR + 0x78 + CSRCR1);
- /* APR = 0 */
- writel(0x00000000, WEIM_BASE_ADDR + 0x78 + CSRCR2);
What is this magic offset 0x78 here? Please get rid of using base address + offset notation, use C struncts instead (see previous review comments about this). Please fix globally.
- /* Reset the XUART and Ethernet controllers */
- reg = readw(&(mx51_io_board->sw_reset));
- reg |= 0x9;
- writew(reg, &(mx51_io_board->sw_reset));
- reg &= ~0x9;
- writew(reg, &(mx51_io_board->sw_reset));
+}
+static void setup_fec(void) +{
FEC should only be set up (and eventually only be reset, too), if there is any network support at all on this board.
...
+int board_mmc_init(bd_t *bis) +{
- u32 interface_esdhc = 0;
- s32 status = 0;
- u32 esdhc_base_pointer;
- for (interface_esdhc = 0; interface_esdhc < CONFIG_SYS_FSL_ESDHC_NUM; interface_esdhc++) {
switch (interface_esdhc) {
case 0:
Incorrect indent. And line too loing above, of course.
...
break;
case 1:
...
break;
}
Incorrect indent. Default case?
diff --git a/board/freescale/mx51evk/mx51evk.h b/board/freescale/mx51evk/mx51evk.h new file mode 100644 index 0000000..fec886d --- /dev/null +++ b/board/freescale/mx51evk/mx51evk.h @@ -0,0 +1,49 @@ +/*
- Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- */
Please get rid off the "All Rights Reserved."
+/*
- The code contained herein is licensed under the GNU General Public
- License. You may obtain a copy of the GNU General Public License
- Version 2 or later at the following locations:
As mentioned before, this clause is not acceptable.
diff --git a/include/configs/mx51evk.h b/include/configs/mx51evk.h new file mode 100644 index 0000000..c8b2970 --- /dev/null +++ b/include/configs/mx51evk.h
...
- /* High Level Configuration Options */
+#define CONFIG_SYS_APCS_GNU
What's this? It seems to be not used anywhere, nor documented?
+#define CONFIG_L2_OFF
Is this a "High Level Configuration Option"? Move down!
+#define CONFIG_SYS_MEMTEST_START CSD0_BASE_ADDR +#define CONFIG_SYS_MEMTEST_END 0x10000
+#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR
Here and everywhere else: please use TABs for vertical alignment.
+#define CONFIG_ENV_SECT_SIZE (128 * 1024) +#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE +#define CONFIG_ENV_IS_NOWHERE
Seems strange to me to define an environment sector size and an environment size and then to say there is no environment at all?
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Stefano Babic,
Hi Wolfgang,
+$(obj)u-boot.imx: $(obj)u-boot.bin
$(obj)tools/mkimage -n $(IMX_CONFIG) -T imximage \
-e $(TEXT_BASE) -d $< $@
This actually belongs into the patch that adds the imx image format support.
Correct, thanks for the tip. I move it to the right patch.
+static void setup_fec(void) +{
FEC should only be set up (and eventually only be reset, too), if there is any network support at all on this board.
The name is misleading, too. The FEC is not initialized here and the function is responsible only to set the IOMUX pin multiplexer for the network controller. Nothing more. The name shoud be something such as "set_iomux_network".
I can of course surround the function with #ifdef CONFIG_FEC_MXC, but really do I need ? We cannot change how the processor's pins are connected on the board, even if we do not want to add network support for this board. I think it should be ok if the pin multiplexer is always configured, independently if there is a network device or not.
+#define CONFIG_SYS_APCS_GNU
What's this? It seems to be not used anywhere, nor documented?
I get already rid of the meaningless usage. I forget to drop its define. Thanks !
+#define CONFIG_ENV_SECT_SIZE (128 * 1024) +#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE +#define CONFIG_ENV_IS_NOWHERE
Seems strange to me to define an environment sector size and an environment size and then to say there is no environment at all?
Right. The mx51evk board has neither NOR nor NAND flash. However, a SPI flash is available and this defines are required when the spi will be supported. At the moment, I can drop them and reinsert later.
Best regards, Stefano Babic

Dear Stefano Babic,
In message 4B540EF1.9050109@denx.de you wrote:
+static void setup_fec(void) +{
FEC should only be set up (and eventually only be reset, too), if there is any network support at all on this board.
The name is misleading, too. The FEC is not initialized here and the function is responsible only to set the IOMUX pin multiplexer for the network controller. Nothing more. The name shoud be something such as "set_iomux_network".
Ah, I see.
I can of course surround the function with #ifdef CONFIG_FEC_MXC, but really do I need ? We cannot change how the processor's pins are connected on the board, even if we do not want to add network support for this board. I think it should be ok if the pin multiplexer is always configured, independently if there is a network device or not.
This is indeed ok.My concern was not to enable peripherals and clocks unless needed. The thing is, such an initial port will be used as reference by all others that will add new boards of the same architecture, and it's easier not to enable interfaces initially (people will notice that - say - Ethenret is not working) then to try to reduce the power consumpion of the device later, not knowing which unused clocks or peripherals might be turned on and sucking off the battery.
+#define CONFIG_ENV_SECT_SIZE (128 * 1024) +#define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE +#define CONFIG_ENV_IS_NOWHERE
Seems strange to me to define an environment sector size and an environment size and then to say there is no environment at all?
Right. The mx51evk board has neither NOR nor NAND flash. However, a SPI flash is available and this defines are required when the spi will be supported. At the moment, I can drop them and reinsert later.
So at the moment we cannot save the envrionment? Arghhh...
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Stefano Babic,
Hi Wolfgang,
So at the moment we cannot save the envrionment? Arghhh...
Yes, I know. I managed to change the mxc_spi driver, but I have really changed a lot of code. I have not only added support for the i.MX51, but I needed to remove the limitations due to the buffer alignment and the fact that transfer of more than one word is broken. I see a recent thread on this issue. I will send soon a patch to the ML, but as I said I changed a lot of code (I rewrite the transfer functions) and I assume it takes some time before anything is cleared. So it would better to add the patch for the mx51evk as it is (I mean, without the possibility to save the environment) and later add support for it when SPI is working.
Best regards, Stefano Babic

Dear Stefano Babic,
In message 1263212760-27272-8-git-send-email-sbabic@denx.de you wrote:
The esdhc controller in the mx51 processor is quite the same as the one in some powerpc processors (MPC83xx, MPC85xx). This patches adapts the driver to support the arm mx51.
Signed-off-by: Stefano Babic sbabic@denx.de
drivers/mmc/fsl_esdhc.c | 72 +++++++++++++++++++++++++++++++++++++++------- include/asm-arm/io.h | 21 +++++++++++++ include/fsl_esdhc.h | 6 +++- include/mmc.h | 1 + 4 files changed, 88 insertions(+), 12 deletions(-)
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index c6e9e6e..5dcf6a8 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -37,6 +37,10 @@ #include <fdt_support.h> #include <asm/io.h>
+#ifndef CONFIG_PPC +#define out_be32(a,v) writel(v,a) +#define in_be32(a) __raw_readl(a) +#endif
Are you sure these are correct definitions for all architectures? If so, they should go into a global header file, not here.
@@ -129,7 +133,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) out_be32(®s->blkattr, data->blocks << 16 | data->blocksize);
/* Calculate the timeout period for data transactions */
- timeout = __ilog2(mmc->tran_speed/10);
- timeout = fls(mmc->tran_speed/10) - 1;
What's the reason for this change?
@@ -236,11 +240,18 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
void set_sysctl(struct mmc *mmc, uint clock) { +#ifdef CONFIG_PPC int sdhc_clk = gd->sdhc_clk; +#else
- int sdhc_clk = mxc_get_clock(MXC_IPG_PERCLK);
+#endif
Can we avoid such #ifdef's here? Why don't we use gd->sdhc_clk everywhere?
int div, pre_div; volatile struct fsl_esdhc *regs = mmc->priv; uint clk;
- if (clock < mmc->f_min)
clock = mmc->f_min;
Print warning message ?
@@ -257,11 +268,14 @@ void set_sysctl(struct mmc *mmc, uint clock)
clk = (pre_div << 8) | (div << 4);
- /* On imx the clock must be stopped before changing frequency */
- clrbits_be32(®s->sysctl, SYSCTL_CKEN);
Is this compatible with the other architectures?
static void esdhc_set_ios(struct mmc *mmc) @@ -278,15 +292,26 @@ static void esdhc_set_ios(struct mmc *mmc) setbits_be32(®s->proctl, PROCTL_DTW_4); else if (mmc->bus_width == 8) setbits_be32(®s->proctl, PROCTL_DTW_8);
}
Please delete this empty line.
static int esdhc_init(struct mmc *mmc) { struct fsl_esdhc *regs = mmc->priv; int timeout = 1000;
- int ret = 0;
+#ifdef CONFIG_PPC /* Enable cache snooping */ out_be32(®s->scr, 0x00000040); +#endif
Why only on PPC? [I'm asking again because I don;t want to see so many #ifdef's in such code.]
- /* Reset the entire host controller */
- out_be32(®s->sysctl, SYSCTL_RSTA);
- /* Wait until the controller is available */
- while ((in_be32(®s->sysctl) & SYSCTL_RSTA) && --timeout)
udelay(1000);
Has this been tested on non-i.MX51 systems as well?
@@ -299,24 +324,44 @@ static int esdhc_init(struct mmc *mmc) /* Put the PROCTL reg back to the default */ out_be32(®s->proctl, PROCTL_INIT);
- while (!(in_be32(®s->prsstat) & PRSSTAT_CINS) && --timeout)
udelay(1000);
- /* Set timout to the maximum value */
- clrsetbits_be32(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
- if (timeout <= 0)
return NO_CARD_ERR;
- /* Check if there is a callback for detecting the card */
- if (!mmc->getcd) {
timeout = 1000;
while (!(in_be32(®s->prsstat) & PRSSTAT_CINS) && --timeout)
udelay(1000);
- return 0;
if (timeout <= 0)
ret = NO_CARD_ERR;
- } else {
if (mmc->getcd(mmc))
ret = NO_CARD_ERR;
- }
- return ret;
}
These are a lot of changes - how mu of this has actually been tested on non-i.MX51 ?
+int fsl_esdhc_initialize(bd_t *bis, uint32_t esdhc_addr, int (*getcd)(struct mmc *mmc)) {
- struct fsl_esdhc *regs = (struct fsl_esdhc *)CONFIG_SYS_FSL_ESDHC_ADDR;
+#ifdef CONFIG_PPC
- int sdhc_clk = gd->sdhc_clk;
+#else
- int sdhc_clk = mxc_get_clock(MXC_IPG_PERCLK);
+#endif
See above.
struct fsl_esdhc *regs; struct mmc *mmc; u32 caps;
mmc = malloc(sizeof(struct mmc));
sprintf(mmc->name, "FSL_ESDHC");
if (!esdhc_addr) {
regs = (struct fsl_esdhc *)CONFIG_SYS_FSL_ESDHC_ADDR;
} else {
regs = (struct fsl_esdhc *)esdhc_addr;
}
Argh... Please don't. Use a common way for configuration, please.
+#ifdef CONFIG_PPC void fdt_fixup_esdhc(void *blob, bd_t *bd) { const char *compat = "fsl,esdhc"; @@ -365,3 +414,4 @@ out: do_fixup_by_compat(blob, compat, "status", status, strlen(status) + 1, 1); } +#endif
Can we drop this #ifdef ?
--- a/include/asm-arm/io.h +++ b/include/asm-arm/io.h @@ -33,6 +33,27 @@ static inline void sync(void) { }
+/* Clear and set bits in one shot. These macros can be used to clear and
- set multiple bits in a register using a single call. These macros can
- also be used to set a multiple-bit bit pattern using a mask, by
- specifying the mask in the 'clear' parameter and the new bit pattern
- in the 'set' parameter.
- */
Incorrect multiline comment style.
+#define clrbits(type, addr, clear) \
- write##type(__raw_read##type(addr) & ~(clear), (addr))
+#define setbits(type, addr, set) \
- write##type(__raw_read##type(addr) | (set), (addr))
+#define clrsetbits(type, addr, clear, set) \
- write##type((__raw_read##type(addr) & ~(clear)) | (set), (addr))
+#define clrbits_be32(addr, clear) clrbits(l, addr, clear) +#define setbits_be32(addr, set) setbits(l, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(l, addr, clear, set)
Are these macros really generally applicaple to all ARM systems, including both big and little endian configurations?
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Stefano Babic,
Hi Wolfgang,
+#ifndef CONFIG_PPC +#define out_be32(a,v) writel(v,a) +#define in_be32(a) __raw_readl(a) +#endif
Are you sure these are correct definitions for all architectures? If so, they should go into a global header file, not here.
The main reason for that is to have the same common way to access esdhc registers on the powerpc and on the arm processors. The driver is already implemented for powerpc and use the out_be32() function to access the internal registers (all registers are 32 bit wide). As counterpart on i.MX51, we have the writel() function.
I am not sure which is the best way to do it and I ask you for help. Maybe changing in all code with a "neutral" function (but this is an additional I/O accessor, there are already a lot of them...) and setting it to point to out_be32() in asm-ppc/io.h and to writel() in asm-arm/io.h. I do not know, but it sounds to me pretty bad.
Do you have a hint to manage that ?
@@ -129,7 +133,7 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data) out_be32(®s->blkattr, data->blocks << 16 | data->blocksize);
/* Calculate the timeout period for data transactions */
- timeout = __ilog2(mmc->tran_speed/10);
- timeout = fls(mmc->tran_speed/10) - 1;
What's the reason for this change?
The only reason is that there is no __ilog2 function for the arm architecture and I preferred to change it in a way that is defined for all architectures, not only powerpc. ilog2 is defined as (fls() - 1) in linux if no architecture specific function is provided. So, even if it is not optimized, the change is suitable for powerpc, too.
@@ -236,11 +240,18 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
void set_sysctl(struct mmc *mmc, uint clock) { +#ifdef CONFIG_PPC int sdhc_clk = gd->sdhc_clk; +#else
- int sdhc_clk = mxc_get_clock(MXC_IPG_PERCLK);
+#endif
Can we avoid such #ifdef's here? Why don't we use gd->sdhc_clk everywhere?
Yes, thanks, good tip. I will add the field sdhc_clk to the global data for arm and I will get rid of these unneeded #ifdef.
@@ -257,11 +268,14 @@ void set_sysctl(struct mmc *mmc, uint clock)
clk = (pre_div << 8) | (div << 4);
- /* On imx the clock must be stopped before changing frequency */
- clrbits_be32(®s->sysctl, SYSCTL_CKEN);
Is this compatible with the other architectures?
Zeroing the bit should be ok as described in PowerQuick manual. The controller in the i.MX51 is (quite) the same as in the powerpc (I checked in the MPC8560 manual), with the exception of some registers. It seems that the controller in the i.MX51 is an evolution and some features (as the possibility to enable/disable the clock when no access to the card is required) are added later. Really to be sure I have to protect the setting of this bit (with #ifndef PPC....)
+#ifdef CONFIG_PPC /* Enable cache snooping */ out_be32(®s->scr, 0x00000040); +#endif
Why only on PPC? [I'm asking again because I don;t want to see so many #ifdef's in such code.]
As I said, the controllers are quite the same but they are not identical. There is not this register on the i.MX51 implementation. Really this has nothing to do with PPC and ARM.
I would prefer to have a general method to ask the controller for its capabilities and setting the bit fields according to the query. However, I have not found a way to to this and I use '#ifdef PPC' to distinguish between the two implementations of the hardware controller.
- /* Reset the entire host controller */
- out_be32(®s->sysctl, SYSCTL_RSTA);
- /* Wait until the controller is available */
- while ((in_be32(®s->sysctl) & SYSCTL_RSTA) && --timeout)
udelay(1000);
Has this been tested on non-i.MX51 systems as well?
No, I could not test on powerpc, but the method is described in powerpc manual, too. In both manuals, the setting of this bit performs a reset of the controller. There is nothing special related to the ARM implementation.
@@ -299,24 +324,44 @@ static int esdhc_init(struct mmc *mmc) /* Put the PROCTL reg back to the default */ out_be32(®s->proctl, PROCTL_INIT);
- while (!(in_be32(®s->prsstat) & PRSSTAT_CINS) && --timeout)
udelay(1000);
- /* Set timout to the maximum value */
- clrsetbits_be32(®s->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
- if (timeout <= 0)
return NO_CARD_ERR;
- /* Check if there is a callback for detecting the card */
- if (!mmc->getcd) {
timeout = 1000;
while (!(in_be32(®s->prsstat) & PRSSTAT_CINS) && --timeout)
udelay(1000);
- return 0;
if (timeout <= 0)
ret = NO_CARD_ERR;
- } else {
if (mmc->getcd(mmc))
ret = NO_CARD_ERR;
- }
- return ret;
}
These are a lot of changes - how mu of this has actually been tested on non-i.MX51 ?
Well, as I said I could not test on PowerQuick, but changes are not related to the architecture.
Let's me explain. The driver up now uses only the internal controller to detect if a SD card is present in the slot. However, this is not a general way. In a lot of cases the pins responsible for this function and connected to the ESDHC controller are required for another peripheral and cannot be used. In these cases, a GPIO can be used for Card Detection. The change adds only a callback in the case a GPIO is required. If the internal controller can be used (!mmc->getcd), the bits defined in PRSSTAT_CINS are still used as before. Agree this code was not tested outside the mx51evk, but changes are smaller as we can think.
struct fsl_esdhc *regs; struct mmc *mmc; u32 caps;
mmc = malloc(sizeof(struct mmc));
sprintf(mmc->name, "FSL_ESDHC");
if (!esdhc_addr) {
regs = (struct fsl_esdhc *)CONFIG_SYS_FSL_ESDHC_ADDR;
} else {
regs = (struct fsl_esdhc *)esdhc_addr;
}
Argh... Please don't. Use a common way for configuration, please.
Well, the main reason for that is to support more than one controller. The MX51 has two ESDHC controllers and both of them are well supported in hardware on the mx51evk. The powerpc implementation supports clearly only one instance. The reason here is not to break the actual implementation on the powerpc boards, allowing in the same time more than one instance on the mx51evk board.
Personally I would prefer to change the powerpc code (but probably should be done in another patch ?), calling fsl_esdhc_mmc_init() in cpu/mpc85xx/cpu.c, cpu/mpc83xx/cpu.c (and in the board related functions, if any) and passing there the HW address of the controller. Something like that (for example, in cpu/mpc85xx/cpu.c:)
--- a/cpu/mpc85xx/cpu.c +++ b/cpu/mpc85xx/cpu.c @@ -323,7 +323,7 @@ void upmconfig (uint upm, uint * table, uint size) int cpu_mmc_init(bd_t *bis) { #ifdef CONFIG_FSL_ESDHC - return fsl_esdhc_mmc_init(bis); + return fsl_esdhc_initialize(bis, CONFIG_SYS_MPC85xx_ESDHC_ADDR, NULL); #else return 0; #endif
+#ifdef CONFIG_PPC void fdt_fixup_esdhc(void *blob, bd_t *bd) { const char *compat = "fsl,esdhc"; @@ -365,3 +414,4 @@ out: do_fixup_by_compat(blob, compat, "status", status, strlen(status) + 1, 1); } +#endif
Can we drop this #ifdef ?
Really replacing it with another #ifdef...
I think the code shold be protect with CONFIG_OF_LIBFDT instead of CONFIG_PPC.
+#define clrbits(type, addr, clear) \
- write##type(__raw_read##type(addr) & ~(clear), (addr))
+#define setbits(type, addr, set) \
- write##type(__raw_read##type(addr) | (set), (addr))
+#define clrsetbits(type, addr, clear, set) \
- write##type((__raw_read##type(addr) & ~(clear)) | (set), (addr))
+#define clrbits_be32(addr, clear) clrbits(l, addr, clear) +#define setbits_be32(addr, set) setbits(l, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(l, addr, clear, set)
Are these macros really generally applicaple to all ARM systems, including both big and little endian configurations?
See above, first issue, it is related. The reason here is to have a general way to add a "native" access method to internal registers for both architectures.
Best regards, Stefano Babic

Dear Stefano Babic,
In message 4B542184.6060706@denx.de you wrote:
+#ifndef CONFIG_PPC +#define out_be32(a,v) writel(v,a) +#define in_be32(a) __raw_readl(a) +#endif
Are you sure these are correct definitions for all architectures? If so, they should go into a global header file, not here.
The main reason for that is to have the same common way to access esdhc registers on the powerpc and on the arm processors. The driver is already implemented for powerpc and use the out_be32() function to access the internal registers (all registers are 32 bit wide). As counterpart on i.MX51, we have the writel() function.
But my understanding is that writel() is a little endian I/O operation?
I am not sure which is the best way to do it and I ask you for help. Maybe changing in all code with a "neutral" function (but this is an additional I/O accessor, there are already a lot of them...) and setting it to point to out_be32() in asm-ppc/io.h and to writel() in asm-arm/io.h. I do not know, but it sounds to me pretty bad.
Do you have a hint to manage that ?
In the long term we indeed want to convert the code (all code, yes) to generic I/O accessors, i. e. ioreadX(), iowriteX().
But that's a bigger task.
My concern here is that defining out_be32() [=explicitely big endian] as writel() [=explicitly little endian] might be plain wrong and thus confusing.
+#ifdef CONFIG_PPC /* Enable cache snooping */ out_be32(®s->scr, 0x00000040); +#endif
Why only on PPC? [I'm asking again because I don;t want to see so many #ifdef's in such code.]
As I said, the controllers are quite the same but they are not identical. There is not this register on the i.MX51 implementation. Really this has nothing to do with PPC and ARM.
Then we should not make this depend on CONFIG_PPC.
I would prefer to have a general method to ask the controller for its capabilities and setting the bit fields according to the query. However, I have not found a way to to this and I use '#ifdef PPC' to distinguish between the two implementations of the hardware controller.
This is not a good idea. We should probably try to find out how the controller versions are named within Freescale (probably they do have internal version IDs attached - we see the same for some NAND controllers) and use these ID's to enable / disable features.
Using CONFIG_PPC here looks wrong to me.
- /* Wait until the controller is available */
- while ((in_be32(®s->sysctl) & SYSCTL_RSTA) && --timeout)
udelay(1000);
Has this been tested on non-i.MX51 systems as well?
No, I could not test on powerpc, but the method is described in powerpc manual, too. In both manuals, the setting of this bit performs a reset of the controller. There is nothing special related to the ARM implementation.
I see. Please add the respective PPC custodians on the Cc: list for this patch, then.
These are a lot of changes - how mu of this has actually been tested on non-i.MX51 ?
Well, as I said I could not test on PowerQuick, but changes are not related to the architecture.
Let's me explain. The driver up now uses only the internal controller to detect if a SD card is present in the slot. However, this is not a general way. In a lot of cases the pins responsible for this function and connected to the ESDHC controller are required for another peripheral and cannot be used. In these cases, a GPIO can be used for Card Detection. The change adds only a callback in the case a GPIO is required. If the internal controller can be used (!mmc->getcd), the bits defined in PRSSTAT_CINS are still used as before. Agree this code was not tested outside the mx51evk, but changes are smaller as we can think.
OK - but please let's at least trigger the respective code maintainers so they get aware of the changes and test it on their platforms.
sprintf(mmc->name, "FSL_ESDHC");
- if (!esdhc_addr) {
regs = (struct fsl_esdhc *)CONFIG_SYS_FSL_ESDHC_ADDR;
- } else {
regs = (struct fsl_esdhc *)esdhc_addr;
- }
Argh... Please don't. Use a common way for configuration, please.
Well, the main reason for that is to support more than one controller. The MX51 has two ESDHC controllers and both of them are well supported in hardware on the mx51evk. The powerpc implementation supports clearly only one instance. The reason here is not to break the actual implementation on the powerpc boards, allowing in the same time more than one instance on the mx51evk board.
Personally I would prefer to change the powerpc code (but probably should be done in another patch ?), calling fsl_esdhc_mmc_init() in cpu/mpc85xx/cpu.c, cpu/mpc83xx/cpu.c (and in the board related functions, if any) and passing there the HW address of the controller. Something like that (for example, in cpu/mpc85xx/cpu.c:)
Looks OK to me. Let's ping the respective custodians...
+#ifdef CONFIG_PPC void fdt_fixup_esdhc(void *blob, bd_t *bd) { const char *compat = "fsl,esdhc"; @@ -365,3 +414,4 @@ out: do_fixup_by_compat(blob, compat, "status", status, strlen(status) + 1, 1); } +#endif
Can we drop this #ifdef ?
Really replacing it with another #ifdef...
I think the code shold be protect with CONFIG_OF_LIBFDT instead of CONFIG_PPC.
OK.
+#define clrbits(type, addr, clear) \
- write##type(__raw_read##type(addr) & ~(clear), (addr))
+#define setbits(type, addr, set) \
- write##type(__raw_read##type(addr) | (set), (addr))
+#define clrsetbits(type, addr, clear, set) \
- write##type((__raw_read##type(addr) & ~(clear)) | (set), (addr))
+#define clrbits_be32(addr, clear) clrbits(l, addr, clear) +#define setbits_be32(addr, set) setbits(l, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(l, addr, clear, set)
Are these macros really generally applicaple to all ARM systems, including both big and little endian configurations?
See above, first issue, it is related. The reason here is to have a general way to add a "native" access method to internal registers for both architectures.
I understand your intentions, but I wonder if the implementation is correct, or if we are mixing big endian and little endian code here in a most confusing way.
Best regards,
Wolfgang Denk

Dear Stefano Babic,
In message 1263212760-27272-7-git-send-email-sbabic@denx.de you wrote:
The patch add support for the Freescale mx51 processor to the FEC ethernet driver.
Signed-off-by: Stefano Babic sbabic@denx.de
drivers/net/fec_mxc.c | 57 ++++++++++++++++++++++++++++++------------------- 1 files changed, 35 insertions(+), 22 deletions(-)
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 19116f2..203832e 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -27,8 +27,10 @@ #include <miiphy.h> #include "fec_mxc.h"
-#include <asm/arch/clock.h> #include <asm/arch/imx-regs.h> +#ifndef CONFIG_MX51 +#include <asm/arch/clock.h> +#endif
Can we not implement the clock stuff for the iMX51 in such a way that we don't need #ifdef's here?
@@ -108,6 +110,23 @@ static int fec_miiphy_read(char *dev, uint8_t phyAddr, uint8_t regAddr, return 0; }
+static void fec_mii_setspeed(struct fec_priv *fec) +{ +#ifdef CONFIG_MX51
- writel((((mxc_get_clock(MXC_IPG_CLK) + 499999) / 5000000) << 1),
&fec->eth->mii_speed);
+#else
- /*
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
* and do not drop the Preamble.
*/
- writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1,
&fec->eth->mii_speed);
What exactly, in addition to the (technically irrelevant) names and the different way how the rounding is implemented, requires the #ifdef here?
The code looks pretty much the same to me. I think we should just use common names for common functions, and get rid of such #ifdef's.
@@ -236,7 +255,7 @@ static int fec_rbd_init(struct fec_priv *fec, int count, int size) fec->rdb_ptr = malloc(size * count + DB_DATA_ALIGNMENT); p = (uint32_t)fec->rdb_ptr; if (!p) {
puts("fec_imx27: not enough malloc memory!\n");
puts("fec_mxc: not enough malloc memory!\n");
Please also drop the '!' while you are changing this line.
static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac) { +#ifndef CONFIG_MX51 struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; int i;
@@ -306,6 +326,9 @@ static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac) mac[6-1-i] = readl(&iim->iim_bank_area0[IIM0_MAC + i]);
return is_valid_ether_addr(mac); +#else
- return -1;
+#endif }
General remark: please use positive logic in cases like this, as it results in simpler code which is much easier to read.
Instead of:
#ifndef CONFIG_MX51 ... many lines of code here followed by a return ...; #else return something_else; #endif
please write:
#ifdef CONFIG_MX51 return something_else; #endif
many lines of code here followed by a return ...;
Less nesting, shorter lines, easier to read and understand.
But why do we need this #ifdef here? If this function is of no use on i.MX51, then why provide it? And why call such a dummy function at all? Please let's get rid of these #ifdef's.
static int fec_set_hwaddr(struct eth_device *dev, unsigned char *mac) @@ -373,7 +396,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd) sizeof(struct fec_bd) + DB_ALIGNMENT); base = (uint32_t)fec->base_ptr; if (!base) {
puts("fec_imx27: not enough malloc memory!\n");
puts("fec_mxc: not enough malloc memory!\n");
See comment above; please apply globally.
static int fec_probe(bd_t *bd) {
- struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE; struct eth_device *edev; struct fec_priv *fec = &gfec; unsigned char ethaddr_str[20]; unsigned char ethaddr[6];
- char *tmp = getenv("ethaddr");
- char *tmp; char *end;
+#ifndef CONFIG_MX51
struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
/* enable FEC clock */ writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0);
+#endif
Can we implement this clock enable in a way that goes without #ifdef ?
/* create and fill edev struct */ edev = (struct eth_device *)malloc(sizeof(struct eth_device)); if (!edev) {
puts("fec_imx27: not enough malloc memory!\n");
return -ENOMEM; } edev->priv = fec;puts("fec_mxc: not enough malloc memory!\n");
@@ -702,14 +721,7 @@ static int fec_probe(bd_t *bd) * Frame length=1518; MII mode; */ writel(0x05ee0024, &fec->eth->r_cntrl); /* FIXME 0x05ee0004 */
- /*
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
* and do not drop the Preamble.
*/
- writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1,
&fec->eth->mii_speed);
- debug("fec_init: mii_speed %#lx\n",
(((imx_get_ahbclk() / 1000000) + 2) / 5) << 1);
fec_mii_setspeed(fec);
sprintf(edev->name, "FEC_MXC");
@@ -717,6 +729,7 @@ static int fec_probe(bd_t *bd)
eth_register(edev);
- tmp = getenv("ethaddr"); if ((NULL != tmp) && (12 <= strlen(tmp))) { int i; /* convert MAC from string to int */
This is wrong and should be fixed. We don't convert to "int" but to "uchar[]"; While we touch this, please dump the code completely and use eth_getenv_enetaddr() instead.
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Stefano Babic,
Hi Wolfgang,
-#include <asm/arch/clock.h> #include <asm/arch/imx-regs.h> +#ifndef CONFIG_MX51 +#include <asm/arch/clock.h>imx_get_ahbclk +#endif
Can we not implement the clock stuff for the iMX51 in such a way that we don't need #ifdef's here?
Good hint, I do it !
@@ -108,6 +110,23 @@ static int fec_miiphy_read(char *dev, uint8_t phyAddr, uint8_t regAddr, return 0; }
+static void fec_mii_setspeed(struct fec_priv *fec) +{ +#ifdef CONFIG_MX51
- writel((((mxc_get_clock(MXC_IPG_CLK) + 499999) / 5000000) << 1),
&fec->eth->mii_speed);
+#else
- /*
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock
* and do not drop the Preamble.
*/
- writel((((imx_get_ahbclk() / 1000000) + 2) / 5) << 1,
&fec->eth->mii_speed);
What exactly, in addition to the (technically irrelevant) names and the different way how the rounding is implemented, requires the #ifdef here?
You are right, there is no technical reason. The only thing here is to get the correct clock source. I will get as in serial_mxc and setting a imx_get_fecclk() for both processors (i.MX27 and i.MX51), removing the ifdef.
static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac) { +#ifndef CONFIG_MX51 struct iim_regs *iim = (struct iim_regs *)IMX_IIM_BASE; int i;
@@ -306,6 +326,9 @@ static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac) mac[6-1-i] = readl(&iim->iim_bank_area0[IIM0_MAC + i]);
return is_valid_ether_addr(mac); +#else
- return -1;
+#endif }
General remark: please use positive logic in cases like this, as it results in simpler code which is much easier to read.
Understood, thanks.
+#ifndef CONFIG_MX51
struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
/* enable FEC clock */ writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0);
+#endif
Can we implement this clock enable in a way that goes without #ifdef ?
I think this should be dropped from the driver. The driver should be responsible to set up the FEC controller and nothing else. Enabling the clock should be done in another place (probably in the cpu related part ?), but not here. However, this is related to the i.MX27, I am not sure where we have to move this code.
- tmp = getenv("ethaddr"); if ((NULL != tmp) && (12 <= strlen(tmp))) { int i; /* convert MAC from string to int */
This is wrong and should be fixed. We don't convert to "int" but to "uchar[]"; While we touch this, please dump the code completely and use eth_getenv_enetaddr() instead.
Thanks, understood.
Regards, Stefano Babic

Dear Stefano Babic,
In message 4B542B4E.4000108@denx.de you wrote:
+#ifndef CONFIG_MX51
struct pll_regs *pll = (struct pll_regs *)IMX_PLL_BASE;
/* enable FEC clock */ writel(readl(&pll->pccr1) | PCCR1_HCLK_FEC, &pll->pccr1); writel(readl(&pll->pccr0) | PCCR0_FEC_EN, &pll->pccr0);
+#endif
Can we implement this clock enable in a way that goes without #ifdef ?
I think this should be dropped from the driver. The driver should be responsible to set up the FEC controller and nothing else. Enabling the clock should be done in another place (probably in the cpu related part ?), but not here. However, this is related to the i.MX27, I am not sure where we have to move this code.
I'm not sure. Here is where we enable the FEC because we want to use it in a network command, right? Then this is the place to enable the needed clocks, too. These should not be globally enabled and running even if no network access is ever made - this would only increase the power dissipation, which is bad on battery operated devices.
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Stefano Babic,
Hi Wolfgang,
I'm not sure. Here is where we enable the FEC because we want to use it in a network command, right?
No, the fec_probe() function is called as part of the cpu_eth_init() and sets the callbacks, among the other things. It is called always, independently if we are ready to use a network command or not, it depends only on CONFIG_FEC_MXC.
I do not find very correct that the MAC address is set in this function (and not set anymore). What happens if I set the ethaddr variable ? Changes will be not effective until next reset of the system. It is a different issue, I know, but related to the same function. I had move setting to fec_init(), but this is already implemented (and I can test only on a i.MX51 board).
Then this is the place to enable the needed clocks, too. These should not be globally enabled and running even if no network access is ever made - this would only increase the power dissipation, which is bad on battery operated devices.
However, I think it is the actual status in the driver, because the fec_probe is always called. The clock initialization should be moved as part of the fec_init() (that is, edev->init) to reach what you propose.
Best regards, Stefano Babic

Stefano,
There is a patch in my mx25 series that factors out a lot of SOC specifics from the fec driver including clocks. It might be useful here.
John
On Mon, Jan 18, 2010 at 5:19 AM, Stefano Babic sbabic@denx.de wrote:
Wolfgang Denk wrote:
Dear Stefano Babic,
Hi Wolfgang,
I'm not sure. Here is where we enable the FEC because we want to use it in a network command, right?
No, the fec_probe() function is called as part of the cpu_eth_init() and sets the callbacks, among the other things. It is called always, independently if we are ready to use a network command or not, it depends only on CONFIG_FEC_MXC.
I do not find very correct that the MAC address is set in this function (and not set anymore). What happens if I set the ethaddr variable ? Changes will be not effective until next reset of the system. It is a different issue, I know, but related to the same function. I had move setting to fec_init(), but this is already implemented (and I can test only on a i.MX51 board).
Then this is the place to enable the needed clocks, too. These should not be globally enabled and running even if no network access is ever made - this would only increase the power dissipation, which is bad on battery operated devices.
However, I think it is the actual status in the driver, because the fec_probe is always called. The clock initialization should be moved as part of the fec_init() (that is, edev->init) to reach what you propose.
Best regards, Stefano Babic
--
DENX Software Engineering GmbH, Â Â MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Â Email: office@denx.de ===================================================================== _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Dear Stefano Babic,
In message 1263212760-27272-6-git-send-email-sbabic@denx.de you wrote:
The patch adds support for the Freescale mx51 processor.
@@ -49,8 +51,14 @@ #define UART_PHYS 0x1001b000 #elif defined(CONFIG_SYS_MX27_UART6) #define UART_PHYS 0x1001c000 +#elif defined(CONFIG_SYS_MX51_UART1) +#define UART_PHYS UART1_BASE_ADDR +#elif defined(CONFIG_SYS_MX51_UART2) +#define UART_PHYS UART2_BASE_ADDR +#elif defined(CONFIG_SYS_MX51_UART3) +#define UART_PHYS UART3_BASE_ADDR
What happens if - for example - CONFIG_SYS_MX51_UART1 _and_ CONFIG_SYS_MX51_UART2 are defiend? How is CONFIG_SERIAL_MULTI going to be supported?
-#error "define CONFIG_SYS_MX31_UARTx to use the mx31 UART driver" +#error "define CONFIG_SYS_MXxx_UARTx to use the mxxx UART driver"
WHat's "mxxx" supposed to mean? This is not readable.
#ifdef CONFIG_MX31 u32 clk = mx31_get_ipg_clk(); +#elif defined(CONFIG_MX51)
- u32 clk = mxc_get_clock(MXC_UART_CLK);
#else u32 clk = imx_get_perclk1(); #endif
Cannot we have a common clock interface?
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Stefano Babic,
Hi Wolfgang,
@@ -49,8 +51,14 @@ #define UART_PHYS 0x1001b000 #elif defined(CONFIG_SYS_MX27_UART6) #define UART_PHYS 0x1001c000 +#elif defined(CONFIG_SYS_MX51_UART1) +#define UART_PHYS UART1_BASE_ADDR +#elif defined(CONFIG_SYS_MX51_UART2) +#define UART_PHYS UART2_BASE_ADDR +#elif defined(CONFIG_SYS_MX51_UART3) +#define UART_PHYS UART3_BASE_ADDR
What happens if - for example - CONFIG_SYS_MX51_UART1 _and_ CONFIG_SYS_MX51_UART2 are defiend? How is CONFIG_SERIAL_MULTI going to be supported?
The patch adds only support for the i.MX51 and does I understand what you mean. However, the driver at moment has the same problem with other processors (MX27, MX31). Should be not better to fix this issue with another patch that has nothing to do with i.MX51 ?
-#error "define CONFIG_SYS_MX31_UARTx to use the mx31 UART driver" +#error "define CONFIG_SYS_MXxx_UARTx to use the mxxx UART driver"
WHat's "mxxx" supposed to mean? This is not readable.
You are right. I want only to get rid of specific processor statement, because according to code this driver runs on several Freescale imx processor. "MXC UART driver" is better defined as what I did.
#ifdef CONFIG_MX31 u32 clk = mx31_get_ipg_clk(); +#elif defined(CONFIG_MX51)
- u32 clk = mxc_get_clock(MXC_UART_CLK);
#else u32 clk = imx_get_perclk1(); #endif
Cannot we have a common clock interface?
There is already a patch by John Rigby to drop them and using a general function for all of them. However, you are reviewing my first patchset. In V2 I have already removed the special implementation for MX51 and I have added the general function imx_get_uartclk(), as John implemented for the other MX processors.
Best regards, Stefano Babic

Dear Stefano Babic,
In message 4B540AB9.5080602@denx.de you wrote:
What happens if - for example - CONFIG_SYS_MX51_UART1 _and_ CONFIG_SYS_MX51_UART2 are defiend? How is CONFIG_SERIAL_MULTI going to be supported?
The patch adds only support for the i.MX51 and does
Something missing here ???
I understand what you mean. However, the driver at moment has the same problem with other processors (MX27, MX31). Should be not better to fix this issue with another patch that has nothing to do with i.MX51 ?
That's OK with me. But then, this shouldbe documented so nobody tries to enable more than one serial port.
There is already a patch by John Rigby to drop them and using a general function for all of them. However, you are reviewing my first patchset.
Sorry, I only noticed this later :-(
In V2 I have already removed the special implementation for MX51 and I have added the general function imx_get_uartclk(), as John implemented for the other MX processors.
Thanks.
Best regards,
Wolfgang Denk

Hi Stefano,
The patch add header files to support the pin multiplexer of the the Freescale i.MX51 processor.
Signed-off-by: Stefano Babic sbabic@denx.de Signed-off-by: Fred Fan fanyefeng@gmail.com
include/asm-arm/arch-mx51/iomux.h | 240 ++++++++++++++++++++++ include/asm-arm/arch-mx51/mx51_pins.h | 365 +++++++++++++++++++++++++++++++++ 2 files changed, 605 insertions(+), 0 deletions(-) create mode 100644 include/asm-arm/arch-mx51/iomux.h create mode 100644 include/asm-arm/arch-mx51/mx51_pins.h
diff --git a/include/asm-arm/arch-mx51/iomux.h b/include/asm-arm/arch-mx51/iomux.h new file mode 100644 index 0000000..3724bb8 --- /dev/null +++ b/include/asm-arm/arch-mx51/iomux.h @@ -0,0 +1,240 @@ +/*
- Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- */
+/*
- The code contained herein is licensed under the GNU General Public
- License. You may obtain a copy of the GNU General Public License
- Version 2 or later at the following locations:
- */
Ok, please check all your files for such a header and fix it, I will stop here complaining about them ;)
Cheers Detlev

Dear Stefano Babic,
In message 1263212760-27272-5-git-send-email-sbabic@denx.de you wrote:
The patch add header files to support the pin multiplexer of the the Freescale i.MX51 processor.
...
+/*!
- various IOMUX pad functions
- */
+typedef enum iomux_pad_config {
- PAD_CTL_SRE_SLOW = 0x0 << 0,
- PAD_CTL_SRE_FAST = 0x1 << 0,
- PAD_CTL_DRV_LOW = 0x0 << 1,
- PAD_CTL_DRV_MEDIUM = 0x1 << 1,
- PAD_CTL_DRV_HIGH = 0x2 << 1,
- PAD_CTL_DRV_MAX = 0x3 << 1,
- PAD_CTL_ODE_OPENDRAIN_NONE = 0x0 << 3,
- PAD_CTL_ODE_OPENDRAIN_ENABLE = 0x1 << 3,
- PAD_CTL_100K_PD = 0x0 << 4,
- PAD_CTL_47K_PU = 0x1 << 4,
- PAD_CTL_100K_PU = 0x2 << 4,
- PAD_CTL_22K_PU = 0x3 << 4,
- PAD_CTL_PUE_KEEPER = 0x0 << 6,
- PAD_CTL_PUE_PULL = 0x1 << 6,
- PAD_CTL_PKE_NONE = 0x0 << 7,
- PAD_CTL_PKE_ENABLE = 0x1 << 7,
- PAD_CTL_HYS_NONE = 0x0 << 8,
- PAD_CTL_HYS_ENABLE = 0x1 << 8,
- PAD_CTL_DDR_INPUT_CMOS = 0x0 << 9,
- PAD_CTL_DDR_INPUT_DDR = 0x1 << 9,
- PAD_CTL_DRV_VOT_LOW = 0x0 << 13,
- PAD_CTL_DRV_VOT_HIGH = 0x1 << 13,
+} iomux_pad_config_t;
Please add comments what these settings actually mean.
+/*!
- Request ownership for an IO pin. This function has to be the first one
- being called before that pin is used. The caller has to check the
- return value to make sure it returns 0.
- @param pin a name defined by \b iomux_pin_name_t
- @param config config as defined in \b #iomux_pin_ocfg_t
- @return 0 if successful; Non-zero otherwise
- */
+void mxc_request_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config);
+/*!
- Release ownership for an IO pin
- @param pin a name defined by \b iomux_pin_name_t
- @param config config as defined in \b #iomux_pin_ocfg_t
- */
+void mxc_free_iomux(iomux_pin_name_t pin, iomux_pin_cfg_t config);
Please provide these comments where the code gets implemented, and omit it here where we just have the prototype declarations.
...
+#define _MXC_BUILD_GPIO_PIN(gp, gi, ga, mi, pi) \
- _MXC_BUILD_PIN(gp, gi, ga, mi, pi)
+#define _MXC_BUILD_NON_GPIO_PIN(mi, pi) \
- _MXC_BUILD_PIN(NON_GPIO_PORT, 0, 0, mi, pi)
Indentation by TAB, please. Please fix globally.
Best regards,
Wolfgang Denk

Hi Stefano,
The patch add header files to support the Freescale i.MX51 processor, setting definitions for internal registers.
Signed-off-by: Stefano Babic sbabic@denx.de Signed-off-by: Fred Fan fanyefeng@gmail.com
include/asm-arm/arch-mx51/crm_regs.h | 182 +++++++++++++++++++++ include/asm-arm/arch-mx51/imx-regs.h | 298 ++++++++++++++++++++++++++++++++++ 2 files changed, 480 insertions(+), 0 deletions(-) create mode 100644 include/asm-arm/arch-mx51/crm_regs.h create mode 100644 include/asm-arm/arch-mx51/imx-regs.h
diff --git a/include/asm-arm/arch-mx51/crm_regs.h b/include/asm-arm/arch-mx51/crm_regs.h new file mode 100644 index 0000000..92da560 --- /dev/null +++ b/include/asm-arm/arch-mx51/crm_regs.h @@ -0,0 +1,182 @@ +/*
- Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- */
+/*
- The code contained herein is licensed under the GNU General Public
- License. You may obtain a copy of the GNU General Public License
- Version 2 or later at the following locations:
- */
Again we need to state explicitely the version of the GPL.
+#ifndef __ARCH_ARM_MACH_MX51_CRM_REGS_H__
+#define __ARCH_ARM_MACH_MX51_CRM_REGS_H__
+#define MXC_CCM_BASE CCM_BASE_ADDR
+/* DPLL register mapping structure */ +struct mxc_pll_reg {
- unsigned int ctrl;
- unsigned int config;
- unsigned int op;
- unsigned int mfd;
- unsigned int mfn;
- unsigned int mfn_minus;
- unsigned int mfn_plus;
- unsigned int hfs_op;
- unsigned int hfs_mfd;
- unsigned int hfs_mfn;
- unsigned int mfn_togc;
- unsigned int destat;
Why not use u32 to explicitely state the width? Same goes for the rest of the file.
Cheers Detlev

Dear Stefano Babic,
In message 1263212760-27272-4-git-send-email-sbabic@denx.de you wrote:
The patch add header files to support the Freescale i.MX51 processor, setting definitions for internal registers.
...
+/* Define the bits in register CBCDR */ +#define MXC_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26) +#define MXC_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25) +#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22)
Please remove the prens around plain numbers like here...
+#define MXC_CCM_CBCDR_EMI_PODF_MASK (0x7 << 22) +#define MXC_CCM_CBCDR_AXI_B_PODF_OFFSET (19)
... and here ... and everywhere else.
...
+/* WEIM registers */ +#define CSGCR1 0x00 +#define CSGCR2 0x04 +#define CSRCR1 0x08 +#define CSRCR2 0x0C +#define CSWCR1 0x10
This looks like something that should be converted into a C struct.
+/* ESDCTL */ +#define ESDCTL_ESDCTL0 0x00 +#define ESDCTL_ESDCFG0 0x04 +#define ESDCTL_ESDCTL1 0x08 +#define ESDCTL_ESDCFG1 0x0C +#define ESDCTL_ESDMISC 0x10 +#define ESDCTL_ESDSCR 0x14 +#define ESDCTL_ESDCDLY1 0x20 +#define ESDCTL_ESDCDLY2 0x24 +#define ESDCTL_ESDCDLY3 0x28 +#define ESDCTL_ESDCDLY4 0x2C +#define ESDCTL_ESDCDLY5 0x30 +#define ESDCTL_ESDCDLYGD 0x34
Ditto.
+/* CCM */ +#define CLKCTL_CCR 0x00 +#define CLKCTL_CCDR 0x04 +#define CLKCTL_CSR 0x08 +#define CLKCTL_CCSR 0x0C +#define CLKCTL_CACRR 0x10 +#define CLKCTL_CBCDR 0x14 +#define CLKCTL_CBCMR 0x18 +#define CLKCTL_CSCMR1 0x1C +#define CLKCTL_CSCMR2 0x20 +#define CLKCTL_CSCDR1 0x24 +#define CLKCTL_CS1CDR 0x28 +#define CLKCTL_CS2CDR 0x2C +#define CLKCTL_CDCDR 0x30 +#define CLKCTL_CHSCCDR 0x34 +#define CLKCTL_CSCDR2 0x38 +#define CLKCTL_CSCDR3 0x3C +#define CLKCTL_CSCDR4 0x40 +#define CLKCTL_CWDR 0x44 +#define CLKCTL_CDHIPR 0x48 +#define CLKCTL_CDCR 0x4C +#define CLKCTL_CTOR 0x50 +#define CLKCTL_CLPCR 0x54 +#define CLKCTL_CISR 0x58 +#define CLKCTL_CIMR 0x5C +#define CLKCTL_CCOSR 0x60 +#define CLKCTL_CGPR 0x64 +#define CLKCTL_CCGR0 0x68 +#define CLKCTL_CCGR1 0x6C +#define CLKCTL_CCGR2 0x70 +#define CLKCTL_CCGR3 0x74 +#define CLKCTL_CCGR4 0x78 +#define CLKCTL_CCGR5 0x7C +#define CLKCTL_CCGR6 0x80 +#define CLKCTL_CMEOR 0x84
And again.
+/* DPLL */ +#define PLL_DP_CTL 0x00 +#define PLL_DP_CONFIG 0x04 +#define PLL_DP_OP 0x08 +#define PLL_DP_MFD 0x0C +#define PLL_DP_MFN 0x10 +#define PLL_DP_MFNMINUS 0x14 +#define PLL_DP_MFNPLUS 0x18 +#define PLL_DP_HFS_OP 0x1C +#define PLL_DP_HFS_MFD 0x20 +#define PLL_DP_HFS_MFN 0x24 +#define PLL_DP_TOGC 0x28 +#define PLL_DP_DESTAT 0x2C
And again.
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Stefano Babic,
Hi Wolfgang,
+#define MXC_CCM_CBCDR_EMI_PODF_OFFSET (22)
Thanks, I do it.
+/* WEIM registers */ +#define CSGCR1 0x00 +#define CSGCR2 0x04 +#define CSRCR1 0x08 +#define CSRCR2 0x0C +#define CSWCR1 0x10
This looks like something that should be converted into a C struct.
You are right.
+#define ESDCTL_ESDCDLY5 0x30 +#define ESDCTL_ESDCDLYGD 0x34
Ditto.
i can say more: this defines are not used anymore and I can drop them. I have already cleanup the code removing unnecessary defines, but it seems not enough.
+/* CCM */ +#define CLKCTL_CCR 0x00 +#define CLKCTL_CCDR 0x04 +#define CLKCTL_CSR 0x08 +#define CLKCTL_CCSR 0x0C +#define CLKCTL_CACRR 0x10 +#define CLKCTL_CBCDR 0x14 +#define CLKCTL_CBCMR 0x18 +#define CLKCTL_CSCMR1 0x1C
They are obsolete,too. There is already a C struct describing them. I drop them.
+#define CLKCTL_CCGR0 0x68 +#define CLKCTL_CCGR1 0x6C +#define CLKCTL_CCGR2 0x70 +#define CLKCTL_CCGR3 0x74 +#define CLKCTL_CCGR4 0x78 +#define CLKCTL_CCGR5 0x7C +#define CLKCTL_CCGR6 0x80 +#define CLKCTL_CMEOR 0x84 +/* DPLL */ +#define PLL_DP_CTL 0x00 +#define PLL_DP_CONFIG 0x04 +#define PLL_DP_OP 0x08 +#define PLL_DP_MFD 0x0C +#define PLL_DP_MFN 0x10 +#define PLL_DP_MFNMINUS 0x14 +#define PLL_DP_MFNPLUS 0x18 +#define PLL_DP_HFS_OP 0x1C +#define PLL_DP_HFS_MFD 0x20 +#define PLL_DP_HFS_MFN 0x24 +#define PLL_DP_TOGC 0x28 +#define PLL_DP_DESTAT 0x2C
And again.
This is a different fall. These defines are used in the assembly lowlevel_init.S in the first initialization. I cannot remove them. However, only a part of these defines are currently used and I will drop the rest of them.
Best regards, Stefano Babic

Dear Stefano,
In message 4B54024E.1070103@denx.de you wrote:
+#define PLL_DP_CTL 0x00 +#define PLL_DP_CONFIG 0x04 +#define PLL_DP_OP 0x08 +#define PLL_DP_MFD 0x0C +#define PLL_DP_MFN 0x10 +#define PLL_DP_MFNMINUS 0x14 +#define PLL_DP_MFNPLUS 0x18 +#define PLL_DP_HFS_OP 0x1C +#define PLL_DP_HFS_MFD 0x20 +#define PLL_DP_HFS_MFN 0x24 +#define PLL_DP_TOGC 0x28 +#define PLL_DP_DESTAT 0x2C
And again.
This is a different fall. These defines are used in the assembly lowlevel_init.S in the first initialization. I cannot remove them. However, only a part of these defines are currently used and I will drop the rest of them.
Such offset definitions should better go into a separate asm-offsets.h file, as we did for the mpc512x (cpu/mpc512x/asm-offsets.h).
If you have some spare cycles, it would be really great if you could try and adapt the Linux method of auto-generating the asm-offsets.h file from the respective C struct declarations - we have a growing number of such cases so that would be really welcome.
Thanks in advance.
Best regards,
Wolfgang Denk

Hi Stefano,
The patch add initial support for the Freescale i.MX51 processor (family arm cortex_a8).
A small comment below.
[...]
diff --git a/cpu/arm_cortexa8/mx51/iomux.c b/cpu/arm_cortexa8/mx51/iomux.c new file mode 100644 index 0000000..a42ec3a --- /dev/null +++ b/cpu/arm_cortexa8/mx51/iomux.c @@ -0,0 +1,205 @@ +/*
- Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- */
+/*
- The code contained herein is licensed under the GNU General Public
- License. You may obtain a copy of the GNU General Public License
- Version 2 or later at the following locations:
- */
This header is not good enough - it is not clear what actual version of the GPL the code is licensed under. Please replace this with a "standard" header.
Cheers Detlev

Detlev Zundel wrote:
Hi Stefano,
Hi Detlev,
--- /dev/null +++ b/cpu/arm_cortexa8/mx51/iomux.c @@ -0,0 +1,205 @@ +/*
- Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- */
+/*
- The code contained herein is licensed under the GNU General Public
- License. You may obtain a copy of the GNU General Public License
- Version 2 or later at the following locations:
- */
This header is not good enough - it is not clear what actual version of the GPL the code is licensed under. Please replace this with a "standard" header.
I agree, but the copyright was set by Freescale and Fred in the first review said, he was not the original author of the code. I think I am not allowed to change this part even if I will not change the copyright statement. Of course, if I can, I will replace it with a standard header.
Stefano

Hi Stefano,
Detlev Zundel wrote:
Hi Stefano,
Hi Detlev,
--- /dev/null +++ b/cpu/arm_cortexa8/mx51/iomux.c @@ -0,0 +1,205 @@ +/*
- Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
- */
+/*
- The code contained herein is licensed under the GNU General Public
- License. You may obtain a copy of the GNU General Public License
- Version 2 or later at the following locations:
- */
This header is not good enough - it is not clear what actual version of the GPL the code is licensed under. Please replace this with a "standard" header.
I agree, but the copyright was set by Freescale and Fred in the first review said, he was not the original author of the code. I think I am not allowed to change this part even if I will not change the copyright statement. Of course, if I can, I will replace it with a standard header.
Well, I presume that we all agree the text wants to be read to mean "GPLv2 or later", although it does not state that clearly enough. So all I ask for is to make this more explicit - it is _not_ a change of the licensing at all.
Thanks Detlev

Hi Stefano,
The patch add initial support for the Freescale i.MX51 processor (family arm cortex_a8).
Signed-off-by: Fred Fan fanyefeng@gmail.com
I just noticed that this format misses the "<>" around the e-mail address, please fix for next round. This also applies to the other patches in this series.
Cheers Detlev

Dear Stefano Babic,
In message 1263212760-27272-3-git-send-email-sbabic@denx.de you wrote:
The patch add initial support for the Freescale i.MX51 processor (family arm cortex_a8).
...
--- /dev/null +++ b/cpu/arm_cortexa8/mx51/clock.c
...
+/*
- Calculate the frequence of this pll.
- */
Typo: frequency
+u32 get_mcu_main_clk(void) +{
- u32 reg, freq;
- reg = (__raw_readl(&mxc_ccm->cacrr) & MXC_CCM_CACRR_ARM_PODF_MASK) >>
MXC_CCM_CACRR_ARM_PODF_OFFSET;
Indentation not by TAB.
...
+/***************************************************/
+U_BOOT_CMD(
- mx51clocks, CONFIG_SYS_MAXARGS, 1, do_mx51_showclocks,
- "display mx51 clocks\n",
- ""
+);
It makes little sense to implement arch specific commands that will most probably repeated - I don;t want to see a "mx51clocks" command here, and "mx25clocks", "mx27clocks", "mx31clocks", "mx35clocks", ... commands on other systems. Just name this "clockinfo" (which is more in line with the existing commands as "bdinfo", "reginfo", "flinfo" etc.) or, if you insist, "showclocks" or just "clocks".
...
+/*!
- This function is used to configure a pin through the IOMUX module.
- @param pin a pin number as defined in \b #iomux_pin_name_t
- @param cfg an output function as defined in \b #iomux_pin_cfg_t
- @return 0 if successful; Non-zero otherwise
Lines too long, please check globally.
And please get rid of the '\b' stuff in the comments (and eventually of the "/*!" things etc., too.).
+void mxc_iomux_set_input(iomux_input_select_t input, u32 config) +{
- u32 reg;
- if (is_soc_rev(CHIP_REV_2_0) < 0) {
if (input == MUX_IN_IPU_IPP_DI_0_IND_DISPB_SD_D_SELECT_INPUT)
input -= 4;
else if (input ==
MUX_IN_IPU_IPP_DI_1_IND_DISPB_SD_D_SELECT_INPUT)
input -= 3;
else if (input >= MUX_IN_KPP_IPP_IND_COL_6_SELECT_INPUT)
input -= 2;
else if (input >=
MUX_IN_HSC_MIPI_MIX_PAR_SISG_TRIG_SELECT_INPUT)
input -= 5;
else if (input >=
MUX_IN_HSC_MIPI_MIX_IPP_IND_SENS1_DATA_EN_SELECT_INPUT)
input -= 3;
else if (input >= MUX_IN_ECSPI2_IPP_IND_SS_B_3_SELECT_INPUT)
input -= 2;
else if (input >= MUX_IN_CCM_PLL1_BYPASS_CLK_SELECT_INPUT)
input -= 1;
reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START_TO1;
- } else
reg = IOMUXSW_INPUT_CTL + (input << 2) + INPUT_CTL_START;
This is pretty much unreadable, and even more difficult to understand. Add comment to explain the logic, and fix indentation in wrapped lines (use TABs only).
diff --git a/cpu/arm_cortexa8/mx51/lowlevel_init.S b/cpu/arm_cortexa8/mx51/lowlevel_init.S new file mode 100644 index 0000000..843a7b8 --- /dev/null +++ b/cpu/arm_cortexa8/mx51/lowlevel_init.S @@ -0,0 +1,320 @@
+/*
- return soc version
- 0x10: TO1
- 0x20: TO2
- 0x30: TO3
- */
+.macro check_soc_version ret, tmp +.endm
??? Please don;t add dead code.
+/*
- L2CC Cache setup/invalidation/disable
- */
+.macro init_l2cc
- /* explicitly disable L2 cache */
mrc 15, 0, r0, c1, c0, 1
bic r0, r0, #0x2
mcr 15, 0, r0, c1, c0, 1
/* reconfigure L2 cache aux control reg */
mov r0, #0xC0 /* tag RAM */
add r0, r0, #0x4 /* data RAM */
orr r0, r0, #(1 << 24) /* disable write allocate delay */
orr r0, r0, #(1 << 23) /* disable write allocate combine */
orr r0, r0, #(1 << 22) /* disable write allocate */
Indentation by TAB only, please. Please check and fix coding style globally, in allpatches.
+/* MAX (Multi-Layer AHB Crossbar Switch) setup */ +.macro init_max +.endm /* init_max */
No dead code, please.
+/* M4IF setup */ +.macro init_m4if
- /* VPU and IPU given higher priority (0x4)
* IPU accesses with ID=0x1 given highest priority (=0xA)
*/
- ldr r0, =M4IF_BASE_ADDR
- ldr r1, =0x00000203
- str r1, [r0, #0x40]
- ldr r1, =0x0
- str r1, [r0, #0x44]
- ldr r1, =0x00120125
- str r1, [r0, #0x9C]
- ldr r1, =0x001901A3
- str r1, [r0, #0x48]
+/*
- ldr r1, =0x00000a01
- str r1, [r0, #0x48]
- ldr r1, =0x00000404
- str r1, [r0, #0x40]
+*/
No dead code please. Please fix globally.
+#if defined(CONFIG_DISPLAY_CPUINFO) +int print_cpuinfo(void) +{
- printf("CPU: Freescale i.MX51 family %d.%dV at %d MHz\n",
(get_board_rev() & 0xFF) >> 4,
(get_board_rev() & 0xF),
get_mcu_main_clk() / 1000000);
This is wrong. You ar enot printing a _BOARD_ revision here, but a processor revision. Please fix.
+ulong get_timer_masked(void) +{
- ulong val = __raw_readl(&cur_gpt->counter);
- val /= (CONFIG_MX51_CLK32 / CONFIG_SYS_HZ);
- if (val >= lastinc)
timestamp += (val - lastinc);
- else
timestamp += ((0xFFFFFFFF / (CONFIG_MX51_CLK32 / CONFIG_SYS_HZ))
- lastinc) + val;
Please use braces for multi-line statements.
- lastinc = val;
- return val;
+}
+ulong get_timer(ulong base) +{
- return get_timer_masked() - base;
+}
+void set_timer(ulong t) +{
- timestamp = t;
+}
+/* delay x useconds AND perserve advance timstamp value */ +void __udelay(unsigned long usec) +{
- unsigned long now, last = readl(&cur_gpt->counter);
- long tmo = usec * (CONFIG_MX51_CLK32 / 1000) / 1000;
- if (!tmo)
tmo = 1;
- while (tmo > 0) {
now = readl(&cur_gpt->counter);
if (last > now)
tmo -= 0xFFFFFFFF - last + now;
else
tmo -= now - last;
Is this correct wrap-around handling?
Best regards,
Wolfgang Denk

Wolfgang Denk wrote:
Dear Stefano Babic,
Hi Wolfgang,
It makes little sense to implement arch specific commands that will most probably repeated - I don;t want to see a "mx51clocks" command here, and "mx25clocks", "mx27clocks", "mx31clocks", "mx35clocks", ... commands on other systems. Just name this "clockinfo" (which is more in line with the existing commands as "bdinfo", "reginfo", "flinfo" etc.) or, if you insist, "showclocks" or just "clocks".
Understood, you are right, clockinfo is a much more neutral name.
+/* delay x useconds AND perserve advance timstamp value */ +void __udelay(unsigned long usec) +{
- unsigned long now, last = readl(&cur_gpt->counter);
- long tmo = usec * (CONFIG_MX51_CLK32 / 1000) / 1000;
- if (!tmo)
tmo = 1;
- while (tmo > 0) {
now = readl(&cur_gpt->counter);
if (last > now)
tmo -= 0xFFFFFFFF - last + now;
else
tmo -= now - last;
Is this correct wrap-around handling?
Well, the code is quite the same as in omap3. It seems that omap suffers from the same issue. Best thing here should be to read the timer before the loop to get a timestamp and to check in the loop for the wrap-around, resetting the counter if needed.
Best regards, Stefano Babic

Dear Stefano Babic,
In message 4B540829.3080305@denx.de you wrote:
- unsigned long now, last = readl(&cur_gpt->counter);
- long tmo = usec * (CONFIG_MX51_CLK32 / 1000) / 1000;
- if (!tmo)
tmo = 1;
- while (tmo > 0) {
now = readl(&cur_gpt->counter);
if (last > now)
tmo -= 0xFFFFFFFF - last + now;
else
tmo -= now - last;
Is this correct wrap-around handling?
Well, the code is quite the same as in omap3. It seems that omap suffers from the same issue. Best thing here should be to read the timer before
Maybe, I didn;t check. Eventually OMAP can be fixed, too.
the loop to get a timestamp and to check in the loop for the wrap-around, resetting the counter if needed.
Do we really have to make it such complicated? All this are "usinged int" operations, right? Then let's just make use of the properties of "usinged int" artihmentics...
IMO the code should be rewritten like this:
unsigned long start, now, timeout;
start = now = readl(&cur_gpt->counter);
while ((now - start) < timeout) now = readl(&cur_gpt->counter);
This should handle wraparounds nicely.
Best regards,
Wolfgang Denk

Hi Stefano,
This patch adds support for "imximage" (MX Boot Image) to the mkimage utility. The imximage is used on the Freescales's MX.51 processors.
Further details under doc/README.imximage.
This patch was tested on a Freescale mx51evk board.
You should run checkpatch over this. Apart from that some comments below.
[...]
diff --git a/tools/imximage.c b/tools/imximage.c new file mode 100644 index 0000000..b40a23b --- /dev/null +++ b/tools/imximage.c @@ -0,0 +1,289 @@ +/*
- (C) Copyright 2009
- Stefano Babic, DENX Software Engineering, sbabic@denx.de.
- (C) Copyright 2008
- Marvell Semiconductor <www.marvell.com>
- Written-by: Prafulla Wadaskar prafulla@marvell.com
- 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 "mkimage.h" +#include <image.h> +#include "imximage.h"
+/*
- Supported commands for configuration file
- */
+static table_entry_t imximage_cmds[] = {
- {CMD_BOOT_FROM, "BOOT_FROM", "boot comand", },
- {CMD_DATA, "DATA", "Reg Write Data", },
- {-1, "", "", },
+};
+/*
- Supported Boot options for configuration file
- this is needed to set the correct flash offset
- */
+static table_entry_t imximage_bootops[] = {
- {FLASH_OFFSET_SPI, "spi", "SPI Flash", },
- {FLASH_OFFSET_NAND, "nand", "NAND Flash", },
- {FLASH_OFFSET_SD, "sd", "SD Card", },
{FLASH_OFFSET_ONENAND, "onenand", "OneNAND Flash",},
Indentation not by tabs
- {-1, "", "Invalid", },
+};
+static struct imx_header imximage_header;
+static uint32_t get_cfg_value(char *token, char *name, int linenr) +{
- char *endptr;
- uint32_t value;
- errno = 0;
- value = strtoul(token, &endptr, 16);
- if (errno || (token == endptr)) {
printf ("Error: %s[%d] - Invalid hex data(%s)\n",
name, linenr, token);
exit (EXIT_FAILURE);
Errors should go to stderr
- }
- return value;
+}
+static int imximage_check_image_types (uint8_t type) +{
- if (type == IH_TYPE_IMXIMAGE)
return EXIT_SUCCESS;
- else
return EXIT_FAILURE;
+}
+static int imximage_verify_header (unsigned char *ptr, int image_size,
struct mkimage_params *params)
+{
- struct imx_header *imx_hdr = (struct imx_header *) ptr;
- flash_header_t *hdr = &imx_hdr->fhdr;
- /* Only a few checks can be done: search for magic numbers */
- if (hdr->app_code_barker != APP_CODE_BARKER)
return -FDT_ERR_BADSTRUCTURE;
- if (imx_hdr->dcd_table.preamble.barker != DCD_BARKER)
return -FDT_ERR_BADSTRUCTURE;
- return 0;
+}
+static void imximage_print_header (const void *ptr) +{
- struct imx_header *imx_hdr = (struct imx_header *) ptr;
- flash_header_t *hdr = &imx_hdr->fhdr;
- uint32_t size;
- flash_cfg_parms_t *ext_header;
- size = imx_hdr->dcd_table.preamble.length;
- if (size > (MAX_HW_CFG_SIZE * sizeof(dcd_type_addr_data_t))) {
printf ("Image corrupt: DCD size %d exceed maximum %d\n",
size / sizeof(dcd_type_addr_data_t), MAX_HW_CFG_SIZE);
stderr
exit (EXIT_FAILURE);
- }
- ext_header = (flash_cfg_parms_t *) ((uint32_t)&imx_hdr->dcd_table + sizeof (dcd_preamble_t) +
size);
- printf ("Image Type: Freescale IMX Boot Image\n");
- printf ("Data Size: ");
- genimg_print_size (ext_header->length);
- printf ("Load Address: %08x\n", (unsigned int)hdr->app_dest_ptr);
- printf ("Entry Point: %08x\n", (unsigned int)hdr->app_code_jump_vector);
+}
+static uint32_t imximage_parse_cfg_file (struct imx_header *imxhdr, char* name) +{
- FILE *fd = NULL;
- char *line = NULL;
- char * token, *saveptr1, *saveptr2;
- int lineno = 0;
- int fld, value;
- uint32_t len;
- int dcd_len = 0;
- dcd_t *dcd = &imxhdr->dcd_table;
- int32_t cmd;
- if ((fd = fopen (name, "r")) == 0) {
printf ("Error:%s - Can't open DCD file\n", name);
stderr and a missing space
exit (EXIT_FAILURE);
- }
- /* Very simple parsing, line starting with # are comments and are dropped */
- while ((getline (&line, &len, fd)) > 0) {
lineno++;
token = strtok_r (line, "\r\n", &saveptr1);
if (token == NULL)
continue;
/* Check inside the single line */
for (fld = CFG_COMMAND, cmd = CMD_INVALID, line = token; ; line = NULL, fld++) {
token = strtok_r (line, " \t", &saveptr2);
if (token == NULL)
break;
/* Drop all text starting with '#' as comments */
if (token[0] == '#')
break;
/* parse all fields in a single line */
switch (fld) {
case CFG_COMMAND:
cmd = get_table_entry_id (imximage_cmds,
"imximage commands", token);
if (cmd < 0) {
printf ("Error: %s[%d] - Invalid command (%s)\n",
name, lineno, token);
exit (EXIT_FAILURE);
}
break;
case CFG_REG_SIZE:
switch (cmd) {
case CMD_BOOT_FROM:
/* Get flash header offset */
imxhdr->flash_offset = get_table_entry_id (imximage_bootops,
"imximage boot option", token);
if (imxhdr->flash_offset == -1) {
printf ("Error: %s[%d] - Invalid boot device (%s)\n",
name, lineno, token);
exit (EXIT_FAILURE);
}
break;
case CMD_DATA:
value = get_cfg_value(token, name, lineno);
/* Byte, halfword, word */
if ((value != 1) && (value != 2) && (value != 4)) {
printf ("Error:%s[%d] - Invalid register size %d\n",
name, lineno, value);
exit (EXIT_FAILURE);
}
dcd->addr_data[dcd_len].type = value;
break;
}
case CFG_REG_ADDRESS:
if (cmd == CMD_DATA) {
dcd->addr_data[dcd_len].addr = get_cfg_value(token, name, lineno);
}
break;
case CFG_REG_VALUE:
if (cmd == CMD_DATA) {
dcd->addr_data[dcd_len].value = get_cfg_value(token, name, lineno);
dcd_len++;
}
break;
}
}
if (dcd_len > MAX_HW_CFG_SIZE) {
printf ("Error:%s[%d] - DCD table exceeds maximum size(%d)\n",
name, lineno, MAX_HW_CFG_SIZE);
}
- }
- dcd->preamble.barker = DCD_BARKER;
- dcd->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t);
- fclose (fd);
- return dcd->preamble.length;
+}
+static void imximage_set_header (void *ptr, struct stat *sbuf, int ifd,
struct mkimage_params *params)
+{
- struct imx_header *hdr = (struct imx_header *)ptr;
- flash_header_t *fhdr = &hdr->fhdr;
- int dcd_len;
- flash_cfg_parms_t *ext_header;
- uint32_t base_offset;
- /* Set default offset */
- hdr->flash_offset = FLASH_OFFSET_STANDARD;
- /* Set magic number */
- fhdr->app_code_barker = APP_CODE_BARKER;
- /* Parse dcd configuration file */
- dcd_len = imximage_parse_cfg_file (hdr, params->imagename);
- fhdr->app_dest_ptr = params->addr;
- fhdr->app_dest_ptr = params->ep - hdr->flash_offset - sizeof(struct imx_header);
- fhdr->app_code_jump_vector = params->ep;
- base_offset = fhdr->app_dest_ptr + hdr->flash_offset ;
- fhdr->dcd_ptr_ptr = (uint32_t) ((uint32_t)&fhdr->dcd_ptr -
(uint32_t)&fhdr->app_code_jump_vector) + base_offset ;
- fhdr->dcd_ptr = base_offset + ((uint32_t)&hdr->dcd_table - (uint32_t)&hdr->fhdr);
- /* The external flash header must be at the end of the DCD table */
- ext_header = (flash_cfg_parms_t *) ((uint32_t)&hdr->dcd_table + dcd_len +
sizeof(dcd_preamble_t));
- ext_header->length = sbuf->st_size + hdr->flash_offset + sizeof(struct imx_header);
- /* Security feature are not supported */
- fhdr->app_code_csf = 0;
- fhdr->super_root_key = NULL;
+}
+int imximage_check_params (struct mkimage_params *params) +{
- if (!params)
return CFG_INVALID;
- if (!strlen (params->imagename)) {
printf ("Error:%s - Configuration file not specified, "
"it is needed for imximage generation\n",
params->cmdname);
stderr and missing space
Apart from those nit-picking comments this looks really good, thanks! Detlev
participants (5)
-
Detlev Zundel
-
Fabio Estevam
-
John Rigby
-
Stefano Babic
-
Wolfgang Denk