Support for the DENX M28 SoM
Subsystems (14)
cover Support for the DENX M28 SoM
This series adds support for DENX M28 SoM and M28EVK kit.
This series depends on previous series:
* Support for both FEC interfaces on i.MX28
* Random NAND fixes and improvements
* SPL modifications
NOTE: Final version of the patchset, rebased on top of u-boot-imx/master as of commit 021ac2c4c80d272f140cd24ac292b826066d6c3c
Marek Vasut (20):
iMX28: Initial support for iMX28 CPU
iMX28: Add SSP MMC driver
FEC: Add support for iMX28 quirks
iMX28: Add PINMUX control
iMX28: Add I2C bus driver
iMX28: Add GPIO control
iMX28: Add SPI driver
iMX28: Add APBH DMA driver
iMX28: Add GPMI NAND driver
iMX28: Add driver for internal RTC
iMX28: Add image header generator tool
iMX28: Add u-boot.sb target to Makefile
iMX28: Add support for DENX M28EVK board
M28: Add MMC SPL
M28: Add doc/README.m28 documentation
iMX28: Fix ARM vector handling
M28: Add memory detection into SPL
iMX28: Add USB and USB PHY register definitions
iMX28: Add USB HOST driver
M28EVK: Enable USB HOST support
.gitignore | 1 + MAINTAINERS | 1 + Makefile | 5 + arch/arm/cpu/arm926ejs/mx28/Makefile | 46 + arch/arm/cpu/arm926ejs/mx28/clock.c | 355 +++++++ arch/arm/cpu/arm926ejs/mx28/iomux.c | 109 +++ arch/arm/cpu/arm926ejs/mx28/mx28.c | 221 +++++ arch/arm/cpu/arm926ejs/mx28/timer.c | 141 +++ arch/arm/include/asm/arch-mx28/clock.h | 61 ++ arch/arm/include/asm/arch-mx28/dma.h | 170 ++++ arch/arm/include/asm/arch-mx28/gpio.h | 32 + arch/arm/include/asm/arch-mx28/imx-regs.h | 39 + arch/arm/include/asm/arch-mx28/iomux-mx28.h | 537 +++++++++++ arch/arm/include/asm/arch-mx28/iomux.h | 168 ++++ arch/arm/include/asm/arch-mx28/regs-apbh.h | 466 +++++++++ arch/arm/include/asm/arch-mx28/regs-base.h | 88 ++ arch/arm/include/asm/arch-mx28/regs-bch.h | 230 +++++ arch/arm/include/asm/arch-mx28/regs-clkctrl.h | 312 ++++++ arch/arm/include/asm/arch-mx28/regs-common.h | 66 ++ arch/arm/include/asm/arch-mx28/regs-gpmi.h | 222 +++++ arch/arm/include/asm/arch-mx28/regs-i2c.h | 207 ++++ arch/arm/include/asm/arch-mx28/regs-ocotp.h | 173 ++++ arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++ arch/arm/include/asm/arch-mx28/regs-power.h | 413 ++++++++ arch/arm/include/asm/arch-mx28/regs-rtc.h | 147 +++ arch/arm/include/asm/arch-mx28/regs-ssp.h | 349 +++++++ arch/arm/include/asm/arch-mx28/regs-timrot.h | 171 ++++ arch/arm/include/asm/arch-mx28/regs-usb.h | 178 ++++ arch/arm/include/asm/arch-mx28/regs-usbphy.h | 151 +++ arch/arm/include/asm/arch-mx28/sys_proto.h | 32 + board/denx/m28evk/Makefile | 56 ++ board/denx/m28evk/m28_init.h | 41 + board/denx/m28evk/m28evk.c | 216 +++++ board/denx/m28evk/mem_init.c | 240 +++++ board/denx/m28evk/mmc_boot.c | 273 ++++++ board/denx/m28evk/power_init.c | 913 ++++++++++++++++++ board/denx/m28evk/start.S | 234 +++++ board/denx/m28evk/u-boot-spl.lds | 87 ++ board/denx/m28evk/u-boot.bd | 14 + boards.cfg | 1 + doc/README.m28 | 223 +++++ drivers/dma/Makefile | 1 + drivers/dma/apbh_dma.c | 691 +++++++++++++ drivers/gpio/Makefile | 1 + drivers/gpio/mxs_gpio.c | 136 +++ drivers/i2c/Makefile | 1 + drivers/i2c/mxs_i2c.c | 246 +++++ drivers/mmc/Makefile | 1 + drivers/mmc/mxsmmc.c | 351 +++++++ drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/mxs_nand.c | 1118 +++++++++++++++++++++ drivers/net/fec_mxc.c | 44 +- drivers/rtc/Makefile | 1 + drivers/rtc/mxsrtc.c | 86 ++ drivers/spi/Makefile | 1 + drivers/spi/mxs_spi.c | 186 ++++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-mxs.c | 154 +++ include/configs/m28evk.h | 303 ++++++ tools/.gitignore | 1 + tools/Makefile | 6 + tools/mxsboot.c | 684 +++++++++++++ 62 files changed, 12685 insertions(+), 2 deletions(-) create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c create mode 100644 arch/arm/cpu/arm926ejs/mx28/iomux.c create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c create mode 100644 arch/arm/include/asm/arch-mx28/clock.h create mode 100644 arch/arm/include/asm/arch-mx28/dma.h create mode 100644 arch/arm/include/asm/arch-mx28/gpio.h create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h create mode 100644 arch/arm/include/asm/arch-mx28/iomux-mx28.h create mode 100644 arch/arm/include/asm/arch-mx28/iomux.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-apbh.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-usb.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-usbphy.h create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h create mode 100644 board/denx/m28evk/Makefile create mode 100644 board/denx/m28evk/m28_init.h create mode 100644 board/denx/m28evk/m28evk.c create mode 100644 board/denx/m28evk/mem_init.c create mode 100644 board/denx/m28evk/mmc_boot.c create mode 100644 board/denx/m28evk/power_init.c create mode 100644 board/denx/m28evk/start.S create mode 100644 board/denx/m28evk/u-boot-spl.lds create mode 100644 board/denx/m28evk/u-boot.bd create mode 100644 doc/README.m28 create mode 100644 drivers/dma/apbh_dma.c create mode 100644 drivers/gpio/mxs_gpio.c create mode 100644 drivers/i2c/mxs_i2c.c create mode 100644 drivers/mmc/mxsmmc.c create mode 100644 drivers/mtd/nand/mxs_nand.c create mode 100644 drivers/rtc/mxsrtc.c create mode 100644 drivers/spi/mxs_spi.c create mode 100644 drivers/usb/host/ehci-mxs.c create mode 100644 include/configs/m28evk.h create mode 100644 tools/mxsboot.c
Signature · 1 line
1.7.7.1
PATCH 1/20 iMX28: Initial support for iMX28 CPU
This patch supports:
- Timers
- Debug UART
- Clock
--- arch/arm/cpu/arm926ejs/mx28/Makefile | 46 + arch/arm/cpu/arm926ejs/mx28/clock.c | 355 +++++++ arch/arm/cpu/arm926ejs/mx28/mx28.c | 193 ++++ arch/arm/cpu/arm926ejs/mx28/timer.c | 141 +++ arch/arm/include/asm/arch-mx28/clock.h | 61 ++ arch/arm/include/asm/arch-mx28/imx-regs.h | 38 + arch/arm/include/asm/arch-mx28/regs-base.h | 88 ++ arch/arm/include/asm/arch-mx28/regs-bch.h | 230 +++++ arch/arm/include/asm/arch-mx28/regs-clkctrl.h | 312 ++++++ arch/arm/include/asm/arch-mx28/regs-common.h | 66 ++ arch/arm/include/asm/arch-mx28/regs-gpmi.h | 222 +++++ arch/arm/include/asm/arch-mx28/regs-i2c.h | 207 ++++ arch/arm/include/asm/arch-mx28/regs-ocotp.h | 173 ++++ arch/arm/include/asm/arch-mx28/regs-pinctrl.h | 1284 +++++++++++++++++++++++++ arch/arm/include/asm/arch-mx28/regs-power.h | 413 ++++++++ arch/arm/include/asm/arch-mx28/regs-rtc.h | 147 +++ arch/arm/include/asm/arch-mx28/regs-ssp.h | 349 +++++++ arch/arm/include/asm/arch-mx28/regs-timrot.h | 171 ++++ arch/arm/include/asm/arch-mx28/sys_proto.h | 30 + 19 files changed, 4526 insertions(+), 0 deletions(-) create mode 100644 arch/arm/cpu/arm926ejs/mx28/Makefile create mode 100644 arch/arm/cpu/arm926ejs/mx28/clock.c create mode 100644 arch/arm/cpu/arm926ejs/mx28/mx28.c create mode 100644 arch/arm/cpu/arm926ejs/mx28/timer.c create mode 100644 arch/arm/include/asm/arch-mx28/clock.h create mode 100644 arch/arm/include/asm/arch-mx28/imx-regs.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-base.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-bch.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-clkctrl.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-common.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-gpmi.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-i2c.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-ocotp.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-pinctrl.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-power.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-rtc.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-ssp.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-timrot.h create mode 100644 arch/arm/include/asm/arch-mx28/sys_proto.h
arch/arm/cpu/arm926ejs/mx28/Makefile new file +46 -0
@@ -0,0 +1,46 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd at 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 +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(SOC).o + +COBJS = clock.o mx28.o timer.o + +SRCS := $(START:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) +START := $(addprefix $(obj),$(START)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +#########################################################################
arch/arm/cpu/arm926ejs/mx28/clock.c new file +355 -0
355 lines not on this page · raw message
arch/arm/cpu/arm926ejs/mx28/mx28.c new file +193 -0
193 lines not on this page · raw message
arch/arm/cpu/arm926ejs/mx28/timer.c new file +141 -0
141 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/clock.h new file +61 -0
61 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/imx-regs.h new file +38 -0
@@ -0,0 +1,38 @@ +/* +* Freescale i.MX28 Registers +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 __IMX_REGS_H__ +#define __IMX_REGS_H__ + +#include <asm/arch/regs-base.h> +#include <asm/arch/regs-bch.h> +#include <asm/arch/regs-clkctrl.h> +#include <asm/arch/regs-gpmi.h> +#include <asm/arch/regs-i2c.h> +#include <asm/arch/regs-ocotp.h> +#include <asm/arch/regs-pinctrl.h> +#include <asm/arch/regs-power.h> +#include <asm/arch/regs-rtc.h> +#include <asm/arch/regs-ssp.h> +#include <asm/arch/regs-timrot.h> + +#endif /* __IMX_REGS_H__ */
arch/arm/include/asm/arch-mx28/regs-base.h new file +88 -0
88 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-bch.h new file +230 -0
230 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-clkctrl.h new file +312 -0
312 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-common.h new file +66 -0
66 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-gpmi.h new file +222 -0
222 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-i2c.h new file +207 -0
207 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-ocotp.h new file +173 -0
173 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-pinctrl.h new file +1284 -0
868 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-power.h new file +413 -0
413 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-rtc.h new file +147 -0
147 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-ssp.h new file +349 -0
349 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/regs-timrot.h new file +171 -0
171 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/sys_proto.h new file +30 -0
Lines of this file are not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
Signature · 1 line
1.7.7.1
Part of the diff is not shown here. View the raw message.
PATCH 2/20 iMX28: Add SSP MMC driver
In reply to Marek Vasut--- arch/arm/include/asm/arch-mx28/sys_proto.h | 2 + drivers/mmc/Makefile | 1 + drivers/mmc/mxsmmc.c | 351 ++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+), 0 deletions(-) create mode 100644 drivers/mmc/mxsmmc.c
arch/arm/include/asm/arch-mx28/sys_proto.h +2 -0
@@ -27,4 +27,6 @@ int mx28_reset_block(struct mx28_register *reg);int mx28_wait_mask_set (struct mx28_register *reg,uint32_t mask,int timeout);int mx28_wait_mask_clr (struct mx28_register *reg,uint32_t mask,int timeout); +int mxsmmc_initialize (bd_t *bis,int id,int (*wp)(int )); +#endif /* __MX28_H__ */
drivers/mmc/Makefile +1 -0
@@ -36,6 +36,7 @@ COBJS-$(CONFIG_MMC_SPI) += mmc_spi.o COBJS-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o COBJS-$(CONFIG_MV_SDHCI) += mv_sdhci.o COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o +COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o COBJS-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
drivers/mmc/mxsmmc.c new file +351 -0
351 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 2/20 iMX28: Add SSP MMC driver
Quoted 382 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Andy Fleming <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- arch/arm/include/asm/arch-mx28/sys_proto.h | 2 + drivers/mmc/Makefile | 1 + drivers/mmc/mxsmmc.c | 351 ++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+), 0 deletions(-) create mode 100644 drivers/mmc/mxsmmc.carch/arm/include/asm/arch-mx28/sys_proto.h +2
-0@@ -27,4 +27,6 @@ int mx28_reset_block(struct mx28_register *reg);int mx28_wait_mask_set (struct mx28_register *reg,uint32_t mask,int timeout);int mx28_wait_mask_clr (struct mx28_register *reg,uint32_t mask,int timeout); +int mxsmmc_initialize (bd_t *bis,int id,int (*wp)(int )); +#endif /* __MX28_H__ */ drivers/mmc/Makefile +1
-0@@ -36,6 +36,7 @@ COBJS-$(CONFIG_MMC_SPI) += mmc_spi.o COBJS-$(CONFIG_ARM_PL180_MMCI) += arm_pl180_mmci.o COBJS-$(CONFIG_MV_SDHCI) += mv_sdhci.o COBJS-$(CONFIG_MXC_MMC) += mxcmmc.o +COBJS-$(CONFIG_MXS_MMC) += mxsmmc.o COBJS-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o COBJS-$(CONFIG_PXA_MMC) += pxa_mmc.o COBJS-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.odrivers/mmc/mxsmmc.c new file +341
-0@@ -0,0 +1,351 @@ +/* +* Freescale i.MX28 SSP MMC driver +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* Based on code from LTIB: +* (C) Copyright 2008-2010 Freescale Semiconductor, Inc. +* Terry Lv +* +* Copyright 2007, Freescale Semiconductor, Inc +* Andy Fleming +* +* Based vaguely on the pxa mmc code: +* (C) Copyright 2003 +* Kyle Harris, Nexus Technologies, Inc. kharris at nexus-tech.net +* +* 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 <malloc.h> +#include <mmc.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> + +struct mxsmmc_priv { +int id; +struct mx28_ssp_regs *regs; +uint32_t clkseq_bypass; +uint32_t *clkctrl_ssp; +uint32_t buswidth; +int (*mmc_is_wp)(int ); +}; + +#define MXSMMC_MAX_TIMEOUT 10000 + +/* +* Sends a command out on the bus. Takes the mmc pointer, +* a command pointer, and an optional data pointer. +*/ +static int +mxsmmc_send_cmd (struct mmc *mmc,struct mmc_cmd *cmd,struct mmc_data *data) +{ +struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv; +struct mx28_ssp_regs *ssp_regs = priv->regs; +uint32_t reg; +int timeout; +uint32_t data_count; +uint32_t *data_ptr; +uint32_t ctrl0; + +debug ("MMC%d: CMD%d\n" , mmc->block_dev.dev, cmd->cmdidx); + +/* Check bus busy */ + timeout =MXSMMC_MAX_TIMEOUT ; +while (--timeout) { +udelay (1000 ); + reg =readl (&ssp_regs->hw_ssp_status); +if (!(reg & + (SSP_STATUS_BUSY |SSP_STATUS_DATA_BUSY | +SSP_STATUS_CMD_BUSY ))) { +break ; + } + } + +if (!timeout) { +printf ("MMC%d: Bus busy timeout!\n" , mmc->block_dev.dev); +return TIMEOUT ; + } + +/* See if card is present */ +if (readl (&ssp_regs->hw_ssp_status) &SSP_STATUS_CARD_DETECT ) { +printf ("MMC%d: No card detected!\n" , mmc->block_dev.dev); +return NO_CARD_ERR ; + } + +/* Start building CTRL0 contents */ + ctrl0 = priv->buswidth; + +/* Set up command */ +if (!(cmd->resp_type &MMC_RSP_CRC )) + ctrl0 |=SSP_CTRL0_IGNORE_CRC ; +if (cmd->resp_type &MMC_RSP_PRESENT )/* Need to get response */ + ctrl0 |=SSP_CTRL0_GET_RESP ; +if (cmd->resp_type &MMC_RSP_136 )/* It's a 136 bits response */ + ctrl0 |=SSP_CTRL0_LONG_RESP ; + +/* Command index */ + reg =readl (&ssp_regs->hw_ssp_cmd0); + reg &= ~(SSP_CMD0_CMD_MASK |SSP_CMD0_APPEND_8CYC ); + reg |= cmd->cmdidx <<SSP_CMD0_CMD_OFFSET ; +if (cmd->cmdidx ==MMC_CMD_STOP_TRANSMISSION ) + reg |=SSP_CMD0_APPEND_8CYC ; +writel (reg, &ssp_regs->hw_ssp_cmd0); + +/* Command argument */ +writel (cmd->cmdarg, &ssp_regs->hw_ssp_cmd1); + +/* Set up data */ +if (data) { +/* READ or WRITE */ +if (data->flags &MMC_DATA_READ ) { + ctrl0 |=SSP_CTRL0_READ ; + }else if (priv->mmc_is_wp (mmc->block_dev.dev)) { +printf ("MMC%d: Can not write a locked card!\n" , + mmc->block_dev.dev); +return UNUSABLE_ERR ; + } + + ctrl0 |=SSP_CTRL0_DATA_XFER ; + reg = ((data->blocks -1 ) << +SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET ) | + ((ffs (data->blocksize) -1 ) << +SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET ); +writel (reg, &ssp_regs->hw_ssp_block_size); + + reg = data->blocksize * data->blocks; +writel (reg, &ssp_regs->hw_ssp_xfer_size); + } + +/* Kick off the command */ + ctrl0 |=SSP_CTRL0_WAIT_FOR_IRQ |SSP_CTRL0_ENABLE |SSP_CTRL0_RUN ; +writel (ctrl0, &ssp_regs->hw_ssp_ctrl0); + +/* Wait for the command to complete */ + timeout =MXSMMC_MAX_TIMEOUT ; +while (--timeout) { +udelay (1000 ); + reg =readl (&ssp_regs->hw_ssp_status); +if (!(reg &SSP_STATUS_CMD_BUSY )) +break ; + } + +if (!timeout) { +printf ("MMC%d: Command %d busy\n" , + mmc->block_dev.dev, cmd->cmdidx); +return TIMEOUT ; + } + +/* Check command timeout */ +if (reg &SSP_STATUS_RESP_TIMEOUT ) { +printf ("MMC%d: Command %d timeout (status 0x%08x)\n" , + mmc->block_dev.dev, cmd->cmdidx, reg); +return TIMEOUT ; + } + +/* Check command errors */ +if (reg & (SSP_STATUS_RESP_CRC_ERR |SSP_STATUS_RESP_ERR )) { +printf ("MMC%d: Command %d error (status 0x%08x)!\n" , + mmc->block_dev.dev, cmd->cmdidx, reg); +return COMM_ERR ; + } + +/* Copy response to response buffer */ +if (cmd->resp_type &MMC_RSP_136 ) { + cmd->response[3 ] =readl (&ssp_regs->hw_ssp_sdresp0); + cmd->response[2 ] =readl (&ssp_regs->hw_ssp_sdresp1); + cmd->response[1 ] =readl (&ssp_regs->hw_ssp_sdresp2); + cmd->response[0 ] =readl (&ssp_regs->hw_ssp_sdresp3); + }else + cmd->response[0 ] =readl (&ssp_regs->hw_ssp_sdresp0); + +/* Return if no data to process */ +if (!data) +return 0 ; + +/* Process the data */ + data_count = data->blocksize * data->blocks; + timeout =MXSMMC_MAX_TIMEOUT ; +if (data->flags &MMC_DATA_READ ) { + data_ptr = (uint32_t *)data->dest; +while (data_count && --timeout) { + reg =readl (&ssp_regs->hw_ssp_status); +if (!(reg &SSP_STATUS_FIFO_EMPTY )) { + *data_ptr++ =readl (&ssp_regs->hw_ssp_data); + data_count -=4 ; + timeout =MXSMMC_MAX_TIMEOUT ; + }else +udelay (1000 ); + } + }else { + data_ptr = (uint32_t *)data->src; + timeout *=100 ; +while (data_count && --timeout) { + reg =readl (&ssp_regs->hw_ssp_status); +if (!(reg &SSP_STATUS_FIFO_FULL )) { +writel (*data_ptr++, &ssp_regs->hw_ssp_data); + data_count -=4 ; + timeout =MXSMMC_MAX_TIMEOUT ; + }else +udelay (1000 ); + } + } + +if (!timeout) { +printf ("MMC%d: Data timeout with command %d (status 0x%08x)!\n" , + mmc->block_dev.dev, cmd->cmdidx, reg); +return COMM_ERR ; + } + +/* Check data errors */ + reg =readl (&ssp_regs->hw_ssp_status); +if (reg & + (SSP_STATUS_TIMEOUT |SSP_STATUS_DATA_CRC_ERR | +SSP_STATUS_FIFO_OVRFLW |SSP_STATUS_FIFO_UNDRFLW )) { +printf ("MMC%d: Data error with command %d (status 0x%08x)!\n" , + mmc->block_dev.dev, cmd->cmdidx, reg); +return COMM_ERR ; + } + +return 0 ; +} + +static void mxsmmc_set_ios (struct mmc *mmc) +{ +struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv; +struct mx28_ssp_regs *ssp_regs = priv->regs; + +/* Set the clock speed */ +if (mmc->clock) +mx28_set_ssp_busclock (priv->id, mmc->clock /1000 ); + +switch (mmc->bus_width) { +case 1 : + priv->buswidth =SSP_CTRL0_BUS_WIDTH_ONE_BIT ; +break ; +case 4 : + priv->buswidth =SSP_CTRL0_BUS_WIDTH_FOUR_BIT ; +break ; +case 8 : + priv->buswidth =SSP_CTRL0_BUS_WIDTH_EIGHT_BIT ; +break ; + } + +/* Set the bus width */ +clrsetbits_le32 (&ssp_regs->hw_ssp_ctrl0, +SSP_CTRL0_BUS_WIDTH_MASK , priv->buswidth); + +debug ("MMC%d: Set %d bits bus width\n" , + mmc->block_dev.dev, mmc->bus_width); +} + +static int mxsmmc_init (struct mmc *mmc) +{ +struct mxsmmc_priv *priv = (struct mxsmmc_priv *)mmc->priv; +struct mx28_ssp_regs *ssp_regs = priv->regs; + +/* Reset SSP */ +mx28_reset_block (&ssp_regs->hw_ssp_ctrl0_reg); + +/* 8 bits word length in MMC mode */ +clrsetbits_le32 (&ssp_regs->hw_ssp_ctrl1, +SSP_CTRL1_SSP_MODE_MASK |SSP_CTRL1_WORD_LENGTH_MASK , +SSP_CTRL1_SSP_MODE_SD_MMC |SSP_CTRL1_WORD_LENGTH_EIGHT_BITS ); + +/* Set initial bit clock 400 KHz */ +mx28_set_ssp_busclock (priv->id,400 ); + +/* Send initial 74 clock cycles (185 us @ 400 KHz)*/ +writel (SSP_CMD0_CONT_CLKING_EN , &ssp_regs->hw_ssp_cmd0_set); +udelay (200 ); +writel (SSP_CMD0_CONT_CLKING_EN , &ssp_regs->hw_ssp_cmd0_clr); + +return 0 ; +} + +int mxsmmc_initialize (bd_t *bis,int id,int (*wp)(int )) +{ +struct mx28_clkctrl_regs *clkctrl_regs = + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; +struct mmc *mmc =NULL ; +struct mxsmmc_priv *priv =NULL ; + + mmc =malloc (sizeof (struct mmc )); +if (!mmc) +return -ENOMEM ; + + priv =malloc (sizeof (struct mxsmmc_priv )); +if (!priv) { +free (mmc); +return -ENOMEM ; + } + + priv->mmc_is_wp = wp; + priv->id = id; +switch (id) { +case 0 : + priv->regs = (struct mx28_ssp_regs *)MXS_SSP0_BASE ; + priv->clkseq_bypass =CLKCTRL_CLKSEQ_BYPASS_SSP0 ; + priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp0; +break ; +case 1 : + priv->regs = (struct mx28_ssp_regs *)MXS_SSP1_BASE ; + priv->clkseq_bypass =CLKCTRL_CLKSEQ_BYPASS_SSP1 ; + priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp1; +break ; +case 2 : + priv->regs = (struct mx28_ssp_regs *)MXS_SSP2_BASE ; + priv->clkseq_bypass =CLKCTRL_CLKSEQ_BYPASS_SSP2 ; + priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp2; +break ; +case 3 : + priv->regs = (struct mx28_ssp_regs *)MXS_SSP3_BASE ; + priv->clkseq_bypass =CLKCTRL_CLKSEQ_BYPASS_SSP3 ; + priv->clkctrl_ssp = &clkctrl_regs->hw_clkctrl_ssp3; +break ; + } + +sprintf (mmc->name,"MXS MMC" ); + mmc->send_cmd = mxsmmc_send_cmd; + mmc->set_ios = mxsmmc_set_ios; + mmc->init = mxsmmc_init; + mmc->priv = priv; + + mmc->voltages =MMC_VDD_32_33 |MMC_VDD_33_34 ; + + mmc->host_caps =MMC_MODE_4BIT |MMC_MODE_8BIT | + MMC_MODE_HS_52MHz |MMC_MODE_HS ; + +/* +* SSPCLK = 480 * 18 / 29 / 1 = 297.731 MHz +* SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
drivers/mmc/mxsmmc.c line 351
Quoted 10 lines
drivers/mmc/mxsmmc.c new file +10
-0+* CLOCK_DIVIDE has to be an even value from 2 to 254, and +* CLOCK_RATE could be any integer from 0 to 255. +*/ + mmc->f_min =400000 ; + mmc->f_max =mxc_get_clock (MXC_SSP0_CLK + id) *1000 /2 ; + mmc->b_max =0 ; + +mmc_register (mmc); +return 0 ; +}
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 3/20 FEC: Add support for iMX28 quirks
In reply to Marek Vasut--- drivers/net/fec_mxc.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 42 insertions(+), 2 deletions(-)
drivers/net/fec_mxc.c +42 -2
@@ -42,6 +42,14 @@ DECLARE_GLOBAL_DATA_PTR;#define CONFIG_FEC_XCV_TYPE MII100#endif +/* +* The i.MX28 operates with packets in big endian. We need to swap them before +* sending and after receiving. +*/ +#ifdef CONFIG_MX28 +#define CONFIG_FEC_MXC_SWAP_PACKET +#endif +#undef DEBUGstruct nbuf {
@@ -51,6 +59,32 @@ struct nbuf {uint8_t head[16 ];/**< MAC header(6 + 6 + 2) + 2(aligned) */ }; +#ifdef CONFIG_FEC_MXC_SWAP_PACKET +static void swap_packet (uint32_t *packet,int length) +{ +int i; + +for (i =0 ; i <DIV_ROUND_UP (length,4 ); i++) + packet[i] =__swab32 (packet[i]); +} +#endif + +/* +* The i.MX28 has two ethernet interfaces, but they are not equal. +* Only the first one can access the MDIO bus. +*/ +#ifdef CONFIG_MX28 +static inline struct ethernet_regs *fec_miiphy_fec_to_eth (struct fec_priv *fec) +{ +return (struct ethernet_regs *)MXS_ENET0_BASE ; +} +#else +static inline struct ethernet_regs *fec_miiphy_fec_to_eth (struct fec_priv *fec) +{ +return fec->eth; +} +#endif +/* * MII-interface related functions */
@@ -59,7 +93,7 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr, {struct eth_device *edev =eth_get_dev_by_name (dev);struct fec_priv *fec = (struct fec_priv *)edev->priv; -struct ethernet_regs *eth = fec->eth; +struct ethernet_regs *eth =fec_miiphy_fec_to_eth (fec);uint32_t reg;/* convenient holder for the PHY register */ uint32_t phy;/* convenient holder for the PHY */
@@ -117,7 +151,7 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr, {struct eth_device *edev =eth_get_dev_by_name (dev);struct fec_priv *fec = (struct fec_priv *)edev->priv; -struct ethernet_regs *eth = fec->eth; +struct ethernet_regs *eth =fec_miiphy_fec_to_eth (fec);uint32_t reg;/* convenient holder for the PHY register */ uint32_t phy;/* convenient holder for the PHY */
@@ -572,6 +606,9 @@ static int fec_send(struct eth_device *dev, volatile void* packet, int length)* Note: We are always using the first buffer for transmission, * the second will be empty and only used to stop the DMA engine */ +#ifdef CONFIG_FEC_MXC_SWAP_PACKET +swap_packet ((uint32_t *)packet, length); +#endif writew (length, &fec->tbd_base[fec->tbd_index].data_length);writel ((uint32_t )packet, &fec->tbd_base[fec->tbd_index].data_pointer);/*
@@ -668,6 +705,9 @@ static int fec_recv(struct eth_device *dev)/* * Fill the buffer and pass it to upper layers */ +#ifdef CONFIG_FEC_MXC_SWAP_PACKET +swap_packet ((uint32_t *)frame->data, frame_length); +#endif memcpy (buff, frame->data, frame_length);NetReceive (buff, frame_length); len = frame_length;
Signature · 1 line
1.7.7.1
PATCH 3/20 FEC: Add support for iMX28 quirks
Quoted 90 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Ben Warren <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- drivers/net/fec_mxc.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 42 insertions(+), 2 deletions(-)drivers/net/fec_mxc.c +39
-2@@ -42,6 +42,14 @@ DECLARE_GLOBAL_DATA_PTR;#define CONFIG_FEC_XCV_TYPE MII100#endif +/* +* The i.MX28 operates with packets in big endian. We need to swap them before +* sending and after receiving. +*/ +#ifdef CONFIG_MX28 +#define CONFIG_FEC_MXC_SWAP_PACKET +#endif +#undef DEBUGstruct nbuf {@@ -51,6 +59,32 @@ struct nbuf {uint8_t head[16 ];/**< MAC header(6 + 6 + 2) + 2(aligned) */ }; +#ifdef CONFIG_FEC_MXC_SWAP_PACKET +static void swap_packet (uint32_t *packet,int length) +{ +int i; + +for (i =0 ; i <DIV_ROUND_UP (length,4 ); i++) + packet[i] =__swab32 (packet[i]); +} +#endif + +/* +* The i.MX28 has two ethernet interfaces, but they are not equal. +* Only the first one can access the MDIO bus. +*/ +#ifdef CONFIG_MX28 +static inline struct ethernet_regs *fec_miiphy_fec_to_eth (struct fec_priv *fec) +{ +return (struct ethernet_regs *)MXS_ENET0_BASE ; +} +#else +static inline struct ethernet_regs *fec_miiphy_fec_to_eth (struct fec_priv *fec) +{ +return fec->eth; +} +#endif +/* * MII-interface related functions */ @@ -59,7 +93,7 @@ static int fec_miiphy_read(const char *dev, uint8_t phyAddr, uint8_t regAddr, {struct eth_device *edev =eth_get_dev_by_name (dev);struct fec_priv *fec = (struct fec_priv *)edev->priv; -struct ethernet_regs *eth = fec->eth; +struct ethernet_regs *eth =fec_miiphy_fec_to_eth (fec);uint32_t reg;/* convenient holder for the PHY register */ uint32_t phy;/* convenient holder for the PHY */ @@ -117,7 +151,7 @@ static int fec_miiphy_write(const char *dev, uint8_t phyAddr, uint8_t regAddr, {struct eth_device *edev =eth_get_dev_by_name (dev);struct fec_priv *fec = (struct fec_priv *)edev->priv; -struct ethernet_regs *eth = fec->eth; +struct ethernet_regs *eth =fec_miiphy_fec_to_eth (fec);uint32_t reg;/* convenient holder for the PHY register */ uint32_t phy;/* convenient holder for the PHY */ @@ -572,6 +606,9 @@ static int fec_send(struct eth_device *dev, volatile void* packet, int length)* Note: We are always using the first buffer for transmission, * the second will be empty and only used to stop the DMA engine */ +#ifdef CONFIG_FEC_MXC_SWAP_PACKET +swap_packet ((uint32_t *)packet, length); +#endif writew (length, &fec->tbd_base[fec->tbd_index].data_length);writel ((uint32_t )packet, &fec->tbd_base[fec->tbd_index].data_pointer);/*
drivers/net/fec_mxc.c static int fec_recv(struct eth_device *dev) · line 713
Quoted 9 lines
drivers/net/fec_mxc.c +3
-0@@ -668,6 +705,9 @@ static int fec_recv(struct eth_device *dev)/* * Fill the buffer and pass it to upper layers */ +#ifdef CONFIG_FEC_MXC_SWAP_PACKET +swap_packet ((uint32_t *)frame->data, frame_length); +#endif memcpy (buff, frame->data, frame_length);NetReceive (buff, frame_length); len = frame_length;
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 4/20 iMX28: Add PINMUX control
In reply to Marek VasutTaken from Linux kernel with minor modifications:
commit bf985969e27b507f734435a99df8bf745a3dbb2b
Author: Shawn Guo <[email protected]> Date: Mon Dec 20 22:57:43 2010 +0800
ARM: mxs: Add iomux support
--- arch/arm/cpu/arm926ejs/mx28/Makefile | 2 +- arch/arm/cpu/arm926ejs/mx28/iomux.c | 109 ++++++ arch/arm/include/asm/arch-mx28/iomux-mx28.h | 537 +++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx28/iomux.h | 168 +++++++++ 4 files changed, 815 insertions(+), 1 deletions(-) create mode 100644 arch/arm/cpu/arm926ejs/mx28/iomux.c create mode 100644 arch/arm/include/asm/arch-mx28/iomux-mx28.h create mode 100644 arch/arm/include/asm/arch-mx28/iomux.h
arch/arm/cpu/arm926ejs/mx28/Makefile +1 -1
@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o -COBJS = clock.o mx28.o timer.o +COBJS = clock.o mx28.o iomux.o timer.o SRCS := $(START:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS))
arch/arm/cpu/arm926ejs/mx28/iomux.c new file +109 -0
109 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/iomux-mx28.h new file +537 -0
537 lines not on this page · raw message
arch/arm/include/asm/arch-mx28/iomux.h new file +168 -0
168 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 4/20 iMX28: Add PINMUX control
Quoted 857 lines · Marek Vasut
Taken from Linux kernel with minor modifications:
commit
bf985969e27b507f734435a99df8bf745a3dbb2bAuthor: Shawn Guo <[email protected]> Date: Mon Dec 20 22:57:43 2010 +0800ARM: mxs: Add iomux support
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- arch/arm/cpu/arm926ejs/mx28/Makefile | 2 +- arch/arm/cpu/arm926ejs/mx28/iomux.c | 109 ++++++ arch/arm/include/asm/arch-mx28/iomux-mx28.h | 537 +++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx28/iomux.h | 168 +++++++++ 4 files changed, 815 insertions(+), 1 deletions(-) create mode 100644 arch/arm/cpu/arm926ejs/mx28/iomux.c create mode 100644 arch/arm/include/asm/arch-mx28/iomux-mx28.h create mode 100644 arch/arm/include/asm/arch-mx28/iomux.harch/arm/cpu/arm926ejs/mx28/Makefile +1
-1@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o -COBJS = clock.o mx28.o timer.o +COBJS = clock.o mx28.o iomux.o timer.o SRCS := $(START:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS))arch/arm/cpu/arm926ejs/mx28/iomux.c new file +109
-0@@ -0,0 +1,109 @@ +/* +* Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved. +* Copyright (C) 2008 by Sascha Hauer <[email protected]> +* Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH, +* <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +*/ + +#include <common.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/iomux.h> +#include <asm/arch/imx-regs.h> + +#if defined(CONFIG_MX23 ) +#define DRIVE_OFFSET 0x200 +#define PULL_OFFSET 0x400 +#elif defined(CONFIG_MX28 ) +#define DRIVE_OFFSET 0x300 +#define PULL_OFFSET 0x600 +#else +#error "Please select CONFIG_MX23 or CONFIG_MX28" +#endif + +/* +* configures a single pad in the iomuxer +*/ +int mxs_iomux_setup_pad (iomux_cfg_t pad) +{ +u32 reg, ofs, bp, bm; +void *iomux_base = (void *)MXS_PINCTRL_BASE ; +struct mx28_register *mxs_reg; + +/* muxsel */ + ofs =0x100 ; + ofs +=PAD_BANK (pad) *0x20 +PAD_PIN (pad) /16 *0x10 ; + bp =PAD_PIN (pad) %16 *2 ; + bm =0x3 << bp; + reg =readl (iomux_base + ofs); + reg &= ~bm; + reg |=PAD_MUXSEL (pad) << bp; +writel (reg, iomux_base + ofs); + +/* drive */ + ofs =DRIVE_OFFSET ; + ofs +=PAD_BANK (pad) *0x40 +PAD_PIN (pad) /8 *0x10 ; +/* mA */ +if (PAD_MA_VALID (pad)) { + bp =PAD_PIN (pad) %8 *4 ; + bm =0x3 << bp; + reg =readl (iomux_base + ofs); + reg &= ~bm; + reg |=PAD_MA (pad) << bp; +writel (reg, iomux_base + ofs); + } +/* vol */ +if (PAD_VOL_VALID (pad)) { + bp =PAD_PIN (pad) %8 *4 +2 ; + mxs_reg = (struct mx28_register *)(iomux_base + ofs); +if (PAD_VOL (pad)) +writel (1 << bp, &mxs_reg->reg_set); +else +writel (1 << bp, &mxs_reg->reg_clr); + } + +/* pull */ +if (PAD_PULL_VALID (pad)) { + ofs =PULL_OFFSET ; + ofs +=PAD_BANK (pad) *0x10 ; + bp =PAD_PIN (pad); + mxs_reg = (struct mx28_register *)(iomux_base + ofs); +if (PAD_PULL (pad)) +writel (1 << bp, &mxs_reg->reg_set); +else +writel (1 << bp, &mxs_reg->reg_clr); + } + +return 0 ; +} + +int mxs_iomux_setup_multiple_pads (const iomux_cfg_t *pad_list,unsigned count) +{ +const iomux_cfg_t *p = pad_list; +int i; +int ret; + +for (i =0 ; i < count; i++) { + ret =mxs_iomux_setup_pad (*p); +if (ret) +return ret; + p++; + } + +return 0 ; +}arch/arm/include/asm/arch-mx28/iomux-mx28.h new file +537
-0@@ -0,0 +1,537 @@ +/* +* Copyright (C) 2009-2010 Amit Kucheria <[email protected]> +* Copyright (C) 2010 Freescale Semiconductor, Inc. +* +* 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_IOMUX_MX28_H__ +#define __MACH_IOMUX_MX28_H__ + +#include <asm/arch/iomux.h> + +/* +* The naming convention for the pad modes is MX28_PAD_<padname>__<padmode> +* If <padname> or <padmode> refers to a GPIO, it is named GPIO_<unit>_<num> +* See also iomux.h +* +* BANK PIN MUX +*/ +/* MUXSEL_0 */ +#define MX28_PAD_GPMI_D00__GPMI_D0 MXS_IOMUX_PAD_NAKED(0, 0, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_D01__GPMI_D1 MXS_IOMUX_PAD_NAKED(0, 1, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_D02__GPMI_D2 MXS_IOMUX_PAD_NAKED(0, 2, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_D03__GPMI_D3 MXS_IOMUX_PAD_NAKED(0, 3, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_D04__GPMI_D4 MXS_IOMUX_PAD_NAKED(0, 4, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_D05__GPMI_D5 MXS_IOMUX_PAD_NAKED(0, 5, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_D06__GPMI_D6 MXS_IOMUX_PAD_NAKED(0, 6, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_D07__GPMI_D7 MXS_IOMUX_PAD_NAKED(0, 7, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_CE0N__GPMI_CE0N MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_CE1N__GPMI_CE1N MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_CE2N__GPMI_CE2N MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_CE3N__GPMI_CE3N MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_RDY0__GPMI_READY0 MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_RDY1__GPMI_READY1 MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_RDY2__GPMI_READY2 MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_RDY3__GPMI_READY3 MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_RDN__GPMI_RDN MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_WRN__GPMI_WRN MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_ALE__GPMI_ALE MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_CLE__GPMI_CLE MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_0) +#define MX28_PAD_GPMI_RESETN__GPMI_RESETN MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_0) + +#define MX28_PAD_LCD_D00__LCD_D0 MXS_IOMUX_PAD_NAKED(1, 0, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D01__LCD_D1 MXS_IOMUX_PAD_NAKED(1, 1, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D02__LCD_D2 MXS_IOMUX_PAD_NAKED(1, 2, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D03__LCD_D3 MXS_IOMUX_PAD_NAKED(1, 3, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D04__LCD_D4 MXS_IOMUX_PAD_NAKED(1, 4, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D05__LCD_D5 MXS_IOMUX_PAD_NAKED(1, 5, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D06__LCD_D6 MXS_IOMUX_PAD_NAKED(1, 6, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D07__LCD_D7 MXS_IOMUX_PAD_NAKED(1, 7, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D08__LCD_D8 MXS_IOMUX_PAD_NAKED(1, 8, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D09__LCD_D9 MXS_IOMUX_PAD_NAKED(1, 9, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D10__LCD_D10 MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D11__LCD_D11 MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D12__LCD_D12 MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D13__LCD_D13 MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D14__LCD_D14 MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D15__LCD_D15 MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D16__LCD_D16 MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D17__LCD_D17 MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D18__LCD_D18 MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D19__LCD_D19 MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D20__LCD_D20 MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D21__LCD_D21 MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D22__LCD_D22 MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_0) +#define MX28_PAD_LCD_D23__LCD_D23 MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_0) +#define MX28_PAD_LCD_RD_E__LCD_RD_E MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_0) +#define MX28_PAD_LCD_WR_RWN__LCD_WR_RWN MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_0) +#define MX28_PAD_LCD_RS__LCD_RS MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_0) +#define MX28_PAD_LCD_CS__LCD_CS MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_0) +#define MX28_PAD_LCD_VSYNC__LCD_VSYNC MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_0) +#define MX28_PAD_LCD_HSYNC__LCD_HSYNC MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_0) +#define MX28_PAD_LCD_DOTCLK__LCD_DOTCLK MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_0) +#define MX28_PAD_LCD_ENABLE__LCD_ENABLE MXS_IOMUX_PAD_NAKED(1, 31, PAD_MUXSEL_0) + +#define MX28_PAD_SSP0_DATA0__SSP0_D0 MXS_IOMUX_PAD_NAKED(2, 0, PAD_MUXSEL_0) +#define MX28_PAD_SSP0_DATA1__SSP0_D1 MXS_IOMUX_PAD_NAKED(2, 1, PAD_MUXSEL_0) +#define MX28_PAD_SSP0_DATA2__SSP0_D2 MXS_IOMUX_PAD_NAKED(2, 2, PAD_MUXSEL_0) +#define MX28_PAD_SSP0_DATA3__SSP0_D3 MXS_IOMUX_PAD_NAKED(2, 3, PAD_MUXSEL_0) +#define MX28_PAD_SSP0_DATA4__SSP0_D4 MXS_IOMUX_PAD_NAKED(2, 4, PAD_MUXSEL_0) +#define MX28_PAD_SSP0_DATA5__SSP0_D5 MXS_IOMUX_PAD_NAKED(2, 5, PAD_MUXSEL_0) +#define MX28_PAD_SSP0_DATA6__SSP0_D6 MXS_IOMUX_PAD_NAKED(2, 6, PAD_MUXSEL_0) +#define MX28_PAD_SSP0_DATA7__SSP0_D7 MXS_IOMUX_PAD_NAKED(2, 7, PAD_MUXSEL_0) +#define MX28_PAD_SSP0_CMD__SSP0_CMD MXS_IOMUX_PAD_NAKED(2, 8, PAD_MUXSEL_0) +#define MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT MXS_IOMUX_PAD_NAKED(2, 9, PAD_MUXSEL_0) +#define MX28_PAD_SSP0_SCK__SSP0_SCK MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_0) +#define MX28_PAD_SSP1_SCK__SSP1_SCK MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_0) +#define MX28_PAD_SSP1_CMD__SSP1_CMD MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_0) +#define MX28_PAD_SSP1_DATA0__SSP1_D0 MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_0) +#define MX28_PAD_SSP1_DATA3__SSP1_D3 MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_0) +#define MX28_PAD_SSP2_SCK__SSP2_SCK MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_0) +#define MX28_PAD_SSP2_MOSI__SSP2_CMD MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_0) +#define MX28_PAD_SSP2_MISO__SSP2_D0 MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_0) +#define MX28_PAD_SSP2_SS0__SSP2_D3 MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_0) +#define MX28_PAD_SSP2_SS1__SSP2_D4 MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_0) +#define MX28_PAD_SSP2_SS2__SSP2_D5 MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_0) +#define MX28_PAD_SSP3_SCK__SSP3_SCK MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_0) +#define MX28_PAD_SSP3_MOSI__SSP3_CMD MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_0) +#define MX28_PAD_SSP3_MISO__SSP3_D0 MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_0) +#define MX28_PAD_SSP3_SS0__SSP3_D3 MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_0) + +#define MX28_PAD_AUART0_RX__AUART0_RX MXS_IOMUX_PAD_NAKED(3, 0, PAD_MUXSEL_0) +#define MX28_PAD_AUART0_TX__AUART0_TX MXS_IOMUX_PAD_NAKED(3, 1, PAD_MUXSEL_0) +#define MX28_PAD_AUART0_CTS__AUART0_CTS MXS_IOMUX_PAD_NAKED(3, 2, PAD_MUXSEL_0) +#define MX28_PAD_AUART0_RTS__AUART0_RTS MXS_IOMUX_PAD_NAKED(3, 3, PAD_MUXSEL_0) +#define MX28_PAD_AUART1_RX__AUART1_RX MXS_IOMUX_PAD_NAKED(3, 4, PAD_MUXSEL_0) +#define MX28_PAD_AUART1_TX__AUART1_TX MXS_IOMUX_PAD_NAKED(3, 5, PAD_MUXSEL_0) +#define MX28_PAD_AUART1_CTS__AUART1_CTS MXS_IOMUX_PAD_NAKED(3, 6, PAD_MUXSEL_0) +#define MX28_PAD_AUART1_RTS__AUART1_RTS MXS_IOMUX_PAD_NAKED(3, 7, PAD_MUXSEL_0) +#define MX28_PAD_AUART2_RX__AUART2_RX MXS_IOMUX_PAD_NAKED(3, 8, PAD_MUXSEL_0) +#define MX28_PAD_AUART2_TX__AUART2_TX MXS_IOMUX_PAD_NAKED(3, 9, PAD_MUXSEL_0) +#define MX28_PAD_AUART2_CTS__AUART2_CTS MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_0) +#define MX28_PAD_AUART2_RTS__AUART2_RTS MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_0) +#define MX28_PAD_AUART3_RX__AUART3_RX MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_0) +#define MX28_PAD_AUART3_TX__AUART3_TX MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_0) +#define MX28_PAD_AUART3_CTS__AUART3_CTS MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_0) +#define MX28_PAD_AUART3_RTS__AUART3_RTS MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_0) +#define MX28_PAD_PWM0__PWM_0 MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_0) +#define MX28_PAD_PWM1__PWM_1 MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_0) +#define MX28_PAD_PWM2__PWM_2 MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_0) +#define MX28_PAD_SAIF0_MCLK__SAIF0_MCLK MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_0) +#define MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_0) +#define MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_0) +#define MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_0) +#define MX28_PAD_I2C0_SCL__I2C0_SCL MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_0) +#define MX28_PAD_I2C0_SDA__I2C0_SDA MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_0) +#define MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_0) +#define MX28_PAD_SPDIF__SPDIF_TX MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_0) +#define MX28_PAD_PWM3__PWM_3 MXS_IOMUX_PAD_NAKED(3, 28, PAD_MUXSEL_0) +#define MX28_PAD_PWM4__PWM_4 MXS_IOMUX_PAD_NAKED(3, 29, PAD_MUXSEL_0) +#define MX28_PAD_LCD_RESET__LCD_RESET MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_0) + +#define MX28_PAD_ENET0_MDC__ENET0_MDC MXS_IOMUX_PAD_NAKED(4, 0, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_MDIO__ENET0_MDIO MXS_IOMUX_PAD_NAKED(4, 1, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_RX_EN__ENET0_RX_EN MXS_IOMUX_PAD_NAKED(4, 2, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_RXD0__ENET0_RXD0 MXS_IOMUX_PAD_NAKED(4, 3, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_RXD1__ENET0_RXD1 MXS_IOMUX_PAD_NAKED(4, 4, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_TX_CLK__ENET0_TX_CLK MXS_IOMUX_PAD_NAKED(4, 5, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_TX_EN__ENET0_TX_EN MXS_IOMUX_PAD_NAKED(4, 6, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_TXD0__ENET0_TXD0 MXS_IOMUX_PAD_NAKED(4, 7, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_TXD1__ENET0_TXD1 MXS_IOMUX_PAD_NAKED(4, 8, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_RXD2__ENET0_RXD2 MXS_IOMUX_PAD_NAKED(4, 9, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_RXD3__ENET0_RXD3 MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_TXD2__ENET0_TXD2 MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_TXD3__ENET0_TXD3 MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_CLK MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_COL__ENET0_COL MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_0) +#define MX28_PAD_ENET0_CRS__ENET0_CRS MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_0) +#define MX28_PAD_ENET_CLK__CLKCTRL_ENET MXS_IOMUX_PAD_NAKED(4, 16, PAD_MUXSEL_0) +#define MX28_PAD_JTAG_RTCK__JTAG_RTCK MXS_IOMUX_PAD_NAKED(4, 20, PAD_MUXSEL_0) + +#define MX28_PAD_EMI_D00__EMI_DATA0 MXS_IOMUX_PAD_NAKED(5, 0, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D01__EMI_DATA1 MXS_IOMUX_PAD_NAKED(5, 1, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D02__EMI_DATA2 MXS_IOMUX_PAD_NAKED(5, 2, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D03__EMI_DATA3 MXS_IOMUX_PAD_NAKED(5, 3, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D04__EMI_DATA4 MXS_IOMUX_PAD_NAKED(5, 4, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D05__EMI_DATA5 MXS_IOMUX_PAD_NAKED(5, 5, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D06__EMI_DATA6 MXS_IOMUX_PAD_NAKED(5, 6, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D07__EMI_DATA7 MXS_IOMUX_PAD_NAKED(5, 7, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D08__EMI_DATA8 MXS_IOMUX_PAD_NAKED(5, 8, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D09__EMI_DATA9 MXS_IOMUX_PAD_NAKED(5, 9, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D10__EMI_DATA10 MXS_IOMUX_PAD_NAKED(5, 10, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D11__EMI_DATA11 MXS_IOMUX_PAD_NAKED(5, 11, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D12__EMI_DATA12 MXS_IOMUX_PAD_NAKED(5, 12, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D13__EMI_DATA13 MXS_IOMUX_PAD_NAKED(5, 13, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D14__EMI_DATA14 MXS_IOMUX_PAD_NAKED(5, 14, PAD_MUXSEL_0) +#define MX28_PAD_EMI_D15__EMI_DATA15 MXS_IOMUX_PAD_NAKED(5, 15, PAD_MUXSEL_0) +#define MX28_PAD_EMI_ODT0__EMI_ODT0 MXS_IOMUX_PAD_NAKED(5, 16, PAD_MUXSEL_0) +#define MX28_PAD_EMI_DQM0__EMI_DQM0 MXS_IOMUX_PAD_NAKED(5, 17, PAD_MUXSEL_0) +#define MX28_PAD_EMI_ODT1__EMI_ODT1 MXS_IOMUX_PAD_NAKED(5, 18, PAD_MUXSEL_0) +#define MX28_PAD_EMI_DQM1__EMI_DQM1 MXS_IOMUX_PAD_NAKED(5, 19, PAD_MUXSEL_0) +#define MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK MXS_IOMUX_PAD_NAKED(5, 20, PAD_MUXSEL_0) +#define MX28_PAD_EMI_CLK__EMI_CLK MXS_IOMUX_PAD_NAKED(5, 21, PAD_MUXSEL_0) +#define MX28_PAD_EMI_DQS0__EMI_DQS0 MXS_IOMUX_PAD_NAKED(5, 22, PAD_MUXSEL_0) +#define MX28_PAD_EMI_DQS1__EMI_DQS1 MXS_IOMUX_PAD_NAKED(5, 23, PAD_MUXSEL_0) +#define MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN MXS_IOMUX_PAD_NAKED(5, 26, PAD_MUXSEL_0) + +#define MX28_PAD_EMI_A00__EMI_ADDR0 MXS_IOMUX_PAD_NAKED(6, 0, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A01__EMI_ADDR1 MXS_IOMUX_PAD_NAKED(6, 1, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A02__EMI_ADDR2 MXS_IOMUX_PAD_NAKED(6, 2, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A03__EMI_ADDR3 MXS_IOMUX_PAD_NAKED(6, 3, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A04__EMI_ADDR4 MXS_IOMUX_PAD_NAKED(6, 4, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A05__EMI_ADDR5 MXS_IOMUX_PAD_NAKED(6, 5, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A06__EMI_ADDR6 MXS_IOMUX_PAD_NAKED(6, 6, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A07__EMI_ADDR7 MXS_IOMUX_PAD_NAKED(6, 7, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A08__EMI_ADDR8 MXS_IOMUX_PAD_NAKED(6, 8, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A09__EMI_ADDR9 MXS_IOMUX_PAD_NAKED(6, 9, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A10__EMI_ADDR10 MXS_IOMUX_PAD_NAKED(6, 10, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A11__EMI_ADDR11 MXS_IOMUX_PAD_NAKED(6, 11, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A12__EMI_ADDR12 MXS_IOMUX_PAD_NAKED(6, 12, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A13__EMI_ADDR13 MXS_IOMUX_PAD_NAKED(6, 13, PAD_MUXSEL_0) +#define MX28_PAD_EMI_A14__EMI_ADDR14 MXS_IOMUX_PAD_NAKED(6, 14, PAD_MUXSEL_0) +#define MX28_PAD_EMI_BA0__EMI_BA0 MXS_IOMUX_PAD_NAKED(6, 16, PAD_MUXSEL_0) +#define MX28_PAD_EMI_BA1__EMI_BA1 MXS_IOMUX_PAD_NAKED(6, 17, PAD_MUXSEL_0) +#define MX28_PAD_EMI_BA2__EMI_BA2 MXS_IOMUX_PAD_NAKED(6, 18, PAD_MUXSEL_0) +#define MX28_PAD_EMI_CASN__EMI_CASN MXS_IOMUX_PAD_NAKED(6, 19, PAD_MUXSEL_0) +#define MX28_PAD_EMI_RASN__EMI_RASN MXS_IOMUX_PAD_NAKED(6, 20, PAD_MUXSEL_0) +#define MX28_PAD_EMI_WEN__EMI_WEN MXS_IOMUX_PAD_NAKED(6, 21, PAD_MUXSEL_0) +#define MX28_PAD_EMI_CE0N__EMI_CE0N MXS_IOMUX_PAD_NAKED(6, 22, PAD_MUXSEL_0) +#define MX28_PAD_EMI_CE1N__EMI_CE1N MXS_IOMUX_PAD_NAKED(6, 23, PAD_MUXSEL_0) +#define MX28_PAD_EMI_CKE__EMI_CKE MXS_IOMUX_PAD_NAKED(6, 24, PAD_MUXSEL_0) + +/* MUXSEL_1 */ +#define MX28_PAD_GPMI_D00__SSP1_D0 MXS_IOMUX_PAD_NAKED(0, 0, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_D01__SSP1_D1 MXS_IOMUX_PAD_NAKED(0, 1, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_D02__SSP1_D2 MXS_IOMUX_PAD_NAKED(0, 2, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_D03__SSP1_D3 MXS_IOMUX_PAD_NAKED(0, 3, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_D04__SSP1_D4 MXS_IOMUX_PAD_NAKED(0, 4, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_D05__SSP1_D5 MXS_IOMUX_PAD_NAKED(0, 5, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_D06__SSP1_D6 MXS_IOMUX_PAD_NAKED(0, 6, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_D07__SSP1_D7 MXS_IOMUX_PAD_NAKED(0, 7, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_CE0N__SSP3_D0 MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_CE1N__SSP3_D3 MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_CE2N__CAN1_TX MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_CE3N__CAN1_RX MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_RDY1__SSP1_CMD MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_RDY2__CAN0_TX MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_RDY3__CAN0_RX MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_RDN__SSP3_SCK MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_WRN__SSP1_SCK MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_ALE__SSP3_D1 MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_CLE__SSP3_D2 MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_1) +#define MX28_PAD_GPMI_RESETN__SSP3_CMD MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_1) + +#define MX28_PAD_LCD_D03__ETM_DA8 MXS_IOMUX_PAD_NAKED(1, 3, PAD_MUXSEL_1) +#define MX28_PAD_LCD_D04__ETM_DA9 MXS_IOMUX_PAD_NAKED(1, 4, PAD_MUXSEL_1) +#define MX28_PAD_LCD_D08__ETM_DA3 MXS_IOMUX_PAD_NAKED(1, 8, PAD_MUXSEL_1) +#define MX28_PAD_LCD_D09__ETM_DA4 MXS_IOMUX_PAD_NAKED(1, 9, PAD_MUXSEL_1) +#define MX28_PAD_LCD_D20__ENET1_1588_EVENT2_OUT MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_1) +#define MX28_PAD_LCD_D21__ENET1_1588_EVENT2_IN MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_1) +#define MX28_PAD_LCD_D22__ENET1_1588_EVENT3_OUT MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_1) +#define MX28_PAD_LCD_D23__ENET1_1588_EVENT3_IN MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_1) +#define MX28_PAD_LCD_RD_E__LCD_VSYNC MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_1) +#define MX28_PAD_LCD_WR_RWN__LCD_HSYNC MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_1) +#define MX28_PAD_LCD_RS__LCD_DOTCLK MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_1) +#define MX28_PAD_LCD_CS__LCD_ENABLE MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_1) +#define MX28_PAD_LCD_VSYNC__SAIF1_SDATA0 MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_1) +#define MX28_PAD_LCD_HSYNC__SAIF1_SDATA1 MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_1) +#define MX28_PAD_LCD_DOTCLK__SAIF1_MCLK MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_1) + +#define MX28_PAD_SSP0_DATA4__SSP2_D0 MXS_IOMUX_PAD_NAKED(2, 4, PAD_MUXSEL_1) +#define MX28_PAD_SSP0_DATA5__SSP2_D3 MXS_IOMUX_PAD_NAKED(2, 5, PAD_MUXSEL_1) +#define MX28_PAD_SSP0_DATA6__SSP2_CMD MXS_IOMUX_PAD_NAKED(2, 6, PAD_MUXSEL_1) +#define MX28_PAD_SSP0_DATA7__SSP2_SCK MXS_IOMUX_PAD_NAKED(2, 7, PAD_MUXSEL_1) +#define MX28_PAD_SSP1_SCK__SSP2_D1 MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_1) +#define MX28_PAD_SSP1_CMD__SSP2_D2 MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_1) +#define MX28_PAD_SSP1_DATA0__SSP2_D6 MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_1) +#define MX28_PAD_SSP1_DATA3__SSP2_D7 MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_1) +#define MX28_PAD_SSP2_SCK__AUART2_RX MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_1) +#define MX28_PAD_SSP2_MOSI__AUART2_TX MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_1) +#define MX28_PAD_SSP2_MISO__AUART3_RX MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_1) +#define MX28_PAD_SSP2_SS0__AUART3_TX MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_1) +#define MX28_PAD_SSP2_SS1__SSP2_D1 MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_1) +#define MX28_PAD_SSP2_SS2__SSP2_D2 MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_1) +#define MX28_PAD_SSP3_SCK__AUART4_TX MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_1) +#define MX28_PAD_SSP3_MOSI__AUART4_RX MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_1) +#define MX28_PAD_SSP3_MISO__AUART4_RTS MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_1) +#define MX28_PAD_SSP3_SS0__AUART4_CTS MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_1) + +#define MX28_PAD_AUART0_RX__I2C0_SCL MXS_IOMUX_PAD_NAKED(3, 0, PAD_MUXSEL_1) +#define MX28_PAD_AUART0_TX__I2C0_SDA MXS_IOMUX_PAD_NAKED(3, 1, PAD_MUXSEL_1) +#define MX28_PAD_AUART0_CTS__AUART4_RX MXS_IOMUX_PAD_NAKED(3, 2, PAD_MUXSEL_1) +#define MX28_PAD_AUART0_RTS__AUART4_TX MXS_IOMUX_PAD_NAKED(3, 3, PAD_MUXSEL_1) +#define MX28_PAD_AUART1_RX__SSP2_CARD_DETECT MXS_IOMUX_PAD_NAKED(3, 4, PAD_MUXSEL_1) +#define MX28_PAD_AUART1_TX__SSP3_CARD_DETECT MXS_IOMUX_PAD_NAKED(3, 5, PAD_MUXSEL_1) +#define MX28_PAD_AUART1_CTS__USB0_OVERCURRENT MXS_IOMUX_PAD_NAKED(3, 6, PAD_MUXSEL_1) +#define MX28_PAD_AUART1_RTS__USB0_ID MXS_IOMUX_PAD_NAKED(3, 7, PAD_MUXSEL_1) +#define MX28_PAD_AUART2_RX__SSP3_D1 MXS_IOMUX_PAD_NAKED(3, 8, PAD_MUXSEL_1) +#define MX28_PAD_AUART2_TX__SSP3_D2 MXS_IOMUX_PAD_NAKED(3, 9, PAD_MUXSEL_1) +#define MX28_PAD_AUART2_CTS__I2C1_SCL MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_1) +#define MX28_PAD_AUART2_RTS__I2C1_SDA MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_1) +#define MX28_PAD_AUART3_RX__CAN0_TX MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_1) +#define MX28_PAD_AUART3_TX__CAN0_RX MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_1) +#define MX28_PAD_AUART3_CTS__CAN1_TX MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_1) +#define MX28_PAD_AUART3_RTS__CAN1_RX MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_1) +#define MX28_PAD_PWM0__I2C1_SCL MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_1) +#define MX28_PAD_PWM1__I2C1_SDA MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_1) +#define MX28_PAD_PWM2__USB0_ID MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_1) +#define MX28_PAD_SAIF0_MCLK__PWM_3 MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_1) +#define MX28_PAD_SAIF0_LRCLK__PWM_4 MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_1) +#define MX28_PAD_SAIF0_BITCLK__PWM_5 MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_1) +#define MX28_PAD_SAIF0_SDATA0__PWM_6 MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_1) +#define MX28_PAD_I2C0_SCL__TIMROT_ROTARYA MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_1) +#define MX28_PAD_I2C0_SDA__TIMROT_ROTARYB MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_1) +#define MX28_PAD_SAIF1_SDATA0__PWM_7 MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_1) +#define MX28_PAD_LCD_RESET__LCD_VSYNC MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_1) + +#define MX28_PAD_ENET0_MDC__GPMI_CE4N MXS_IOMUX_PAD_NAKED(4, 0, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_MDIO__GPMI_CE5N MXS_IOMUX_PAD_NAKED(4, 1, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_RX_EN__GPMI_CE6N MXS_IOMUX_PAD_NAKED(4, 2, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_RXD0__GPMI_CE7N MXS_IOMUX_PAD_NAKED(4, 3, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_RXD1__GPMI_READY4 MXS_IOMUX_PAD_NAKED(4, 4, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_TX_CLK__HSADC_TRIGGER MXS_IOMUX_PAD_NAKED(4, 5, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_TX_EN__GPMI_READY5 MXS_IOMUX_PAD_NAKED(4, 6, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_TXD0__GPMI_READY6 MXS_IOMUX_PAD_NAKED(4, 7, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_TXD1__GPMI_READY7 MXS_IOMUX_PAD_NAKED(4, 8, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_RXD2__ENET1_RXD0 MXS_IOMUX_PAD_NAKED(4, 9, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_RXD3__ENET1_RXD1 MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_TXD2__ENET1_TXD0 MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_TXD3__ENET1_TXD1 MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_RX_CLK__ENET0_RX_ER MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_COL__ENET1_TX_EN MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_1) +#define MX28_PAD_ENET0_CRS__ENET1_RX_EN MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_1) + +/* MUXSEL_2 */ +#define MX28_PAD_GPMI_CE2N__ENET0_RX_ER MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_2) +#define MX28_PAD_GPMI_CE3N__SAIF1_MCLK MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_2) +#define MX28_PAD_GPMI_RDY0__USB0_ID MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_2) +#define MX28_PAD_GPMI_RDY2__ENET0_TX_ER MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_2) +#define MX28_PAD_GPMI_RDY3__HSADC_TRIGGER MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_2) +#define MX28_PAD_GPMI_ALE__SSP3_D4 MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_2) +#define MX28_PAD_GPMI_CLE__SSP3_D5 MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_2) + +#define MX28_PAD_LCD_D00__ETM_DA0 MXS_IOMUX_PAD_NAKED(1, 0, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D01__ETM_DA1 MXS_IOMUX_PAD_NAKED(1, 1, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D02__ETM_DA2 MXS_IOMUX_PAD_NAKED(1, 2, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D03__ETM_DA3 MXS_IOMUX_PAD_NAKED(1, 3, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D04__ETM_DA4 MXS_IOMUX_PAD_NAKED(1, 4, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D05__ETM_DA5 MXS_IOMUX_PAD_NAKED(1, 5, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D06__ETM_DA6 MXS_IOMUX_PAD_NAKED(1, 6, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D07__ETM_DA7 MXS_IOMUX_PAD_NAKED(1, 7, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D08__ETM_DA8 MXS_IOMUX_PAD_NAKED(1, 8, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D09__ETM_DA9 MXS_IOMUX_PAD_NAKED(1, 9, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D10__ETM_DA10 MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D11__ETM_DA11 MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D12__ETM_DA12 MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D13__ETM_DA13 MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D14__ETM_DA14 MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D15__ETM_DA15 MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D16__ETM_DA7 MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D17__ETM_DA6 MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D18__ETM_DA5 MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D19__ETM_DA4 MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D20__ETM_DA3 MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D21__ETM_DA2 MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D22__ETM_DA1 MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_2) +#define MX28_PAD_LCD_D23__ETM_DA0 MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_2) +#define MX28_PAD_LCD_RD_E__ETM_TCTL MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_2) +#define MX28_PAD_LCD_WR_RWN__ETM_TCLK MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_2) +#define MX28_PAD_LCD_HSYNC__ETM_TCTL MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_2) +#define MX28_PAD_LCD_DOTCLK__ETM_TCLK MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_2) + +#define MX28_PAD_SSP1_SCK__ENET0_1588_EVENT2_OUT MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_2) +#define MX28_PAD_SSP1_CMD__ENET0_1588_EVENT2_IN MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_2) +#define MX28_PAD_SSP1_DATA0__ENET0_1588_EVENT3_OUT MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_2) +#define MX28_PAD_SSP1_DATA3__ENET0_1588_EVENT3_IN MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_2) +#define MX28_PAD_SSP2_SCK__SAIF0_SDATA1 MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_2) +#define MX28_PAD_SSP2_MOSI__SAIF0_SDATA2 MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_2) +#define MX28_PAD_SSP2_MISO__SAIF1_SDATA1 MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_2) +#define MX28_PAD_SSP2_SS0__SAIF1_SDATA2 MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_2) +#define MX28_PAD_SSP2_SS1__USB1_OVERCURRENT MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_2) +#define MX28_PAD_SSP2_SS2__USB0_OVERCURRENT MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_2) +#define MX28_PAD_SSP3_SCK__ENET1_1588_EVENT0_OUT MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_2) +#define MX28_PAD_SSP3_MOSI__ENET1_1588_EVENT0_IN MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_2) +#define MX28_PAD_SSP3_MISO__ENET1_1588_EVENT1_OUT MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_2) +#define MX28_PAD_SSP3_SS0__ENET1_1588_EVENT1_IN MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_2) + +#define MX28_PAD_AUART0_RX__DUART_CTS MXS_IOMUX_PAD_NAKED(3, 0, PAD_MUXSEL_2) +#define MX28_PAD_AUART0_TX__DUART_RTS MXS_IOMUX_PAD_NAKED(3, 1, PAD_MUXSEL_2) +#define MX28_PAD_AUART0_CTS__DUART_RX MXS_IOMUX_PAD_NAKED(3, 2, PAD_MUXSEL_2) +#define MX28_PAD_AUART0_RTS__DUART_TX MXS_IOMUX_PAD_NAKED(3, 3, PAD_MUXSEL_2) +#define MX28_PAD_AUART1_RX__PWM_0 MXS_IOMUX_PAD_NAKED(3, 4, PAD_MUXSEL_2) +#define MX28_PAD_AUART1_TX__PWM_1 MXS_IOMUX_PAD_NAKED(3, 5, PAD_MUXSEL_2) +#define MX28_PAD_AUART1_CTS__TIMROT_ROTARYA MXS_IOMUX_PAD_NAKED(3, 6, PAD_MUXSEL_2) +#define MX28_PAD_AUART1_RTS__TIMROT_ROTARYB MXS_IOMUX_PAD_NAKED(3, 7, PAD_MUXSEL_2) +#define MX28_PAD_AUART2_RX__SSP3_D4 MXS_IOMUX_PAD_NAKED(3, 8, PAD_MUXSEL_2) +#define MX28_PAD_AUART2_TX__SSP3_D5 MXS_IOMUX_PAD_NAKED(3, 9, PAD_MUXSEL_2) +#define MX28_PAD_AUART2_CTS__SAIF1_BITCLK MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_2) +#define MX28_PAD_AUART2_RTS__SAIF1_LRCLK MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_2) +#define MX28_PAD_AUART3_RX__ENET0_1588_EVENT0_OUT MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_2) +#define MX28_PAD_AUART3_TX__ENET0_1588_EVENT0_IN MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_2) +#define MX28_PAD_AUART3_CTS__ENET0_1588_EVENT1_OUT MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_2) +#define MX28_PAD_AUART3_RTS__ENET0_1588_EVENT1_IN MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_2) +#define MX28_PAD_PWM0__DUART_RX MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_2) +#define MX28_PAD_PWM1__DUART_TX MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_2) +#define MX28_PAD_PWM2__USB1_OVERCURRENT MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_2) +#define MX28_PAD_SAIF0_MCLK__AUART4_CTS MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_2) +#define MX28_PAD_SAIF0_LRCLK__AUART4_RTS MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_2) +#define MX28_PAD_SAIF0_BITCLK__AUART4_RX MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_2) +#define MX28_PAD_SAIF0_SDATA0__AUART4_TX MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_2) +#define MX28_PAD_I2C0_SCL__DUART_RX MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_2) +#define MX28_PAD_I2C0_SDA__DUART_TX MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_2) +#define MX28_PAD_SAIF1_SDATA0__SAIF0_SDATA1 MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_2) +#define MX28_PAD_SPDIF__ENET1_RX_ER MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_2) + +#define MX28_PAD_ENET0_MDC__SAIF0_SDATA1 MXS_IOMUX_PAD_NAKED(4, 0, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_MDIO__SAIF0_SDATA2 MXS_IOMUX_PAD_NAKED(4, 1, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_RX_EN__SAIF1_SDATA1 MXS_IOMUX_PAD_NAKED(4, 2, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_RXD0__SAIF1_SDATA2 MXS_IOMUX_PAD_NAKED(4, 3, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_TX_CLK__ENET0_1588_EVENT2_OUT MXS_IOMUX_PAD_NAKED(4, 5, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_RXD2__ENET0_1588_EVENT0_OUT MXS_IOMUX_PAD_NAKED(4, 9, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_RXD3__ENET0_1588_EVENT0_IN MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_TXD2__ENET0_1588_EVENT1_OUT MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_TXD3__ENET0_1588_EVENT1_IN MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_RX_CLK__ENET0_1588_EVENT2_IN MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_COL__ENET0_1588_EVENT3_OUT MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_2) +#define MX28_PAD_ENET0_CRS__ENET0_1588_EVENT3_IN MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_2) + +/* MUXSEL_GPIO */ +#define MX28_PAD_GPMI_D00__GPIO_0_0 MXS_IOMUX_PAD_NAKED(0, 0, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_D01__GPIO_0_1 MXS_IOMUX_PAD_NAKED(0, 1, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_D02__GPIO_0_2 MXS_IOMUX_PAD_NAKED(0, 2, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_D03__GPIO_0_3 MXS_IOMUX_PAD_NAKED(0, 3, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_D04__GPIO_0_4 MXS_IOMUX_PAD_NAKED(0, 4, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_D05__GPIO_0_5 MXS_IOMUX_PAD_NAKED(0, 5, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_D06__GPIO_0_6 MXS_IOMUX_PAD_NAKED(0, 6, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_D07__GPIO_0_7 MXS_IOMUX_PAD_NAKED(0, 7, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_CE0N__GPIO_0_16 MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_CE1N__GPIO_0_17 MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_CE2N__GPIO_0_18 MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_CE3N__GPIO_0_19 MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_RDY0__GPIO_0_20 MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_RDY1__GPIO_0_21 MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_RDY2__GPIO_0_22 MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_RDY3__GPIO_0_23 MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_RDN__GPIO_0_24 MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_WRN__GPIO_0_25 MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_ALE__GPIO_0_26 MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_CLE__GPIO_0_27 MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO) +#define MX28_PAD_GPMI_RESETN__GPIO_0_28 MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO) + +#define MX28_PAD_LCD_D00__GPIO_1_0 MXS_IOMUX_PAD_NAKED(1, 0, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D01__GPIO_1_1 MXS_IOMUX_PAD_NAKED(1, 1, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D02__GPIO_1_2 MXS_IOMUX_PAD_NAKED(1, 2, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D03__GPIO_1_3 MXS_IOMUX_PAD_NAKED(1, 3, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D04__GPIO_1_4 MXS_IOMUX_PAD_NAKED(1, 4, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D05__GPIO_1_5 MXS_IOMUX_PAD_NAKED(1, 5, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D06__GPIO_1_6 MXS_IOMUX_PAD_NAKED(1, 6, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D07__GPIO_1_7 MXS_IOMUX_PAD_NAKED(1, 7, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D08__GPIO_1_8 MXS_IOMUX_PAD_NAKED(1, 8, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D09__GPIO_1_9 MXS_IOMUX_PAD_NAKED(1, 9, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D10__GPIO_1_10 MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D11__GPIO_1_11 MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D12__GPIO_1_12 MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D13__GPIO_1_13 MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D14__GPIO_1_14 MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D15__GPIO_1_15 MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D16__GPIO_1_16 MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D17__GPIO_1_17 MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D18__GPIO_1_18 MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D19__GPIO_1_19 MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D20__GPIO_1_20 MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D21__GPIO_1_21 MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D22__GPIO_1_22 MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_D23__GPIO_1_23 MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_RD_E__GPIO_1_24 MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_WR_RWN__GPIO_1_25 MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_RS__GPIO_1_26 MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_CS__GPIO_1_27 MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_VSYNC__GPIO_1_28 MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_HSYNC__GPIO_1_29 MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_DOTCLK__GPIO_1_30 MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_ENABLE__GPIO_1_31 MXS_IOMUX_PAD_NAKED(1, 31, PAD_MUXSEL_GPIO) + +#define MX28_PAD_SSP0_DATA0__GPIO_2_0 MXS_IOMUX_PAD_NAKED(2, 0, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP0_DATA1__GPIO_2_1 MXS_IOMUX_PAD_NAKED(2, 1, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP0_DATA2__GPIO_2_2 MXS_IOMUX_PAD_NAKED(2, 2, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP0_DATA3__GPIO_2_3 MXS_IOMUX_PAD_NAKED(2, 3, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP0_DATA4__GPIO_2_4 MXS_IOMUX_PAD_NAKED(2, 4, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP0_DATA5__GPIO_2_5 MXS_IOMUX_PAD_NAKED(2, 5, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP0_DATA6__GPIO_2_6 MXS_IOMUX_PAD_NAKED(2, 6, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP0_DATA7__GPIO_2_7 MXS_IOMUX_PAD_NAKED(2, 7, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP0_CMD__GPIO_2_8 MXS_IOMUX_PAD_NAKED(2, 8, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP0_DETECT__GPIO_2_9 MXS_IOMUX_PAD_NAKED(2, 9, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP0_SCK__GPIO_2_10 MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP1_SCK__GPIO_2_12 MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP1_CMD__GPIO_2_13 MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP1_DATA0__GPIO_2_14 MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP1_DATA3__GPIO_2_15 MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP2_SCK__GPIO_2_16 MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP2_MOSI__GPIO_2_17 MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP2_MISO__GPIO_2_18 MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP2_SS0__GPIO_2_19 MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP2_SS1__GPIO_2_20 MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP2_SS2__GPIO_2_21 MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP3_SCK__GPIO_2_24 MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP3_MOSI__GPIO_2_25 MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP3_MISO__GPIO_2_26 MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO) +#define MX28_PAD_SSP3_SS0__GPIO_2_27 MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO) + +#define MX28_PAD_AUART0_RX__GPIO_3_0 MXS_IOMUX_PAD_NAKED(3, 0, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART0_TX__GPIO_3_1 MXS_IOMUX_PAD_NAKED(3, 1, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART0_CTS__GPIO_3_2 MXS_IOMUX_PAD_NAKED(3, 2, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART0_RTS__GPIO_3_3 MXS_IOMUX_PAD_NAKED(3, 3, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART1_RX__GPIO_3_4 MXS_IOMUX_PAD_NAKED(3, 4, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART1_TX__GPIO_3_5 MXS_IOMUX_PAD_NAKED(3, 5, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART1_CTS__GPIO_3_6 MXS_IOMUX_PAD_NAKED(3, 6, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART1_RTS__GPIO_3_7 MXS_IOMUX_PAD_NAKED(3, 7, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART2_RX__GPIO_3_8 MXS_IOMUX_PAD_NAKED(3, 8, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART2_TX__GPIO_3_9 MXS_IOMUX_PAD_NAKED(3, 9, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART2_CTS__GPIO_3_10 MXS_IOMUX_PAD_NAKED(3, 10, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART2_RTS__GPIO_3_11 MXS_IOMUX_PAD_NAKED(3, 11, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART3_RX__GPIO_3_12 MXS_IOMUX_PAD_NAKED(3, 12, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART3_TX__GPIO_3_13 MXS_IOMUX_PAD_NAKED(3, 13, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART3_CTS__GPIO_3_14 MXS_IOMUX_PAD_NAKED(3, 14, PAD_MUXSEL_GPIO) +#define MX28_PAD_AUART3_RTS__GPIO_3_15 MXS_IOMUX_PAD_NAKED(3, 15, PAD_MUXSEL_GPIO) +#define MX28_PAD_PWM0__GPIO_3_16 MXS_IOMUX_PAD_NAKED(3, 16, PAD_MUXSEL_GPIO) +#define MX28_PAD_PWM1__GPIO_3_17 MXS_IOMUX_PAD_NAKED(3, 17, PAD_MUXSEL_GPIO) +#define MX28_PAD_PWM2__GPIO_3_18 MXS_IOMUX_PAD_NAKED(3, 18, PAD_MUXSEL_GPIO) +#define MX28_PAD_SAIF0_MCLK__GPIO_3_20 MXS_IOMUX_PAD_NAKED(3, 20, PAD_MUXSEL_GPIO) +#define MX28_PAD_SAIF0_LRCLK__GPIO_3_21 MXS_IOMUX_PAD_NAKED(3, 21, PAD_MUXSEL_GPIO) +#define MX28_PAD_SAIF0_BITCLK__GPIO_3_22 MXS_IOMUX_PAD_NAKED(3, 22, PAD_MUXSEL_GPIO) +#define MX28_PAD_SAIF0_SDATA0__GPIO_3_23 MXS_IOMUX_PAD_NAKED(3, 23, PAD_MUXSEL_GPIO) +#define MX28_PAD_I2C0_SCL__GPIO_3_24 MXS_IOMUX_PAD_NAKED(3, 24, PAD_MUXSEL_GPIO) +#define MX28_PAD_I2C0_SDA__GPIO_3_25 MXS_IOMUX_PAD_NAKED(3, 25, PAD_MUXSEL_GPIO) +#define MX28_PAD_SAIF1_SDATA0__GPIO_3_26 MXS_IOMUX_PAD_NAKED(3, 26, PAD_MUXSEL_GPIO) +#define MX28_PAD_SPDIF__GPIO_3_27 MXS_IOMUX_PAD_NAKED(3, 27, PAD_MUXSEL_GPIO) +#define MX28_PAD_PWM3__GPIO_3_28 MXS_IOMUX_PAD_NAKED(3, 28, PAD_MUXSEL_GPIO) +#define MX28_PAD_PWM4__GPIO_3_29 MXS_IOMUX_PAD_NAKED(3, 29, PAD_MUXSEL_GPIO) +#define MX28_PAD_LCD_RESET__GPIO_3_30 MXS_IOMUX_PAD_NAKED(3, 30, PAD_MUXSEL_GPIO) + +#define MX28_PAD_ENET0_MDC__GPIO_4_0 MXS_IOMUX_PAD_NAKED(4, 0, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_MDIO__GPIO_4_1 MXS_IOMUX_PAD_NAKED(4, 1, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_RX_EN__GPIO_4_2 MXS_IOMUX_PAD_NAKED(4, 2, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_RXD0__GPIO_4_3 MXS_IOMUX_PAD_NAKED(4, 3, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_RXD1__GPIO_4_4 MXS_IOMUX_PAD_NAKED(4, 4, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_TX_CLK__GPIO_4_5 MXS_IOMUX_PAD_NAKED(4, 5, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_TX_EN__GPIO_4_6 MXS_IOMUX_PAD_NAKED(4, 6, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_TXD0__GPIO_4_7 MXS_IOMUX_PAD_NAKED(4, 7, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_TXD1__GPIO_4_8 MXS_IOMUX_PAD_NAKED(4, 8, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_RXD2__GPIO_4_9 MXS_IOMUX_PAD_NAKED(4, 9, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_RXD3__GPIO_4_10 MXS_IOMUX_PAD_NAKED(4, 10, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_TXD2__GPIO_4_11 MXS_IOMUX_PAD_NAKED(4, 11, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_TXD3__GPIO_4_12 MXS_IOMUX_PAD_NAKED(4, 12, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_RX_CLK__GPIO_4_13 MXS_IOMUX_PAD_NAKED(4, 13, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_COL__GPIO_4_14 MXS_IOMUX_PAD_NAKED(4, 14, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET0_CRS__GPIO_4_15 MXS_IOMUX_PAD_NAKED(4, 15, PAD_MUXSEL_GPIO) +#define MX28_PAD_ENET_CLK__GPIO_4_16 MXS_IOMUX_PAD_NAKED(4, 16, PAD_MUXSEL_GPIO) +#define MX28_PAD_JTAG_RTCK__GPIO_4_20 MXS_IOMUX_PAD_NAKED(4, 20, PAD_MUXSEL_GPIO) + +#endif /* __MACH_IOMUX_MX28_H__ */ arch/arm/include/asm/arch-mx28/iomux.h new file +158
-0@@ -0,0 +1,168 @@ +/* +* Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH, +* <[email protected]> +* Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +*/ + +#ifndef __MACH_MXS_IOMUX_H__ +#define __MACH_MXS_IOMUX_H__ + +/* +* IOMUX/PAD Bit field definitions +* +* PAD_BANK: 0..2 (3) +* PAD_PIN: 3..7 (5) +* PAD_MUXSEL: 8..9 (2) +* PAD_MA: 10..11 (2) +* PAD_MA_VALID: 12 (1) +* PAD_VOL: 13 (1) +* PAD_VOL_VALID: 14 (1) +* PAD_PULL: 15 (1) +* PAD_PULL_VALID: 16 (1) +* RESERVED: 17..31 (15) +*/ +typedef u32 iomux_cfg_t ; + +#define MXS_PAD_BANK_SHIFT 0 +#define MXS_PAD_BANK_MASK ((iomux_cfg_t)0x7 << MXS_PAD_BANK_SHIFT) +#define MXS_PAD_PIN_SHIFT 3 +#define MXS_PAD_PIN_MASK ((iomux_cfg_t)0x1f << MXS_PAD_PIN_SHIFT) +#define MXS_PAD_MUXSEL_SHIFT 8 +#define MXS_PAD_MUXSEL_MASK ((iomux_cfg_t)0x3 << MXS_PAD_MUXSEL_SHIFT) +#define MXS_PAD_MA_SHIFT 10 +#define MXS_PAD_MA_MASK ((iomux_cfg_t)0x3 << MXS_PAD_MA_SHIFT) +#define MXS_PAD_MA_VALID_SHIFT 12 +#define MXS_PAD_MA_VALID_MASK ((iomux_cfg_t)0x1 << MXS_PAD_MA_VALID_SHIFT) +#define MXS_PAD_VOL_SHIFT 13 +#define MXS_PAD_VOL_MASK ((iomux_cfg_t)0x1 << MXS_PAD_VOL_SHIFT) +#define MXS_PAD_VOL_VALID_SHIFT 14 +#define MXS_PAD_VOL_VALID_MASK ((iomux_cfg_t)0x1 << MXS_PAD_VOL_VALID_SHIFT) +#define MXS_PAD_PULL_SHIFT 15 +#define MXS_PAD_PULL_MASK ((iomux_cfg_t)0x1 << MXS_PAD_PULL_SHIFT) +#define MXS_PAD_PULL_VALID_SHIFT 16 +#define MXS_PAD_PULL_VALID_MASK ((iomux_cfg_t)0x1 << MXS_PAD_PULL_VALID_SHIFT) + +#define PAD_MUXSEL_0 0 +#define PAD_MUXSEL_1 1 +#define PAD_MUXSEL_2 2 +#define PAD_MUXSEL_GPIO 3 + +#define PAD_4MA 0 +#define PAD_8MA 1 +#define PAD_12MA 2 +#define PAD_16MA 3 + +#define PAD_1V8 0 +#define PAD_3V3 1 + +#define PAD_NOPULL 0 +#define PAD_PULLUP 1 + +#define MXS_PAD_4MA ((PAD_4MA << MXS_PAD_MA_SHIFT) | \ + MXS_PAD_MA_VALID_MASK) +#define MXS_PAD_8MA ((PAD_8MA << MXS_PAD_MA_SHIFT) | \ + MXS_PAD_MA_VALID_MASK) +#define MXS_PAD_12MA ((PAD_12MA << MXS_PAD_MA_SHIFT) | \ + MXS_PAD_MA_VALID_MASK) +#define MXS_PAD_16MA ((PAD_16MA << MXS_PAD_MA_SHIFT) | \ + MXS_PAD_MA_VALID_MASK) + +#define MXS_PAD_1V8 ((PAD_1V8 << MXS_PAD_VOL_SHIFT) | \ + MXS_PAD_VOL_VALID_MASK) +#define MXS_PAD_3V3 ((PAD_3V3 << MXS_PAD_VOL_SHIFT) | \ + MXS_PAD_VOL_VALID_MASK) + +#define MXS_PAD_NOPULL ((PAD_NOPULL << MXS_PAD_PULL_SHIFT) | \ + MXS_PAD_PULL_VALID_MASK) +#define MXS_PAD_PULLUP ((PAD_PULLUP << MXS_PAD_PULL_SHIFT) | \ + MXS_PAD_PULL_VALID_MASK) + +/* generic pad control used in most cases */ +#define MXS_PAD_CTRL (MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL) + +#define MXS_IOMUX_PAD (_bank, _pin, _muxsel, _ma, _vol, _pull) \ + (((iomux_cfg_t)(_bank) << MXS_PAD_BANK_SHIFT) | \ + ((iomux_cfg_t)(_pin) << MXS_PAD_PIN_SHIFT) | \ + ((iomux_cfg_t)(_muxsel) << MXS_PAD_MUXSEL_SHIFT) | \ + ((iomux_cfg_t)(_ma) << MXS_PAD_MA_SHIFT) | \ + ((iomux_cfg_t)(_vol) << MXS_PAD_VOL_SHIFT) | \ + ((iomux_cfg_t)(_pull) << MXS_PAD_PULL_SHIFT)) + +/* +* A pad becomes naked, when none of mA, vol or pull +* validity bits is set. +*/ +#define MXS_IOMUX_PAD_NAKED (_bank, _pin, _muxsel) \ + MXS_IOMUX_PAD(_bank, _pin, _muxsel, 0, 0, 0) + +static inline unsigned int PAD_BANK (iomux_cfg_t pad) +{ +return (pad &MXS_PAD_BANK_MASK ) >>MXS_PAD_BANK_SHIFT ; +} + +static inline unsigned int PAD_PIN (iomux_cfg_t pad) +{ +return (pad &MXS_PAD_PIN_MASK ) >>MXS_PAD_PIN_SHIFT ; +} + +static inline unsigned int PAD_MUXSEL (iomux_cfg_t pad) +{ +return (pad &MXS_PAD_MUXSEL_MASK ) >>MXS_PAD_MUXSEL_SHIFT ; +} + +static inline unsigned int PAD_MA (iomux_cfg_t pad) +{ +return (pad &MXS_PAD_MA_MASK ) >>MXS_PAD_MA_SHIFT ; +} + +static inline unsigned int PAD_MA_VALID (iomux_cfg_t pad) +{ +return (pad &MXS_PAD_MA_VALID_MASK ) >>MXS_PAD_MA_VALID_SHIFT ; +} + +static inline unsigned int PAD_VOL (iomux_cfg_t pad) +{ +return (pad &MXS_PAD_VOL_MASK ) >>MXS_PAD_VOL_SHIFT ; +} + +static inline unsigned int PAD_VOL_VALID (iomux_cfg_t pad) +{ +return (pad &MXS_PAD_VOL_VALID_MASK ) >>MXS_PAD_VOL_VALID_SHIFT ; +} + +static inline unsigned int PAD_PULL (iomux_cfg_t pad) +{ +return (pad &MXS_PAD_PULL_MASK ) >>MXS_PAD_PULL_SHIFT ; +} + +static inline unsigned int PAD_PULL_VALID (iomux_cfg_t pad) +{ +return (pad &MXS_PAD_PULL_VALID_MASK ) >>MXS_PAD_PULL_VALID_SHIFT ; +} + +/* +* configures a single pad in the iomuxer
arch/arm/include/asm/arch-mx28/iomux.h line 168
Quoted 10 lines
arch/arm/include/asm/arch-mx28/iomux.h new file +10
-0+*/ +int mxs_iomux_setup_pad (iomux_cfg_t pad); + +/* +* configures multiple pads +* convenient way to call the above function with tables +*/ +int mxs_iomux_setup_multiple_pads (const iomux_cfg_t *pad_list,unsigned count); + +#endif /* __MACH_MXS_IOMUX_H__*/
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 5/20 iMX28: Add I2C bus driver
In reply to Marek Vasut--- drivers/i2c/Makefile | 1 + drivers/i2c/mxs_i2c.c | 246 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+), 0 deletions(-) create mode 100644 drivers/i2c/mxs_i2c.c
drivers/i2c/Makefile +1 -0
@@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o COBJS-$(CONFIG_I2C_MVTWSI) += mvtwsi.o COBJS-$(CONFIG_I2C_MV) += mv_i2c.o COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o +COBJS-$(CONFIG_I2C_MXS) += mxs_i2c.o COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o
drivers/i2c/mxs_i2c.c new file +246 -0
246 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 5/20 iMX28: Add I2C bus driver
Hello Marek,
Quoted 10 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Heiko Schocher <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- drivers/i2c/Makefile | 1 + drivers/i2c/mxs_i2c.c | 246 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+), 0 deletions(-) create mode 100644 drivers/i2c/mxs_i2c.c
Is this a repost from:
http://lists.denx.de/pipermail/u-boot/2011-September/100716.html
I acked this patch here:
http://lists.denx.de/pipermail/u-boot/2011-September/100771.html
missing in this patch, so again:
bye,
Heiko
Signature · 2 lines
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
PATCH 5/20 iMX28: Add I2C bus driver
Quoted 22 lines
Hello Marek,
Quoted 5 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Heiko Schocher <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>Quoted 7 lines
---
drivers/i2c/Makefile | 1 + drivers/i2c/mxs_i2c.c | 246 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+), 0 deletions(-) create mode 100644 drivers/i2c/mxs_i2c.cIs this a repost from:
http://lists.denx.de/pipermail/u-boot/2011-September/100716.html
I acked this patch here:
Quoted 8 lines
http://lists.denx.de/pipermail/u-boot/2011-September/100771.html
missing in this patch, so again:
Acked-by Heiko Schocher<[email protected]>bye,
Heiko
Sorry Heiko,
yes, it's a repost. I resent it to make Stefano's job easier when picking the whole series.
M
PATCH 5/20 iMX28: Add I2C bus driver
In reply to Marek VasutQuoted 265 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Heiko Schocher <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- drivers/i2c/Makefile | 1 + drivers/i2c/mxs_i2c.c | 246 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+), 0 deletions(-) create mode 100644 drivers/i2c/mxs_i2c.cdrivers/i2c/Makefile +1
-0@@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o COBJS-$(CONFIG_I2C_MVTWSI) += mvtwsi.o COBJS-$(CONFIG_I2C_MV) += mv_i2c.o COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o +COBJS-$(CONFIG_I2C_MXS) += mxs_i2c.o COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.odrivers/i2c/mxs_i2c.c new file +236
-0@@ -0,0 +1,246 @@ +/* +* Freescale i.MX28 I2C Driver +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* Partly based on Linux kernel i2c-mxs.c driver: +* Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. +* +* Which was based on a (non-working) driver which was: +* Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#include <common.h> +#include <malloc.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> + +#define MXS_I2C_MAX_TIMEOUT 1000000 + +void mxs_i2c_reset (void ) +{ +struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE ; +int ret; + + ret =mx28_reset_block (&i2c_regs->hw_i2c_ctrl0_reg); +if (ret) { +debug ("MXS I2C: Block reset timeout\n" ); +return ; + } + +writel (I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ |I2C_CTRL1_NO_SLAVE_ACK_IRQ | +I2C_CTRL1_EARLY_TERM_IRQ |I2C_CTRL1_MASTER_LOSS_IRQ | +I2C_CTRL1_SLAVE_STOP_IRQ |I2C_CTRL1_SLAVE_IRQ , + &i2c_regs->hw_i2c_ctrl1_clr); + +writel (I2C_QUEUECTRL_PIO_QUEUE_MODE , &i2c_regs->hw_i2c_queuectrl_set); +} + +void mxs_i2c_setup_read (uint8_t chip,int len) +{ +struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE ; + +writel (I2C_QUEUECMD_RETAIN_CLOCK |I2C_QUEUECMD_PRE_SEND_START | +I2C_QUEUECMD_MASTER_MODE |I2C_QUEUECMD_DIRECTION | + (1 <<I2C_QUEUECMD_XFER_COUNT_OFFSET ), + &i2c_regs->hw_i2c_queuecmd); + +writel ((chip <<1 ) |1 , &i2c_regs->hw_i2c_data); + +writel (I2C_QUEUECMD_SEND_NAK_ON_LAST |I2C_QUEUECMD_MASTER_MODE | + (len <<I2C_QUEUECMD_XFER_COUNT_OFFSET ) | +I2C_QUEUECMD_POST_SEND_STOP , &i2c_regs->hw_i2c_queuecmd); + +writel (I2C_QUEUECTRL_QUEUE_RUN , &i2c_regs->hw_i2c_queuectrl_set); +} + +void mxs_i2c_write (uchar chip,uint addr,int alen, +uchar *buf,int blen,int stop) +{ +struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE ; +uint32_t data; +int i, remain, off; + +if ((alen >4 ) || (alen ==0 )) { +debug ("MXS I2C: Invalid address length\n" ); +return ; + } + +if (stop) + stop =I2C_QUEUECMD_POST_SEND_STOP ; + +writel (I2C_QUEUECMD_PRE_SEND_START | +I2C_QUEUECMD_MASTER_MODE |I2C_QUEUECMD_DIRECTION | + ((blen + alen +1 ) <<I2C_QUEUECMD_XFER_COUNT_OFFSET ) | stop, + &i2c_regs->hw_i2c_queuecmd); + + data = (chip <<1 ) <<24 ; + +for (i =0 ; i < alen; i++) { + data >>=8 ; + data |= ((char *)&addr)[i] <<24 ; +if ((i &3 ) ==2 ) +writel (data, &i2c_regs->hw_i2c_data); + } + + off = i; +for (; i < off + blen; i++) { + data >>=8 ; + data |= buf[i - off] <<24 ; +if ((i &3 ) ==2 ) +writel (data, &i2c_regs->hw_i2c_data); + } + + remain =24 - ((i &3 ) *8 ); +if (remain) +writel (data >> remain, &i2c_regs->hw_i2c_data); + +writel (I2C_QUEUECTRL_QUEUE_RUN , &i2c_regs->hw_i2c_queuectrl_set); +} + +int mxs_i2c_wait_for_ack (void ) +{ +struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE ; +uint32_t tmp; +int timeout =MXS_I2C_MAX_TIMEOUT ; + +for (;;) { + tmp =readl (&i2c_regs->hw_i2c_ctrl1); +if (tmp &I2C_CTRL1_NO_SLAVE_ACK_IRQ ) { +debug ("MXS I2C: No slave ACK\n" ); + goto err; + } + +if (tmp & ( +I2C_CTRL1_EARLY_TERM_IRQ |I2C_CTRL1_MASTER_LOSS_IRQ | +I2C_CTRL1_SLAVE_STOP_IRQ |I2C_CTRL1_SLAVE_IRQ )) { +debug ("MXS I2C: Error (CTRL1 = %08x)\n" , tmp); + goto err; + } + +if (tmp &I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ ) +break ; + +if (!timeout--) { +debug ("MXS I2C: Operation timed out\n" ); + goto err; + } + +udelay (1 ); + } + +return 0 ; + +err: +mxs_i2c_reset (); +return 1 ; +} + +int i2c_read (uchar chip,uint addr,int alen,uchar *buffer,int len) +{ +struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE ; +uint32_t tmp =0 ; +int ret; +int i; + +mxs_i2c_write (chip, addr, alen,NULL ,0 ,0 ); + ret =mxs_i2c_wait_for_ack (); +if (ret) { +debug ("MXS I2C: Failed writing address\n" ); +return ret; + } + +mxs_i2c_setup_read (chip, len); + ret =mxs_i2c_wait_for_ack (); +if (ret) { +debug ("MXS I2C: Failed reading address\n" ); +return ret; + } + +for (i =0 ; i < len; i++) { +if (!(i &3 )) { +while (readl (&i2c_regs->hw_i2c_queuestat) & +I2C_QUEUESTAT_RD_QUEUE_EMPTY ) + ; + tmp =readl (&i2c_regs->hw_i2c_queuedata); + } + buffer[i] = tmp &0xff ; + tmp >>=8 ; + } + +return 0 ; +} + +int i2c_write (uchar chip,uint addr,int alen,uchar *buffer,int len) +{ +int ret; +mxs_i2c_write (chip, addr, alen, buffer, len,1 ); + ret =mxs_i2c_wait_for_ack (); +if (ret) +debug ("MXS I2C: Failed writing address\n" ); + +return ret; +} + +int i2c_probe (uchar chip) +{ +int ret; +mxs_i2c_write (chip,0 ,1 ,NULL ,0 ,1 ); + ret =mxs_i2c_wait_for_ack (); +mxs_i2c_reset (); +return ret; +} + +void i2c_init (int speed,int slaveadd) +{ +struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE ; + +mxs_i2c_reset (); + +switch (speed) { +case 100000 : +writel ((0x0078 <<I2C_TIMING0_HIGH_COUNT_OFFSET ) | + (0x0030 <<I2C_TIMING0_RCV_COUNT_OFFSET ), + &i2c_regs->hw_i2c_timing0); +writel ((0x0080 <<I2C_TIMING1_LOW_COUNT_OFFSET ) | + (0x0030 <<I2C_TIMING1_XMIT_COUNT_OFFSET ), + &i2c_regs->hw_i2c_timing1); +break ; +case 400000 : +writel ((0x000f <<I2C_TIMING0_HIGH_COUNT_OFFSET ) | + (0x0007 <<I2C_TIMING0_RCV_COUNT_OFFSET ), + &i2c_regs->hw_i2c_timing0); +writel ((0x001f <<I2C_TIMING1_LOW_COUNT_OFFSET ) | + (0x000f <<I2C_TIMING1_XMIT_COUNT_OFFSET ), + &i2c_regs->hw_i2c_timing1); +break ; +default :
drivers/i2c/mxs_i2c.c line 246
Quoted 10 lines
drivers/i2c/mxs_i2c.c new file +10
-0+printf ("MXS I2C: Invalid speed selected (%d Hz)\n" , speed); +return ; + } + +writel ((0x0015 <<I2C_TIMING2_BUS_FREE_OFFSET ) | + (0x000d <<I2C_TIMING2_LEADIN_COUNT_OFFSET ), + &i2c_regs->hw_i2c_timing2); + +return ; +}
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 6/20 iMX28: Add GPIO control
In reply to Marek Vasut--- arch/arm/cpu/arm926ejs/mx28/mx28.c | 6 ++ arch/arm/include/asm/arch-mx28/gpio.h | 32 ++++++++ drivers/gpio/Makefile | 1 + drivers/gpio/mxs_gpio.c | 136 +++++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch-mx28/gpio.h create mode 100644 drivers/gpio/mxs_gpio.c
arch/arm/cpu/arm926ejs/mx28/mx28.c +6 -0
@@ -31,6 +31,7 @@#include <asm/io.h> #include <asm/arch/clock.h> #include <asm/arch/gpio.h> +#include <asm/arch/iomux.h> #include <asm/arch/imx-regs.h> #include <asm/arch/sys_proto.h>
@@ -134,6 +135,11 @@ int arch_cpu_init(void)udelay (1000 ); +/* +* Configure GPIO unit +*/ +mxs_gpio_init (); + return 0; }#endif
arch/arm/include/asm/arch-mx28/gpio.h new file +32 -0
@@ -0,0 +1,32 @@ +/* +* Freescale i.MX28 GPIO +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 __MX28_GPIO_H__ +#define __MX28_GPIO_H__ + +#ifdef CONFIG_MXS_GPIO +void mxs_gpio_init (void ); +#else +inline void mxs_gpio_init (void ) {} +#endif + +#endif /* __MX28_GPIO_H__ */
drivers/gpio/Makefile +1 -0
@@ -30,6 +30,7 @@ COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o COBJS-$(CONFIG_MARVELL_GPIO) += mvgpio.o COBJS-$(CONFIG_MARVELL_MFP) += mvmfp.o COBJS-$(CONFIG_MXC_GPIO) += mxc_gpio.o +COBJS-$(CONFIG_MXS_GPIO) += mxs_gpio.o COBJS-$(CONFIG_PCA953X) += pca953x.o COBJS-$(CONFIG_PCA9698) += pca9698.o COBJS-$(CONFIG_S5P) += s5p_gpio.o
drivers/gpio/mxs_gpio.c new file +136 -0
136 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 6/20 iMX28: Add GPIO control
Quoted 219 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- arch/arm/cpu/arm926ejs/mx28/mx28.c | 6 ++ arch/arm/include/asm/arch-mx28/gpio.h | 32 ++++++++ drivers/gpio/Makefile | 1 + drivers/gpio/mxs_gpio.c | 136 +++++++++++++++++++++++++++++++++ 4 files changed, 175 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch-mx28/gpio.h create mode 100644 drivers/gpio/mxs_gpio.carch/arm/cpu/arm926ejs/mx28/mx28.c +6
-0@@ -31,6 +31,7 @@#include <asm/io.h> #include <asm/arch/clock.h> #include <asm/arch/gpio.h> +#include <asm/arch/iomux.h> #include <asm/arch/imx-regs.h> #include <asm/arch/sys_proto.h> @@ -134,6 +135,11 @@ int arch_cpu_init(void)udelay (1000 ); +/* +* Configure GPIO unit +*/ +mxs_gpio_init (); + return 0; }#endif arch/arm/include/asm/arch-mx28/gpio.h new file +32
-0@@ -0,0 +1,32 @@ +/* +* Freescale i.MX28 GPIO +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 __MX28_GPIO_H__ +#define __MX28_GPIO_H__ + +#ifdef CONFIG_MXS_GPIO +void mxs_gpio_init (void ); +#else +inline void mxs_gpio_init (void ) {} +#endif + +#endif /* __MX28_GPIO_H__ */ drivers/gpio/Makefile +1
-0@@ -30,6 +30,7 @@ COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o COBJS-$(CONFIG_MARVELL_GPIO) += mvgpio.o COBJS-$(CONFIG_MARVELL_MFP) += mvmfp.o COBJS-$(CONFIG_MXC_GPIO) += mxc_gpio.o +COBJS-$(CONFIG_MXS_GPIO) += mxs_gpio.o COBJS-$(CONFIG_PCA953X) += pca953x.o COBJS-$(CONFIG_PCA9698) += pca9698.o COBJS-$(CONFIG_S5P) += s5p_gpio.odrivers/gpio/mxs_gpio.c new file +126
-0@@ -0,0 +1,136 @@ +/* +* Freescale i.MX28 GPIO control code +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 <netdev.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/iomux.h> +#include <asm/arch/imx-regs.h> + +#if defined(CONFIG_MX23 ) +#define PINCTRL_BANKS 3 +#define PINCTRL_DOUT (n) (0x0500 + ((n) * 0x10)) +#define PINCTRL_DIN (n) (0x0600 + ((n) * 0x10)) +#define PINCTRL_DOE (n) (0x0700 + ((n) * 0x10)) +#define PINCTRL_PIN2IRQ (n) (0x0800 + ((n) * 0x10)) +#define PINCTRL_IRQEN (n) (0x0900 + ((n) * 0x10)) +#define PINCTRL_IRQSTAT (n) (0x0c00 + ((n) * 0x10)) +#elif defined(CONFIG_MX28 ) +#define PINCTRL_BANKS 5 +#define PINCTRL_DOUT (n) (0x0700 + ((n) * 0x10)) +#define PINCTRL_DIN (n) (0x0900 + ((n) * 0x10)) +#define PINCTRL_DOE (n) (0x0b00 + ((n) * 0x10)) +#define PINCTRL_PIN2IRQ (n) (0x1000 + ((n) * 0x10)) +#define PINCTRL_IRQEN (n) (0x1100 + ((n) * 0x10)) +#define PINCTRL_IRQSTAT (n) (0x1400 + ((n) * 0x10)) +#else +#error "Please select CONFIG_MX23 or CONFIG_MX28" +#endif + +#define GPIO_INT_FALL_EDGE 0x0 +#define GPIO_INT_LOW_LEV 0x1 +#define GPIO_INT_RISE_EDGE 0x2 +#define GPIO_INT_HIGH_LEV 0x3 +#define GPIO_INT_LEV_MASK (1 << 0) +#define GPIO_INT_POL_MASK (1 << 1) + +void mxs_gpio_init (void ) +{ +int i; + +for (i =0 ; i <PINCTRL_BANKS ; i++) { +writel (0 ,MXS_PINCTRL_BASE +PINCTRL_PIN2IRQ (i)); +writel (0 ,MXS_PINCTRL_BASE +PINCTRL_IRQEN (i)); +/* Use SCT address here to clear the IRQSTAT bits */ +writel (0xffffffff ,MXS_PINCTRL_BASE +PINCTRL_IRQSTAT (i) +8 ); + } +} + +int gpio_get_value (int gp) +{ +uint32_t bank =PAD_BANK (gp); +uint32_t offset =PINCTRL_DIN (bank); +struct mx28_register *reg = + (struct mx28_register *)(MXS_PINCTRL_BASE + offset); + +return (readl (®->reg) >>PAD_PIN (gp)) &1 ; +} + +void gpio_set_value (int gp,int value) +{ +uint32_t bank =PAD_BANK (gp); +uint32_t offset =PINCTRL_DOUT (bank); +struct mx28_register *reg = + (struct mx28_register *)(MXS_PINCTRL_BASE + offset); + +if (value) +writel (1 <<PAD_PIN (gp), ®->reg_set); +else +writel (1 <<PAD_PIN (gp), ®->reg_clr); +} + +int gpio_direction_input (int gp) +{ +uint32_t bank =PAD_BANK (gp); +uint32_t offset =PINCTRL_DOE (bank); +struct mx28_register *reg = + (struct mx28_register *)(MXS_PINCTRL_BASE + offset); + +writel (1 <<PAD_PIN (gp), ®->reg_clr); + +return 0 ; +} + +int gpio_direction_output (int gp,int value) +{ +uint32_t bank =PAD_BANK (gp); +uint32_t offset =PINCTRL_DOE (bank); +struct mx28_register *reg = + (struct mx28_register *)(MXS_PINCTRL_BASE + offset); + +writel (1 <<PAD_PIN (gp), ®->reg_set); + +gpio_set_value (gp, value); + +return 0 ; +} + +int gpio_request (int gp,const char *label) +{ +if (PAD_BANK (gp) >PINCTRL_BANKS ) +return -EINVAL ; + +return 0 ;
drivers/gpio/mxs_gpio.c line 136
Quoted 10 lines
drivers/gpio/mxs_gpio.c new file +10
-0+} + +void gpio_free (int gp) +{ +} + +void gpio_toggle_value (int gp) +{ +gpio_set_value (gp, !gpio_get_value (gp)); +}
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 6/20 iMX28: Add GPIO control
In reply to Marek VasutQuoted 1 line · On Wednesday 09 November 2011 04:18:13 Marek Vasut wrote:
+int
gpio_request(int gp, const char *label)
all of these gpio funcs should be "unsigned gpio"
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20111110/560b5132/attachment.pgp
PATCH 6/20 iMX28: Add GPIO control
Quoted 5 lines · On Wednesday 09 November 2011 04:18:13 Marek Vasut wrote:
Quoted 1 line
+int
gpio_request(int gp, const char *label)all of these gpio funcs should be "unsigned gpio"
-mike
It's a problem of API then?
include/asm/gpio.h:int gpio_request(int gp, const char *label);
TBH, I can't imagine gpio number to be lower than zero, but who knows.
M
PATCH 6/20 iMX28: Add GPIO control
Quoted 8 lines · On Thursday 10 November 2011 11:58:17 Marek Vasut wrote:
Quoted 4 lines · On Wednesday 09 November 2011 04:18:13 Marek Vasut wrote:
Quoted 1 line
+int
gpio_request(int gp, const char *label)all of these gpio funcs should be "unsigned gpio"
It's a problem of API then?
include/asm/gpio.h:int
gpio_request(int gp, const char *label);
a patch has been posted already to fix that
Quoted 1 line
TBH, I can't imagine gpio number to be lower than zero, but who knows.
such a value makes no sense. the incoming number is interpreted by the gpio driver, so the starting/ending numbers are completely arbitrary. thus we deal with unsigned only.
-mike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part.
Url : http://lists.denx.de/pipermail/u-boot/attachments/20111110/eb21ba2c/attachment.pgp
PATCH 6/20 iMX28: Add GPIO control
Quoted 11 lines · On Thursday 10 November 2011 11:58:17 Marek Vasut wrote:
Quoted 8 lines
Quoted 4 lines · On Wednesday 09 November 2011 04:18:13 Marek Vasut wrote:
Quoted 1 line
+int
gpio_request(int gp, const char *label)all of these gpio funcs should be "unsigned gpio"
It's a problem of API then?
include/asm/gpio.h:int
gpio_request(int gp, const char *label);a patch has been posted already to fix that
Posted, yes ... applied?
Quoted 7 lines
Quoted 2 lines
TBH, I can't imagine gpio number to be lower than zero, but who knows.
such a value makes no sense. the incoming number is interpreted by the gpio driver, so the starting/ending numbers are completely arbitrary. thus we deal with unsigned only.
-mike
Definitelly.
PATCH 7/20 iMX28: Add SPI driver
In reply to Marek Vasut--- drivers/spi/Makefile | 1 + drivers/spi/mxs_spi.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+), 0 deletions(-) create mode 100644 drivers/spi/mxs_spi.c
drivers/spi/Makefile +1 -0
@@ -37,6 +37,7 @@ COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o +COBJS-$(CONFIG_MXS_SPI) += mxs_spi.o COBJS-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
drivers/spi/mxs_spi.c new file +186 -0
186 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 7/20 iMX28: Add SPI driver
Quoted 204 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- drivers/spi/Makefile | 1 + drivers/spi/mxs_spi.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+), 0 deletions(-) create mode 100644 drivers/spi/mxs_spi.cdrivers/spi/Makefile +1
-0@@ -37,6 +37,7 @@ COBJS-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o COBJS-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o COBJS-$(CONFIG_MXC_SPI) += mxc_spi.o +COBJS-$(CONFIG_MXS_SPI) += mxs_spi.o COBJS-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o COBJS-$(CONFIG_OMAP3_SPI) += omap3_spi.o COBJS-$(CONFIG_SOFT_SPI) += soft_spi.odrivers/spi/mxs_spi.c new file +176
-0@@ -0,0 +1,186 @@ +/* +* Freescale i.MX28 SPI driver +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 +* +* NOTE: This driver only supports the SPI-controller chipselects, +* GPIO driven chipselects are not supported. +*/ + +#include <common.h> +#include <malloc.h> +#include <spi.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> + +#define MXS_SPI_MAX_TIMEOUT 1000000 +#define MXS_SPI_PORT_OFFSET 0x2000 + +struct mxs_spi_slave { +struct spi_slave slave; +uint32_t max_khz; +uint32_t mode; +struct mx28_ssp_regs *regs; +}; + +static inline struct mxs_spi_slave *to_mxs_slave (struct spi_slave *slave) +{ + return container_of(slave, struct mxs_spi_slave, slave); +} + +void spi_init (void ) +{ +} + +struct spi_slave *spi_setup_slave (unsigned int bus,unsigned int cs, +unsigned int max_hz,unsigned int mode) +{ +struct mxs_spi_slave *mxs_slave; +uint32_t addr; + +if (bus >3 ) { +printf ("MXS SPI: Max bus number is 3\n" ); +return NULL ; + } + + mxs_slave =malloc (sizeof (struct mxs_spi_slave )); +if (!mxs_slave) +return NULL ; + + addr =MXS_SSP0_BASE + (bus *MXS_SPI_PORT_OFFSET ); + + mxs_slave->slave.bus = bus; + mxs_slave->slave.cs = cs; + mxs_slave->max_khz = max_hz /1000 ; + mxs_slave->mode = mode; + mxs_slave->regs = (struct mx28_ssp_regs *)addr; + +return &mxs_slave->slave; +} + +void spi_free_slave (struct spi_slave *slave) +{ +struct mxs_spi_slave *mxs_slave =to_mxs_slave (slave); +free (mxs_slave); +} + +int spi_claim_bus (struct spi_slave *slave) +{ +struct mxs_spi_slave *mxs_slave =to_mxs_slave (slave); +struct mx28_ssp_regs *ssp_regs = mxs_slave->regs; +uint32_t reg =0 ; + +mx28_reset_block (&ssp_regs->hw_ssp_ctrl0_reg); + +writel (SSP_CTRL0_BUS_WIDTH_ONE_BIT , &ssp_regs->hw_ssp_ctrl0); + + reg =SSP_CTRL1_SSP_MODE_SPI |SSP_CTRL1_WORD_LENGTH_EIGHT_BITS ; + reg |= (mxs_slave->mode &SPI_CPOL ) ?SSP_CTRL1_POLARITY :0 ; + reg |= (mxs_slave->mode &SPI_CPHA ) ?SSP_CTRL1_PHASE :0 ; +writel (reg, &ssp_regs->hw_ssp_ctrl1); + +writel (0 , &ssp_regs->hw_ssp_cmd0); + +mx28_set_ssp_busclock (slave->bus, mxs_slave->max_khz); + +return 0 ; +} + +void spi_release_bus (struct spi_slave *slave) +{ +} + +static void mxs_spi_start_xfer (struct mx28_ssp_regs *ssp_regs) +{ +writel (SSP_CTRL0_LOCK_CS , &ssp_regs->hw_ssp_ctrl0_set); +writel (SSP_CTRL0_IGNORE_CRC , &ssp_regs->hw_ssp_ctrl0_clr); +} + +static void mxs_spi_end_xfer (struct mx28_ssp_regs *ssp_regs) +{ +writel (SSP_CTRL0_LOCK_CS , &ssp_regs->hw_ssp_ctrl0_clr); +writel (SSP_CTRL0_IGNORE_CRC , &ssp_regs->hw_ssp_ctrl0_set); +} + +int spi_xfer (struct spi_slave *slave,unsigned int bitlen, +const void *dout,void *din,unsigned long flags) +{ +struct mxs_spi_slave *mxs_slave =to_mxs_slave (slave); +struct mx28_ssp_regs *ssp_regs = mxs_slave->regs; +int len = bitlen /8 ; +const char *tx = dout; +char *rx = din; + +if (bitlen ==0 ) +return 0 ; + +if (!rx && !tx) +return 0 ; + +if (flags &SPI_XFER_BEGIN ) +mxs_spi_start_xfer (ssp_regs); + +while (len--) { +/* We transfer 1 byte */ +writel (1 , &ssp_regs->hw_ssp_xfer_size); + +if ((flags &SPI_XFER_END ) && !len) +mxs_spi_end_xfer (ssp_regs); + +if (tx) +writel (SSP_CTRL0_READ , &ssp_regs->hw_ssp_ctrl0_clr); +else +writel (SSP_CTRL0_READ , &ssp_regs->hw_ssp_ctrl0_set); + +writel (SSP_CTRL0_RUN , &ssp_regs->hw_ssp_ctrl0_set); + +if (mx28_wait_mask_set (&ssp_regs->hw_ssp_ctrl0_reg, +SSP_CTRL0_RUN ,MXS_SPI_MAX_TIMEOUT )) { +printf ("MXS SPI: Timeout waiting for start\n" ); +return -1 ; + } + +if (tx) +writel (*tx++, &ssp_regs->hw_ssp_data); + +writel (SSP_CTRL0_DATA_XFER , &ssp_regs->hw_ssp_ctrl0_set); + +if (rx) { +if (mx28_wait_mask_clr (&ssp_regs->hw_ssp_status_reg, +SSP_STATUS_FIFO_EMPTY ,MXS_SPI_MAX_TIMEOUT )) { +printf ("MXS SPI: Timeout waiting for data\n" ); +return -1 ; + } + + *rx =readl (&ssp_regs->hw_ssp_data); + rx++; + }
drivers/spi/mxs_spi.c line 186
Quoted 10 lines
drivers/spi/mxs_spi.c new file +10
-0+ +if (mx28_wait_mask_clr (&ssp_regs->hw_ssp_ctrl0_reg, +SSP_CTRL0_RUN ,MXS_SPI_MAX_TIMEOUT )) { +printf ("MXS SPI: Timeout waiting for finish\n" ); +return -1 ; + } + } + +return 0 ; +}
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 8/20 iMX28: Add APBH DMA driver
In reply to Marek Vasut--- arch/arm/include/asm/arch-mx28/dma.h | 170 +++++++ arch/arm/include/asm/arch-mx28/imx-regs.h | 1 + arch/arm/include/asm/arch-mx28/regs-apbh.h | 466 +++++++++++++++++++ drivers/dma/Makefile | 1 + drivers/dma/apbh_dma.c | 691 ++++++++++++++++++++++++++++ 5 files changed, 1329 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch-mx28/dma.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-apbh.h create mode 100644 drivers/dma/apbh_dma.c
arch/arm/include/asm/arch-mx28/dma.h new file +170 -0
@@ -0,0 +1,170 @@ +/* +* Freescale i.MX28 APBH DMA +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* Based on code from LTIB: +* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef __DMA_H__ +#define __DMA_H__ + +#include <linux/list.h> + +#ifndef CONFIG_ARCH_DMA_PIO_WORDS +#define DMA_PIO_WORDS 15 +#else +#define DMA_PIO_WORDS CONFIG_ARCH_DMA_PIO_WORDS +#endif + +#define MXS_DMA_ALIGNMENT 32 + +/* +* MXS DMA channels +*/ +enum { +MXS_DMA_CHANNEL_AHB_APBH_SSP0 =0 , +MXS_DMA_CHANNEL_AHB_APBH_SSP1 , +MXS_DMA_CHANNEL_AHB_APBH_SSP2 , +MXS_DMA_CHANNEL_AHB_APBH_SSP3 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI0 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI1 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI2 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI3 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI4 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI5 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI6 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI7 , +MXS_DMA_CHANNEL_AHB_APBH_SSP , +MXS_MAX_DMA_CHANNELS , +}; + +/* +* MXS DMA hardware command. +* +* This structure describes the in-memory layout of an entire DMA command, +* including space for the maximum number of PIO accesses. See the appropriate +* reference manual for a detailed description of what these fields mean to the +* DMA hardware. +*/ +#define MXS_DMA_DESC_COMMAND_MASK 0x3 +#define MXS_DMA_DESC_COMMAND_OFFSET 0 +#define MXS_DMA_DESC_COMMAND_NO_DMAXFER 0x0 +#define MXS_DMA_DESC_COMMAND_DMA_WRITE 0x1 +#define MXS_DMA_DESC_COMMAND_DMA_READ 0x2 +#define MXS_DMA_DESC_COMMAND_DMA_SENSE 0x3 +#define MXS_DMA_DESC_CHAIN (1 << 2) +#define MXS_DMA_DESC_IRQ (1 << 3) +#define MXS_DMA_DESC_NAND_LOCK (1 << 4) +#define MXS_DMA_DESC_NAND_WAIT_4_READY (1 << 5) +#define MXS_DMA_DESC_DEC_SEM (1 << 6) +#define MXS_DMA_DESC_WAIT4END (1 << 7) +#define MXS_DMA_DESC_HALT_ON_TERMINATE (1 << 8) +#define MXS_DMA_DESC_TERMINATE_FLUSH (1 << 9) +#define MXS_DMA_DESC_PIO_WORDS_MASK (0xf << 12) +#define MXS_DMA_DESC_PIO_WORDS_OFFSET 12 +#define MXS_DMA_DESC_BYTES_MASK (0xffff << 16) +#define MXS_DMA_DESC_BYTES_OFFSET 16 + +struct mxs_dma_cmd { +unsigned long next; +unsigned long data; +union { +dma_addr_t address; +unsigned long alternate; + }; +unsigned long pio_words[DMA_PIO_WORDS ]; +}; + +/* +* MXS DMA command descriptor. +* +* This structure incorporates an MXS DMA hardware command structure, along +* with metadata. +*/ +#define MXS_DMA_DESC_FIRST (1 << 0) +#define MXS_DMA_DESC_LAST (1 << 1) +#define MXS_DMA_DESC_READY (1 << 31) + +struct mxs_dma_desc { +struct mxs_dma_cmd cmd; +unsigned int flags; +dma_addr_t address; +void *buffer; +struct list_head node; +}; + +/** +* MXS DMA channel +* +* This structure represents a single DMA channel. The MXS platform code +* maintains an array of these structures to represent every DMA channel in the +* system (see mxs_dma_channels). +*/ +#define MXS_DMA_FLAGS_IDLE 0 +#define MXS_DMA_FLAGS_BUSY (1 << 0) +#define MXS_DMA_FLAGS_FREE 0 +#define MXS_DMA_FLAGS_ALLOCATED (1 << 16) +#define MXS_DMA_FLAGS_VALID (1 << 31) + +struct mxs_dma_chan { +const char *name; +unsigned long dev; +struct mxs_dma_device *dma; +unsigned int flags; +unsigned int active_num; +unsigned int pending_num; +struct list_head active; +struct list_head done; +}; + +/* Hardware management ops */ +int mxs_dma_enable (int channel); +int mxs_dma_disable (int channel); +int mxs_dma_reset (int channel); +int mxs_dma_freeze (int channel); +int mxs_dma_unfreeze (int channel); +int mxs_dma_read_semaphore (int channel); +int mxs_dma_enable_irq (int channel,int enable); +int mxs_dma_irq_is_pending (int channel); +int mxs_dma_ack_irq (int channel); + +/* Channel management ops */ +int mxs_dma_request (int channel); +int mxs_dma_release (int channel); + +/* Descriptor management ops */ +struct mxs_dma_desc *mxs_dma_desc_alloc (void ); +void mxs_dma_desc_free (struct mxs_dma_desc *); + +unsigned int mxs_dma_cmd_address (struct mxs_dma_desc *desc); +int mxs_dma_desc_pending (struct mxs_dma_desc *pdesc); + +int mxs_dma_desc_append (int channel,struct mxs_dma_desc *pdesc); + +int mxs_dma_get_finished (int channel,struct list_head *head); +int mxs_dma_finish (int channel,struct list_head *head); + +int mxs_dma_wait_complete (uint32_t timeout,unsigned int chan); +int mxs_dma_go (int chan); + +int mxs_dma_init (void ); + +#endif /* __DMA_H__ */
arch/arm/include/asm/arch-mx28/imx-regs.h +1 -0
@@ -23,6 +23,7 @@#ifndef __IMX_REGS_H__#define __IMX_REGS_H__ +#include <asm/arch/regs-apbh.h> #include <asm/arch/regs-base.h> #include <asm/arch/regs-bch.h> #include <asm/arch/regs-clkctrl.h>
arch/arm/include/asm/arch-mx28/regs-apbh.h new file +466 -0
466 lines not on this page · raw message
drivers/dma/Makefile +1 -0
@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libdma.o COBJS-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o +COBJS-$(CONFIG_APBH_DMA) += apbh_dma.o COBJS-$(CONFIG_FSL_DMA) += fsl_dma.o COBJS-$(CONFIG_OMAP3_DMA) += omap3_dma.o
drivers/dma/apbh_dma.c new file +691 -0
691 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 8/20 iMX28: Add APBH DMA driver
Quoted 1,374 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- arch/arm/include/asm/arch-mx28/dma.h | 170 +++++++ arch/arm/include/asm/arch-mx28/imx-regs.h | 1 + arch/arm/include/asm/arch-mx28/regs-apbh.h | 466 +++++++++++++++++++ drivers/dma/Makefile | 1 + drivers/dma/apbh_dma.c | 691 ++++++++++++++++++++++++++++ 5 files changed, 1329 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch-mx28/dma.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-apbh.h create mode 100644 drivers/dma/apbh_dma.carch/arm/include/asm/arch-mx28/dma.h new file +170
-0@@ -0,0 +1,170 @@ +/* +* Freescale i.MX28 APBH DMA +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* Based on code from LTIB: +* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef __DMA_H__ +#define __DMA_H__ + +#include <linux/list.h> + +#ifndef CONFIG_ARCH_DMA_PIO_WORDS +#define DMA_PIO_WORDS 15 +#else +#define DMA_PIO_WORDS CONFIG_ARCH_DMA_PIO_WORDS +#endif + +#define MXS_DMA_ALIGNMENT 32 + +/* +* MXS DMA channels +*/ +enum { +MXS_DMA_CHANNEL_AHB_APBH_SSP0 =0 , +MXS_DMA_CHANNEL_AHB_APBH_SSP1 , +MXS_DMA_CHANNEL_AHB_APBH_SSP2 , +MXS_DMA_CHANNEL_AHB_APBH_SSP3 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI0 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI1 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI2 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI3 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI4 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI5 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI6 , +MXS_DMA_CHANNEL_AHB_APBH_GPMI7 , +MXS_DMA_CHANNEL_AHB_APBH_SSP , +MXS_MAX_DMA_CHANNELS , +}; + +/* +* MXS DMA hardware command. +* +* This structure describes the in-memory layout of an entire DMA command, +* including space for the maximum number of PIO accesses. See the appropriate +* reference manual for a detailed description of what these fields mean to the +* DMA hardware. +*/ +#define MXS_DMA_DESC_COMMAND_MASK 0x3 +#define MXS_DMA_DESC_COMMAND_OFFSET 0 +#define MXS_DMA_DESC_COMMAND_NO_DMAXFER 0x0 +#define MXS_DMA_DESC_COMMAND_DMA_WRITE 0x1 +#define MXS_DMA_DESC_COMMAND_DMA_READ 0x2 +#define MXS_DMA_DESC_COMMAND_DMA_SENSE 0x3 +#define MXS_DMA_DESC_CHAIN (1 << 2) +#define MXS_DMA_DESC_IRQ (1 << 3) +#define MXS_DMA_DESC_NAND_LOCK (1 << 4) +#define MXS_DMA_DESC_NAND_WAIT_4_READY (1 << 5) +#define MXS_DMA_DESC_DEC_SEM (1 << 6) +#define MXS_DMA_DESC_WAIT4END (1 << 7) +#define MXS_DMA_DESC_HALT_ON_TERMINATE (1 << 8) +#define MXS_DMA_DESC_TERMINATE_FLUSH (1 << 9) +#define MXS_DMA_DESC_PIO_WORDS_MASK (0xf << 12) +#define MXS_DMA_DESC_PIO_WORDS_OFFSET 12 +#define MXS_DMA_DESC_BYTES_MASK (0xffff << 16) +#define MXS_DMA_DESC_BYTES_OFFSET 16 + +struct mxs_dma_cmd { +unsigned long next; +unsigned long data; +union { +dma_addr_t address; +unsigned long alternate; + }; +unsigned long pio_words[DMA_PIO_WORDS ]; +}; + +/* +* MXS DMA command descriptor. +* +* This structure incorporates an MXS DMA hardware command structure, along +* with metadata. +*/ +#define MXS_DMA_DESC_FIRST (1 << 0) +#define MXS_DMA_DESC_LAST (1 << 1) +#define MXS_DMA_DESC_READY (1 << 31) + +struct mxs_dma_desc { +struct mxs_dma_cmd cmd; +unsigned int flags; +dma_addr_t address; +void *buffer; +struct list_head node; +}; + +/** +* MXS DMA channel +* +* This structure represents a single DMA channel. The MXS platform code +* maintains an array of these structures to represent every DMA channel in the +* system (see mxs_dma_channels). +*/ +#define MXS_DMA_FLAGS_IDLE 0 +#define MXS_DMA_FLAGS_BUSY (1 << 0) +#define MXS_DMA_FLAGS_FREE 0 +#define MXS_DMA_FLAGS_ALLOCATED (1 << 16) +#define MXS_DMA_FLAGS_VALID (1 << 31) + +struct mxs_dma_chan { +const char *name; +unsigned long dev; +struct mxs_dma_device *dma; +unsigned int flags; +unsigned int active_num; +unsigned int pending_num; +struct list_head active; +struct list_head done; +}; + +/* Hardware management ops */ +int mxs_dma_enable (int channel); +int mxs_dma_disable (int channel); +int mxs_dma_reset (int channel); +int mxs_dma_freeze (int channel); +int mxs_dma_unfreeze (int channel); +int mxs_dma_read_semaphore (int channel); +int mxs_dma_enable_irq (int channel,int enable); +int mxs_dma_irq_is_pending (int channel); +int mxs_dma_ack_irq (int channel); + +/* Channel management ops */ +int mxs_dma_request (int channel); +int mxs_dma_release (int channel); + +/* Descriptor management ops */ +struct mxs_dma_desc *mxs_dma_desc_alloc (void ); +void mxs_dma_desc_free (struct mxs_dma_desc *); + +unsigned int mxs_dma_cmd_address (struct mxs_dma_desc *desc); +int mxs_dma_desc_pending (struct mxs_dma_desc *pdesc); + +int mxs_dma_desc_append (int channel,struct mxs_dma_desc *pdesc); + +int mxs_dma_get_finished (int channel,struct list_head *head); +int mxs_dma_finish (int channel,struct list_head *head); + +int mxs_dma_wait_complete (uint32_t timeout,unsigned int chan); +int mxs_dma_go (int chan); + +int mxs_dma_init (void ); + +#endif /* __DMA_H__ */ arch/arm/include/asm/arch-mx28/imx-regs.h +1
-0@@ -23,6 +23,7 @@#ifndef __IMX_REGS_H__#define __IMX_REGS_H__ +#include <asm/arch/regs-apbh.h> #include <asm/arch/regs-base.h> #include <asm/arch/regs-bch.h> #include <asm/arch/regs-clkctrl.h> arch/arm/include/asm/arch-mx28/regs-apbh.h new file +466
-0@@ -0,0 +1,466 @@ +/* +* Freescale i.MX28 APBH Register Definitions +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* Based on code from LTIB: +* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +* +*/ + +#ifndef __REGS_APBH_H__ +#define __REGS_APBH_H__ + +#include <asm/arch/regs-common.h> + +#ifndef __ASSEMBLY__ +struct mx28_apbh_regs { + mx28_reg(hw_apbh_ctrl0) + mx28_reg(hw_apbh_ctrl1) + mx28_reg(hw_apbh_ctrl2) + mx28_reg(hw_apbh_channel_ctrl) + mx28_reg(hw_apbh_devsel) + mx28_reg(hw_apbh_dma_burst_size) + mx28_reg(hw_apbh_debug) + + uint32_t reserved[36]; + + union { + struct { + mx28_reg(hw_apbh_ch_curcmdar) + mx28_reg(hw_apbh_ch_nxtcmdar) + mx28_reg(hw_apbh_ch_cmd) + mx28_reg(hw_apbh_ch_bar) + mx28_reg(hw_apbh_ch_sema) + mx28_reg(hw_apbh_ch_debug1) + mx28_reg(hw_apbh_ch_debug2) + } ch[16]; + struct { + mx28_reg(hw_apbh_ch0_curcmdar) + mx28_reg(hw_apbh_ch0_nxtcmdar) + mx28_reg(hw_apbh_ch0_cmd) + mx28_reg(hw_apbh_ch0_bar) + mx28_reg(hw_apbh_ch0_sema) + mx28_reg(hw_apbh_ch0_debug1) + mx28_reg(hw_apbh_ch0_debug2) + mx28_reg(hw_apbh_ch1_curcmdar) + mx28_reg(hw_apbh_ch1_nxtcmdar) + mx28_reg(hw_apbh_ch1_cmd) + mx28_reg(hw_apbh_ch1_bar) + mx28_reg(hw_apbh_ch1_sema) + mx28_reg(hw_apbh_ch1_debug1) + mx28_reg(hw_apbh_ch1_debug2) + mx28_reg(hw_apbh_ch2_curcmdar) + mx28_reg(hw_apbh_ch2_nxtcmdar) + mx28_reg(hw_apbh_ch2_cmd) + mx28_reg(hw_apbh_ch2_bar) + mx28_reg(hw_apbh_ch2_sema) + mx28_reg(hw_apbh_ch2_debug1) + mx28_reg(hw_apbh_ch2_debug2) + mx28_reg(hw_apbh_ch3_curcmdar) + mx28_reg(hw_apbh_ch3_nxtcmdar) + mx28_reg(hw_apbh_ch3_cmd) + mx28_reg(hw_apbh_ch3_bar) + mx28_reg(hw_apbh_ch3_sema) + mx28_reg(hw_apbh_ch3_debug1) + mx28_reg(hw_apbh_ch3_debug2) + mx28_reg(hw_apbh_ch4_curcmdar) + mx28_reg(hw_apbh_ch4_nxtcmdar) + mx28_reg(hw_apbh_ch4_cmd) + mx28_reg(hw_apbh_ch4_bar) + mx28_reg(hw_apbh_ch4_sema) + mx28_reg(hw_apbh_ch4_debug1) + mx28_reg(hw_apbh_ch4_debug2) + mx28_reg(hw_apbh_ch5_curcmdar) + mx28_reg(hw_apbh_ch5_nxtcmdar) + mx28_reg(hw_apbh_ch5_cmd) + mx28_reg(hw_apbh_ch5_bar) + mx28_reg(hw_apbh_ch5_sema) + mx28_reg(hw_apbh_ch5_debug1) + mx28_reg(hw_apbh_ch5_debug2) + mx28_reg(hw_apbh_ch6_curcmdar) + mx28_reg(hw_apbh_ch6_nxtcmdar) + mx28_reg(hw_apbh_ch6_cmd) + mx28_reg(hw_apbh_ch6_bar) + mx28_reg(hw_apbh_ch6_sema) + mx28_reg(hw_apbh_ch6_debug1) + mx28_reg(hw_apbh_ch6_debug2) + mx28_reg(hw_apbh_ch7_curcmdar) + mx28_reg(hw_apbh_ch7_nxtcmdar) + mx28_reg(hw_apbh_ch7_cmd) + mx28_reg(hw_apbh_ch7_bar) + mx28_reg(hw_apbh_ch7_sema) + mx28_reg(hw_apbh_ch7_debug1) + mx28_reg(hw_apbh_ch7_debug2) + mx28_reg(hw_apbh_ch8_curcmdar) + mx28_reg(hw_apbh_ch8_nxtcmdar) + mx28_reg(hw_apbh_ch8_cmd) + mx28_reg(hw_apbh_ch8_bar) + mx28_reg(hw_apbh_ch8_sema) + mx28_reg(hw_apbh_ch8_debug1) + mx28_reg(hw_apbh_ch8_debug2) + mx28_reg(hw_apbh_ch9_curcmdar) + mx28_reg(hw_apbh_ch9_nxtcmdar) + mx28_reg(hw_apbh_ch9_cmd) + mx28_reg(hw_apbh_ch9_bar) + mx28_reg(hw_apbh_ch9_sema) + mx28_reg(hw_apbh_ch9_debug1) + mx28_reg(hw_apbh_ch9_debug2) + mx28_reg(hw_apbh_ch10_curcmdar) + mx28_reg(hw_apbh_ch10_nxtcmdar) + mx28_reg(hw_apbh_ch10_cmd) + mx28_reg(hw_apbh_ch10_bar) + mx28_reg(hw_apbh_ch10_sema) + mx28_reg(hw_apbh_ch10_debug1) + mx28_reg(hw_apbh_ch10_debug2) + mx28_reg(hw_apbh_ch11_curcmdar) + mx28_reg(hw_apbh_ch11_nxtcmdar) + mx28_reg(hw_apbh_ch11_cmd) + mx28_reg(hw_apbh_ch11_bar) + mx28_reg(hw_apbh_ch11_sema) + mx28_reg(hw_apbh_ch11_debug1) + mx28_reg(hw_apbh_ch11_debug2) + mx28_reg(hw_apbh_ch12_curcmdar) + mx28_reg(hw_apbh_ch12_nxtcmdar) + mx28_reg(hw_apbh_ch12_cmd) + mx28_reg(hw_apbh_ch12_bar) + mx28_reg(hw_apbh_ch12_sema) + mx28_reg(hw_apbh_ch12_debug1) + mx28_reg(hw_apbh_ch12_debug2) + mx28_reg(hw_apbh_ch13_curcmdar) + mx28_reg(hw_apbh_ch13_nxtcmdar) + mx28_reg(hw_apbh_ch13_cmd) + mx28_reg(hw_apbh_ch13_bar) + mx28_reg(hw_apbh_ch13_sema) + mx28_reg(hw_apbh_ch13_debug1) + mx28_reg(hw_apbh_ch13_debug2) + mx28_reg(hw_apbh_ch14_curcmdar) + mx28_reg(hw_apbh_ch14_nxtcmdar) + mx28_reg(hw_apbh_ch14_cmd) + mx28_reg(hw_apbh_ch14_bar) + mx28_reg(hw_apbh_ch14_sema) + mx28_reg(hw_apbh_ch14_debug1) + mx28_reg(hw_apbh_ch14_debug2) + mx28_reg(hw_apbh_ch15_curcmdar) + mx28_reg(hw_apbh_ch15_nxtcmdar) + mx28_reg(hw_apbh_ch15_cmd) + mx28_reg(hw_apbh_ch15_bar) + mx28_reg(hw_apbh_ch15_sema) + mx28_reg(hw_apbh_ch15_debug1) + mx28_reg(hw_apbh_ch15_debug2) + }; + }; + mx28_reg(hw_apbh_version) +}; +#endif + +#define APBH_CTRL0_SFTRST (1 << 31) +#define APBH_CTRL0_CLKGATE (1 << 30) +#define APBH_CTRL0_AHB_BURST8_EN (1 << 29) +#define APBH_CTRL0_APB_BURST_EN (1 << 28) +#define APBH_CTRL0_RSVD0_MASK (0xfff << 16) +#define APBH_CTRL0_RSVD0_OFFSET 16 +#define APBH_CTRL0_CLKGATE_CHANNEL_MASK 0xffff +#define APBH_CTRL0_CLKGATE_CHANNEL_OFFSET 0 +#define APBH_CTRL0_CLKGATE_CHANNEL_SSP0 0x0001 +#define APBH_CTRL0_CLKGATE_CHANNEL_SSP1 0x0002 +#define APBH_CTRL0_CLKGATE_CHANNEL_SSP2 0x0004 +#define APBH_CTRL0_CLKGATE_CHANNEL_SSP3 0x0008 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND0 0x0010 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND1 0x0020 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND2 0x0040 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND3 0x0080 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND4 0x0100 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND5 0x0200 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND6 0x0400 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND7 0x0800 +#define APBH_CTRL0_CLKGATE_CHANNEL_HSADC 0x1000 +#define APBH_CTRL0_CLKGATE_CHANNEL_LCDIF 0x2000 + +#define APBH_CTRL1_CH15_CMDCMPLT_IRQ_EN (1 << 31) +#define APBH_CTRL1_CH14_CMDCMPLT_IRQ_EN (1 << 30) +#define APBH_CTRL1_CH13_CMDCMPLT_IRQ_EN (1 << 29) +#define APBH_CTRL1_CH12_CMDCMPLT_IRQ_EN (1 << 28) +#define APBH_CTRL1_CH11_CMDCMPLT_IRQ_EN (1 << 27) +#define APBH_CTRL1_CH10_CMDCMPLT_IRQ_EN (1 << 26) +#define APBH_CTRL1_CH9_CMDCMPLT_IRQ_EN (1 << 25) +#define APBH_CTRL1_CH8_CMDCMPLT_IRQ_EN (1 << 24) +#define APBH_CTRL1_CH7_CMDCMPLT_IRQ_EN (1 << 23) +#define APBH_CTRL1_CH6_CMDCMPLT_IRQ_EN (1 << 22) +#define APBH_CTRL1_CH5_CMDCMPLT_IRQ_EN (1 << 21) +#define APBH_CTRL1_CH4_CMDCMPLT_IRQ_EN (1 << 20) +#define APBH_CTRL1_CH3_CMDCMPLT_IRQ_EN (1 << 19) +#define APBH_CTRL1_CH2_CMDCMPLT_IRQ_EN (1 << 18) +#define APBH_CTRL1_CH1_CMDCMPLT_IRQ_EN (1 << 17) +#define APBH_CTRL1_CH0_CMDCMPLT_IRQ_EN (1 << 16) +#define APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_OFFSET 16 +#define APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_MASK (0xffff << 16) +#define APBH_CTRL1_CH15_CMDCMPLT_IRQ (1 << 15) +#define APBH_CTRL1_CH14_CMDCMPLT_IRQ (1 << 14) +#define APBH_CTRL1_CH13_CMDCMPLT_IRQ (1 << 13) +#define APBH_CTRL1_CH12_CMDCMPLT_IRQ (1 << 12) +#define APBH_CTRL1_CH11_CMDCMPLT_IRQ (1 << 11) +#define APBH_CTRL1_CH10_CMDCMPLT_IRQ (1 << 10) +#define APBH_CTRL1_CH9_CMDCMPLT_IRQ (1 << 9) +#define APBH_CTRL1_CH8_CMDCMPLT_IRQ (1 << 8) +#define APBH_CTRL1_CH7_CMDCMPLT_IRQ (1 << 7) +#define APBH_CTRL1_CH6_CMDCMPLT_IRQ (1 << 6) +#define APBH_CTRL1_CH5_CMDCMPLT_IRQ (1 << 5) +#define APBH_CTRL1_CH4_CMDCMPLT_IRQ (1 << 4) +#define APBH_CTRL1_CH3_CMDCMPLT_IRQ (1 << 3) +#define APBH_CTRL1_CH2_CMDCMPLT_IRQ (1 << 2) +#define APBH_CTRL1_CH1_CMDCMPLT_IRQ (1 << 1) +#define APBH_CTRL1_CH0_CMDCMPLT_IRQ (1 << 0) + +#define APBH_CTRL2_CH15_ERROR_STATUS (1 << 31) +#define APBH_CTRL2_CH14_ERROR_STATUS (1 << 30) +#define APBH_CTRL2_CH13_ERROR_STATUS (1 << 29) +#define APBH_CTRL2_CH12_ERROR_STATUS (1 << 28) +#define APBH_CTRL2_CH11_ERROR_STATUS (1 << 27) +#define APBH_CTRL2_CH10_ERROR_STATUS (1 << 26) +#define APBH_CTRL2_CH9_ERROR_STATUS (1 << 25) +#define APBH_CTRL2_CH8_ERROR_STATUS (1 << 24) +#define APBH_CTRL2_CH7_ERROR_STATUS (1 << 23) +#define APBH_CTRL2_CH6_ERROR_STATUS (1 << 22) +#define APBH_CTRL2_CH5_ERROR_STATUS (1 << 21) +#define APBH_CTRL2_CH4_ERROR_STATUS (1 << 20) +#define APBH_CTRL2_CH3_ERROR_STATUS (1 << 19) +#define APBH_CTRL2_CH2_ERROR_STATUS (1 << 18) +#define APBH_CTRL2_CH1_ERROR_STATUS (1 << 17) +#define APBH_CTRL2_CH0_ERROR_STATUS (1 << 16) +#define APBH_CTRL2_CH15_ERROR_IRQ (1 << 15) +#define APBH_CTRL2_CH14_ERROR_IRQ (1 << 14) +#define APBH_CTRL2_CH13_ERROR_IRQ (1 << 13) +#define APBH_CTRL2_CH12_ERROR_IRQ (1 << 12) +#define APBH_CTRL2_CH11_ERROR_IRQ (1 << 11) +#define APBH_CTRL2_CH10_ERROR_IRQ (1 << 10) +#define APBH_CTRL2_CH9_ERROR_IRQ (1 << 9) +#define APBH_CTRL2_CH8_ERROR_IRQ (1 << 8) +#define APBH_CTRL2_CH7_ERROR_IRQ (1 << 7) +#define APBH_CTRL2_CH6_ERROR_IRQ (1 << 6) +#define APBH_CTRL2_CH5_ERROR_IRQ (1 << 5) +#define APBH_CTRL2_CH4_ERROR_IRQ (1 << 4) +#define APBH_CTRL2_CH3_ERROR_IRQ (1 << 3) +#define APBH_CTRL2_CH2_ERROR_IRQ (1 << 2) +#define APBH_CTRL2_CH1_ERROR_IRQ (1 << 1) +#define APBH_CTRL2_CH0_ERROR_IRQ (1 << 0) + +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_MASK (0xffff << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET 16 +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP0 (0x0001 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP1 (0x0002 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP2 (0x0004 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP3 (0x0008 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND0 (0x0010 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND1 (0x0020 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND2 (0x0040 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND3 (0x0080 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND4 (0x0100 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND5 (0x0200 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND6 (0x0400 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_NAND7 (0x0800 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_HSADC (0x1000 << 16) +#define APBH_CHANNEL_CTRL_RESET_CHANNEL_LCDIF (0x2000 << 16) +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_MASK 0xffff +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET 0 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP0 0x0001 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP1 0x0002 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP2 0x0004 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_SSP3 0x0008 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND0 0x0010 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND1 0x0020 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND2 0x0040 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND3 0x0080 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND4 0x0100 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND5 0x0200 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND6 0x0400 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND7 0x0800 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_HSADC 0x1000 +#define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_LCDIF 0x2000 + +#define APBH_DEVSEL_CH15_MASK (0x3 << 30) +#define APBH_DEVSEL_CH15_OFFSET 30 +#define APBH_DEVSEL_CH14_MASK (0x3 << 28) +#define APBH_DEVSEL_CH14_OFFSET 28 +#define APBH_DEVSEL_CH13_MASK (0x3 << 26) +#define APBH_DEVSEL_CH13_OFFSET 26 +#define APBH_DEVSEL_CH12_MASK (0x3 << 24) +#define APBH_DEVSEL_CH12_OFFSET 24 +#define APBH_DEVSEL_CH11_MASK (0x3 << 22) +#define APBH_DEVSEL_CH11_OFFSET 22 +#define APBH_DEVSEL_CH10_MASK (0x3 << 20) +#define APBH_DEVSEL_CH10_OFFSET 20 +#define APBH_DEVSEL_CH9_MASK (0x3 << 18) +#define APBH_DEVSEL_CH9_OFFSET 18 +#define APBH_DEVSEL_CH8_MASK (0x3 << 16) +#define APBH_DEVSEL_CH8_OFFSET 16 +#define APBH_DEVSEL_CH7_MASK (0x3 << 14) +#define APBH_DEVSEL_CH7_OFFSET 14 +#define APBH_DEVSEL_CH6_MASK (0x3 << 12) +#define APBH_DEVSEL_CH6_OFFSET 12 +#define APBH_DEVSEL_CH5_MASK (0x3 << 10) +#define APBH_DEVSEL_CH5_OFFSET 10 +#define APBH_DEVSEL_CH4_MASK (0x3 << 8) +#define APBH_DEVSEL_CH4_OFFSET 8 +#define APBH_DEVSEL_CH3_MASK (0x3 << 6) +#define APBH_DEVSEL_CH3_OFFSET 6 +#define APBH_DEVSEL_CH2_MASK (0x3 << 4) +#define APBH_DEVSEL_CH2_OFFSET 4 +#define APBH_DEVSEL_CH1_MASK (0x3 << 2) +#define APBH_DEVSEL_CH1_OFFSET 2 +#define APBH_DEVSEL_CH0_MASK (0x3 << 0) +#define APBH_DEVSEL_CH0_OFFSET 0 + +#define APBH_DMA_BURST_SIZE_CH15_MASK (0x3 << 30) +#define APBH_DMA_BURST_SIZE_CH15_OFFSET 30 +#define APBH_DMA_BURST_SIZE_CH14_MASK (0x3 << 28) +#define APBH_DMA_BURST_SIZE_CH14_OFFSET 28 +#define APBH_DMA_BURST_SIZE_CH13_MASK (0x3 << 26) +#define APBH_DMA_BURST_SIZE_CH13_OFFSET 26 +#define APBH_DMA_BURST_SIZE_CH12_MASK (0x3 << 24) +#define APBH_DMA_BURST_SIZE_CH12_OFFSET 24 +#define APBH_DMA_BURST_SIZE_CH11_MASK (0x3 << 22) +#define APBH_DMA_BURST_SIZE_CH11_OFFSET 22 +#define APBH_DMA_BURST_SIZE_CH10_MASK (0x3 << 20) +#define APBH_DMA_BURST_SIZE_CH10_OFFSET 20 +#define APBH_DMA_BURST_SIZE_CH9_MASK (0x3 << 18) +#define APBH_DMA_BURST_SIZE_CH9_OFFSET 18 +#define APBH_DMA_BURST_SIZE_CH8_MASK (0x3 << 16) +#define APBH_DMA_BURST_SIZE_CH8_OFFSET 16 +#define APBH_DMA_BURST_SIZE_CH8_BURST0 (0x0 << 16) +#define APBH_DMA_BURST_SIZE_CH8_BURST4 (0x1 << 16) +#define APBH_DMA_BURST_SIZE_CH8_BURST8 (0x2 << 16) +#define APBH_DMA_BURST_SIZE_CH7_MASK (0x3 << 14) +#define APBH_DMA_BURST_SIZE_CH7_OFFSET 14 +#define APBH_DMA_BURST_SIZE_CH6_MASK (0x3 << 12) +#define APBH_DMA_BURST_SIZE_CH6_OFFSET 12 +#define APBH_DMA_BURST_SIZE_CH5_MASK (0x3 << 10) +#define APBH_DMA_BURST_SIZE_CH5_OFFSET 10 +#define APBH_DMA_BURST_SIZE_CH4_MASK (0x3 << 8) +#define APBH_DMA_BURST_SIZE_CH4_OFFSET 8 +#define APBH_DMA_BURST_SIZE_CH3_MASK (0x3 << 6) +#define APBH_DMA_BURST_SIZE_CH3_OFFSET 6 +#define APBH_DMA_BURST_SIZE_CH3_BURST0 (0x0 << 6) +#define APBH_DMA_BURST_SIZE_CH3_BURST4 (0x1 << 6) +#define APBH_DMA_BURST_SIZE_CH3_BURST8 (0x2 << 6) + +#define APBH_DMA_BURST_SIZE_CH2_MASK (0x3 << 4) +#define APBH_DMA_BURST_SIZE_CH2_OFFSET 4 +#define APBH_DMA_BURST_SIZE_CH2_BURST0 (0x0 << 4) +#define APBH_DMA_BURST_SIZE_CH2_BURST4 (0x1 << 4) +#define APBH_DMA_BURST_SIZE_CH2_BURST8 (0x2 << 4) +#define APBH_DMA_BURST_SIZE_CH1_MASK (0x3 << 2) +#define APBH_DMA_BURST_SIZE_CH1_OFFSET 2 +#define APBH_DMA_BURST_SIZE_CH1_BURST0 (0x0 << 2) +#define APBH_DMA_BURST_SIZE_CH1_BURST4 (0x1 << 2) +#define APBH_DMA_BURST_SIZE_CH1_BURST8 (0x2 << 2) + +#define APBH_DMA_BURST_SIZE_CH0_MASK 0x3 +#define APBH_DMA_BURST_SIZE_CH0_OFFSET 0 +#define APBH_DMA_BURST_SIZE_CH0_BURST0 0x0 +#define APBH_DMA_BURST_SIZE_CH0_BURST4 0x1 +#define APBH_DMA_BURST_SIZE_CH0_BURST8 0x2 + +#define APBH_DEBUG_GPMI_ONE_FIFO (1 << 0) + +#define APBH_CHn_CURCMDAR_CMD_ADDR_MASK 0xffffffff +#define APBH_CHn_CURCMDAR_CMD_ADDR_OFFSET 0 + +#define APBH_CHn_NXTCMDAR_CMD_ADDR_MASK 0xffffffff +#define APBH_CHn_NXTCMDAR_CMD_ADDR_OFFSET 0 + +#define APBH_CHn_CMD_XFER_COUNT_MASK (0xffff << 16) +#define APBH_CHn_CMD_XFER_COUNT_OFFSET 16 +#define APBH_CHn_CMD_CMDWORDS_MASK (0xf << 12) +#define APBH_CHn_CMD_CMDWORDS_OFFSET 12 +#define APBH_CHn_CMD_HALTONTERMINATE (1 << 8) +#define APBH_CHn_CMD_WAIT4ENDCMD (1 << 7) +#define APBH_CHn_CMD_SEMAPHORE (1 << 6) +#define APBH_CHn_CMD_NANDWAIT4READY (1 << 5) +#define APBH_CHn_CMD_NANDLOCK (1 << 4) +#define APBH_CHn_CMD_IRQONCMPLT (1 << 3) +#define APBH_CHn_CMD_CHAIN (1 << 2) +#define APBH_CHn_CMD_COMMAND_MASK 0x3 +#define APBH_CHn_CMD_COMMAND_OFFSET 0 +#define APBH_CHn_CMD_COMMAND_NO_DMA_XFER 0x0 +#define APBH_CHn_CMD_COMMAND_DMA_WRITE 0x1 +#define APBH_CHn_CMD_COMMAND_DMA_READ 0x2 +#define APBH_CHn_CMD_COMMAND_DMA_SENSE 0x3 + +#define APBH_CHn_BAR_ADDRESS_MASK 0xffffffff +#define APBH_CHn_BAR_ADDRESS_OFFSET 0 + +#define APBH_CHn_SEMA_RSVD2_MASK (0xff << 24) +#define APBH_CHn_SEMA_RSVD2_OFFSET 24 +#define APBH_CHn_SEMA_PHORE_MASK (0xff << 16) +#define APBH_CHn_SEMA_PHORE_OFFSET 16 +#define APBH_CHn_SEMA_RSVD1_MASK (0xff << 8) +#define APBH_CHn_SEMA_RSVD1_OFFSET 8 +#define APBH_CHn_SEMA_INCREMENT_SEMA_MASK (0xff << 0) +#define APBH_CHn_SEMA_INCREMENT_SEMA_OFFSET 0 + +#define APBH_CHn_DEBUG1_REQ (1 << 31) +#define APBH_CHn_DEBUG1_BURST (1 << 30) +#define APBH_CHn_DEBUG1_KICK (1 << 29) +#define APBH_CHn_DEBUG1_END (1 << 28) +#define APBH_CHn_DEBUG1_SENSE (1 << 27) +#define APBH_CHn_DEBUG1_READY (1 << 26) +#define APBH_CHn_DEBUG1_LOCK (1 << 25) +#define APBH_CHn_DEBUG1_NEXTCMDADDRVALID (1 << 24) +#define APBH_CHn_DEBUG1_RD_FIFO_EMPTY (1 << 23) +#define APBH_CHn_DEBUG1_RD_FIFO_FULL (1 << 22) +#define APBH_CHn_DEBUG1_WR_FIFO_EMPTY (1 << 21) +#define APBH_CHn_DEBUG1_WR_FIFO_FULL (1 << 20) +#define APBH_CHn_DEBUG1_RSVD1_MASK (0x7fff << 5) +#define APBH_CHn_DEBUG1_RSVD1_OFFSET 5 +#define APBH_CHn_DEBUG1_STATEMACHINE_MASK 0x1f +#define APBH_CHn_DEBUG1_STATEMACHINE_OFFSET 0 +#define APBH_CHn_DEBUG1_STATEMACHINE_IDLE 0x00 +#define APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD1 0x01 +#define APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD3 0x02 +#define APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD2 0x03 +#define APBH_CHn_DEBUG1_STATEMACHINE_XFER_DECODE 0x04 +#define APBH_CHn_DEBUG1_STATEMACHINE_REQ_WAIT 0x05 +#define APBH_CHn_DEBUG1_STATEMACHINE_REQ_CMD4 0x06 +#define APBH_CHn_DEBUG1_STATEMACHINE_PIO_REQ 0x07 +#define APBH_CHn_DEBUG1_STATEMACHINE_READ_FLUSH 0x08 +#define APBH_CHn_DEBUG1_STATEMACHINE_READ_WAIT 0x09 +#define APBH_CHn_DEBUG1_STATEMACHINE_WRITE 0x0c +#define APBH_CHn_DEBUG1_STATEMACHINE_READ_REQ 0x0d +#define APBH_CHn_DEBUG1_STATEMACHINE_CHECK_CHAIN 0x0e +#define APBH_CHn_DEBUG1_STATEMACHINE_XFER_COMPLETE 0x0f +#define APBH_CHn_DEBUG1_STATEMACHINE_TERMINATE 0x14 +#define APBH_CHn_DEBUG1_STATEMACHINE_WAIT_END 0x15 +#define APBH_CHn_DEBUG1_STATEMACHINE_WRITE_WAIT 0x1c +#define APBH_CHn_DEBUG1_STATEMACHINE_HALT_AFTER_TERM 0x1d +#define APBH_CHn_DEBUG1_STATEMACHINE_CHECK_WAIT 0x1e +#define APBH_CHn_DEBUG1_STATEMACHINE_WAIT_READY 0x1f + +#define APBH_CHn_DEBUG2_APB_BYTES_MASK (0xffff << 16) +#define APBH_CHn_DEBUG2_APB_BYTES_OFFSET 16 +#define APBH_CHn_DEBUG2_AHB_BYTES_MASK 0xffff +#define APBH_CHn_DEBUG2_AHB_BYTES_OFFSET 0 + +#define APBH_VERSION_MAJOR_MASK (0xff << 24) +#define APBH_VERSION_MAJOR_OFFSET 24 +#define APBH_VERSION_MINOR_MASK (0xff << 16) +#define APBH_VERSION_MINOR_OFFSET 16 +#define APBH_VERSION_STEP_MASK 0xffff +#define APBH_VERSION_STEP_OFFSET 0 + +#endif /* __REGS_APBH_H__ */drivers/dma/Makefile +1
-0@@ -26,6 +26,7 @@ include $(TOPDIR)/config.mk LIB := $(obj)libdma.o COBJS-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o +COBJS-$(CONFIG_APBH_DMA) += apbh_dma.o COBJS-$(CONFIG_FSL_DMA) += fsl_dma.o COBJS-$(CONFIG_OMAP3_DMA) += omap3_dma.odrivers/dma/apbh_dma.c new file +681
-0@@ -0,0 +1,691 @@ +/* +* Freescale i.MX28 APBH DMA driver +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* Based on code from LTIB: +* Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include <linux/list.h> + +#include <common.h> +#include <malloc.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/dma.h> + +static struct mxs_dma_chan mxs_dma_channels[MXS_MAX_DMA_CHANNELS ]; + +/* +* Test is the DMA channel is valid channel +*/ +int mxs_dma_validate_chan (int channel) +{ +struct mxs_dma_chan *pchan; + +if ((channel <0 ) || (channel >=MXS_MAX_DMA_CHANNELS )) +return -EINVAL ; + + pchan = mxs_dma_channels + channel; +if (!(pchan->flags &MXS_DMA_FLAGS_ALLOCATED )) +return -EINVAL ; + +return 0 ; +} + +/* +* Enable a DMA channel. +* +* If the given channel has any DMA descriptors on its active list, this +* function causes the DMA hardware to begin processing them. +* +* This function marks the DMA channel as "busy," whether or not there are any +* descriptors to process. +*/ +int mxs_dma_enable (int channel) +{ +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +unsigned int sem; +struct mxs_dma_chan *pchan; +struct mxs_dma_desc *pdesc; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + + pchan = mxs_dma_channels + channel; + +if (pchan->pending_num ==0 ) { + pchan->flags |=MXS_DMA_FLAGS_BUSY ; +return 0 ; + } + + pdesc = list_first_entry(&pchan->active, struct mxs_dma_desc, node); +if (pdesc ==NULL ) +return -EFAULT ; + +if (pchan->flags &MXS_DMA_FLAGS_BUSY ) { +if (!(pdesc->cmd.data &MXS_DMA_DESC_CHAIN )) +return 0 ; + + sem =mxs_dma_read_semaphore (channel); +if (sem ==0 ) +return 0 ; + +if (sem ==1 ) { + pdesc =list_entry (pdesc->node.next, + struct mxs_dma_desc, node); +writel (mxs_dma_cmd_address (pdesc), + &apbh_regs->ch[channel].hw_apbh_ch_nxtcmdar); + } +writel (pchan->pending_num, + &apbh_regs->ch[channel].hw_apbh_ch_sema); + pchan->active_num += pchan->pending_num; + pchan->pending_num =0 ; + }else { + pchan->active_num += pchan->pending_num; + pchan->pending_num =0 ; +writel (mxs_dma_cmd_address (pdesc), + &apbh_regs->ch[channel].hw_apbh_ch_nxtcmdar); +writel (pchan->active_num, + &apbh_regs->ch[channel].hw_apbh_ch_sema); +writel (1 << (channel +APBH_CTRL0_CLKGATE_CHANNEL_OFFSET ), + &apbh_regs->hw_apbh_ctrl0_clr); + } + + pchan->flags |=MXS_DMA_FLAGS_BUSY ; +return 0 ; +} + +/* +* Disable a DMA channel. +* +* This function shuts down a DMA channel and marks it as "not busy." Any +* descriptors on the active list are immediately moved to the head of the +* "done" list, whether or not they have actually been processed by the +* hardware. The "ready" flags of these descriptors are NOT cleared, so they +* still appear to be active. +* +* This function immediately shuts down a DMA channel's hardware, aborting any +* I/O that may be in progress, potentially leaving I/O hardware in an undefined +* state. It is unwise to call this function if there is ANY chance the hardware +* is still processing a command. +*/ +int mxs_dma_disable (int channel) +{ +struct mxs_dma_chan *pchan; +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + + pchan = mxs_dma_channels + channel; + +if (!(pchan->flags &MXS_DMA_FLAGS_BUSY )) +return -EINVAL ; + +writel (1 << (channel +APBH_CTRL0_CLKGATE_CHANNEL_OFFSET ), + &apbh_regs->hw_apbh_ctrl0_set); + + pchan->flags &= ~MXS_DMA_FLAGS_BUSY ; + pchan->active_num =0 ; + pchan->pending_num =0 ; +list_splice_init (&pchan->active, &pchan->done); + +return 0 ; +} + +/* +* Resets the DMA channel hardware. +*/ +int mxs_dma_reset (int channel) +{ +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + +writel (1 << (channel +APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET ), + &apbh_regs->hw_apbh_channel_ctrl_set); + +return 0 ; +} + +/* +* Freeze a DMA channel. +* +* This function causes the channel to continuously fail arbitration for bus +* access, which halts all forward progress without losing any state. A call to +* mxs_dma_unfreeze() will cause the channel to continue its current operation +* with no ill effect. +*/ +int mxs_dma_freeze (int channel) +{ +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + +writel (1 << (channel +APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET ), + &apbh_regs->hw_apbh_channel_ctrl_set); + +return 0 ; +} + +/* +* Unfreeze a DMA channel. +* +* This function reverses the effect of mxs_dma_freeze(), enabling the DMA +* channel to continue from where it was frozen. +*/ +int mxs_dma_unfreeze (int channel) +{ +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + +writel (1 << (channel +APBH_CHANNEL_CTRL_FREEZE_CHANNEL_OFFSET ), + &apbh_regs->hw_apbh_channel_ctrl_clr); + +return 0 ; +} + +/* +* Read a DMA channel's hardware semaphore. +* +* As used by the MXS platform's DMA software, the DMA channel's hardware +* semaphore reflects the number of DMA commands the hardware will process, but +* has not yet finished. This is a volatile value read directly from hardware, +* so it must be be viewed as immediately stale. +* +* If the channel is not marked busy, or has finished processing all its +* commands, this value should be zero. +* +* See mxs_dma_append() for details on how DMA command blocks must be configured +* to maintain the expected behavior of the semaphore's value. +*/ +int mxs_dma_read_semaphore (int channel) +{ +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +uint32_t tmp; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + + tmp =readl (&apbh_regs->ch[channel].hw_apbh_ch_sema); + + tmp &= APBH_CHn_SEMA_PHORE_MASK; + tmp >>= APBH_CHn_SEMA_PHORE_OFFSET; + +return tmp; +} + +/* +* Enable or disable DMA interrupt. +* +* This function enables the given DMA channel to interrupt the CPU. +*/ +int mxs_dma_enable_irq (int channel,int enable) +{ +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + +if (enable) +writel (1 << (channel +APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_OFFSET ), + &apbh_regs->hw_apbh_ctrl1_set); +else +writel (1 << (channel +APBH_CTRL1_CH_CMDCMPLT_IRQ_EN_OFFSET ), + &apbh_regs->hw_apbh_ctrl1_clr); + +return 0 ; +} + +/* +* Check if a DMA interrupt is pending. +*/ +int mxs_dma_irq_is_pending (int channel) +{ +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +uint32_t tmp; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + + tmp =readl (&apbh_regs->hw_apbh_ctrl1); + tmp |=readl (&apbh_regs->hw_apbh_ctrl2); + +return (tmp >> channel) &1 ; +} + +/* +* Clear DMA interrupt. +* +* The software that is using the DMA channel must register to receive its +* interrupts and, when they arrive, must call this function to clear them. +*/ +int mxs_dma_ack_irq (int channel) +{ +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + +writel (1 << channel, &apbh_regs->hw_apbh_ctrl1_clr); +writel (1 << channel, &apbh_regs->hw_apbh_ctrl2_clr); + +return 0 ; +} + +/* +* Request to reserve a DMA channel +*/ +int mxs_dma_request (int channel) +{ +struct mxs_dma_chan *pchan; + +if ((channel <0 ) || (channel >=MXS_MAX_DMA_CHANNELS )) +return -EINVAL ; + + pchan = mxs_dma_channels + channel; +if ((pchan->flags &MXS_DMA_FLAGS_VALID ) !=MXS_DMA_FLAGS_VALID ) +return -ENODEV ; + +if (pchan->flags &MXS_DMA_FLAGS_ALLOCATED ) +return -EBUSY ; + + pchan->flags |=MXS_DMA_FLAGS_ALLOCATED ; + pchan->active_num =0 ; + pchan->pending_num =0 ; + +INIT_LIST_HEAD (&pchan->active); +INIT_LIST_HEAD (&pchan->done); + +return 0 ; +} + +/* +* Release a DMA channel. +* +* This function releases a DMA channel from its current owner. +* +* The channel will NOT be released if it's marked "busy" (see +* mxs_dma_enable()). +*/ +int mxs_dma_release (int channel) +{ +struct mxs_dma_chan *pchan; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + + pchan = mxs_dma_channels + channel; + +if (pchan->flags &MXS_DMA_FLAGS_BUSY ) +return -EBUSY ; + + pchan->dev =0 ; + pchan->active_num =0 ; + pchan->pending_num =0 ; + pchan->flags &= ~MXS_DMA_FLAGS_ALLOCATED ; + +return 0 ; +} + +/* +* Allocate DMA descriptor +*/ +struct mxs_dma_desc *mxs_dma_desc_alloc (void ) +{ +struct mxs_dma_desc *pdesc; + + pdesc =memalign (MXS_DMA_ALIGNMENT ,sizeof (struct mxs_dma_desc )); + +if (pdesc ==NULL ) +return NULL ; + +memset (pdesc,0 ,sizeof (*pdesc)); + pdesc->address = (dma_addr_t )pdesc; + +return pdesc; +}; + +/* +* Free DMA descriptor +*/ +void mxs_dma_desc_free (struct mxs_dma_desc *pdesc) +{ +if (pdesc ==NULL ) +return ; + +free (pdesc); +} + +/* +* Return the address of the command within a descriptor. +*/ +unsigned int mxs_dma_cmd_address (struct mxs_dma_desc *desc) +{ +return desc->address + offsetof(struct mxs_dma_desc , cmd); +} + +/* +* Check if descriptor is on a channel's active list. +* +* This function returns the state of a descriptor's "ready" flag. This flag is +* usually set only if the descriptor appears on a channel's active list. The +* descriptor may or may not have already been processed by the hardware. +* +* The "ready" flag is set when the descriptor is submitted to a channel by a +* call to mxs_dma_append() or mxs_dma_append_list(). The "ready" flag is +* cleared when a processed descriptor is moved off the active list by a call +* to mxs_dma_finish(). The "ready" flag is NOT cleared if the descriptor is +* aborted by a call to mxs_dma_disable(). +*/ +int mxs_dma_desc_pending (struct mxs_dma_desc *pdesc) +{ +return pdesc->flags &MXS_DMA_DESC_READY ; +} + +/* +* Add a DMA descriptor to a channel. +* +* If the descriptor list for this channel is not empty, this function sets the +* CHAIN bit and the NEXTCMD_ADDR fields in the last descriptor's DMA command so +* it will chain to the new descriptor's command. +* +* Then, this function marks the new descriptor as "ready," adds it to the end +* of the active descriptor list, and increments the count of pending +* descriptors. +* +* The MXS platform DMA software imposes some rules on DMA commands to maintain +* important invariants. These rules are NOT checked, but they must be carefully +* applied by software that uses MXS DMA channels. +* +* Invariant: +* The DMA channel's hardware semaphore must reflect the number of DMA +* commands the hardware will process, but has not yet finished. +* +* Explanation: +* A DMA channel begins processing commands when its hardware semaphore is +* written with a value greater than zero, and it stops processing commands +* when the semaphore returns to zero. +* +* When a channel finishes a DMA command, it will decrement its semaphore if +* the DECREMENT_SEMAPHORE bit is set in that command's flags bits. +* +* In principle, it's not necessary for the DECREMENT_SEMAPHORE to be set, +* unless it suits the purposes of the software. For example, one could +* construct a series of five DMA commands, with the DECREMENT_SEMAPHORE +* bit set only in the last one. Then, setting the DMA channel's hardware +* semaphore to one would cause the entire series of five commands to be +* processed. However, this example would violate the invariant given above. +* +* Rule: +* ALL DMA commands MUST have the DECREMENT_SEMAPHORE bit set so that the DMA +* channel's hardware semaphore will be decremented EVERY time a command is +* processed. +*/ +int mxs_dma_desc_append (int channel,struct mxs_dma_desc *pdesc) +{ +struct mxs_dma_chan *pchan; +struct mxs_dma_desc *last; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + + pchan = mxs_dma_channels + channel; + + pdesc->cmd.next =mxs_dma_cmd_address (pdesc); + pdesc->flags |=MXS_DMA_DESC_FIRST |MXS_DMA_DESC_LAST ; + +if (!list_empty (&pchan->active)) { + last = list_entry(pchan->active.prev, struct mxs_dma_desc, + node); + + pdesc->flags &= ~MXS_DMA_DESC_FIRST ; + last->flags &= ~MXS_DMA_DESC_LAST ; + + last->cmd.next =mxs_dma_cmd_address (pdesc); + last->cmd.data |=MXS_DMA_DESC_CHAIN ; + } + pdesc->flags |=MXS_DMA_DESC_READY ; +if (pdesc->flags &MXS_DMA_DESC_FIRST ) + pchan->pending_num++; +list_add_tail (&pdesc->node, &pchan->active); + +return ret; +} + +/* +* Retrieve processed DMA descriptors. +* +* This function moves all the descriptors from the DMA channel's "done" list to +* the head of the given list. +*/ +int mxs_dma_get_finished (int channel,struct list_head *head) +{ +struct mxs_dma_chan *pchan; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + +if (head ==NULL ) +return 0 ; + + pchan = mxs_dma_channels + channel; + +list_splice (&pchan->done, head); + +return 0 ; +} + +/* +* Clean up processed DMA descriptors. +* +* This function removes processed DMA descriptors from the "active" list. Pass +* in a non-NULL list head to get the descriptors moved to your list. Pass NULL +* to get the descriptors moved to the channel's "done" list. Descriptors on +* the "done" list can be retrieved with mxs_dma_get_finished(). +* +* This function marks the DMA channel as "not busy" if no unprocessed +* descriptors remain on the "active" list. +*/ +int mxs_dma_finish (int channel,struct list_head *head) +{ +int sem; +struct mxs_dma_chan *pchan; +struct list_head *p, *q; +struct mxs_dma_desc *pdesc; +int ret; + + ret =mxs_dma_validate_chan (channel); +if (ret) +return ret; + + pchan = mxs_dma_channels + channel; + + sem =mxs_dma_read_semaphore (channel); +if (sem <0 ) +return sem; + +if (sem == pchan->active_num) +return 0 ; + +list_for_each_safe (p, q, &pchan->active) { +if ((pchan->active_num) <= sem) +break ; + + pdesc = list_entry(p, struct mxs_dma_desc, node); + pdesc->flags &= ~MXS_DMA_DESC_READY ; + +if (head) +list_move_tail (p, head); +else +list_move_tail (p, &pchan->done); + +if (pdesc->flags &MXS_DMA_DESC_LAST ) + pchan->active_num--; + } + +if (sem ==0 ) + pchan->flags &= ~MXS_DMA_FLAGS_BUSY ; + +return 0 ; +} + +/* +* Wait for DMA channel to complete +*/ +int mxs_dma_wait_complete (uint32_t timeout,unsigned int chan) +{ +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +int ret; + + ret =mxs_dma_validate_chan (chan); +if (ret) +return ret; + +if (mx28_wait_mask_set (&apbh_regs->hw_apbh_ctrl1_reg, +1 << chan, timeout)) { + ret = -ETIMEDOUT ; +mxs_dma_reset (chan); + } + +return 0 ; +} + +/* +* Execute the DMA channel +*/ +int mxs_dma_go (int chan) +{ +uint32_t timeout =10000 ; +int ret; + +LIST_HEAD (tmp_desc_list); + +mxs_dma_enable_irq (chan,1 ); +mxs_dma_enable (chan); + +/* Wait for DMA to finish. */ + ret =mxs_dma_wait_complete (timeout, chan); + +/* Clear out the descriptors we just ran. */ +mxs_dma_finish (chan, &tmp_desc_list); + +/* Shut the DMA channel down. */ +mxs_dma_ack_irq (chan); +mxs_dma_reset (chan); +mxs_dma_enable_irq (chan,0 ); +mxs_dma_disable (chan); + +return ret; +} + +/* +* Initialize the DMA hardware +*/ +int mxs_dma_init (void ) +{ +struct mx28_apbh_regs *apbh_regs = + (struct mx28_apbh_regs *)MXS_APBH_BASE ; +struct mxs_dma_chan *pchan; +int ret, channel; + +mx28_reset_block (&apbh_regs->hw_apbh_ctrl0_reg); + +#ifdef CONFIG_APBH_DMA_BURST8 +writel (APBH_CTRL0_AHB_BURST8_EN , + &apbh_regs->hw_apbh_ctrl0_set); +#else +writel (APBH_CTRL0_AHB_BURST8_EN , + &apbh_regs->hw_apbh_ctrl0_clr); +#endif + +#ifdef CONFIG_APBH_DMA_BURST +writel (APBH_CTRL0_APB_BURST_EN , + &apbh_regs->hw_apbh_ctrl0_set); +#else +writel (APBH_CTRL0_APB_BURST_EN , + &apbh_regs->hw_apbh_ctrl0_clr); +#endif + +for (channel =0 ; channel <MXS_MAX_DMA_CHANNELS ; channel++) { + pchan = mxs_dma_channels + channel; + pchan->flags =MXS_DMA_FLAGS_VALID ; + + ret =mxs_dma_request (channel); + +if (ret) { +printf ("MXS DMA: Can't acquire DMA channel %i\n" , + channel); + + goto err; + } + +mxs_dma_reset (channel);
drivers/dma/apbh_dma.c line 691
Quoted 10 lines
drivers/dma/apbh_dma.c new file +10
-0+mxs_dma_ack_irq (channel); + } + +return 0 ; + +err: +while (--channel >=0 ) +mxs_dma_release (channel); +return ret; +}
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 9/20 iMX28: Add GPMI NAND driver
In reply to Marek Vasut--- drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/mxs_nand.c | 1118 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1119 insertions(+), 0 deletions(-) create mode 100644 drivers/mtd/nand/mxs_nand.c
drivers/mtd/nand/Makefile +1 -0
@@ -54,6 +54,7 @@ COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o COBJS-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o +COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o COBJS-$(CONFIG_NAND_NDFC) += ndfc.o COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
drivers/mtd/nand/mxs_nand.c new file +1118 -0
1,118 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 9/20 iMX28: Add GPMI NAND driver
Quoted 1,137 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Scott Wood <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/mxs_nand.c | 1118 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1119 insertions(+), 0 deletions(-) create mode 100644 drivers/mtd/nand/mxs_nand.cdrivers/mtd/nand/Makefile +1
-0@@ -54,6 +54,7 @@ COBJS-$(CONFIG_NAND_KIRKWOOD) += kirkwood_nand.o COBJS-$(CONFIG_NAND_KMETER1) += kmeter1_nand.o COBJS-$(CONFIG_NAND_MPC5121_NFC) += mpc5121_nfc.o COBJS-$(CONFIG_NAND_MXC) += mxc_nand.o +COBJS-$(CONFIG_NAND_MXS) += mxs_nand.o COBJS-$(CONFIG_NAND_NDFC) += ndfc.o COBJS-$(CONFIG_NAND_NOMADIK) += nomadik.o COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.odrivers/mtd/nand/mxs_nand.c new file +1108
-0@@ -0,0 +1,1118 @@ +/* +* Freescale i.MX28 NAND flash driver +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* Based on code from LTIB: +* Freescale GPMI NFC NAND Flash Driver +* +* Copyright (C) 2010 Freescale Semiconductor, Inc. +* Copyright (C) 2008 Embedded Alley Solutions, 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., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include <linux/mtd/mtd.h> +#include <linux/mtd/nand.h> +#include <linux/types.h> +#include <common.h> +#include <malloc.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/dma.h> + +#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4 + +#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512 +#define MXS_NAND_METADATA_SIZE 10 + +#define MXS_NAND_COMMAND_BUFFER_SIZE 32 + +#define MXS_NAND_BCH_TIMEOUT 10000 + +struct mxs_nand_info { +int cur_chip; + +uint32_t cmd_queue_len; + +uint8_t *cmd_buf; +uint8_t *data_buf; +uint8_t *oob_buf; + +uint8_t marking_block_bad; +uint8_t raw_oob_mode; + +/* Functions with altered behaviour */ +int (*hooked_read_oob)(struct mtd_info *mtd, +loff_t from,struct mtd_oob_ops *ops); +int (*hooked_write_oob)(struct mtd_info *mtd, +loff_t to,struct mtd_oob_ops *ops); +int (*hooked_block_markbad)(struct mtd_info *mtd, +loff_t ofs); + +/* DMA descriptors */ +struct mxs_dma_desc **desc; +uint32_t desc_index; +}; + +struct nand_ecclayout fake_ecc_layout; + +static struct mxs_dma_desc *mxs_nand_get_dma_desc (struct mxs_nand_info *info) +{ +struct mxs_dma_desc *desc; + +if (info->desc_index >=MXS_NAND_DMA_DESCRIPTOR_COUNT ) { +printf ("MXS NAND: Too many DMA descriptors requested\n" ); +return NULL ; + } + + desc = info->desc[info->desc_index]; + info->desc_index++; + +return desc; +} + +static void mxs_nand_return_dma_descs (struct mxs_nand_info *info) +{ +int i; +struct mxs_dma_desc *desc; + +for (i =0 ; i < info->desc_index; i++) { + desc = info->desc[i]; +memset (desc,0 ,sizeof (struct mxs_dma_desc )); + desc->address = (dma_addr_t )desc; + } + + info->desc_index =0 ; +} + +static uint32_t mxs_nand_ecc_chunk_cnt (uint32_t page_data_size) +{ +return page_data_size /MXS_NAND_CHUNK_DATA_CHUNK_SIZE ; +} + +static uint32_t mxs_nand_ecc_size_in_bits (uint32_t ecc_strength) +{ +return ecc_strength *13 ; +} + +static uint32_t mxs_nand_aux_status_offset (void ) +{ +return (MXS_NAND_METADATA_SIZE +0x3 ) & ~0x3 ; +} + +static inline uint32_t mxs_nand_get_ecc_strength (uint32_t page_data_size, +uint32_t page_oob_size) +{ +if (page_data_size ==2048 ) +return 8 ; + +if (page_data_size ==4096 ) { +if (page_oob_size ==128 ) +return 8 ; + +if (page_oob_size ==218 ) +return 16 ; + } + +return 0 ; +} + +static inline uint32_t mxs_nand_get_mark_offset (uint32_t page_data_size, +uint32_t ecc_strength) +{ +uint32_t chunk_data_size_in_bits; +uint32_t chunk_ecc_size_in_bits; +uint32_t chunk_total_size_in_bits; +uint32_t block_mark_chunk_number; +uint32_t block_mark_chunk_bit_offset; +uint32_t block_mark_bit_offset; + + chunk_data_size_in_bits =MXS_NAND_CHUNK_DATA_CHUNK_SIZE *8 ; + chunk_ecc_size_in_bits =mxs_nand_ecc_size_in_bits (ecc_strength); + + chunk_total_size_in_bits = + chunk_data_size_in_bits + chunk_ecc_size_in_bits; + +/* Compute the bit offset of the block mark within the physical page. */ + block_mark_bit_offset = page_data_size *8 ; + +/* Subtract the metadata bits. */ + block_mark_bit_offset -=MXS_NAND_METADATA_SIZE *8 ; + +/* +* Compute the chunk number (starting at zero) in which the block mark +* appears. +*/ + block_mark_chunk_number = + block_mark_bit_offset / chunk_total_size_in_bits; + +/* +* Compute the bit offset of the block mark within its chunk, and +* validate it. +*/ + block_mark_chunk_bit_offset = block_mark_bit_offset - + (block_mark_chunk_number * chunk_total_size_in_bits); + +if (block_mark_chunk_bit_offset > chunk_data_size_in_bits) +return 1 ; + +/* +* Now that we know the chunk number in which the block mark appears, +* we can subtract all the ECC bits that appear before it. +*/ + block_mark_bit_offset -= + block_mark_chunk_number * chunk_ecc_size_in_bits; + +return block_mark_bit_offset; +} + +static uint32_t mxs_nand_mark_byte_offset (struct mtd_info *mtd) +{ +uint32_t ecc_strength; + ecc_strength =mxs_nand_get_ecc_strength (mtd->writesize, mtd->oobsize); +return mxs_nand_get_mark_offset (mtd->writesize, ecc_strength) >>3 ; +} + +static uint32_t mxs_nand_mark_bit_offset (struct mtd_info *mtd) +{ +uint32_t ecc_strength; + ecc_strength =mxs_nand_get_ecc_strength (mtd->writesize, mtd->oobsize); +return mxs_nand_get_mark_offset (mtd->writesize, ecc_strength) &0x7 ; +} + +/* +* Wait for BCH complete IRQ and clear the IRQ +*/ +static int mxs_nand_wait_for_bch_complete (void ) +{ +struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE ; +int timeout =MXS_NAND_BCH_TIMEOUT ; +int ret; + + ret =mx28_wait_mask_set (&bch_regs->hw_bch_ctrl_reg, +BCH_CTRL_COMPLETE_IRQ , timeout); + +writel (BCH_CTRL_COMPLETE_IRQ , &bch_regs->hw_bch_ctrl_clr); + +return ret; +} + +/* +* This is the function that we install in the cmd_ctrl function pointer of the +* owning struct nand_chip. The only functions in the reference implementation +* that use these functions pointers are cmdfunc and select_chip. +* +* In this driver, we implement our own select_chip, so this function will only +* be called by the reference implementation's cmdfunc. For this reason, we can +* ignore the chip enable bit and concentrate only on sending bytes to the NAND +* Flash. +*/ +static void mxs_nand_cmd_ctrl (struct mtd_info *mtd,int data,unsigned int ctrl) +{ +struct nand_chip *nand = mtd->priv; +struct mxs_nand_info *nand_info = nand->priv; +struct mxs_dma_desc *d; +uint32_t channel =MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; +int ret; + +/* +* If this condition is true, something is _VERY_ wrong in MTD +* subsystem! +*/ +if (nand_info->cmd_queue_len ==MXS_NAND_COMMAND_BUFFER_SIZE ) { +printf ("MXS NAND: Command queue too long\n" ); +return ; + } + +/* +* Every operation begins with a command byte and a series of zero or +* more address bytes. These are distinguished by either the Address +* Latch Enable (ALE) or Command Latch Enable (CLE) signals being +* asserted. When MTD is ready to execute the command, it will +* deasert both latch enables. +* +* Rather than run a separate DMA operation for every single byte, we +* queue them up and run a single DMA operation for the entire series +* of command and data bytes. +*/ +if (ctrl & (NAND_ALE |NAND_CLE )) { +if (data !=NAND_CMD_NONE ) + nand_info->cmd_buf[nand_info->cmd_queue_len++] = data; +return ; + } + +/* +* If control arrives here, MTD has deasserted both the ALE and CLE, +* which means it's ready to run an operation. Check if we have any +* bytes to send. +*/ +if (nand_info->cmd_queue_len ==0 ) +return ; + +/* Compile the DMA descriptor -- a descriptor that sends command. */ + d =mxs_nand_get_dma_desc (nand_info); + d->cmd.data = +MXS_DMA_DESC_COMMAND_DMA_READ |MXS_DMA_DESC_IRQ | +MXS_DMA_DESC_CHAIN |MXS_DMA_DESC_DEC_SEM | +MXS_DMA_DESC_WAIT4END | (3 <<MXS_DMA_DESC_PIO_WORDS_OFFSET ) | + (nand_info->cmd_queue_len <<MXS_DMA_DESC_BYTES_OFFSET ); + + d->cmd.address = (dma_addr_t )nand_info->cmd_buf; + + d->cmd.pio_words[0 ] = +GPMI_CTRL0_COMMAND_MODE_WRITE | +GPMI_CTRL0_WORD_LENGTH | + (nand_info->cur_chip <<GPMI_CTRL0_CS_OFFSET ) | +GPMI_CTRL0_ADDRESS_NAND_CLE | +GPMI_CTRL0_ADDRESS_INCREMENT | + nand_info->cmd_queue_len; + +mxs_dma_desc_append (channel, d); + +/* Execute the DMA chain. */ + ret =mxs_dma_go (channel); +if (ret) +printf ("MXS NAND: Error sending command\n" ); + +mxs_nand_return_dma_descs (nand_info); + +/* Reset the command queue. */ + nand_info->cmd_queue_len =0 ; +} + +/* +* Test if the NAND flash is ready. +*/ +static int mxs_nand_device_ready (struct mtd_info *mtd) +{ +struct nand_chip *chip = mtd->priv; +struct mxs_nand_info *nand_info = chip->priv; +struct mx28_gpmi_regs *gpmi_regs = + (struct mx28_gpmi_regs *)MXS_GPMI_BASE ; +uint32_t tmp; + + tmp =readl (&gpmi_regs->hw_gpmi_stat); + tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip); + +return tmp &1 ; +} + +/* +* Select the NAND chip. +*/ +static void mxs_nand_select_chip (struct mtd_info *mtd,int chip) +{ +struct nand_chip *nand = mtd->priv; +struct mxs_nand_info *nand_info = nand->priv; + + nand_info->cur_chip = chip; +} + +/* +* Handle block mark swapping. +* +* Note that, when this function is called, it doesn't know whether it's +* swapping the block mark, or swapping it *back* -- but it doesn't matter +* because the the operation is the same. +*/ +static void mxs_nand_swap_block_mark (struct mtd_info *mtd, +uint8_t *data_buf,uint8_t *oob_buf) +{ +uint32_t bit_offset; +uint32_t buf_offset; + +uint32_t src; +uint32_t dst; + + bit_offset =mxs_nand_mark_bit_offset (mtd); + buf_offset =mxs_nand_mark_byte_offset (mtd); + +/* +* Get the byte from the data area that overlays the block mark. Since +* the ECC engine applies its own view to the bits in the page, the +* physical block mark won't (in general) appear on a byte boundary in +* the data. +*/ + src = data_buf[buf_offset] >> bit_offset; + src |= data_buf[buf_offset +1 ] << (8 - bit_offset); + + dst = oob_buf[0 ]; + + oob_buf[0 ] = src; + + data_buf[buf_offset] &= ~(0xff << bit_offset); + data_buf[buf_offset +1 ] &=0xff << bit_offset; + + data_buf[buf_offset] |= dst << bit_offset; + data_buf[buf_offset +1 ] |= dst >> (8 - bit_offset); +} + +/* +* Read data from NAND. +*/ +static void mxs_nand_read_buf (struct mtd_info *mtd,uint8_t *buf,int length) +{ +struct nand_chip *nand = mtd->priv; +struct mxs_nand_info *nand_info = nand->priv; +struct mxs_dma_desc *d; +uint32_t channel =MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; +int ret; + +if (length >NAND_MAX_PAGESIZE ) { +printf ("MXS NAND: DMA buffer too big\n" ); +return ; + } + +if (!buf) { +printf ("MXS NAND: DMA buffer is NULL\n" ); +return ; + } + +/* Compile the DMA descriptor - a descriptor that reads data. */ + d =mxs_nand_get_dma_desc (nand_info); + d->cmd.data = +MXS_DMA_DESC_COMMAND_DMA_WRITE |MXS_DMA_DESC_IRQ | +MXS_DMA_DESC_DEC_SEM |MXS_DMA_DESC_WAIT4END | + (1 <<MXS_DMA_DESC_PIO_WORDS_OFFSET ) | + (length <<MXS_DMA_DESC_BYTES_OFFSET ); + + d->cmd.address = (dma_addr_t )nand_info->data_buf; + + d->cmd.pio_words[0 ] = +GPMI_CTRL0_COMMAND_MODE_READ | +GPMI_CTRL0_WORD_LENGTH | + (nand_info->cur_chip <<GPMI_CTRL0_CS_OFFSET ) | +GPMI_CTRL0_ADDRESS_NAND_DATA | + length; + +mxs_dma_desc_append (channel, d); + +/* +* A DMA descriptor that waits for the command to end and the chip to +* become ready. +* +* I think we actually should *not* be waiting for the chip to become +* ready because, after all, we don't care. I think the original code +* did that and no one has re-thought it yet. +*/ + d =mxs_nand_get_dma_desc (nand_info); + d->cmd.data = +MXS_DMA_DESC_COMMAND_NO_DMAXFER |MXS_DMA_DESC_IRQ | +MXS_DMA_DESC_NAND_WAIT_4_READY |MXS_DMA_DESC_DEC_SEM | +MXS_DMA_DESC_WAIT4END | (4 <<MXS_DMA_DESC_PIO_WORDS_OFFSET ); + + d->cmd.address =0 ; + + d->cmd.pio_words[0 ] = +GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY | +GPMI_CTRL0_WORD_LENGTH | + (nand_info->cur_chip <<GPMI_CTRL0_CS_OFFSET ) | +GPMI_CTRL0_ADDRESS_NAND_DATA ; + +mxs_dma_desc_append (channel, d); + +/* Execute the DMA chain. */ + ret =mxs_dma_go (channel); +if (ret) { +printf ("MXS NAND: DMA read error\n" ); + goto rtn; + } + +memcpy (buf, nand_info->data_buf, length); + +rtn: +mxs_nand_return_dma_descs (nand_info); +} + +/* +* Write data to NAND. +*/ +static void mxs_nand_write_buf (struct mtd_info *mtd,const uint8_t *buf, +int length) +{ +struct nand_chip *nand = mtd->priv; +struct mxs_nand_info *nand_info = nand->priv; +struct mxs_dma_desc *d; +uint32_t channel =MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; +int ret; + +if (length >NAND_MAX_PAGESIZE ) { +printf ("MXS NAND: DMA buffer too big\n" ); +return ; + } + +if (!buf) { +printf ("MXS NAND: DMA buffer is NULL\n" ); +return ; + } + +memcpy (nand_info->data_buf, buf, length); + +/* Compile the DMA descriptor - a descriptor that writes data. */ + d =mxs_nand_get_dma_desc (nand_info); + d->cmd.data = +MXS_DMA_DESC_COMMAND_DMA_READ |MXS_DMA_DESC_IRQ | +MXS_DMA_DESC_DEC_SEM |MXS_DMA_DESC_WAIT4END | + (4 <<MXS_DMA_DESC_PIO_WORDS_OFFSET ) | + (length <<MXS_DMA_DESC_BYTES_OFFSET ); + + d->cmd.address = (dma_addr_t )nand_info->data_buf; + + d->cmd.pio_words[0 ] = +GPMI_CTRL0_COMMAND_MODE_WRITE | +GPMI_CTRL0_WORD_LENGTH | + (nand_info->cur_chip <<GPMI_CTRL0_CS_OFFSET ) | +GPMI_CTRL0_ADDRESS_NAND_DATA | + length; + +mxs_dma_desc_append (channel, d); + +/* Execute the DMA chain. */ + ret =mxs_dma_go (channel); +if (ret) +printf ("MXS NAND: DMA write error\n" ); + +mxs_nand_return_dma_descs (nand_info); +} + +/* +* Read a single byte from NAND. +*/ +static uint8_t mxs_nand_read_byte (struct mtd_info *mtd) +{ +uint8_t buf; +mxs_nand_read_buf (mtd, &buf,1 ); +return buf; +} + +/* +* Read a page from NAND. +*/ +static int mxs_nand_ecc_read_page (struct mtd_info *mtd,struct nand_chip *nand, +uint8_t *buf,int page) +{ +struct mxs_nand_info *nand_info = nand->priv; +struct mxs_dma_desc *d; +uint32_t channel =MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; +uint32_t corrected =0 , failed =0 ; +uint8_t *status; +int i, ret; + +/* Compile the DMA descriptor - wait for ready. */ + d =mxs_nand_get_dma_desc (nand_info); + d->cmd.data = +MXS_DMA_DESC_COMMAND_NO_DMAXFER |MXS_DMA_DESC_CHAIN | +MXS_DMA_DESC_NAND_WAIT_4_READY |MXS_DMA_DESC_WAIT4END | + (1 <<MXS_DMA_DESC_PIO_WORDS_OFFSET ); + + d->cmd.address =0 ; + + d->cmd.pio_words[0 ] = +GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY | +GPMI_CTRL0_WORD_LENGTH | + (nand_info->cur_chip <<GPMI_CTRL0_CS_OFFSET ) | +GPMI_CTRL0_ADDRESS_NAND_DATA ; + +mxs_dma_desc_append (channel, d); + +/* Compile the DMA descriptor - enable the BCH block and read. */ + d =mxs_nand_get_dma_desc (nand_info); + d->cmd.data = +MXS_DMA_DESC_COMMAND_NO_DMAXFER |MXS_DMA_DESC_CHAIN | +MXS_DMA_DESC_WAIT4END | (6 <<MXS_DMA_DESC_PIO_WORDS_OFFSET ); + + d->cmd.address =0 ; + + d->cmd.pio_words[0 ] = +GPMI_CTRL0_COMMAND_MODE_READ | +GPMI_CTRL0_WORD_LENGTH | + (nand_info->cur_chip <<GPMI_CTRL0_CS_OFFSET ) | +GPMI_CTRL0_ADDRESS_NAND_DATA | + (mtd->writesize + mtd->oobsize); + d->cmd.pio_words[1 ] =0 ; + d->cmd.pio_words[2 ] = +GPMI_ECCCTRL_ENABLE_ECC | +GPMI_ECCCTRL_ECC_CMD_DECODE | +GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE ; + d->cmd.pio_words[3 ] = mtd->writesize + mtd->oobsize; + d->cmd.pio_words[4 ] = (dma_addr_t )nand_info->data_buf; + d->cmd.pio_words[5 ] = (dma_addr_t )nand_info->oob_buf; + +mxs_dma_desc_append (channel, d); + +/* Compile the DMA descriptor - disable the BCH block. */ + d =mxs_nand_get_dma_desc (nand_info); + d->cmd.data = +MXS_DMA_DESC_COMMAND_NO_DMAXFER |MXS_DMA_DESC_CHAIN | +MXS_DMA_DESC_NAND_WAIT_4_READY |MXS_DMA_DESC_WAIT4END | + (3 <<MXS_DMA_DESC_PIO_WORDS_OFFSET ); + + d->cmd.address =0 ; + + d->cmd.pio_words[0 ] = +GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY | +GPMI_CTRL0_WORD_LENGTH | + (nand_info->cur_chip <<GPMI_CTRL0_CS_OFFSET ) | +GPMI_CTRL0_ADDRESS_NAND_DATA | + (mtd->writesize + mtd->oobsize); + d->cmd.pio_words[1 ] =0 ; + d->cmd.pio_words[2 ] =0 ; + +mxs_dma_desc_append (channel, d); + +/* Compile the DMA descriptor - deassert the NAND lock and interrupt. */ + d =mxs_nand_get_dma_desc (nand_info); + d->cmd.data = +MXS_DMA_DESC_COMMAND_NO_DMAXFER |MXS_DMA_DESC_IRQ | +MXS_DMA_DESC_DEC_SEM ; + + d->cmd.address =0 ; + +mxs_dma_desc_append (channel, d); + +/* Execute the DMA chain. */ + ret =mxs_dma_go (channel); +if (ret) { +printf ("MXS NAND: DMA read error\n" ); + goto rtn; + } + + ret =mxs_nand_wait_for_bch_complete (); +if (ret) { +printf ("MXS NAND: BCH read timeout\n" ); + goto rtn; + } + +/* Read DMA completed, now do the mark swapping. */ +mxs_nand_swap_block_mark (mtd, nand_info->data_buf, nand_info->oob_buf); + +/* Loop over status bytes, accumulating ECC status. */ + status = nand_info->oob_buf +mxs_nand_aux_status_offset (); +for (i =0 ; i <mxs_nand_ecc_chunk_cnt (mtd->writesize); i++) { +if (status[i] ==0x00 ) +continue ; + +if (status[i] ==0xff ) +continue ; + +if (status[i] ==0xfe ) { + failed++; +continue ; + } + + corrected += status[i]; + } + +/* Propagate ECC status to the owning MTD. */ + mtd->ecc_stats.failed += failed; + mtd->ecc_stats.corrected += corrected; + +/* +* It's time to deliver the OOB bytes. See mxs_nand_ecc_read_oob() for +* details about our policy for delivering the OOB. +* +* We fill the caller's buffer with set bits, and then copy the block +* mark to the caller's buffer. Note that, if block mark swapping was +* necessary, it has already been done, so we can rely on the first +* byte of the auxiliary buffer to contain the block mark. +*/ +memset (nand->oob_poi,0xff , mtd->oobsize); + + nand->oob_poi[0 ] = nand_info->oob_buf[0 ]; + +memcpy (buf, nand_info->data_buf, mtd->writesize); + +rtn: +mxs_nand_return_dma_descs (nand_info); + +return ret; +} + +/* +* Write a page to NAND. +*/ +static void mxs_nand_ecc_write_page (struct mtd_info *mtd, +struct nand_chip *nand,const uint8_t *buf) +{ +struct mxs_nand_info *nand_info = nand->priv; +struct mxs_dma_desc *d; +uint32_t channel =MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip; +int ret; + +memcpy (nand_info->data_buf, buf, mtd->writesize); +memcpy (nand_info->oob_buf, nand->oob_poi, mtd->oobsize); + +/* Handle block mark swapping. */ +mxs_nand_swap_block_mark (mtd, nand_info->data_buf, nand_info->oob_buf); + +/* Compile the DMA descriptor - write data. */ + d =mxs_nand_get_dma_desc (nand_info); + d->cmd.data = +MXS_DMA_DESC_COMMAND_NO_DMAXFER |MXS_DMA_DESC_IRQ | +MXS_DMA_DESC_DEC_SEM |MXS_DMA_DESC_WAIT4END | + (6 <<MXS_DMA_DESC_PIO_WORDS_OFFSET ); + + d->cmd.address =0 ; + + d->cmd.pio_words[0 ] = +GPMI_CTRL0_COMMAND_MODE_WRITE | +GPMI_CTRL0_WORD_LENGTH | + (nand_info->cur_chip <<GPMI_CTRL0_CS_OFFSET ) | +GPMI_CTRL0_ADDRESS_NAND_DATA ; + d->cmd.pio_words[1 ] =0 ; + d->cmd.pio_words[2 ] = +GPMI_ECCCTRL_ENABLE_ECC | +GPMI_ECCCTRL_ECC_CMD_ENCODE | +GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE ; + d->cmd.pio_words[3 ] = (mtd->writesize + mtd->oobsize); + d->cmd.pio_words[4 ] = (dma_addr_t )nand_info->data_buf; + d->cmd.pio_words[5 ] = (dma_addr_t )nand_info->oob_buf; + +mxs_dma_desc_append (channel, d); + +/* Execute the DMA chain. */ + ret =mxs_dma_go (channel); +if (ret) { +printf ("MXS NAND: DMA write error\n" ); + goto rtn; + } + + ret =mxs_nand_wait_for_bch_complete (); +if (ret) { +printf ("MXS NAND: BCH write timeout\n" ); + goto rtn; + } + +rtn: +mxs_nand_return_dma_descs (nand_info); +} + +/* +* Read OOB from NAND. +* +* This function is a veneer that replaces the function originally installed by +* the NAND Flash MTD code. +*/ +static int mxs_nand_hook_read_oob (struct mtd_info *mtd,loff_t from, +struct mtd_oob_ops *ops) +{ +struct nand_chip *chip = mtd->priv; +struct mxs_nand_info *nand_info = chip->priv; +int ret; + +if (ops->mode ==MTD_OOB_RAW ) + nand_info->raw_oob_mode =1 ; +else + nand_info->raw_oob_mode =0 ; + + ret = nand_info->hooked_read_oob (mtd, from, ops); + + nand_info->raw_oob_mode =0 ; + +return ret; +} + +/* +* Write OOB to NAND. +* +* This function is a veneer that replaces the function originally installed by +* the NAND Flash MTD code. +*/ +static int mxs_nand_hook_write_oob (struct mtd_info *mtd,loff_t to, +struct mtd_oob_ops *ops) +{ +struct nand_chip *chip = mtd->priv; +struct mxs_nand_info *nand_info = chip->priv; +int ret; + +if (ops->mode ==MTD_OOB_RAW ) + nand_info->raw_oob_mode =1 ; +else + nand_info->raw_oob_mode =0 ; + + ret = nand_info->hooked_write_oob (mtd, to, ops); + + nand_info->raw_oob_mode =0 ; + +return ret; +} + +/* +* Mark a block bad in NAND. +* +* This function is a veneer that replaces the function originally installed by +* the NAND Flash MTD code. +*/ +static int mxs_nand_hook_block_markbad (struct mtd_info *mtd,loff_t ofs) +{ +struct nand_chip *chip = mtd->priv; +struct mxs_nand_info *nand_info = chip->priv; +int ret; + + nand_info->marking_block_bad =1 ; + + ret = nand_info->hooked_block_markbad (mtd, ofs); + + nand_info->marking_block_bad =0 ; + +return ret; +} + +/* +* There are several places in this driver where we have to handle the OOB and +* block marks. This is the function where things are the most complicated, so +* this is where we try to explain it all. All the other places refer back to +* here. +* +* These are the rules, in order of decreasing importance: +* +* 1) Nothing the caller does can be allowed to imperil the block mark, so all +* write operations take measures to protect it. +* +* 2) In read operations, the first byte of the OOB we return must reflect the +* true state of the block mark, no matter where that block mark appears in +* the physical page. +* +* 3) ECC-based read operations return an OOB full of set bits (since we never +* allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads +* return). +* +* 4) "Raw" read operations return a direct view of the physical bytes in the +* page, using the conventional definition of which bytes are data and which +* are OOB. This gives the caller a way to see the actual, physical bytes +* in the page, without the distortions applied by our ECC engine. +* +* What we do for this specific read operation depends on whether we're doing +* "raw" read, or an ECC-based read. +* +* It turns out that knowing whether we want an "ECC-based" or "raw" read is not +* easy. When reading a page, for example, the NAND Flash MTD code calls our +* ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an +* ECC-based or raw view of the page is implicit in which function it calls +* (there is a similar pair of ECC-based/raw functions for writing). +* +* Since MTD assumes the OOB is not covered by ECC, there is no pair of +* ECC-based/raw functions for reading or or writing the OOB. The fact that the +* caller wants an ECC-based or raw view of the page is not propagated down to +* this driver. +* +* Since our OOB *is* covered by ECC, we need this information. So, we hook the +* ecc.read_oob and ecc.write_oob function pointers in the owning +* struct mtd_info with our own functions. These hook functions set the +* raw_oob_mode field so that, when control finally arrives here, we'll know +* what to do. +*/ +static int mxs_nand_ecc_read_oob (struct mtd_info *mtd,struct nand_chip *nand, +int page,int cmd) +{ +struct mxs_nand_info *nand_info = nand->priv; + +/* +* First, fill in the OOB buffer. If we're doing a raw read, we need to +* get the bytes from the physical page. If we're not doing a raw read, +* we need to fill the buffer with set bits. +*/ +if (nand_info->raw_oob_mode) { +/* +* If control arrives here, we're doing a "raw" read. Send the +* command to read the conventional OOB and read it. +*/ + nand->cmdfunc (mtd,NAND_CMD_READ0 , mtd->writesize, page); + nand->read_buf (mtd, nand->oob_poi, mtd->oobsize); + }else { +/* +* If control arrives here, we're not doing a "raw" read. Fill +* the OOB buffer with set bits and correct the block mark. +*/ +memset (nand->oob_poi,0xff , mtd->oobsize); + + nand->cmdfunc (mtd,NAND_CMD_READ0 , mtd->writesize, page); +mxs_nand_read_buf (mtd, nand->oob_poi,1 ); + } + +return 0 ; + +} + +/* +* Write OOB data to NAND. +*/ +static int mxs_nand_ecc_write_oob (struct mtd_info *mtd,struct nand_chip *nand, +int page) +{ +struct mxs_nand_info *nand_info = nand->priv; +uint8_t block_mark =0 ; + +/* +* There are fundamental incompatibilities between the i.MX GPMI NFC and +* the NAND Flash MTD model that make it essentially impossible to write +* the out-of-band bytes. +* +* We permit *ONE* exception. If the *intent* of writing the OOB is to +* mark a block bad, we can do that. +*/ + +if (!nand_info->marking_block_bad) { +printf ("NXS NAND: Writing OOB isn't supported\n" ); +return -EIO ; + } + +/* Write the block mark. */ + nand->cmdfunc (mtd,NAND_CMD_SEQIN , mtd->writesize, page); + nand->write_buf (mtd, &block_mark,1 ); + nand->cmdfunc (mtd,NAND_CMD_PAGEPROG ,-1 ,-1 ); + +/* Check if it worked. */ +if (nand->waitfunc (mtd, nand) &NAND_STATUS_FAIL ) +return -EIO ; + +return 0 ; +} + +/* +* Claims all blocks are good. +* +* In principle, this function is *only* called when the NAND Flash MTD system +* isn't allowed to keep an in-memory bad block table, so it is forced to ask +* the driver for bad block information. +* +* In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so +* this function is *only* called when we take it away. +* +* Thus, this function is only called when we want *all* blocks to look good, +* so it *always* return success. +*/ +static int mxs_nand_block_bad (struct mtd_info *mtd,loff_t ofs,int getchip) +{ +return 0 ; +} + +/* +* Nominally, the purpose of this function is to look for or create the bad +* block table. In fact, since the we call this function at the very end of +* the initialization process started by nand_scan(), and we doesn't have a +* more formal mechanism, we "hook" this function to continue init process. +* +* At this point, the physical NAND Flash chips have been identified and +* counted, so we know the physical geometry. This enables us to make some +* important configuration decisions. +* +* The return value of this function propogates directly back to this driver's +* call to nand_scan(). Anything other than zero will cause this driver to +* tear everything down and declare failure. +*/ +static int mxs_nand_scan_bbt (struct mtd_info *mtd) +{ +struct nand_chip *nand = mtd->priv; +struct mxs_nand_info *nand_info = nand->priv; +struct mx28_bch_regs *bch_regs = (struct mx28_bch_regs *)MXS_BCH_BASE ; +uint32_t tmp; + +/* Configure BCH and set NFC geometry */ +mx28_reset_block (&bch_regs->hw_bch_ctrl_reg); + +/* Configure layout 0 */ + tmp = (mxs_nand_ecc_chunk_cnt (mtd->writesize) -1 ) + <<BCH_FLASHLAYOUT0_NBLOCKS_OFFSET ; + tmp |=MXS_NAND_METADATA_SIZE <<BCH_FLASHLAYOUT0_META_SIZE_OFFSET ; + tmp |= (mxs_nand_get_ecc_strength (mtd->writesize, mtd->oobsize) >>1 ) + <<BCH_FLASHLAYOUT0_ECC0_OFFSET ; + tmp |=MXS_NAND_CHUNK_DATA_CHUNK_SIZE ; +writel (tmp, &bch_regs->hw_bch_flash0layout0); + + tmp = (mtd->writesize + mtd->oobsize) + <<BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET ; + tmp |= (mxs_nand_get_ecc_strength (mtd->writesize, mtd->oobsize) >>1 ) + <<BCH_FLASHLAYOUT1_ECCN_OFFSET ; + tmp |=MXS_NAND_CHUNK_DATA_CHUNK_SIZE ; +writel (tmp, &bch_regs->hw_bch_flash0layout1); + +/* Set *all* chip selects to use layout 0 */ +writel (0 , &bch_regs->hw_bch_layoutselect); + +/* Enable BCH complete interrupt */ +writel (BCH_CTRL_COMPLETE_IRQ_EN , &bch_regs->hw_bch_ctrl_set); + +/* Hook some operations at the MTD level. */ +if (mtd->read_oob != mxs_nand_hook_read_oob) { + nand_info->hooked_read_oob = mtd->read_oob; + mtd->read_oob = mxs_nand_hook_read_oob; + } + +if (mtd->write_oob != mxs_nand_hook_write_oob) { + nand_info->hooked_write_oob = mtd->write_oob; + mtd->write_oob = mxs_nand_hook_write_oob; + } + +if (mtd->block_markbad != mxs_nand_hook_block_markbad) { + nand_info->hooked_block_markbad = mtd->block_markbad; + mtd->block_markbad = mxs_nand_hook_block_markbad; + } + +/* We use the reference implementation for bad block management. */ +return nand_default_bbt (mtd); +} + +/* +* Allocate DMA buffers +*/ +int mxs_nand_alloc_buffers (struct mxs_nand_info *nand_info) +{ +uint8_t *buf; +const int size =NAND_MAX_PAGESIZE +NAND_MAX_OOBSIZE ; + +/* DMA buffers */ + buf =memalign (MXS_DMA_ALIGNMENT , size); +if (!buf) { +printf ("MXS NAND: Error allocating DMA buffers\n" ); +return -ENOMEM ; + } + +memset (buf,0 , size); + + nand_info->data_buf = buf; + nand_info->oob_buf = buf +NAND_MAX_PAGESIZE ; + +/* Command buffers */ + nand_info->cmd_buf =memalign (MXS_DMA_ALIGNMENT , +MXS_NAND_COMMAND_BUFFER_SIZE ); +if (!nand_info->cmd_buf) { +free (buf); +printf ("MXS NAND: Error allocating command buffers\n" ); +return -ENOMEM ; + } +memset (nand_info->cmd_buf,0 ,MXS_NAND_COMMAND_BUFFER_SIZE ); + nand_info->cmd_queue_len =0 ; + +return 0 ; +} + +/* +* Initializes the NFC hardware. +*/ +int mxs_nand_init (struct mxs_nand_info *info) +{ +struct mx28_gpmi_regs *gpmi_regs = + (struct mx28_gpmi_regs *)MXS_GPMI_BASE ; +int i =0 ; + + info->desc =malloc (sizeof (struct mxs_dma_desc *) * +MXS_NAND_DMA_DESCRIPTOR_COUNT ); +if (!info->desc) + goto err1; + +/* Allocate the DMA descriptors. */ +for (i =0 ; i <MXS_NAND_DMA_DESCRIPTOR_COUNT ; i++) { + info->desc[i] =mxs_dma_desc_alloc (); +if (!info->desc[i]) + goto err2; + } + +/* Init the DMA controller. */ +mxs_dma_init (); + +/* Reset the GPMI block. */ +mx28_reset_block (&gpmi_regs->hw_gpmi_ctrl0_reg); + +/* +* Choose NAND mode, set IRQ polarity, disable write protection and +* select BCH ECC. +*/ +clrsetbits_le32 (&gpmi_regs->hw_gpmi_ctrl1, +GPMI_CTRL1_GPMI_MODE , +GPMI_CTRL1_ATA_IRQRDY_POLARITY |GPMI_CTRL1_DEV_RESET | +GPMI_CTRL1_BCH_MODE ); + +return 0 ; + +err2: +free (info->desc); +err1: +for (--i; i >=0 ; i--) +mxs_dma_desc_free (info->desc[i]); +printf ("MXS NAND: Unable to allocate DMA descriptors\n" ); +return -ENOMEM ; +} + +/*! +* This function is called during the driver binding process. +* +* @param pdev the device structure used to store device specific +* information that is used by the suspend, resume and +* remove functions +* +* @return The function always returns 0. +*/ +int board_nand_init (struct nand_chip *nand) +{ +struct mxs_nand_info *nand_info; +int err; + + nand_info =malloc (sizeof (struct mxs_nand_info )); +if (!nand_info) { +printf ("MXS NAND: Failed to allocate private data\n" ); +return -ENOMEM ; + } +memset (nand_info,0 ,sizeof (struct mxs_nand_info )); + + err =mxs_nand_alloc_buffers (nand_info); +if (err) + goto err1; + + err =mxs_nand_init (nand_info); +if (err) + goto err2; + +memset (&fake_ecc_layout,0 ,sizeof (fake_ecc_layout)); + + nand->priv = nand_info; + nand->options |=NAND_NO_SUBPAGE_WRITE ; + + nand->cmd_ctrl = mxs_nand_cmd_ctrl; + + nand->dev_ready = mxs_nand_device_ready; + nand->select_chip = mxs_nand_select_chip; + nand->block_bad = mxs_nand_block_bad; + nand->scan_bbt = mxs_nand_scan_bbt; + + nand->read_byte = mxs_nand_read_byte; + + nand->read_buf = mxs_nand_read_buf; + nand->write_buf = mxs_nand_write_buf; + + nand->ecc.read_page = mxs_nand_ecc_read_page; + nand->ecc.write_page = mxs_nand_ecc_write_page; + nand->ecc.read_oob = mxs_nand_ecc_read_oob; + nand->ecc.write_oob = mxs_nand_ecc_write_oob; + + nand->ecc.layout = &fake_ecc_layout; + nand->ecc.mode =NAND_ECC_HW ; + nand->ecc.bytes =9 ; + nand->ecc.size =512 ;
drivers/mtd/nand/mxs_nand.c line 1118
Quoted 10 lines
drivers/mtd/nand/mxs_nand.c new file +10
-0+ +return 0 ; + +err2: +free (nand_info->data_buf); +free (nand_info->cmd_buf); +err1: +free (nand_info); +return err; +}
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 10/20 iMX28: Add driver for internal RTC
In reply to Marek Vasut--- drivers/rtc/Makefile | 1 + drivers/rtc/mxsrtc.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 0 deletions(-) create mode 100644 drivers/rtc/mxsrtc.c
drivers/rtc/Makefile +1 -0
@@ -57,6 +57,7 @@ COBJS-$(CONFIG_RTC_MK48T59) += mk48t59.o COBJS-$(CONFIG_RTC_MPC5200) += mpc5xxx.o COBJS-$(CONFIG_RTC_MPC8xx) += mpc8xx.o COBJS-$(CONFIG_RTC_MV) += mvrtc.o +COBJS-$(CONFIG_RTC_MXS) += mxsrtc.o COBJS-$(CONFIG_RTC_PCF8563) += pcf8563.o COBJS-$(CONFIG_RTC_PL031) += pl031.o COBJS-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
drivers/rtc/mxsrtc.c new file +86 -0
86 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 10/20 iMX28: Add driver for internal RTC
Quoted 104 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- drivers/rtc/Makefile | 1 + drivers/rtc/mxsrtc.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 0 deletions(-) create mode 100644 drivers/rtc/mxsrtc.cdrivers/rtc/Makefile +1
-0@@ -57,6 +57,7 @@ COBJS-$(CONFIG_RTC_MK48T59) += mk48t59.o COBJS-$(CONFIG_RTC_MPC5200) += mpc5xxx.o COBJS-$(CONFIG_RTC_MPC8xx) += mpc8xx.o COBJS-$(CONFIG_RTC_MV) += mvrtc.o +COBJS-$(CONFIG_RTC_MXS) += mxsrtc.o COBJS-$(CONFIG_RTC_PCF8563) += pcf8563.o COBJS-$(CONFIG_RTC_PL031) += pl031.o COBJS-$(CONFIG_RTC_PT7C4338) += pt7c4338.odrivers/rtc/mxsrtc.c new file +76
-0@@ -0,0 +1,86 @@ +/* +* Freescale i.MX28 RTC Driver +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 <rtc.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/sys_proto.h> + +#define MXS_RTC_MAX_TIMEOUT 1000000 + +/* Set time in seconds since 1970-01-01 */ +int mxs_rtc_set_time (uint32_t secs) +{ +struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE ; +int ret; + +writel (secs, &rtc_regs->hw_rtc_seconds); + +/* +* The 0x80 here means seconds were copied to analog. This information +* is taken from the linux kernel driver for the STMP37xx RTC since +* documentation doesn't mention it. +*/ + ret =mx28_wait_mask_clr (&rtc_regs->hw_rtc_stat_reg, +0x80 <<RTC_STAT_STALE_REGS_OFFSET ,MXS_RTC_MAX_TIMEOUT ); + +if (ret) +printf ("MXS RTC: Timeout waiting for update\n" ); + +return ret; +} + +int rtc_get (struct rtc_time *time) +{ +struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE ; +uint32_t secs; + + secs =readl (&rtc_regs->hw_rtc_seconds); +to_tm (secs, time); + +return 0 ; +} + +int rtc_set (struct rtc_time *time) +{ +uint32_t secs; + + secs =mktime (time->tm_year, time->tm_mon, time->tm_mday, + time->tm_hour, time->tm_min, time->tm_sec); + +return mxs_rtc_set_time (secs); +} + +void rtc_reset (void ) +{ +struct mx28_rtc_regs *rtc_regs = (struct mx28_rtc_regs *)MXS_RTC_BASE ;
drivers/rtc/mxsrtc.c line 86
Quoted 10 lines
drivers/rtc/mxsrtc.c new file +10
-0+int ret; + +/* Set time to 1970-01-01 */ +mxs_rtc_set_time (0 ); + +/* Reset the RTC block */ + ret =mx28_reset_block (&rtc_regs->hw_rtc_ctrl_reg); +if (ret) +printf ("MXS RTC: Block reset timeout\n" ); +}
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 11/20 iMX28: Add image header generator tool
In reply to Marek VasutThis tool can now generate proper image for "BootStream" files.
NOTE: This tool now works only for NAND.
--- tools/.gitignore | 1 + tools/Makefile | 6 + tools/mxsboot.c | 684 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 691 insertions(+), 0 deletions(-) create mode 100644 tools/mxsboot.c
tools/.gitignore +1 -0
@@ -4,6 +4,7 @@ /img2srec /mkimage /mpc86x_clk +/mxsboot /ncb /ncp /ubsha1
tools/Makefile +6 -0
@@ -67,6 +67,7 @@ BIN_FILES-$(CONFIG_CMD_NET) += gen_eth_addr$(SFX) BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX) BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) BIN_FILES-y += mkimage$(SFX) +BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX) BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)
@@ -91,6 +92,7 @@ NOPED_OBJ_FILES-y += kwbimage.o NOPED_OBJ_FILES-y += imximage.o NOPED_OBJ_FILES-y += omapimage.o NOPED_OBJ_FILES-y += mkimage.o +OBJ_FILES-$(CONFIG_MX28) += mxsboot.o OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o NOPED_OBJ_FILES-y += os_support.o OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o
@@ -206,6 +208,10 @@ $(obj)mpc86x_clk$(SFX): $(obj)mpc86x_clk.o $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTSTRIP) $@ +$(obj)mxsboot$(SFX): $(obj)mxsboot.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + $(obj)ncb$(SFX): $(obj)ncb.o $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTSTRIP) $@
tools/mxsboot.c new file +684 -0
684 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 11/20 iMX28: Add image header generator tool
Quoted 738 lines · Marek Vasut
This tool can now generate proper image for "BootStream" files.
NOTE: This tool now works only for NAND.
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- tools/.gitignore | 1 + tools/Makefile | 6 + tools/mxsboot.c | 684 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 691 insertions(+), 0 deletions(-) create mode 100644 tools/mxsboot.ctools/.gitignore +1
-0@@ -4,6 +4,7 @@ /img2srec /mkimage /mpc86x_clk +/mxsboot /ncb /ncp /ubsha1tools/Makefile +6
-0@@ -67,6 +67,7 @@ BIN_FILES-$(CONFIG_CMD_NET) += gen_eth_addr$(SFX) BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX) BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) BIN_FILES-y += mkimage$(SFX) +BIN_FILES-$(CONFIG_MX28) += mxsboot$(SFX) BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX)@@ -91,6 +92,7 @@ NOPED_OBJ_FILES-y += kwbimage.o NOPED_OBJ_FILES-y += imximage.o NOPED_OBJ_FILES-y += omapimage.o NOPED_OBJ_FILES-y += mkimage.o +OBJ_FILES-$(CONFIG_MX28) += mxsboot.o OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o NOPED_OBJ_FILES-y += os_support.o OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o@@ -206,6 +208,10 @@ $(obj)mpc86x_clk$(SFX): $(obj)mpc86x_clk.o $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTSTRIP) $@ +$(obj)mxsboot$(SFX): $(obj)mxsboot.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + $(obj)ncb$(SFX): $(obj)ncb.o $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTSTRIP) $@tools/mxsboot.c new file +674
-0@@ -0,0 +1,684 @@ +/* +* Freescale i.MX28 image generator +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "compiler.h" + +/* +* Default BCB layout. +* +* TWEAK this if you have blown any OCOTP fuses. +*/ +#define STRIDE_PAGES 64 +#define STRIDE_COUNT 4 + +/* +* Layout for 256Mb big NAND with 2048b page size, 64b OOB size and +* 128kb erase size. +* +* TWEAK this if you have different kind of NAND chip. +*/ +uint32_t nand_writesize =2048 ; +uint32_t nand_oobsize =64 ; +uint32_t nand_erasesize =128 *1024 ; + +/* +* Sector on which the SigmaTel boot partition (0x53) starts. +*/ +uint32_t sd_sector =2048 ; + +/* +* Each of the U-Boot bootstreams is at maximum 1MB big. +* +* TWEAK this if, for some wild reason, you need to boot bigger image. +*/ +#define MAX_BOOTSTREAM_SIZE (1 * 1024 * 1024) + +/* i.MX28 NAND controller-specific constants. DO NOT TWEAK! */ +#define MXS_NAND_DMA_DESCRIPTOR_COUNT 4 +#define MXS_NAND_CHUNK_DATA_CHUNK_SIZE 512 +#define MXS_NAND_METADATA_SIZE 10 +#define MXS_NAND_COMMAND_BUFFER_SIZE 32 + +struct mx28_nand_fcb { +uint32_t checksum; +uint32_t fingerprint; +uint32_t version; +struct { +uint8_t data_setup; +uint8_t data_hold; +uint8_t address_setup; +uint8_t dsample_time; +uint8_t nand_timing_state; +uint8_t rea; +uint8_t rloh; +uint8_t rhoh; + } timing; +uint32_t page_data_size; +uint32_t total_page_size; +uint32_t sectors_per_block; +uint32_t number_of_nands;/* Ignored */ +uint32_t total_internal_die;/* Ignored */ +uint32_t cell_type;/* Ignored */ +uint32_t ecc_block_n_ecc_type; +uint32_t ecc_block_0_size; +uint32_t ecc_block_n_size; +uint32_t ecc_block_0_ecc_type; +uint32_t metadata_bytes; +uint32_t num_ecc_blocks_per_page; +uint32_t ecc_block_n_ecc_level_sdk;/* Ignored */ +uint32_t ecc_block_0_size_sdk;/* Ignored */ +uint32_t ecc_block_n_size_sdk;/* Ignored */ +uint32_t ecc_block_0_ecc_level_sdk;/* Ignored */ +uint32_t num_ecc_blocks_per_page_sdk;/* Ignored */ +uint32_t metadata_bytes_sdk;/* Ignored */ +uint32_t erase_threshold; +uint32_t boot_patch; +uint32_t patch_sectors; +uint32_t firmware1_starting_sector; +uint32_t firmware2_starting_sector; +uint32_t sectors_in_firmware1; +uint32_t sectors_in_firmware2; +uint32_t dbbt_search_area_start_address; +uint32_t badblock_marker_byte; +uint32_t badblock_marker_start_bit; +uint32_t bb_marker_physical_offset; +}; + +struct mx28_nand_dbbt { +uint32_t checksum; +uint32_t fingerprint; +uint32_t version; +uint32_t number_bb; +uint32_t number_2k_pages_bb; +}; + +struct mx28_nand_bbt { +uint32_t nand; +uint32_t number_bb; +uint32_t badblock[510 ]; +}; + +struct mx28_sd_drive_info { +uint32_t chip_num; +uint32_t drive_type; +uint32_t tag; +uint32_t first_sector_number; +uint32_t sector_count; +}; + +struct mx28_sd_config_block { +uint32_t signature; +uint32_t primary_boot_tag; +uint32_t secondary_boot_tag; +uint32_t num_copies; +struct mx28_sd_drive_info drv_info[1 ]; +}; + +static inline uint32_t mx28_nand_ecc_size_in_bits (uint32_t ecc_strength) +{ +return ecc_strength *13 ; +} + +static inline uint32_t mx28_nand_get_ecc_strength (uint32_t page_data_size, +uint32_t page_oob_size) +{ +if (page_data_size ==2048 ) +return 8 ; + +if (page_data_size ==4096 ) { +if (page_oob_size ==128 ) +return 8 ; + +if (page_oob_size ==218 ) +return 16 ; + } + +return 0 ; +} + +static inline uint32_t mx28_nand_get_mark_offset (uint32_t page_data_size, +uint32_t ecc_strength) +{ +uint32_t chunk_data_size_in_bits; +uint32_t chunk_ecc_size_in_bits; +uint32_t chunk_total_size_in_bits; +uint32_t block_mark_chunk_number; +uint32_t block_mark_chunk_bit_offset; +uint32_t block_mark_bit_offset; + + chunk_data_size_in_bits =MXS_NAND_CHUNK_DATA_CHUNK_SIZE *8 ; + chunk_ecc_size_in_bits =mx28_nand_ecc_size_in_bits (ecc_strength); + + chunk_total_size_in_bits = + chunk_data_size_in_bits + chunk_ecc_size_in_bits; + +/* Compute the bit offset of the block mark within the physical page. */ + block_mark_bit_offset = page_data_size *8 ; + +/* Subtract the metadata bits. */ + block_mark_bit_offset -=MXS_NAND_METADATA_SIZE *8 ; + +/* +* Compute the chunk number (starting at zero) in which the block mark +* appears. +*/ + block_mark_chunk_number = + block_mark_bit_offset / chunk_total_size_in_bits; + +/* +* Compute the bit offset of the block mark within its chunk, and +* validate it. +*/ + block_mark_chunk_bit_offset = block_mark_bit_offset - + (block_mark_chunk_number * chunk_total_size_in_bits); + +if (block_mark_chunk_bit_offset > chunk_data_size_in_bits) +return 1 ; + +/* +* Now that we know the chunk number in which the block mark appears, +* we can subtract all the ECC bits that appear before it. +*/ + block_mark_bit_offset -= + block_mark_chunk_number * chunk_ecc_size_in_bits; + +return block_mark_bit_offset; +} + +static inline uint32_t mx28_nand_mark_byte_offset (void ) +{ +uint32_t ecc_strength; + ecc_strength =mx28_nand_get_ecc_strength (nand_writesize, nand_oobsize); +return mx28_nand_get_mark_offset (nand_writesize, ecc_strength) >>3 ; +} + +static inline uint32_t mx28_nand_mark_bit_offset (void ) +{ +uint32_t ecc_strength; + ecc_strength =mx28_nand_get_ecc_strength (nand_writesize, nand_oobsize); +return mx28_nand_get_mark_offset (nand_writesize, ecc_strength) &0x7 ; +} + +static uint32_t mx28_nand_block_csum (uint8_t *block,uint32_t size) +{ +uint32_t csum =0 ; +int i; + +for (i =0 ; i < size; i++) + csum += block[i]; + +return csum ^0xffffffff ; +} + +static struct mx28_nand_fcb *mx28_nand_get_fcb (uint32_t size) +{ +struct mx28_nand_fcb *fcb; +uint32_t bcb_size_bytes; +uint32_t stride_size_bytes; +uint32_t bootstream_size_pages; +uint32_t fw1_start_page; +uint32_t fw2_start_page; + + fcb =malloc (nand_writesize); +if (!fcb) { +printf ("MX28 NAND: Unable to allocate FCB\n" ); +return NULL ; + } + +memset (fcb,0 , nand_writesize); + + fcb->fingerprint =0x20424346 ; + fcb->version =0x01000000 ; + +/* +* FIXME: These here are default values as found in kobs-ng. We should +* probably retrieve the data from NAND or something. +*/ + fcb->timing.data_setup =80 ; + fcb->timing.data_hold =60 ; + fcb->timing.address_setup =25 ; + fcb->timing.dsample_time =6 ; + + fcb->page_data_size = nand_writesize; + fcb->total_page_size = nand_writesize + nand_oobsize; + fcb->sectors_per_block = nand_erasesize / nand_writesize; + + fcb->num_ecc_blocks_per_page = (nand_writesize /512 ) -1 ; + fcb->ecc_block_0_size =512 ; + fcb->ecc_block_n_size =512 ; + fcb->metadata_bytes =10 ; + +if (nand_writesize ==2048 ) { + fcb->ecc_block_n_ecc_type =4 ; + fcb->ecc_block_0_ecc_type =4 ; + }else if (nand_writesize ==4096 ) { +if (nand_oobsize ==128 ) { + fcb->ecc_block_n_ecc_type =4 ; + fcb->ecc_block_0_ecc_type =4 ; + }else if (nand_oobsize ==218 ) { + fcb->ecc_block_n_ecc_type =8 ; + fcb->ecc_block_0_ecc_type =8 ; + } + } + +if (fcb->ecc_block_n_ecc_type ==0 ) { +printf ("MX28 NAND: Unsupported NAND geometry\n" ); + goto err; + } + + fcb->boot_patch =0 ; + fcb->patch_sectors =0 ; + + fcb->badblock_marker_byte =mx28_nand_mark_byte_offset (); + fcb->badblock_marker_start_bit =mx28_nand_mark_bit_offset (); + fcb->bb_marker_physical_offset = nand_writesize; + + stride_size_bytes =STRIDE_PAGES * nand_writesize; + bcb_size_bytes = stride_size_bytes *STRIDE_COUNT ; + + bootstream_size_pages = (size + (nand_writesize -1 )) / + nand_writesize; + + fw1_start_page =2 * bcb_size_bytes / nand_writesize; + fw2_start_page = (2 * bcb_size_bytes +MAX_BOOTSTREAM_SIZE ) / + nand_writesize; + + fcb->firmware1_starting_sector = fw1_start_page; + fcb->firmware2_starting_sector = fw2_start_page; + fcb->sectors_in_firmware1 = bootstream_size_pages; + fcb->sectors_in_firmware2 = bootstream_size_pages; + + fcb->dbbt_search_area_start_address =STRIDE_PAGES *STRIDE_COUNT ; + +return fcb; + +err: +free (fcb); +return NULL ; +} + +static struct mx28_nand_dbbt *mx28_nand_get_dbbt (void ) +{ +struct mx28_nand_dbbt *dbbt; + + dbbt =malloc (nand_writesize); +if (!dbbt) { +printf ("MX28 NAND: Unable to allocate DBBT\n" ); +return NULL ; + } + +memset (dbbt,0 , nand_writesize); + + dbbt->fingerprint =0x54424244 ; + dbbt->version =0x1 ; + +return dbbt; +} + +static inline uint8_t mx28_nand_parity_13_8 (const uint8_t b) +{ +uint32_t parity =0 , tmp; + + tmp = ((b >>6 ) ^ (b >>5 ) ^ (b >>3 ) ^ (b >>2 )) &1 ; + parity |= tmp <<0 ; + + tmp = ((b >>7 ) ^ (b >>5 ) ^ (b >>4 ) ^ (b >>2 ) ^ (b >>1 )) &1 ; + parity |= tmp <<1 ; + + tmp = ((b >>7 ) ^ (b >>6 ) ^ (b >>5 ) ^ (b >>1 ) ^ (b >>0 )) &1 ; + parity |= tmp <<2 ; + + tmp = ((b >>7 ) ^ (b >>4 ) ^ (b >>3 ) ^ (b >>0 )) &1 ; + parity |= tmp <<3 ; + + tmp = ((b >>6 ) ^ (b >>4 ) ^ (b >>3 ) ^ + (b >>2 ) ^ (b >>1 ) ^ (b >>0 )) &1 ; + parity |= tmp <<4 ; + +return parity; +} + +static uint8_t *mx28_nand_fcb_block (struct mx28_nand_fcb *fcb) +{ +uint8_t *block; +uint8_t *ecc; +int i; + + block =malloc (nand_writesize + nand_oobsize); +if (!block) { +printf ("MX28 NAND: Unable to allocate FCB block\n" ); +return NULL ; + } + +memset (block,0 , nand_writesize + nand_oobsize); + +/* Update the FCB checksum */ + fcb->checksum =mx28_nand_block_csum (((uint8_t *)fcb) +4 ,508 ); + +/* Figure 12-11. in iMX28RM, rev. 1, says FCB is at offset 12 */ +memcpy (block +12 , fcb,sizeof (struct mx28_nand_fcb )); + +/* ECC is at offset 12 + 512 */ + ecc = block +12 +512 ; + +/* Compute the ECC parity */ +for (i =0 ; i <sizeof (struct mx28_nand_fcb ); i++) + ecc[i] =mx28_nand_parity_13_8 (block[i +12 ]); + +return block; +} + +static int mx28_nand_write_fcb (struct mx28_nand_fcb *fcb,char *buf) +{ +uint32_t offset; +uint8_t *fcbblock; +int ret =0 ; +int i; + + fcbblock =mx28_nand_fcb_block (fcb); +if (!fcbblock) +return -1 ; + +for (i =0 ; i <STRIDE_PAGES *STRIDE_COUNT ; i +=STRIDE_PAGES ) { + offset = i * nand_writesize; +memcpy (buf + offset, fcbblock, nand_writesize + nand_oobsize); + } + +free (fcbblock); +return ret; +} + +static int mx28_nand_write_dbbt (struct mx28_nand_dbbt *dbbt,char *buf) +{ +uint32_t offset; +int i =STRIDE_PAGES *STRIDE_COUNT ; + +for (; i <2 *STRIDE_PAGES *STRIDE_COUNT ; i +=STRIDE_PAGES ) { + offset = i * nand_writesize; +memcpy (buf + offset, dbbt,sizeof (struct mx28_nand_dbbt )); + } + +return 0 ; +} + +static int mx28_nand_write_firmware (struct mx28_nand_fcb *fcb,int infd, +char *buf) +{ +int ret; +off_t size; +uint32_t offset1, offset2; + + size =lseek (infd,0 ,SEEK_END ); +lseek (infd,0 ,SEEK_SET ); + + offset1 = fcb->firmware1_starting_sector * nand_writesize; + offset2 = fcb->firmware2_starting_sector * nand_writesize; + + ret =read (infd, buf + offset1, size); +if (ret != size) +return -1 ; + +memcpy (buf + offset2, buf + offset1, size); + +return 0 ; +} + +void usage (void ) +{ +printf ( +"Usage: mx28image [ops] <type> <infile> <outfile>\n" +"Augment BootStream file with a proper header for i.MX28 boot\n" +"\n" +" <type> type of image:\n" +" \"nand\" for NAND image\n" +" \"sd\" for SD image\n" +" <infile> input file, the u-boot.sb bootstream\n" +" <outfile> output file, the bootable image\n" +"\n" ); +printf ( +"For NAND boot, these options are accepted:\n" +" -w <size> NAND page size\n" +" -o <size> NAND OOB size\n" +" -e <size> NAND erase size\n" +"\n" +"For SD boot, these options are accepted:\n" +" -p <sector> Sector where the SGTL partition starts\n" + ); +} + +static int mx28_create_nand_image (int infd,int outfd) +{ +struct mx28_nand_fcb *fcb; +struct mx28_nand_dbbt *dbbt; +int ret =-1 ; +char *buf; +int size; +ssize_t wr_size; + + size = nand_writesize *512 +2 *MAX_BOOTSTREAM_SIZE ; + + buf =malloc (size); +if (!buf) { +printf ("Can not allocate output buffer of %d bytes\n" , size); + goto err0; + } + +memset (buf,0 , size); + + fcb =mx28_nand_get_fcb (MAX_BOOTSTREAM_SIZE ); +if (!fcb) { +printf ("Unable to compile FCB\n" ); + goto err1; + } + + dbbt =mx28_nand_get_dbbt (); +if (!dbbt) { +printf ("Unable to compile DBBT\n" ); + goto err2; + } + + ret =mx28_nand_write_fcb (fcb, buf); +if (ret) { +printf ("Unable to write FCB to buffer\n" ); + goto err3; + } + + ret =mx28_nand_write_dbbt (dbbt, buf); +if (ret) { +printf ("Unable to write DBBT to buffer\n" ); + goto err3; + } + + ret =mx28_nand_write_firmware (fcb, infd, buf); +if (ret) { +printf ("Unable to write firmware to buffer\n" ); + goto err3; + } + + wr_size =write (outfd, buf, size); +if (wr_size != size) { + ret =-1 ; + goto err3; + } + + ret =0 ; + +err3: +free (dbbt); +err2: +free (fcb); +err1: +free (buf); +err0: +return ret; +} + +static int mx28_create_sd_image (int infd,int outfd) +{ +int ret =-1 ; +uint32_t *buf; +int size; +off_t fsize; +ssize_t wr_size; +struct mx28_sd_config_block *cb; + + fsize =lseek (infd,0 ,SEEK_END ); +lseek (infd,0 ,SEEK_SET ); + size = fsize +512 ; + + buf =malloc (size); +if (!buf) { +printf ("Can not allocate output buffer of %d bytes\n" , size); + goto err0; + } + + ret =read (infd, (uint8_t *)buf +512 , fsize); +if (ret != fsize) { + ret =-1 ; + goto err1; + } + + cb = (struct mx28_sd_config_block *)buf; + + cb->signature =0x00112233 ; + cb->primary_boot_tag =0x1 ; + cb->secondary_boot_tag =0x1 ; + cb->num_copies =1 ; + cb->drv_info[0 ].chip_num =0x0 ; + cb->drv_info[0 ].drive_type =0x0 ; + cb->drv_info[0 ].tag =0x1 ; + cb->drv_info[0 ].first_sector_number = sd_sector +1 ; + cb->drv_info[0 ].sector_count = (size -1 ) /512 ; + + wr_size =write (outfd, buf, size); +if (wr_size != size) { + ret =-1 ; + goto err1; + } + + ret =0 ; + +err1: +free (buf); +err0: +return ret; +} + +int parse_ops (int argc,char **argv) +{ +int i; +int tmp; +char *end; +enum param { +PARAM_WRITE , +PARAM_OOB , +PARAM_ERASE , +PARAM_PART , +PARAM_SD , +PARAM_NAND + }; +int type; + +for (i =1 ; i < argc; i++) { +if (!strncmp (argv[i],"-w" ,2 )) + type =PARAM_WRITE ; +else if (!strncmp (argv[i],"-o" ,2 )) + type =PARAM_OOB ; +else if (!strncmp (argv[i],"-e" ,2 )) + type =PARAM_ERASE ; +else if (!strncmp (argv[i],"-p" ,2 )) + type =PARAM_PART ; +else /* SD/MMC */ +break ; + + tmp =strtol (argv[++i], &end,10 ); +if (tmp %2 ) +return -1 ; +if (tmp <=0 ) +return -1 ; + +if (type ==PARAM_WRITE ) + nand_writesize = tmp; +if (type ==PARAM_OOB ) + nand_oobsize = tmp; +if (type ==PARAM_ERASE ) + nand_erasesize = tmp; +if (type ==PARAM_PART ) + sd_sector = tmp; + } + +if (strcmp (argv[i],"sd" ) &&strcmp (argv[i],"nand" )) +return -1 ; + +if (i +3 != argc) +return -1 ; + +return i; +} + +int main (int argc,char **argv) +{ +int infd, outfd; +int ret =0 ; +int offset; + + offset =parse_ops (argc, argv); +if (offset <0 ) { +usage (); + ret =1 ; + goto err1; + } + + infd =open (argv[offset +1 ],O_RDONLY ); +if (infd <0 ) { +printf ("Input BootStream file can not be opened\n" ); + ret =2 ; + goto err1; + } + + outfd =open (argv[offset +2 ],O_CREAT |O_TRUNC |O_WRONLY , +S_IRUSR |S_IWUSR ); +if (outfd <0 ) { +printf ("Output file can not be created\n" ); + ret =3 ; + goto err2; + } + +if (!strcmp (argv[offset],"sd" ))
tools/mxsboot.c line 684
Quoted 10 lines
tools/mxsboot.c new file +10
-0+ ret =mx28_create_sd_image (infd, outfd); + else if (!strcmp(argv[offset], "nand")) + ret =mx28_create_nand_image (infd, outfd); + +close (outfd); +err2: +close (infd); +err1: +return ret; +}
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 12/20 iMX28: Add u-boot.sb target to Makefile
In reply to Marek Vasut--- .gitignore | 1 + Makefile | 5 +++++ 2 files changed, 6 insertions(+), 0 deletions(-)
.gitignore +1 -0
@@ -36,6 +36,7 @@ /u-boot.lds /u-boot.ubl /u-boot.dtb +/u-boot.sb # # Generated files
Makefile +5 -0
@@ -424,6 +424,10 @@ $(obj)u-boot.ubl: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin rm $(obj)u-boot-ubl.bin rm $(obj)spl/u-boot-spl-pad.bin +$(obj)u-boot.sb: $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin + elftosb -zdf imx28 -c $(TOPDIR)/board/$(BOARDDIR)/u-boot.bd \ + -o $(obj)u-boot.sb + ifeq ($(CONFIG_SANDBOX),y) GEN_UBOOT = \ cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds \
@@ -791,6 +795,7 @@ clobber: clean @rm -f $(obj)u-boot.imx @rm -f $(obj)u-boot.ubl @rm -f $(obj)u-boot.dtb + @rm -f $(obj)u-boot.sb @rm -f $(obj)tools/{env/crc32.c,inca-swap-bytes} @rm -f $(obj)arch/powerpc/cpu/mpc824x/bedbug_603e.c @rm -fr $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm
Signature · 1 line
1.7.7.1
PATCH 12/20 iMX28: Add u-boot.sb target to Makefile
Quoted 37 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- .gitignore | 1 + Makefile | 5 +++++ 2 files changed, 6 insertions(+), 0 deletions(-).gitignore +1
-0@@ -36,6 +36,7 @@ /u-boot.lds /u-boot.ubl /u-boot.dtb +/u-boot.sb # # Generated filesMakefile +4
-0@@ -424,6 +424,10 @@ $(obj)u-boot.ubl: $(obj)spl/u-boot-spl.bin $(obj)u-boot.bin rm $(obj)u-boot-ubl.bin rm $(obj)spl/u-boot-spl-pad.bin +$(obj)u-boot.sb: $(obj)u-boot.bin $(obj)spl/u-boot-spl.bin + elftosb -zdf imx28 -c $(TOPDIR)/board/$(BOARDDIR)/u-boot.bd \ + -o $(obj)u-boot.sb + ifeq ($(CONFIG_SANDBOX),y) GEN_UBOOT = \ cd $(LNDIR) && $(CC) $(SYMS) -T $(obj)u-boot.lds \
Makefile clobber: clean · line 801
Quoted 7 lines
Makefile +1
-0@@ -791,6 +795,7 @@ clobber: clean @rm -f $(obj)u-boot.imx @rm -f $(obj)u-boot.ubl @rm -f $(obj)u-boot.dtb + @rm -f $(obj)u-boot.sb @rm -f $(obj)tools/{env/crc32.c,inca-swap-bytes} @rm -f $(obj)arch/powerpc/cpu/mpc824x/bedbug_603e.c @rm -fr $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 13/20 iMX28: Add support for DENX M28EVK board
In reply to Marek VasutThis contains support for the following components:
- DUART
- MMC
- Both FEC interfaces
- NAND
- I2C (RTC, EEPROM)
- SPI (FLASH)
--- MAINTAINERS | 1 + board/denx/m28evk/Makefile | 43 +++++++ board/denx/m28evk/m28evk.c | 195 ++++++++++++++++++++++++++++++ boards.cfg | 1 + include/configs/m28evk.h | 282 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 522 insertions(+), 0 deletions(-) create mode 100644 board/denx/m28evk/Makefile create mode 100644 board/denx/m28evk/m28evk.c create mode 100644 include/configs/m28evk.h
MAINTAINERS +1 -0
@@ -859,6 +859,7 @@ Marek Vasut <[email protected]> palmtc xscale/pxa vpac270 xscale/pxa zipitz2 xscale/pxa + m28evk i.MX28 efikamx i.MX51 efikasb i.MX51
board/denx/m28evk/Makefile new file +43 -0
43 lines not on this page · raw message
board/denx/m28evk/m28evk.c new file +195 -0
195 lines not on this page · raw message
boards.cfg +1 -0
@@ -157,6 +157,7 @@ tx25 arm arm926ejs tx25 karo zmx25 arm arm926ejs zmx25 syteco mx25 imx27lite arm arm926ejs imx27lite logicpd mx27 magnesium arm arm926ejs imx27lite logicpd mx27 +m28evk arm arm926ejs - denx mx28 nhk8815 arm arm926ejs nhk8815 st nomadik nhk8815_onenand arm arm926ejs nhk8815 st nomadik nhk8815:BOOT_ONENAND omap5912osk arm arm926ejs - ti omap
include/configs/m28evk.h new file +282 -0
282 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 13/20 iMX28: Add support for DENX M28EVK board
Quoted 575 lines · Marek Vasut
This contains support for the following components:
- DUART
- MMC
- Both FEC interfaces
- NAND
- I2C (RTC, EEPROM)
- SPI (FLASH)Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- MAINTAINERS | 1 + board/denx/m28evk/Makefile | 43 +++++++ board/denx/m28evk/m28evk.c | 195 ++++++++++++++++++++++++++++++ boards.cfg | 1 + include/configs/m28evk.h | 282 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 522 insertions(+), 0 deletions(-) create mode 100644 board/denx/m28evk/Makefile create mode 100644 board/denx/m28evk/m28evk.c create mode 100644 include/configs/m28evk.hMAINTAINERS +1
-0@@ -859,6 +859,7 @@ Marek Vasut <[email protected]> palmtc xscale/pxa vpac270 xscale/pxa zipitz2 xscale/pxa + m28evk i.MX28 efikamx i.MX51 efikasb i.MX51board/denx/m28evk/Makefile new file +43
-0@@ -0,0 +1,43 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd at 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 +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).o + +COBJS := m28evk.o + +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +$(LIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +#########################################################################board/denx/m28evk/m28evk.c new file +195
-0@@ -0,0 +1,195 @@ +/* +* DENX M28 module +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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/gpio.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/iomux-mx28.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <linux/mii.h> +#include <miiphy.h> +#include <netdev.h> +#include <errno.h> + +DECLARE_GLOBAL_DATA_PTR ; + +/* +* Functions +*/ +int board_early_init_f (void ) +{ +/* IO0 clock at 480MHz */ +mx28_set_ioclk (MXC_IOCLK0 ,480000 ); +/* IO1 clock at 480MHz */ +mx28_set_ioclk (MXC_IOCLK1 ,480000 ); + +/* SSP0 clock at 96MHz */ +mx28_set_sspclk (MXC_SSPCLK0 ,96000 ,0 ); +/* SSP2 clock at 96MHz */ +mx28_set_sspclk (MXC_SSPCLK2 ,96000 ,0 ); + +return 0 ; +} + +int board_init (void ) +{ +/* Adress of boot parameters */ + gd->bd->bi_boot_params =PHYS_SDRAM_1 +0x100 ; + +return 0 ; +} + +int dram_init (void ) +{ +/* dram_init must store complete ramsize in gd->ram_size */ + gd->ram_size =get_ram_size ((long *)PHYS_SDRAM_1 ,PHYS_SDRAM_1_SIZE ); +return 0 ; +} + +#ifdef CONFIG_CMD_MMC +static int m28_mmc_wp (int id) +{ +if (id !=0 ) { +printf ("MXS MMC: Invalid card selected (card id = %d)\n" , id); +return 1 ; + } + +return gpio_get_value (MX28_PAD_AUART2_CTS__GPIO_3_10 ); +} + +int board_mmc_init (bd_t *bis) +{ +/* Configure WP as output */ +gpio_direction_input (MX28_PAD_AUART2_CTS__GPIO_3_10 ); + +return mxsmmc_initialize (bis,0 , m28_mmc_wp); +} +#endif + +#ifdef CONFIG_CMD_NET + +#define MII_OPMODE_STRAP_OVERRIDE 0x16 +#define MII_PHY_CTRL1 0x1e +#define MII_PHY_CTRL2 0x1f + +int fecmxc_mii_postcall (int phy) +{ +miiphy_write ("FEC1" , phy,MII_BMCR ,0x9000 ); +miiphy_write ("FEC1" , phy,MII_OPMODE_STRAP_OVERRIDE ,0x0202 ); +if (phy ==3 ) +miiphy_write ("FEC1" ,3 ,MII_PHY_CTRL2 ,0x8180 ); +return 0 ; +} + +int board_eth_init (bd_t *bis) +{ +struct mx28_clkctrl_regs *clkctrl_regs = + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; +struct eth_device *dev; +int ret; + + ret =cpu_eth_init (bis); + +clrsetbits_le32 (&clkctrl_regs->hw_clkctrl_enet, +CLKCTRL_ENET_TIME_SEL_MASK |CLKCTRL_ENET_CLK_OUT_EN , +CLKCTRL_ENET_TIME_SEL_RMII_CLK ); + + ret =fecmxc_initialize_multi (bis,0 ,0 ,MXS_ENET0_BASE ); +if (ret) { +printf ("FEC MXS: Unable to init FEC0\n" ); +return ret; + } + + ret =fecmxc_initialize_multi (bis,1 ,3 ,MXS_ENET1_BASE ); +if (ret) { +printf ("FEC MXS: Unable to init FEC1\n" ); +return ret; + } + + dev =eth_get_dev_by_name ("FEC0" ); +if (!dev) { +printf ("FEC MXS: Unable to get FEC0 device entry\n" ); +return -EINVAL ; + } + + ret =fecmxc_register_mii_postcall (dev, fecmxc_mii_postcall); +if (ret) { +printf ("FEC MXS: Unable to register FEC0 mii postcall\n" ); +return ret; + } + + dev =eth_get_dev_by_name ("FEC1" ); +if (!dev) { +printf ("FEC MXS: Unable to get FEC1 device entry\n" ); +return -EINVAL ; + } + + ret =fecmxc_register_mii_postcall (dev, fecmxc_mii_postcall); +if (ret) { +printf ("FEC MXS: Unable to register FEC1 mii postcall\n" ); +return ret; + } + +return ret; +} + +#ifdef CONFIG_M28_FEC_MAC_IN_OCOTP + +#define MXS_OCOTP_MAX_TIMEOUT 1000000 +void imx_get_mac_from_fuse (char *mac) +{ +struct mx28_ocotp_regs *ocotp_regs = + (struct mx28_ocotp_regs *)MXS_OCOTP_BASE ; +uint32_t data; + +memset (mac,0 ,6 ); + +writel (OCOTP_CTRL_RD_BANK_OPEN , &ocotp_regs->hw_ocotp_ctrl_set); + +if (mx28_wait_mask_clr (&ocotp_regs->hw_ocotp_ctrl_reg,OCOTP_CTRL_BUSY , +MXS_OCOTP_MAX_TIMEOUT )) { +printf ("MXS FEC: Can't get MAC from OCOTP\n" ); +return ; + } + + data =readl (&ocotp_regs->hw_ocotp_cust0); + + mac[0 ] =0x00 ; + mac[1 ] =0x04 ; + mac[2 ] = (data >>24 ) &0xff ; + mac[3 ] = (data >>16 ) &0xff ; + mac[4 ] = (data >>8 ) &0xff ; + mac[5 ] = data &0xff ; +} +#else +void imx_get_mac_from_fuse (char *mac) +{ +memset (mac,0 ,6 ); +} +#endif + +#endif boards.cfg +1
-0@@ -157,6 +157,7 @@ tx25 arm arm926ejs tx25 karo zmx25 arm arm926ejs zmx25 syteco mx25 imx27lite arm arm926ejs imx27lite logicpd mx27 magnesium arm arm926ejs imx27lite logicpd mx27 +m28evk arm arm926ejs - denx mx28 nhk8815 arm arm926ejs nhk8815 st nomadik nhk8815_onenand arm arm926ejs nhk8815 st nomadik nhk8815:BOOT_ONENAND omap5912osk arm arm926ejs - ti omapinclude/configs/m28evk.h new file +272
-0@@ -0,0 +1,282 @@ +/* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 __M28_H__ +#define __M28_H__ + +#include <asm/arch/regs-base.h> + +/* +* SoC configurations +*/ +#define CONFIG_MX28 /* i.MX28 SoC */ +#define CONFIG_MXS_GPIO /* GPIO control */ +#define CONFIG_SYS_HZ 1000/* Ticks per second */ + +/* +* Define M28EVK machine type by hand until it lands in mach-types +*/ +#define MACH_TYPE_M28EVK 3613 + +#define CONFIG_MACH_TYPE MACH_TYPE_M28EVK + +#define CONFIG_SYS_NO_FLASH +#define CONFIG_SYS_ICACHE_OFF +#define CONFIG_SYS_DCACHE_OFF +#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_ARCH_CPU_INIT + +/* +* U-Boot Commands +*/ +#include <config_cmd_default.h> +#define CONFIG_DISPLAY_CPUINFO +#define CONFIG_DOS_PARTITION + +#define CONFIG_CMD_CACHE +#define CONFIG_CMD_DATE +#define CONFIG_CMD_DHCP +#define CONFIG_CMD_EEPROM +#define CONFIG_CMD_EXT2 +#define CONFIG_CMD_FAT +#define CONFIG_CMD_GPIO +#define CONFIG_CMD_I2C +#define CONFIG_CMD_MII +#define CONFIG_CMD_MMC +#define CONFIG_CMD_NAND +#define CONFIG_CMD_NET +#define CONFIG_CMD_NFS +#define CONFIG_CMD_PING +#define CONFIG_CMD_SETEXPR +#define CONFIG_CMD_SF +#define CONFIG_CMD_SPI + +/* +* Memory configurations +*/ +#define CONFIG_NR_DRAM_BANKS 1/* 2 banks of DRAM */ +#define PHYS_SDRAM_1 0x40000000/* Base address */ +#define PHYS_SDRAM_1_SIZE 0x08000000/* 128 MB */ +#define CONFIG_STACKSIZE 0x00010000/* 128 KB stack */ +#define CONFIG_SYS_MALLOC_LEN 0x00400000/* 4 MB for malloc */ +#define CONFIG_SYS_GBL_DATA_SIZE 128/* Initial data */ +#define CONFIG_SYS_MEMTEST_START 0x40000000/* Memtest start adr */ +#define CONFIG_SYS_MEMTEST_END 0x40400000/* 4 MB RAM test */ +#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1 +/* Point initial SP in SRAM so SPL can use it too. */ +#define CONFIG_SYS_INIT_SP_ADDR 0x00002000 +/* +* We need to sacrifice first 4 bytes of RAM here to avoid triggering some +* strange BUG in ROM corrupting first 4 bytes of RAM when loading U-Boot +* binary. In case there was more of this mess, 0x100 bytes are skipped. +*/ +#define CONFIG_SYS_TEXT_BASE 0x40000100 + +/* +* U-Boot general configurations +*/ +#define CONFIG_SYS_LONGHELP +#define CONFIG_SYS_PROMPT "=> " +#define CONFIG_SYS_CBSIZE 1024/* Console I/O buffer size */ +#define CONFIG_SYS_PBSIZE \ + (CONFIG_SYS_CBSIZE + sizeof(CONFIG_SYS_PROMPT) + 16) +/* Print buffer size */ +#define CONFIG_SYS_MAXARGS 32/* Max number of command args */ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE +/* Boot argument buffer size */ +#define CONFIG_VERSION_VARIABLE /* U-BOOT version */ +#define CONFIG_AUTO_COMPLETE /* Command auto complete */ +#define CONFIG_CMDLINE_EDITING /* Command history etc */ +#define CONFIG_SYS_HUSH_PARSER +#define CONFIG_SYS_PROMPT_HUSH_PS2 "> " + +/* +* Serial Driver +*/ +#define CONFIG_PL011_SERIAL +#define CONFIG_PL011_CLOCK 24000000 +#define CONFIG_PL01x_PORTS { (void *)MXS_UARTDBG_BASE } +#define CONFIG_CONS_INDEX 0 +#define CONFIG_BAUDRATE 115200/* Default baud rate */ +#define CONFIG_SYS_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/* +* MMC Driver +*/ +#ifdef CONFIG_CMD_MMC +#define CONFIG_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_MXS_MMC +#endif + +/* +* NAND +*/ +#ifdef CONFIG_CMD_NAND +#define CONFIG_NAND_MXS +#define CONFIG_APBH_DMA +#define CONFIG_SYS_MAX_NAND_DEVICE 1 +#define CONFIG_SYS_NAND_BASE 0x60000000 +#define CONFIG_SYS_NAND_5_ADDR_CYCLE +#define NAND_MAX_CHIPS 8 + +/* Environment is in NAND */ +#define CONFIG_ENV_IS_IN_NAND +#define CONFIG_ENV_SIZE (16 * 1024) +#define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE +#define CONFIG_ENV_SECT_SIZE (128 * 1024) +#define CONFIG_ENV_RANGE (512 * 1024) +#define CONFIG_ENV_OFFSET 0x300000 +#define CONFIG_ENV_OFFSET_REDUND \ + (CONFIG_ENV_OFFSET + CONFIG_ENV_RANGE) + +#define CONFIG_CMD_UBI +#define CONFIG_CMD_UBIFS +#define CONFIG_CMD_MTDPARTS +#define CONFIG_RBTREE +#define CONFIG_LZO +#define CONFIG_MTD_DEVICE +#define CONFIG_MTD_PARTITIONS +#define MTDIDS_DEFAULT "nand0=gpmi-nand.0" +#define MTDPARTS_DEFAULT \ + "mtdparts=gpmi-nand.0:" \ + "3m(bootloader)ro," \ + "512k(environment)," \ + "512k(redundant-environment)," \ + "4m(kernel)," \ + "-(filesystem)" +#endif + +/* +* Ethernet on SOC (FEC) +*/ +#ifdef CONFIG_CMD_NET +#define CONFIG_NET_MULTI +#define CONFIG_ETHPRIME "FEC0" +#define CONFIG_FEC_MXC +#define CONFIG_FEC_MXC_MULTI +#define CONFIG_MII +#define CONFIG_DISCOVER_PHY +#define CONFIG_FEC_XCV_TYPE RMII +#endif + +/* +* I2C +*/ +#ifdef CONFIG_CMD_I2C +#define CONFIG_I2C_MXS +#define CONFIG_HARD_I2C +#define CONFIG_SYS_I2C_SPEED 400000 +#endif + +/* +* EEPROM +*/ +#ifdef CONFIG_CMD_EEPROM +#define CONFIG_SYS_I2C_MULTI_EEPROMS +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 +#endif + +/* +* RTC +*/ +#ifdef CONFIG_CMD_DATE +/* Use the internal RTC in the MXS chip */ +#define CONFIG_RTC_INTERNAL +#ifdef CONFIG_RTC_INTERNAL +#define CONFIG_RTC_MXS +#else +#define CONFIG_RTC_M41T62 +#define CONFIG_SYS_I2C_RTC_ADDR 0x68 +#define CONFIG_SYS_M41T11_BASE_YEAR 2000 +#endif +#endif + +/* +* SPI +*/ +#ifdef CONFIG_CMD_SPI +#define CONFIG_HARD_SPI +#define CONFIG_MXS_SPI +#define CONFIG_SPI_HALF_DUPLEX +#define CONFIG_DEFAULT_SPI_BUS 2 +#define CONFIG_DEFAULT_SPI_MODE SPI_MODE_0 + +/* SPI FLASH */ +#ifdef CONFIG_CMD_SF +#define CONFIG_SPI_FLASH +#define CONFIG_SPI_FLASH_STMICRO +#define CONFIG_SPI_FLASH_CS 2 +#define CONFIG_SF_DEFAULT_MODE SPI_MODE_0 +#define CONFIG_SF_DEFAULT_SPEED 24000000 + +#define CONFIG_ENV_SPI_CS 0 +#define CONFIG_ENV_SPI_BUS 2 +#define CONFIG_ENV_SPI_MAX_HZ 24000000 +#define CONFIG_ENV_SPI_MODE SPI_MODE_0 +#endif +#endif + +/* +* Boot Linux +*/ +#define CONFIG_CMDLINE_TAG +#define CONFIG_SETUP_MEMORY_TAGS +#define CONFIG_BOOTDELAY 3 +#define CONFIG_BOOTFILE "uImage" +#define CONFIG_BOOTARGS "console=ttyAM0,115200n8 " +#define CONFIG_BOOTCOMMAND "run bootcmd_net" +#define CONFIG_LOADADDR 0x42000000 +#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR + +/* +* Extra Environments +*/ +#define CONFIG_EXTRA_ENV_SETTINGS \ + "update_nand_full_filename=u-boot.nand\0" \ + "update_nand_firmware_filename=u-boot.sb\0" \ + "update_nand_firmware_maxsz=0x100000\0" \ + "update_nand_stride=0x40\0"/* MX28 datasheet ch. 12.12 */ \ +"update_nand_count=0x4\0" /* MX28 datasheet ch. 12.12 */ \ +"update_nand_get_fcb_size=" /* Get size of FCB blocks */ \ +"nand device 0 ; " \ +"nand info ; " \ +"setexpr fcb_sz ${update_nand_stride} * ${update_nand_count};" \ +"setexpr update_nand_fcb ${fcb_sz} * ${nand_writesize}\0" \ +"update_nand_full=" /* Update FCB, DBBT and FW */ \ +"if tftp ${update_nand_full_filename} ; then " \ +"run update_nand_get_fcb_size ; " \ +"nand scrub -y 0x0 ${filesize} ; " \ +"nand write.raw ${loadaddr} 0x0 ${update_nand_fcb} ; " \ +"setexpr update_off ${loadaddr} + ${update_nand_fcb} ; " \ +"setexpr update_sz ${filesize} - ${update_nand_fcb} ; " \ +"nand write ${update_off} ${update_nand_fcb} ${update_sz} ; " \ +"fi\0" \ +"update_nand_firmware=" /* Update only firmware */ \ +"if tftp ${update_nand_firmware_filename} ; then " \
include/configs/m28evk.h line 282
Quoted 10 lines
include/configs/m28evk.h new file +10
-0+"run update_nand_get_fcb_size ; " \ +"setexpr fcb_sz ${update_nand_fcb} * 2 ; " /* FCB + DBBT */ \ +"setexpr fw_sz ${update_nand_firmware_maxsz} * 2 ; " \ +"setexpr fw_off ${fcb_sz} + ${update_nand_firmware_maxsz};" \ +"nand erase ${fcb_sz} ${fw_sz} ; " \ +"nand write ${loadaddr} ${fcb_sz} ${filesize} ; " \ +"nand write ${loadaddr} ${fw_off} ${filesize} ; " \ + "fi\0" + +#endif /* __M28_H__ */
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 14/20 M28: Add MMC SPL
In reply to Marek VasutThis patch adds SPL code for the M28 board.
--- board/denx/m28evk/Makefile | 8 + board/denx/m28evk/m28_init.h | 41 ++ board/denx/m28evk/mem_init.c | 213 +++++++++ board/denx/m28evk/mmc_boot.c | 273 ++++++++++++ board/denx/m28evk/power_init.c | 913 ++++++++++++++++++++++++++++++++++++++ board/denx/m28evk/start.S | 396 +++++++++++++++++ board/denx/m28evk/u-boot-spl.lds | 87 ++++ board/denx/m28evk/u-boot.bd | 14 + include/configs/m28evk.h | 8 + 9 files changed, 1953 insertions(+), 0 deletions(-) create mode 100644 board/denx/m28evk/m28_init.h create mode 100644 board/denx/m28evk/mem_init.c create mode 100644 board/denx/m28evk/mmc_boot.c create mode 100644 board/denx/m28evk/power_init.c create mode 100644 board/denx/m28evk/start.S create mode 100644 board/denx/m28evk/u-boot-spl.lds create mode 100644 board/denx/m28evk/u-boot.bd
board/denx/m28evk/Makefile +8 -0
@@ -25,7 +25,13 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).o +ifndef CONFIG_SPL_BUILD COBJS := m28evk.o +endif + +ifdef CONFIG_SPL_BUILD +COBJS := mem_init.o mmc_boot.o power_init.o +endif SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS))
@@ -33,6 +39,8 @@ OBJS := $(addprefix $(obj),$(COBJS)) $(LIB): $(obj).depend $(OBJS) $(call cmd_link_o_target, $(OBJS)) +all: $(ALL) + ######################################################################### # defines $(obj).depend target
board/denx/m28evk/m28_init.h new file +41 -0
41 lines not on this page · raw message
board/denx/m28evk/mem_init.c new file +213 -0
213 lines not on this page · raw message
board/denx/m28evk/mmc_boot.c new file +273 -0
273 lines not on this page · raw message
board/denx/m28evk/power_init.c new file +913 -0
913 lines not on this page · raw message
board/denx/m28evk/start.S new file +396 -0
396 lines not on this page · raw message
board/denx/m28evk/u-boot-spl.lds new file +87 -0
87 lines not on this page · raw message
board/denx/m28evk/u-boot.bd new file +14 -0
@@ -0,0 +1,14 @@ +sources { + u_boot_spl="spl/u-boot-spl.bin"; + u_boot="u-boot.bin"; +} + +section (0) { + load u_boot_spl > 0x0000; + load ivt (entry = 0x0014) > 0x8000; + hab call 0x8000; + + load u_boot > 0x40000100; + load ivt (entry = 0x40000100) > 0x8000; + hab call 0x8000; +}
include/configs/m28evk.h +8 -0
@@ -43,6 +43,14 @@#define CONFIG_ARCH_CPU_INIT /* +* SPL +*/ +#define CONFIG_SPL +#define CONFIG_SPL_NO_CPU_SUPPORT_CODE +#define CONFIG_SPL_START_S_PATH "board/denx/m28evk" +#define CONFIG_SPL_LDSCRIPT "board/denx/m28evk/u-boot-spl.lds" + +/* * U-Boot Commands */ #include <config_cmd_default.h>
Signature · 1 line
1.7.7.1
PATCH 14/20 M28: Add MMC SPL
Quoted 2,041 lines · Marek Vasut
This patch adds SPL code for the M28 board.
Signed-off-by Marek Vasut <[email protected]>Cc Andy Fleming <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- board/denx/m28evk/Makefile | 8 + board/denx/m28evk/m28_init.h | 41 ++ board/denx/m28evk/mem_init.c | 213 +++++++++ board/denx/m28evk/mmc_boot.c | 273 ++++++++++++ board/denx/m28evk/power_init.c | 913 ++++++++++++++++++++++++++++++++++++++ board/denx/m28evk/start.S | 396 +++++++++++++++++ board/denx/m28evk/u-boot-spl.lds | 87 ++++ board/denx/m28evk/u-boot.bd | 14 + include/configs/m28evk.h | 8 + 9 files changed, 1953 insertions(+), 0 deletions(-) create mode 100644 board/denx/m28evk/m28_init.h create mode 100644 board/denx/m28evk/mem_init.c create mode 100644 board/denx/m28evk/mmc_boot.c create mode 100644 board/denx/m28evk/power_init.c create mode 100644 board/denx/m28evk/start.S create mode 100644 board/denx/m28evk/u-boot-spl.lds create mode 100644 board/denx/m28evk/u-boot.bdboard/denx/m28evk/Makefile +8
-0@@ -25,7 +25,13 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).o +ifndef CONFIG_SPL_BUILD COBJS := m28evk.o +endif + +ifdef CONFIG_SPL_BUILD +COBJS := mem_init.o mmc_boot.o power_init.o +endif SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS))@@ -33,6 +39,8 @@ OBJS := $(addprefix $(obj),$(COBJS)) $(LIB): $(obj).depend $(OBJS) $(call cmd_link_o_target, $(OBJS)) +all: $(ALL) + ######################################################################### # defines $(obj).depend targetboard/denx/m28evk/m28_init.h new file +41
-0@@ -0,0 +1,41 @@ +/* +* Freescale i.MX28 SPL functions +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 __M28_INIT_H__ +#define __M28_INIT_H__ + +void early_delay (int delay); + +void mx28_power_init (void ); + +#ifdef CONFIG_SPL_MX28_PSWITCH_WAIT +void mx28_power_wait_pswitch (void ); +#else +static inline void mx28_power_wait_pswitch (void ) { } +#endif + +void mx28_mem_init (void ); + +#endif /* __M28_INIT_H__ */ board/denx/m28evk/mem_init.c new file +213
-0@@ -0,0 +1,213 @@ +/* +* Freescale i.MX28 RAM init +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 <config.h> +#include <asm/io.h> +#include <asm/arch/iomux-mx28.h> +#include <asm/arch/imx-regs.h> + +#include "m28_init.h" + +uint32_t dram_vals[] = { +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000100 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00010101 ,0x01010101 ,0x000f0f01 ,0x0f02020a , +0x00000000 ,0x00010101 ,0x00000100 ,0x00000100 ,0x00000000 , +0x00000002 ,0x01010000 ,0x05060302 ,0x06005003 ,0x0a0000c8 , +0x02009c40 ,0x0000030c ,0x0036a609 ,0x031a0612 ,0x02030202 , +0x00c8001c ,0x00000000 ,0x00000000 ,0x00012100 ,0xffff0303 , +0x00012100 ,0xffff0303 ,0x00012100 ,0xffff0303 ,0x00012100 , +0xffff0303 ,0x00000003 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000612 ,0x01000F02 ,0x06120612 ,0x00000200 , +0x00020007 ,0xf5014b27 ,0xf5014b27 ,0xf5014b27 ,0xf5014b27 , +0x07000300 ,0x07000300 ,0x07000300 ,0x07000300 ,0x00000006 , +0x00000000 ,0x00000000 ,0x01000000 ,0x01020408 ,0x08040201 , +0x000f1133 ,0x00000000 ,0x00001f04 ,0x00001f04 ,0x00001f04 , +0x00001f04 ,0x00001f04 ,0x00001f04 ,0x00001f04 ,0x00001f04 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x00000000 ,0x00010000 ,0x00020304 ,0x00000004 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 , +0x00000000 ,0x01010000 ,0x01000000 ,0x03030000 ,0x00010303 , +0x01020202 ,0x00000000 ,0x02040303 ,0x21002103 ,0x00061200 , +0x06120612 ,0x04320432 ,0x04320432 ,0x00040004 ,0x00040004 , +0x00000000 ,0x00000000 ,0x00000000 ,0x00000000 ,0x00010001 +}; + +void init_m28_200mhz_ddr2 (void ) +{ +int i; + +for (i =0 ; i <ARRAY_SIZE (dram_vals); i++) +writel (dram_vals[i],MXS_DRAM_BASE + (4 * i)); +} + +void mx28_mem_init_clock (void ) +{ +struct mx28_clkctrl_regs *clkctrl_regs = + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; + +/* Gate EMI clock */ +writel (CLKCTRL_FRAC0_CLKGATEEMI , + &clkctrl_regs->hw_clkctrl_frac0_set); + +/* EMI = 205MHz */ +writel (CLKCTRL_FRAC0_EMIFRAC_MASK , + &clkctrl_regs->hw_clkctrl_frac0_set); +writel ((0x2a <<CLKCTRL_FRAC0_EMIFRAC_OFFSET ) & +CLKCTRL_FRAC0_EMIFRAC_MASK , + &clkctrl_regs->hw_clkctrl_frac0_clr); + +/* Ungate EMI clock */ +writel (CLKCTRL_FRAC0_CLKGATEEMI , + &clkctrl_regs->hw_clkctrl_frac0_clr); + +early_delay (11000 ); + +writel ((2 <<CLKCTRL_EMI_DIV_EMI_OFFSET ) | + (1 <<CLKCTRL_EMI_DIV_XTAL_OFFSET ), + &clkctrl_regs->hw_clkctrl_emi); + +/* Unbypass EMI */ +writel (CLKCTRL_CLKSEQ_BYPASS_EMI , + &clkctrl_regs->hw_clkctrl_clkseq_clr); + +early_delay (10000 ); +} + +void mx28_mem_setup_cpu_and_hbus (void ) +{ +struct mx28_clkctrl_regs *clkctrl_regs = + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; + +/* CPU = 454MHz and ungate CPU clock */ +clrsetbits_le32 (&clkctrl_regs->hw_clkctrl_frac0, +CLKCTRL_FRAC0_CPUFRAC_MASK |CLKCTRL_FRAC0_CLKGATECPU , +19 <<CLKCTRL_FRAC0_CPUFRAC_OFFSET ); + +/* Set CPU bypass */ +writel (CLKCTRL_CLKSEQ_BYPASS_CPU , + &clkctrl_regs->hw_clkctrl_clkseq_set); + +/* HBUS = 151MHz */ +writel (CLKCTRL_HBUS_DIV_MASK , &clkctrl_regs->hw_clkctrl_hbus_set); +writel (((~3 ) <<CLKCTRL_HBUS_DIV_OFFSET ) &CLKCTRL_HBUS_DIV_MASK , + &clkctrl_regs->hw_clkctrl_hbus_clr); + +early_delay (10000 ); + +/* CPU clock divider = 1 */ +clrsetbits_le32 (&clkctrl_regs->hw_clkctrl_cpu, +CLKCTRL_CPU_DIV_CPU_MASK ,1 ); + +/* Disable CPU bypass */ +writel (CLKCTRL_CLKSEQ_BYPASS_CPU , + &clkctrl_regs->hw_clkctrl_clkseq_clr); +} + +void mx28_mem_setup_vdda (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +writel ((0xc <<POWER_VDDACTRL_TRG_OFFSET ) | + (0x7 <<POWER_VDDACTRL_BO_OFFSET_OFFSET ) | +POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW , + &power_regs->hw_power_vddactrl); +} + +void mx28_mem_setup_vddd (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +writel ((0x1c <<POWER_VDDDCTRL_TRG_OFFSET ) | + (0x7 <<POWER_VDDDCTRL_BO_OFFSET_OFFSET ) | +POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW , + &power_regs->hw_power_vdddctrl); +} + +void mx28_mem_init (void ) +{ +struct mx28_clkctrl_regs *clkctrl_regs = + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; +struct mx28_pinctrl_regs *pinctrl_regs = + (struct mx28_pinctrl_regs *)MXS_PINCTRL_BASE ; + +/* Set DDR2 mode */ +writel (PINCTRL_EMI_DS_CTRL_DDR_MODE_DDR2 , + &pinctrl_regs->hw_pinctrl_emi_ds_ctrl_set); + +/* Power up PLL0 */ +writel (CLKCTRL_PLL0CTRL0_POWER , + &clkctrl_regs->hw_clkctrl_pll0ctrl0_set); + +early_delay (11000 ); + +mx28_mem_init_clock (); + +mx28_mem_setup_vdda (); + +/* +* Configure the DRAM registers +*/ + +/* Clear START bit from DRAM_CTL16 */ +clrbits_le32 (MXS_DRAM_BASE +0x40 ,1 ); + +init_m28_200mhz_ddr2 (); + +/* Clear SREFRESH bit from DRAM_CTL17 */ +clrbits_le32 (MXS_DRAM_BASE +0x44 ,1 ); + +/* Set START bit in DRAM_CTL16 */ +setbits_le32 (MXS_DRAM_BASE +0x40 ,1 ); + +/* Wait for bit 20 (DRAM init complete) in DRAM_CTL58 */ +while (!(readl (MXS_DRAM_BASE +0xe8 ) & (1 <<20 ))) + ; + +mx28_mem_setup_vddd (); + +early_delay (10000 ); + +mx28_mem_setup_cpu_and_hbus (); +}board/denx/m28evk/mmc_boot.c new file +273
-0@@ -0,0 +1,273 @@ +/* +* Freescale i.MX28 Boot setup +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 <config.h> +#include <asm/io.h> +#include <asm/arch/iomux-mx28.h> + +#include "m28_init.h" + +/* +* This delay function is intended to be used only in early stage of boot, where +* clock are not set up yet. The timer used here is reset on every boot and +* takes a few seconds to roll. The boot doesn't take that long, so to keep the +* code simple, it doesn't take rolling into consideration. +*/ +#define HW_DIGCTRL_MICROSECONDS 0x8001c0c0 +void early_delay (int delay) +{ +uint32_t st =readl (HW_DIGCTRL_MICROSECONDS ); + st += delay; +while (st >readl (HW_DIGCTRL_MICROSECONDS )) + ; +} + +#define MUX_CONFIG_LED (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL) +#define MUX_CONFIG_LCD (MXS_PAD_3V3 | MXS_PAD_4MA) +#define MUX_CONFIG_TSC (MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP) +#define MUX_CONFIG_SSP0 (MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_PULLUP) +#define MUX_CONFIG_SSP2 (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP) +#define MUX_CONFIG_GPMI (MXS_PAD_1V8 | MXS_PAD_4MA | MXS_PAD_NOPULL) +#define MUX_CONFIG_ENET (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP) +#define MUX_CONFIG_EMI (MXS_PAD_3V3 | MXS_PAD_12MA | MXS_PAD_NOPULL) + +const iomux_cfg_t iomux_setup[] = { +/* LED */ +MX28_PAD_ENET0_RXD3__GPIO_4_10 |MUX_CONFIG_LED , + +/* framebuffer */ +MX28_PAD_LCD_D00__LCD_D0 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D01__LCD_D1 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D02__LCD_D2 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D03__LCD_D3 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D04__LCD_D4 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D05__LCD_D5 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D06__LCD_D6 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D07__LCD_D7 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D08__LCD_D8 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D09__LCD_D9 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D10__LCD_D10 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D11__LCD_D11 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D12__LCD_D12 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D13__LCD_D13 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D14__LCD_D14 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D15__LCD_D15 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D16__LCD_D16 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D17__LCD_D17 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D18__LCD_D18 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D19__LCD_D19 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D20__LCD_D20 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D21__LCD_D21 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D22__LCD_D22 |MUX_CONFIG_LCD , +MX28_PAD_LCD_D23__LCD_D23 |MUX_CONFIG_LCD , +MX28_PAD_LCD_RD_E__LCD_VSYNC |MUX_CONFIG_LCD , +MX28_PAD_LCD_WR_RWN__LCD_HSYNC |MUX_CONFIG_LCD , +MX28_PAD_LCD_RS__LCD_DOTCLK |MUX_CONFIG_LCD , +MX28_PAD_LCD_CS__LCD_CS |MUX_CONFIG_LCD , +MX28_PAD_LCD_VSYNC__LCD_VSYNC |MUX_CONFIG_LCD , +MX28_PAD_LCD_HSYNC__LCD_HSYNC |MUX_CONFIG_LCD , +MX28_PAD_LCD_DOTCLK__LCD_DOTCLK |MUX_CONFIG_LCD , +MX28_PAD_LCD_ENABLE__GPIO_1_31 |MUX_CONFIG_LCD , +MX28_PAD_LCD_RESET__GPIO_3_30 |MUX_CONFIG_LCD , + +/* UART1 */ +MX28_PAD_PWM0__DUART_RX , +MX28_PAD_PWM1__DUART_TX , +MX28_PAD_AUART0_TX__DUART_RTS , +MX28_PAD_AUART0_RX__DUART_CTS , + +/* UART2 */ +MX28_PAD_AUART1_RX__AUART1_RX , +MX28_PAD_AUART1_TX__AUART1_TX , +MX28_PAD_AUART1_RTS__AUART1_RTS , +MX28_PAD_AUART1_CTS__AUART1_CTS , + +/* CAN */ +MX28_PAD_GPMI_RDY2__CAN0_TX , +MX28_PAD_GPMI_RDY3__CAN0_RX , + +/* I2C */ +MX28_PAD_I2C0_SCL__I2C0_SCL , +MX28_PAD_I2C0_SDA__I2C0_SDA , + +/* TSC2007 */ +MX28_PAD_SAIF0_MCLK__GPIO_3_20 |MUX_CONFIG_TSC , + +/* MMC0 */ +MX28_PAD_SSP0_DATA0__SSP0_D0 |MUX_CONFIG_SSP0 , +MX28_PAD_SSP0_DATA1__SSP0_D1 |MUX_CONFIG_SSP0 , +MX28_PAD_SSP0_DATA2__SSP0_D2 |MUX_CONFIG_SSP0 , +MX28_PAD_SSP0_DATA3__SSP0_D3 |MUX_CONFIG_SSP0 , +MX28_PAD_SSP0_DATA4__SSP0_D4 |MUX_CONFIG_SSP0 , +MX28_PAD_SSP0_DATA5__SSP0_D5 |MUX_CONFIG_SSP0 , +MX28_PAD_SSP0_DATA6__SSP0_D6 |MUX_CONFIG_SSP0 , +MX28_PAD_SSP0_DATA7__SSP0_D7 |MUX_CONFIG_SSP0 , +MX28_PAD_SSP0_CMD__SSP0_CMD |MUX_CONFIG_SSP0 , +MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT | + (MXS_PAD_3V3 |MXS_PAD_12MA |MXS_PAD_NOPULL ), +MX28_PAD_SSP0_SCK__SSP0_SCK | + (MXS_PAD_3V3 |MXS_PAD_12MA |MXS_PAD_NOPULL ), +MX28_PAD_PWM3__GPIO_3_28 |MUX_CONFIG_SSP0 ,/* Power .. FIXME */ +MX28_PAD_AUART2_CTS__GPIO_3_10 ,/* WP ... FIXME */ + +/* GPMI NAND */ +MX28_PAD_GPMI_D00__GPMI_D0 |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_D01__GPMI_D1 |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_D02__GPMI_D2 |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_D03__GPMI_D3 |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_D04__GPMI_D4 |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_D05__GPMI_D5 |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_D06__GPMI_D6 |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_D07__GPMI_D7 |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_CE0N__GPMI_CE0N |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_RDY0__GPMI_READY0 |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_RDN__GPMI_RDN | + (MXS_PAD_1V8 |MXS_PAD_8MA |MXS_PAD_PULLUP ), +MX28_PAD_GPMI_WRN__GPMI_WRN |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_ALE__GPMI_ALE |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_CLE__GPMI_CLE |MUX_CONFIG_GPMI , +MX28_PAD_GPMI_RESETN__GPMI_RESETN |MUX_CONFIG_GPMI , + +/* FEC Ethernet */ +MX28_PAD_ENET0_MDC__ENET0_MDC |MUX_CONFIG_ENET , +MX28_PAD_ENET0_MDIO__ENET0_MDIO |MUX_CONFIG_ENET , +MX28_PAD_ENET0_RX_EN__ENET0_RX_EN |MUX_CONFIG_ENET , +MX28_PAD_ENET0_TX_EN__ENET0_TX_EN |MUX_CONFIG_ENET , +MX28_PAD_ENET0_RXD0__ENET0_RXD0 |MUX_CONFIG_ENET , +MX28_PAD_ENET0_RXD1__ENET0_RXD1 |MUX_CONFIG_ENET , +MX28_PAD_ENET0_TXD0__ENET0_TXD0 |MUX_CONFIG_ENET , +MX28_PAD_ENET0_TXD1__ENET0_TXD1 |MUX_CONFIG_ENET , +MX28_PAD_ENET_CLK__CLKCTRL_ENET |MUX_CONFIG_ENET , + +MX28_PAD_ENET0_COL__ENET1_TX_EN |MUX_CONFIG_ENET , +MX28_PAD_ENET0_CRS__ENET1_RX_EN |MUX_CONFIG_ENET , +MX28_PAD_ENET0_RXD2__ENET1_RXD0 |MUX_CONFIG_ENET , +MX28_PAD_ENET0_RXD3__ENET1_RXD1 |MUX_CONFIG_ENET , +MX28_PAD_ENET0_TXD2__ENET1_TXD0 |MUX_CONFIG_ENET , +MX28_PAD_ENET0_TXD3__ENET1_TXD1 |MUX_CONFIG_ENET , + +/* I2C */ +MX28_PAD_I2C0_SCL__I2C0_SCL , +MX28_PAD_I2C0_SDA__I2C0_SDA , + +/* EMI */ +MX28_PAD_EMI_D00__EMI_DATA0 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D01__EMI_DATA1 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D02__EMI_DATA2 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D03__EMI_DATA3 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D04__EMI_DATA4 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D05__EMI_DATA5 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D06__EMI_DATA6 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D07__EMI_DATA7 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D08__EMI_DATA8 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D09__EMI_DATA9 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D10__EMI_DATA10 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D11__EMI_DATA11 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D12__EMI_DATA12 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D13__EMI_DATA13 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D14__EMI_DATA14 |MUX_CONFIG_EMI , +MX28_PAD_EMI_D15__EMI_DATA15 |MUX_CONFIG_EMI , +MX28_PAD_EMI_ODT0__EMI_ODT0 |MUX_CONFIG_EMI , +MX28_PAD_EMI_DQM0__EMI_DQM0 |MUX_CONFIG_EMI , +MX28_PAD_EMI_ODT1__EMI_ODT1 |MUX_CONFIG_EMI , +MX28_PAD_EMI_DQM1__EMI_DQM1 |MUX_CONFIG_EMI , +MX28_PAD_EMI_DDR_OPEN_FB__EMI_DDR_OPEN_FEEDBACK |MUX_CONFIG_EMI , +MX28_PAD_EMI_CLK__EMI_CLK |MUX_CONFIG_EMI , +MX28_PAD_EMI_DQS0__EMI_DQS0 |MUX_CONFIG_EMI , +MX28_PAD_EMI_DQS1__EMI_DQS1 |MUX_CONFIG_EMI , +MX28_PAD_EMI_DDR_OPEN__EMI_DDR_OPEN |MUX_CONFIG_EMI , + +MX28_PAD_EMI_A00__EMI_ADDR0 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A01__EMI_ADDR1 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A02__EMI_ADDR2 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A03__EMI_ADDR3 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A04__EMI_ADDR4 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A05__EMI_ADDR5 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A06__EMI_ADDR6 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A07__EMI_ADDR7 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A08__EMI_ADDR8 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A09__EMI_ADDR9 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A10__EMI_ADDR10 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A11__EMI_ADDR11 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A12__EMI_ADDR12 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A13__EMI_ADDR13 |MUX_CONFIG_EMI , +MX28_PAD_EMI_A14__EMI_ADDR14 |MUX_CONFIG_EMI , +MX28_PAD_EMI_BA0__EMI_BA0 |MUX_CONFIG_EMI , +MX28_PAD_EMI_BA1__EMI_BA1 |MUX_CONFIG_EMI , +MX28_PAD_EMI_BA2__EMI_BA2 |MUX_CONFIG_EMI , +MX28_PAD_EMI_CASN__EMI_CASN |MUX_CONFIG_EMI , +MX28_PAD_EMI_RASN__EMI_RASN |MUX_CONFIG_EMI , +MX28_PAD_EMI_WEN__EMI_WEN |MUX_CONFIG_EMI , +MX28_PAD_EMI_CE0N__EMI_CE0N |MUX_CONFIG_EMI , +MX28_PAD_EMI_CE1N__EMI_CE1N |MUX_CONFIG_EMI , +MX28_PAD_EMI_CKE__EMI_CKE |MUX_CONFIG_EMI , + +/* SPI2 (for flash) */ +MX28_PAD_SSP2_SCK__SSP2_SCK |MUX_CONFIG_SSP2 , +MX28_PAD_SSP2_MOSI__SSP2_CMD |MUX_CONFIG_SSP2 , +MX28_PAD_SSP2_MISO__SSP2_D0 |MUX_CONFIG_SSP2 , +MX28_PAD_SSP2_SS0__SSP2_D3 | + (MXS_PAD_3V3 |MXS_PAD_8MA |MXS_PAD_PULLUP ), +}; + +void board_init_ll (void ) +{ +mxs_iomux_setup_multiple_pads (iomux_setup,ARRAY_SIZE (iomux_setup)); +mx28_power_init (); +mx28_mem_init (); +mx28_power_wait_pswitch (); +} + +/* Support aparatus */ +inline void board_init_f (unsigned long bootflag) +{ +for (;;) + ; +} + +inline void board_init_r (gd_t *id,ulong dest_addr) +{ +for (;;) + ; +} + +inline int printf (const char *fmt, ...) +{ +return 0 ; +} + +inline void __coloured_LED_init (void ) {} +inline void __red_LED_on (void ) {} +void coloured_LED_init (void ) + __attribute__((weak,alias ("__coloured_LED_init" ))); +void red_LED_on (void ) + __attribute__((weak,alias ("__red_LED_on" ))); +void hang (void ) __attribute__ ((noreturn)); +void hang (void ) +{ +for (;;) + ; +}board/denx/m28evk/power_init.c new file +913
-0@@ -0,0 +1,913 @@ +/* +* Freescale i.MX28 Boot PMIC init +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 <config.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> + +#include "m28_init.h" + +void mx28_power_clock2xtal (void ) +{ +struct mx28_clkctrl_regs *clkctrl_regs = + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; + +/* Set XTAL as CPU reference clock */ +writel (CLKCTRL_CLKSEQ_BYPASS_CPU , + &clkctrl_regs->hw_clkctrl_clkseq_set); +} + +void mx28_power_clock2pll (void ) +{ +struct mx28_clkctrl_regs *clkctrl_regs = + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; + +writel (CLKCTRL_PLL0CTRL0_POWER , + &clkctrl_regs->hw_clkctrl_pll0ctrl0_set); +early_delay (100 ); +writel (CLKCTRL_CLKSEQ_BYPASS_CPU , + &clkctrl_regs->hw_clkctrl_clkseq_clr); +} + +void mx28_power_clear_auto_restart (void ) +{ +struct mx28_rtc_regs *rtc_regs = + (struct mx28_rtc_regs *)MXS_RTC_BASE ; + +writel (RTC_CTRL_SFTRST , &rtc_regs->hw_rtc_ctrl_clr); +while (readl (&rtc_regs->hw_rtc_ctrl) &RTC_CTRL_SFTRST ) + ; + +writel (RTC_CTRL_CLKGATE , &rtc_regs->hw_rtc_ctrl_clr); +while (readl (&rtc_regs->hw_rtc_ctrl) &RTC_CTRL_CLKGATE ) + ; + +/* +* Due to the hardware design bug of mx28 EVK-A +* we need to set the AUTO_RESTART bit. +*/ +if (readl (&rtc_regs->hw_rtc_persistent0) &RTC_PERSISTENT0_AUTO_RESTART ) +return ; + +while (readl (&rtc_regs->hw_rtc_stat) &RTC_STAT_NEW_REGS_MASK ) + ; + +setbits_le32 (&rtc_regs->hw_rtc_persistent0, +RTC_PERSISTENT0_AUTO_RESTART ); +writel (RTC_CTRL_FORCE_UPDATE , &rtc_regs->hw_rtc_ctrl_set); +writel (RTC_CTRL_FORCE_UPDATE , &rtc_regs->hw_rtc_ctrl_clr); +while (readl (&rtc_regs->hw_rtc_stat) &RTC_STAT_NEW_REGS_MASK ) + ; +while (readl (&rtc_regs->hw_rtc_stat) &RTC_STAT_STALE_REGS_MASK ) + ; +} + +void mx28_power_set_linreg (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +/* Set linear regulator 25mV below switching converter */ +clrsetbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_VDDDCTRL_LINREG_OFFSET_MASK , +POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW ); + +clrsetbits_le32 (&power_regs->hw_power_vddactrl, +POWER_VDDACTRL_LINREG_OFFSET_MASK , +POWER_VDDACTRL_LINREG_OFFSET_1STEPS_BELOW ); + +clrsetbits_le32 (&power_regs->hw_power_vddioctrl, +POWER_VDDIOCTRL_LINREG_OFFSET_MASK , +POWER_VDDIOCTRL_LINREG_OFFSET_1STEPS_BELOW ); +} + +void mx28_power_setup_5v_detect (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +/* Start 5V detection */ +clrsetbits_le32 (&power_regs->hw_power_5vctrl, +POWER_5VCTRL_VBUSVALID_TRSH_MASK , +POWER_5VCTRL_VBUSVALID_TRSH_4V4 | +POWER_5VCTRL_PWRUP_VBUS_CMPS ); +} + +void mx28_src_power_init (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +/* Improve efficieny and reduce transient ripple */ +writel (POWER_LOOPCTRL_TOGGLE_DIF |POWER_LOOPCTRL_EN_CM_HYST | +POWER_LOOPCTRL_EN_DF_HYST , &power_regs->hw_power_loopctrl_set); + +clrsetbits_le32 (&power_regs->hw_power_dclimits, +POWER_DCLIMITS_POSLIMIT_BUCK_MASK , +0x30 <<POWER_DCLIMITS_POSLIMIT_BUCK_OFFSET ); + +setbits_le32 (&power_regs->hw_power_battmonitor, +POWER_BATTMONITOR_EN_BATADJ ); + +/* Increase the RCSCALE level for quick DCDC response to dynamic load */ +clrsetbits_le32 (&power_regs->hw_power_loopctrl, +POWER_LOOPCTRL_EN_RCSCALE_MASK , +POWER_LOOPCTRL_RCSCALE_THRESH | +POWER_LOOPCTRL_EN_RCSCALE_8X ); + +clrsetbits_le32 (&power_regs->hw_power_minpwr, +POWER_MINPWR_HALFFETS ,POWER_MINPWR_DOUBLE_FETS ); + +/* 5V to battery handoff ... FIXME */ +setbits_le32 (&power_regs->hw_power_5vctrl,POWER_5VCTRL_DCDC_XFER ); +early_delay (30 ); +clrbits_le32 (&power_regs->hw_power_5vctrl,POWER_5VCTRL_DCDC_XFER ); +} + +void mx28_power_init_4p2_params (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +/* Setup 4P2 parameters */ +clrsetbits_le32 (&power_regs->hw_power_dcdc4p2, +POWER_DCDC4P2_CMPTRIP_MASK |POWER_DCDC4P2_TRG_MASK , +POWER_DCDC4P2_TRG_4V2 | (31 <<POWER_DCDC4P2_CMPTRIP_OFFSET )); + +clrsetbits_le32 (&power_regs->hw_power_5vctrl, +POWER_5VCTRL_HEADROOM_ADJ_MASK , +0x4 <<POWER_5VCTRL_HEADROOM_ADJ_OFFSET ); + +clrsetbits_le32 (&power_regs->hw_power_dcdc4p2, +POWER_DCDC4P2_DROPOUT_CTRL_MASK , +POWER_DCDC4P2_DROPOUT_CTRL_100MV | +POWER_DCDC4P2_DROPOUT_CTRL_SRC_SEL ); + +clrsetbits_le32 (&power_regs->hw_power_5vctrl, +POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK , +0x3f <<POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET ); +} + +void mx28_enable_4p2_dcdc_input (int xfer) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +uint32_t tmp, vbus_thresh, vbus_5vdetect, pwd_bo; +uint32_t prev_5v_brnout, prev_5v_droop; + + prev_5v_brnout =readl (&power_regs->hw_power_5vctrl) & +POWER_5VCTRL_PWDN_5VBRNOUT ; + prev_5v_droop =readl (&power_regs->hw_power_ctrl) & +POWER_CTRL_ENIRQ_VDD5V_DROOP ; + +clrbits_le32 (&power_regs->hw_power_5vctrl,POWER_5VCTRL_PWDN_5VBRNOUT ); +writel (POWER_RESET_UNLOCK_KEY |POWER_RESET_PWD_OFF , + &power_regs->hw_power_reset); + +clrbits_le32 (&power_regs->hw_power_ctrl,POWER_CTRL_ENIRQ_VDD5V_DROOP ); + +if (xfer && (readl (&power_regs->hw_power_5vctrl) & +POWER_5VCTRL_ENABLE_DCDC )) { +return ; + } + +/* +* Recording orignal values that will be modified temporarlily +* to handle a chip bug. See chip errata for CQ ENGR00115837 +*/ + tmp =readl (&power_regs->hw_power_5vctrl); + vbus_thresh = tmp &POWER_5VCTRL_VBUSVALID_TRSH_MASK ; + vbus_5vdetect = tmp &POWER_5VCTRL_VBUSVALID_5VDETECT ; + + pwd_bo =readl (&power_regs->hw_power_minpwr) &POWER_MINPWR_PWD_BO ; + +/* +* Disable mechanisms that get erroneously tripped by when setting +* the DCDC4P2 EN_DCDC +*/ +clrbits_le32 (&power_regs->hw_power_5vctrl, +POWER_5VCTRL_VBUSVALID_5VDETECT | +POWER_5VCTRL_VBUSVALID_TRSH_MASK ); + +writel (POWER_MINPWR_PWD_BO , &power_regs->hw_power_minpwr_set); + +if (xfer) { +setbits_le32 (&power_regs->hw_power_5vctrl, +POWER_5VCTRL_DCDC_XFER ); +early_delay (20 ); +clrbits_le32 (&power_regs->hw_power_5vctrl, +POWER_5VCTRL_DCDC_XFER ); + +setbits_le32 (&power_regs->hw_power_5vctrl, +POWER_5VCTRL_ENABLE_DCDC ); + }else { +setbits_le32 (&power_regs->hw_power_dcdc4p2, +POWER_DCDC4P2_ENABLE_DCDC ); + } + +early_delay (25 ); + +clrsetbits_le32 (&power_regs->hw_power_5vctrl, +POWER_5VCTRL_VBUSVALID_TRSH_MASK , vbus_thresh); + +if (vbus_5vdetect) +writel (vbus_5vdetect, &power_regs->hw_power_5vctrl_set); + +if (!pwd_bo) +clrbits_le32 (&power_regs->hw_power_minpwr,POWER_MINPWR_PWD_BO ); + +while (readl (&power_regs->hw_power_ctrl) &POWER_CTRL_VBUS_VALID_IRQ ) +clrbits_le32 (&power_regs->hw_power_ctrl, +POWER_CTRL_VBUS_VALID_IRQ ); + +if (prev_5v_brnout) { +writel (POWER_5VCTRL_PWDN_5VBRNOUT , + &power_regs->hw_power_5vctrl_set); +writel (POWER_RESET_UNLOCK_KEY , + &power_regs->hw_power_reset); + }else { +writel (POWER_5VCTRL_PWDN_5VBRNOUT , + &power_regs->hw_power_5vctrl_clr); +writel (POWER_RESET_UNLOCK_KEY |POWER_RESET_PWD_OFF , + &power_regs->hw_power_reset); + } + +while (readl (&power_regs->hw_power_ctrl) &POWER_CTRL_VDD5V_DROOP_IRQ ) +clrbits_le32 (&power_regs->hw_power_ctrl, +POWER_CTRL_VDD5V_DROOP_IRQ ); + +if (prev_5v_droop) +clrbits_le32 (&power_regs->hw_power_ctrl, +POWER_CTRL_ENIRQ_VDD5V_DROOP ); +else +setbits_le32 (&power_regs->hw_power_ctrl, +POWER_CTRL_ENIRQ_VDD5V_DROOP ); +} + +void mx28_power_init_4p2_regulator (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +uint32_t tmp, tmp2; + +setbits_le32 (&power_regs->hw_power_dcdc4p2,POWER_DCDC4P2_ENABLE_4P2 ); + +writel (POWER_CHARGE_ENABLE_LOAD , &power_regs->hw_power_charge_set); + +writel (POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK , + &power_regs->hw_power_5vctrl_clr); +clrbits_le32 (&power_regs->hw_power_dcdc4p2,POWER_DCDC4P2_TRG_MASK ); + +/* Power up the 4p2 rail and logic/control */ +writel (POWER_5VCTRL_PWD_CHARGE_4P2_MASK , + &power_regs->hw_power_5vctrl_clr); + +/* +* Start charging up the 4p2 capacitor. We ramp of this charge +* gradually to avoid large inrush current from the 5V cable which can +* cause transients/problems +*/ +mx28_enable_4p2_dcdc_input (0 ); + +if (readl (&power_regs->hw_power_ctrl) &POWER_CTRL_VBUS_VALID_IRQ ) { +/* +* If we arrived here, we were unable to recover from mx23 chip +* errata 5837. 4P2 is disabled and sufficient battery power is +* not present. Exiting to not enable DCDC power during 5V +* connected state. +*/ +clrbits_le32 (&power_regs->hw_power_dcdc4p2, +POWER_DCDC4P2_ENABLE_DCDC ); +writel (POWER_5VCTRL_PWD_CHARGE_4P2_MASK , + &power_regs->hw_power_5vctrl_set); +hang (); + } + +/* +* Here we set the 4p2 brownout level to something very close to 4.2V. +* We then check the brownout status. If the brownout status is false, +* the voltage is already close to the target voltage of 4.2V so we +* can go ahead and set the 4P2 current limit to our max target limit. +* If the brownout status is true, we need to ramp us the current limit +* so that we don't cause large inrush current issues. We step up the +* current limit until the brownout status is false or until we've +* reached our maximum defined 4p2 current limit. +*/ +clrsetbits_le32 (&power_regs->hw_power_dcdc4p2, +POWER_DCDC4P2_BO_MASK , +22 <<POWER_DCDC4P2_BO_OFFSET );/* 4.15V */ + +if (!(readl (&power_regs->hw_power_sts) &POWER_STS_DCDC_4P2_BO )) { +setbits_le32 (&power_regs->hw_power_5vctrl, +0x3f <<POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET ); + }else { + tmp = (readl (&power_regs->hw_power_5vctrl) & +POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK ) >> +POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET ; +while (tmp <0x3f ) { +if (!(readl (&power_regs->hw_power_sts) & +POWER_STS_DCDC_4P2_BO )) { + tmp =readl (&power_regs->hw_power_5vctrl); + tmp |=POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK ; +early_delay (100 ); +writel (tmp, &power_regs->hw_power_5vctrl); +break ; + }else { + tmp++; + tmp2 =readl (&power_regs->hw_power_5vctrl); + tmp2 &= ~POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK ; + tmp2 |= tmp << +POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET ; +writel (tmp2, &power_regs->hw_power_5vctrl); +early_delay (100 ); + } + } + } + +clrbits_le32 (&power_regs->hw_power_dcdc4p2,POWER_DCDC4P2_BO_MASK ); +writel (POWER_CTRL_DCDC4P2_BO_IRQ , &power_regs->hw_power_ctrl_clr); +} + +void mx28_power_init_dcdc_4p2_source (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +if (!(readl (&power_regs->hw_power_dcdc4p2) & +POWER_DCDC4P2_ENABLE_DCDC )) { +hang (); + } + +mx28_enable_4p2_dcdc_input (1 ); + +if (readl (&power_regs->hw_power_ctrl) &POWER_CTRL_VBUS_VALID_IRQ ) { +clrbits_le32 (&power_regs->hw_power_dcdc4p2, +POWER_DCDC4P2_ENABLE_DCDC ); +writel (POWER_5VCTRL_ENABLE_DCDC , + &power_regs->hw_power_5vctrl_clr); +writel (POWER_5VCTRL_PWD_CHARGE_4P2_MASK , + &power_regs->hw_power_5vctrl_set); + } +} + +void mx28_power_enable_4p2 (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +uint32_t vdddctrl, vddactrl, vddioctrl; +uint32_t tmp; + + vdddctrl =readl (&power_regs->hw_power_vdddctrl); + vddactrl =readl (&power_regs->hw_power_vddactrl); + vddioctrl =readl (&power_regs->hw_power_vddioctrl); + +setbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_VDDDCTRL_DISABLE_FET |POWER_VDDDCTRL_ENABLE_LINREG | +POWER_VDDDCTRL_PWDN_BRNOUT ); + +setbits_le32 (&power_regs->hw_power_vddactrl, +POWER_VDDACTRL_DISABLE_FET |POWER_VDDACTRL_ENABLE_LINREG | +POWER_VDDACTRL_PWDN_BRNOUT ); + +setbits_le32 (&power_regs->hw_power_vddioctrl, +POWER_VDDIOCTRL_DISABLE_FET |POWER_VDDIOCTRL_PWDN_BRNOUT ); + +mx28_power_init_4p2_params (); +mx28_power_init_4p2_regulator (); + +/* Shutdown battery (none present) */ +clrbits_le32 (&power_regs->hw_power_dcdc4p2,POWER_DCDC4P2_BO_MASK ); +writel (POWER_CTRL_DCDC4P2_BO_IRQ , &power_regs->hw_power_ctrl_clr); +writel (POWER_CTRL_ENIRQ_DCDC4P2_BO , &power_regs->hw_power_ctrl_clr); + +mx28_power_init_dcdc_4p2_source (); + +writel (vdddctrl, &power_regs->hw_power_vdddctrl); +early_delay (20 ); +writel (vddactrl, &power_regs->hw_power_vddactrl); +early_delay (20 ); +writel (vddioctrl, &power_regs->hw_power_vddioctrl); + +/* +* Check if FET is enabled on either powerout and if so, +* disable load. +*/ + tmp =0 ; + tmp |= !(readl (&power_regs->hw_power_vdddctrl) & +POWER_VDDDCTRL_DISABLE_FET ); + tmp |= !(readl (&power_regs->hw_power_vddactrl) & +POWER_VDDACTRL_DISABLE_FET ); + tmp |= !(readl (&power_regs->hw_power_vddioctrl) & +POWER_VDDIOCTRL_DISABLE_FET ); +if (tmp) +writel (POWER_CHARGE_ENABLE_LOAD , + &power_regs->hw_power_charge_clr); +} + +void mx28_boot_valid_5v (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +/* +* Use VBUSVALID level instead of VDD5V_GT_VDDIO level to trigger a 5V +* disconnect event. FIXME +*/ +writel (POWER_5VCTRL_VBUSVALID_5VDETECT , + &power_regs->hw_power_5vctrl_set); + +/* Configure polarity to check for 5V disconnection. */ +writel (POWER_CTRL_POLARITY_VBUSVALID | +POWER_CTRL_POLARITY_VDD5V_GT_VDDIO , + &power_regs->hw_power_ctrl_clr); + +writel (POWER_CTRL_VBUS_VALID_IRQ |POWER_CTRL_VDD5V_GT_VDDIO_IRQ , + &power_regs->hw_power_ctrl_clr); + +mx28_power_enable_4p2 (); +} + +void mx28_powerdown (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +writel (POWER_RESET_UNLOCK_KEY , &power_regs->hw_power_reset); +writel (POWER_RESET_UNLOCK_KEY |POWER_RESET_PWD_OFF , + &power_regs->hw_power_reset); +} + +void mx28_handle_5v_conflict (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +uint32_t tmp; + +setbits_le32 (&power_regs->hw_power_vddioctrl, +POWER_VDDIOCTRL_BO_OFFSET_MASK ); + +for (;;) { + tmp =readl (&power_regs->hw_power_sts); + +if (tmp &POWER_STS_VDDIO_BO ) { +mx28_powerdown (); +break ; + } + +if (tmp &POWER_STS_VDD5V_GT_VDDIO ) { +mx28_boot_valid_5v (); +break ; + }else { +mx28_powerdown (); +break ; + } + } +} + +int mx28_get_batt_volt (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +uint32_t volt =readl (&power_regs->hw_power_battmonitor); + volt &=POWER_BATTMONITOR_BATT_VAL_MASK ; + volt >>=POWER_BATTMONITOR_BATT_VAL_OFFSET ; + volt *=8 ; +return volt; +} + +int mx28_is_batt_ready (void ) +{ +return (mx28_get_batt_volt () >=3600 ); +} + +void mx28_5v_boot (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +/* +* NOTE: In original IMX-Bootlets, this also checks for VBUSVALID, +* but their implementation always returns 1 so we omit it here. +*/ +if (readl (&power_regs->hw_power_sts) &POWER_STS_VDD5V_GT_VDDIO ) { +mx28_boot_valid_5v (); +return ; + } + +early_delay (1000 ); +if (readl (&power_regs->hw_power_sts) &POWER_STS_VDD5V_GT_VDDIO ) { +mx28_boot_valid_5v (); +return ; + } + +mx28_handle_5v_conflict (); +} + +void mx28_init_batt_bo (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +/* Brownout at 3V */ +clrsetbits_le32 (&power_regs->hw_power_battmonitor, +POWER_BATTMONITOR_BRWNOUT_LVL_MASK , +15 <<POWER_BATTMONITOR_BRWNOUT_LVL_OFFSET ); + +writel (POWER_CTRL_BATT_BO_IRQ , &power_regs->hw_power_ctrl_clr); +writel (POWER_CTRL_ENIRQ_BATT_BO , &power_regs->hw_power_ctrl_clr); +} + +void mx28_switch_vddd_to_dcdc_source (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +clrsetbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_VDDDCTRL_LINREG_OFFSET_MASK , +POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW ); + +clrbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_VDDDCTRL_DISABLE_FET |POWER_VDDDCTRL_ENABLE_LINREG | +POWER_VDDDCTRL_DISABLE_STEPPING ); +} + +int mx28_is_batt_good (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +uint32_t volt; + + volt =readl (&power_regs->hw_power_battmonitor); + volt &=POWER_BATTMONITOR_BATT_VAL_MASK ; + volt >>=POWER_BATTMONITOR_BATT_VAL_OFFSET ; + volt *=8 ; + +if ((volt >=2400 ) && (volt <=4300 )) +return 1 ; + +clrsetbits_le32 (&power_regs->hw_power_5vctrl, +POWER_5VCTRL_CHARGE_4P2_ILIMIT_MASK , +0x3 <<POWER_5VCTRL_CHARGE_4P2_ILIMIT_OFFSET ); +writel (POWER_5VCTRL_PWD_CHARGE_4P2_MASK , + &power_regs->hw_power_5vctrl_clr); + +clrsetbits_le32 (&power_regs->hw_power_charge, +POWER_CHARGE_STOP_ILIMIT_MASK |POWER_CHARGE_BATTCHRG_I_MASK , +POWER_CHARGE_STOP_ILIMIT_10MA |0x3 ); + +writel (POWER_CHARGE_PWD_BATTCHRG , &power_regs->hw_power_charge_clr); +writel (POWER_5VCTRL_PWD_CHARGE_4P2_MASK , + &power_regs->hw_power_5vctrl_clr); + +early_delay (500000 ); + + volt =readl (&power_regs->hw_power_battmonitor); + volt &=POWER_BATTMONITOR_BATT_VAL_MASK ; + volt >>=POWER_BATTMONITOR_BATT_VAL_OFFSET ; + volt *=8 ; + +if (volt >=3500 ) +return 0 ; + +if (volt >=2400 ) +return 1 ; + +writel (POWER_CHARGE_STOP_ILIMIT_MASK |POWER_CHARGE_BATTCHRG_I_MASK , + &power_regs->hw_power_charge_clr); +writel (POWER_CHARGE_PWD_BATTCHRG , &power_regs->hw_power_charge_set); + +return 0 ; +} + +void mx28_power_configure_power_source (void ) +{ +mx28_src_power_init (); + +mx28_5v_boot (); +mx28_power_clock2pll (); + +mx28_init_batt_bo (); +mx28_switch_vddd_to_dcdc_source (); +} + +void mx28_enable_output_rail_protection (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +writel (POWER_CTRL_VDDD_BO_IRQ |POWER_CTRL_VDDA_BO_IRQ | +POWER_CTRL_VDDIO_BO_IRQ , &power_regs->hw_power_ctrl_clr); + +setbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_VDDDCTRL_PWDN_BRNOUT ); + +setbits_le32 (&power_regs->hw_power_vddactrl, +POWER_VDDACTRL_PWDN_BRNOUT ); + +setbits_le32 (&power_regs->hw_power_vddioctrl, +POWER_VDDIOCTRL_PWDN_BRNOUT ); +} + +int mx28_get_vddio_power_source_off (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +uint32_t tmp; + +if (readl (&power_regs->hw_power_sts) &POWER_STS_VDD5V_GT_VDDIO ) { + tmp =readl (&power_regs->hw_power_vddioctrl); +if (tmp &POWER_VDDIOCTRL_DISABLE_FET ) { +if ((tmp &POWER_VDDIOCTRL_LINREG_OFFSET_MASK ) == +POWER_VDDDCTRL_LINREG_OFFSET_0STEPS ) { +return 1 ; + } + } + +if (!(readl (&power_regs->hw_power_5vctrl) & +POWER_5VCTRL_ENABLE_DCDC )) { +if ((tmp &POWER_VDDIOCTRL_LINREG_OFFSET_MASK ) == +POWER_VDDDCTRL_LINREG_OFFSET_0STEPS ) { +return 1 ; + } + } + } + +return 0 ; + +} + +int mx28_get_vddd_power_source_off (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +uint32_t tmp; + + tmp =readl (&power_regs->hw_power_vdddctrl); +if (tmp &POWER_VDDDCTRL_DISABLE_FET ) { +if ((tmp &POWER_VDDDCTRL_LINREG_OFFSET_MASK ) == +POWER_VDDDCTRL_LINREG_OFFSET_0STEPS ) { +return 1 ; + } + } + +if (readl (&power_regs->hw_power_sts) &POWER_STS_VDD5V_GT_VDDIO ) { +if (!(readl (&power_regs->hw_power_5vctrl) & +POWER_5VCTRL_ENABLE_DCDC )) { +return 1 ; + } + } + +if (!(tmp &POWER_VDDDCTRL_ENABLE_LINREG )) { +if ((tmp &POWER_VDDDCTRL_LINREG_OFFSET_MASK ) == +POWER_VDDDCTRL_LINREG_OFFSET_1STEPS_BELOW ) { +return 1 ; + } + } + +return 0 ; +} + +void mx28_power_set_vddio (uint32_t new_target,uint32_t new_brownout) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +uint32_t cur_target, diff, bo_int =0 ; +uint32_t powered_by_linreg =0 ; + + new_brownout = new_target - new_brownout; + + cur_target =readl (&power_regs->hw_power_vddioctrl); + cur_target &=POWER_VDDIOCTRL_TRG_MASK ; + cur_target *=50 ;/* 50 mV step*/ + cur_target +=2800 ;/* 2800 mV lowest */ + + powered_by_linreg =mx28_get_vddio_power_source_off (); +if (new_target > cur_target) { + +if (powered_by_linreg) { + bo_int =readl (&power_regs->hw_power_vddioctrl); +clrbits_le32 (&power_regs->hw_power_vddioctrl, +POWER_CTRL_ENIRQ_VDDIO_BO ); + } + +setbits_le32 (&power_regs->hw_power_vddioctrl, +POWER_VDDIOCTRL_BO_OFFSET_MASK ); +do { +if (new_target - cur_target >100 ) + diff = cur_target +100 ; +else + diff = new_target; + + diff -=2800 ; + diff /=50 ; + +clrsetbits_le32 (&power_regs->hw_power_vddioctrl, +POWER_VDDIOCTRL_TRG_MASK , diff); + +if (powered_by_linreg) +early_delay (1500 ); +else { +while (!(readl (&power_regs->hw_power_sts) & +POWER_STS_DC_OK )) + ; + + } + + cur_target =readl (&power_regs->hw_power_vddioctrl); + cur_target &=POWER_VDDIOCTRL_TRG_MASK ; + cur_target *=50 ;/* 50 mV step*/ + cur_target +=2800 ;/* 2800 mV lowest */ + }while (new_target > cur_target); + +if (powered_by_linreg) { +writel (POWER_CTRL_VDDIO_BO_IRQ , + &power_regs->hw_power_ctrl_clr); +if (bo_int &POWER_CTRL_ENIRQ_VDDIO_BO ) +setbits_le32 (&power_regs->hw_power_vddioctrl, +POWER_CTRL_ENIRQ_VDDIO_BO ); + } + }else { +do { +if (cur_target - new_target >100 ) + diff = cur_target -100 ; +else + diff = new_target; + + diff -=2800 ; + diff /=50 ; + +clrsetbits_le32 (&power_regs->hw_power_vddioctrl, +POWER_VDDIOCTRL_TRG_MASK , diff); + +if (powered_by_linreg) +early_delay (1500 ); +else { +while (!(readl (&power_regs->hw_power_sts) & +POWER_STS_DC_OK )) + ; + + } + + cur_target =readl (&power_regs->hw_power_vddioctrl); + cur_target &=POWER_VDDIOCTRL_TRG_MASK ; + cur_target *=50 ;/* 50 mV step*/ + cur_target +=2800 ;/* 2800 mV lowest */ + }while (new_target < cur_target); + } + +clrsetbits_le32 (&power_regs->hw_power_vddioctrl, +POWER_VDDDCTRL_BO_OFFSET_MASK , + new_brownout <<POWER_VDDDCTRL_BO_OFFSET_OFFSET ); +} + +void mx28_power_set_vddd (uint32_t new_target,uint32_t new_brownout) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; +uint32_t cur_target, diff, bo_int =0 ; +uint32_t powered_by_linreg =0 ; + + new_brownout = new_target - new_brownout; + + cur_target =readl (&power_regs->hw_power_vdddctrl); + cur_target &=POWER_VDDDCTRL_TRG_MASK ; + cur_target *=25 ;/* 25 mV step*/ + cur_target +=800 ;/* 800 mV lowest */ + + powered_by_linreg =mx28_get_vddd_power_source_off (); +if (new_target > cur_target) { +if (powered_by_linreg) { + bo_int =readl (&power_regs->hw_power_vdddctrl); +clrbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_CTRL_ENIRQ_VDDD_BO ); + } + +setbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_VDDDCTRL_BO_OFFSET_MASK ); + +do { +if (new_target - cur_target >100 ) + diff = cur_target +100 ; +else + diff = new_target; + + diff -=800 ; + diff /=25 ; + +clrsetbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_VDDDCTRL_TRG_MASK , diff); + +if (powered_by_linreg) +early_delay (1500 ); +else { +while (!(readl (&power_regs->hw_power_sts) & +POWER_STS_DC_OK )) + ; + + } + + cur_target =readl (&power_regs->hw_power_vdddctrl); + cur_target &=POWER_VDDDCTRL_TRG_MASK ; + cur_target *=25 ;/* 25 mV step*/ + cur_target +=800 ;/* 800 mV lowest */ + }while (new_target > cur_target); + +if (powered_by_linreg) { +writel (POWER_CTRL_VDDD_BO_IRQ , + &power_regs->hw_power_ctrl_clr); +if (bo_int &POWER_CTRL_ENIRQ_VDDD_BO ) +setbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_CTRL_ENIRQ_VDDD_BO ); + } + }else { +do { +if (cur_target - new_target >100 ) + diff = cur_target -100 ; +else + diff = new_target; + + diff -=800 ; + diff /=25 ; + +clrsetbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_VDDDCTRL_TRG_MASK , diff); + +if (powered_by_linreg) +early_delay (1500 ); +else { +while (!(readl (&power_regs->hw_power_sts) & +POWER_STS_DC_OK )) + ; + + } + + cur_target =readl (&power_regs->hw_power_vdddctrl); + cur_target &=POWER_VDDDCTRL_TRG_MASK ; + cur_target *=25 ;/* 25 mV step*/ + cur_target +=800 ;/* 800 mV lowest */ + }while (new_target < cur_target); + } + +clrsetbits_le32 (&power_regs->hw_power_vdddctrl, +POWER_VDDDCTRL_BO_OFFSET_MASK , + new_brownout <<POWER_VDDDCTRL_BO_OFFSET_OFFSET ); +} + +void mx28_power_init (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +mx28_power_clock2xtal (); +mx28_power_clear_auto_restart (); +mx28_power_set_linreg (); +mx28_power_setup_5v_detect (); +mx28_power_configure_power_source (); +mx28_enable_output_rail_protection (); + +mx28_power_set_vddio (3300 ,3150 ); + +mx28_power_set_vddd (1350 ,1200 ); + +writel (POWER_CTRL_VDDD_BO_IRQ |POWER_CTRL_VDDA_BO_IRQ | +POWER_CTRL_VDDIO_BO_IRQ |POWER_CTRL_VDD5V_DROOP_IRQ | +POWER_CTRL_VBUS_VALID_IRQ |POWER_CTRL_BATT_BO_IRQ | +POWER_CTRL_DCDC4P2_BO_IRQ , &power_regs->hw_power_ctrl_clr); + +writel (POWER_5VCTRL_PWDN_5VBRNOUT , &power_regs->hw_power_5vctrl_set); + +early_delay (1000 ); +} + +#ifdef CONFIG_SPL_MX28_PSWITCH_WAIT +void mx28_power_wait_pswitch (void ) +{ +struct mx28_power_regs *power_regs = + (struct mx28_power_regs *)MXS_POWER_BASE ; + +while (!(readl (&power_regs->hw_power_sts) &POWER_STS_PSWITCH_MASK )) + ; +} +#endif board/denx/m28evk/start.S new file +396
-0@@ -0,0 +1,396 @@ +/* + * armboot - Startup Code for ARM926EJS CPU-core + * + * Copyright (c) 2003 Texas Instruments + * + * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ + * + * Copyright (c) 2001 Marius Groger <[email protected]> + * Copyright (c) 2002 Alex Zupke <[email protected]> + * Copyright (c) 2002 Gary Jennejohn <[email protected]> + * Copyright (c) 2003 Richard Woodruff <[email protected]> + * Copyright (c) 2003 Kshitij <[email protected]> + * Copyright (c) 2010 Albert Aribaud <[email protected]> + * + * Change to support call back into iMX28 bootrom + * Copyright (c) 2011 Marek Vasut <[email protected]> + * on behalf of DENX Software Engineering GmbH + * + * 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 <asm-offsets.h> +#include <config.h> +#include <common.h> +#include <version.h> + +#if defined(CONFIG_OMAP1610) +#include <./configs/omap1510.h> +#elif defined(CONFIG_OMAP730) +#include <./configs/omap730.h> +#endif + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + + +.globl _start +_start: + b reset +#ifdef CONFIG_SPL_BUILD +/* No exception handlers in preloader */ + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + ldr pc, _hang + b reset + ldr pc, _hang + ldr pc, _hang + +_hang: + .word do_hang +/* pad to 64 byte boundary */ + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 + .word 0x12345678 +#else + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: + .word undefined_instruction +_software_interrupt: + .word software_interrupt +_prefetch_abort: + .word prefetch_abort +_data_abort: + .word data_abort +_not_used: + .word not_used +_irq: + .word irq +_fiq: + .word fiq + +#endif /* CONFIG_SPL_BUILD */ + .balignl 16,0xdeadbeef + + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * setup Memory and board specific bits prior to relocation. + * relocate armboot to ram + * setup stack + * + ************************************************************************* + */ + +.globl _TEXT_BASE +_TEXT_BASE: + .word CONFIG_SYS_TEXT_BASE + +/* + * These are defined in the board-specific linker script. + * Subtracting _start from them lets the linker put their + * relative position in the executable instead of leaving + * them null. + */ +.globl _bss_start_ofs +_bss_start_ofs: + .word __bss_start - _start + +.globl _bss_end_ofs +_bss_end_ofs: + .word __bss_end__ - _start + +.globl _end_ofs +_end_ofs: + .word _end - _start + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + +/* + * the actual reset code + */ + +reset: + /* + * Store all registers on old stack pointer, this will allow us later to + * return to the BootROM and let the BootROM load U-Boot into RAM. + */ + push {r0-r12,r14} + + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0xd3 + msr cpsr,r0 + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + bl cpu_init_crit +#endif + + bl board_init_ll + + pop {r0-r12,r14} + bx lr + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +#ifndef CONFIG_SKIP_LOWLEVEL_INIT +cpu_init_crit: + /* + * flush v4 I/D caches + */ + mov r0, #0 + mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ + mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ + + /* + * disable MMU stuff and caches + */ + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ + bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ + orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ + orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ + mcr p15, 0, r0, c1, c0, 0 + + mov pc, lr /* back to my caller */ +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + +#ifndef CONFIG_SPL_BUILD +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + @ carve out a frame on current user stack + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 + ldr r2, IRQ_STACK_START_IN + @ get values for "aborted" pc and cpsr (into parm regs) + ldmia r2, {r2 - r3} + add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr + mov r0, sp @ save current stack into r0 (param register) + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, IRQ_STACK_START_IN @ setup our mode stack + + str lr, [r13] @ save caller lr in position 0 of saved stack + mrs lr, spsr @ get the spsr + str lr, [r13, #4] @ save spsr in position 1 of saved stack + mov r13, #MODE_SVC @ prepare SVC-Mode + @ msr spsr_c, r13 + msr spsr, r13 @ switch modes, make sure moves will execute + mov lr, pc @ capture return pc + movs pc, lr @ jump to next instruction & switch modes. + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm +#endif /* CONFIG_SPL_BUILD */ + +/* + * exception handlers + */ +#ifdef CONFIG_SPL_BUILD + .align 5 +do_hang: + ldr sp, _TEXT_BASE /* switch to abort stack */ +1: + bl 1b /* hang and never return */ +#else /* !CONFIG_SPL_BUILD */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif +#endif /* CONFIG_SPL_BUILD */board/denx/m28evk/u-boot-spl.lds new file +87
-0@@ -0,0 +1,87 @@ +/* + * Copyright (C) 2011 Marek Vasut <[email protected]> + * on behalf of DENX Software Engineering GmbH + * + * January 2004 - Changed to support H4 device + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <[email protected]> + * + * 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 : + { + board/denx/m28evk/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data) + } + + . = ALIGN(4); + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + . = ALIGN(4); + + .rel.dyn : { + __rel_dyn_start = .; + *(.rel*) + __rel_dyn_end = .; + } + + .dynsym : { + __dynsym_start = .; + *(.dynsym) + } + + _end = .; + + .bss __rel_dyn_start (OVERLAY) : { + __bss_start = .; + *(.bss) + . = ALIGN(4); + __bss_end__ = .; + } + + /DISCARD/ : { *(.bss*) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynsym*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.hash*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +}board/denx/m28evk/u-boot.bd new file +14
-0@@ -0,0 +1,14 @@ +sources { + u_boot_spl="spl/u-boot-spl.bin"; + u_boot="u-boot.bin"; +} + +section (0) { + load u_boot_spl > 0x0000; + load ivt (entry = 0x0014) > 0x8000; + hab call 0x8000; + + load u_boot > 0x40000100; + load ivt (entry = 0x40000100) > 0x8000; + hab call 0x8000; +}include/configs/m28evk.h +1
-0@@ -43,6 +43,14 @@#define CONFIG_ARCH_CPU_INIT /* +* SPL
include/configs/m28evk.h line 56
Quoted 10 lines
include/configs/m28evk.h +7
-0+*/ +#define CONFIG_SPL +#define CONFIG_SPL_NO_CPU_SUPPORT_CODE +#define CONFIG_SPL_START_S_PATH "board/denx/m28evk" +#define CONFIG_SPL_LDSCRIPT "board/denx/m28evk/u-boot-spl.lds" + +/* * U-Boot Commands */ #include <config_cmd_default.h>
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 15/20 M28: Add doc/README.m28 documentation
In reply to Marek Vasut--- doc/README.m28 | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 223 insertions(+), 0 deletions(-) create mode 100644 doc/README.m28
doc/README.m28 new file +223 -0
@@ -0,0 +1,223 @@ +DENX M28EVK +=========== + +This document describes the DENX M28/M28EVK U-Boot port. This document mostly +covers topics related to making the module/board bootable. + +Terminology +----------- + +The dollar symbol ($) introduces a snipped of shell code. This shall be typed +into the unix command prompt in U-Boot source code root directory. + +The (=>) introduces a snipped of code that should by typed into U-Boot command +prompt. + +Contents +-------- + +0) Files of the M28/M28EVK port +1) Prerequisites +2) Compiling U-Boot for M28 +3) Installation of U-Boot for M28EVK to SD card +4) Installation of U-Boot for M28 to NAND flash + +0) Files of the M28/M28EVK port +------------------------------- + +arch/arm/cpu/arm926ejs/mx28/ - The CPU support code for the Freescale i.MX28 +arch/arm/include/asm/arch-mx28/ - Header files for the Freescale i.MX28 +board/denx/m28evk/ - M28EVK board specific files +include/configs/m28evk.h - M28EVK configuration file + +1) Prerequisites +---------------- + +To make the M28 module or the M28 module or M28EVK board bootable, some tools +are necessary. The first one is the "elftosb" tool distributed by Freescale +Semiconductor. The other tool is the "mxsboot" tool found in U-Boot source tree. + +Firstly, obtain the elftosb archive from the following location: + + http://foss.doredevelopment.dk/mirrors/imx/elftosb-10.12.01.tar.gz + +We use a $VER variable here to denote the current version. At the time of +writing of this document, that is "10.12.01". To obtain the file from command +line, use: + + $ VER="10.12.01" + $ wget http://foss.doredevelopment.dk/mirrors/imx/elftosb-${VER}.tar.gz + +Extract the file: + + $ tar xzf elftosb-${VER}.tar.gz + +Compile the file. We need to manually tell the linker to use also libm: + + $ cd elftosb-${VER}/ + $ make LIBS="-lstdc++ -lm" elftosb + +Optionally, remove debugging symbols from elftosb: + + $ strip bld/linux/elftosb + +Finally, install the "elftosb" binary. The "install" target is missing, so just +copy the binary by hand: + + $ sudo cp bld/linux/elftosb /usr/local/bin/ + +Make sure the "elftosb" binary can be found in your $PATH, in this case this +means "/usr/local/bin/" has to be in your $PATH. + +2) Compiling U-Boot for M28 +--------------------------- + +Compiling the U-Boot for M28 is straightforward and done as compiling U-Boot +for any other ARM device. For cross-compiler setup, please refer to ELDK5.0 +documentation. First, clean up the source code: + + $ make mrproper + +Next, configure U-Boot for M28EVK: + + $ make m28evk_config + +Lastly, compile U-Boot and prepare a "BootStream". The "BootStream" is a special +type of file, which the i.MX28 CPU can boot. This is handled by the following +command: + + $ make u-boot.sb + +HINT: To speed-up the build process, you can add -j<N>, where N is number of + compiler instances that'll run in parallel. + +The code produces "u-boot.sb" file. This file needs to be augmented with a +proper header to allow successful boot from SD or NAND. Adding the header is +discussed in the following chapters. + +3) Installation of U-Boot for M28EVK to SD card +----------------------------------------------- + +To boot an M28 from SD, set the boot mode DIP switches according to i.MX28 +manual chapter 12.2.1 (Table 12-2), PORT=SSP0, SD/MMC master on SSP0, 3.3V. + +An SD card the i.MX28 CPU can use to boot U-Boot must contain a DOS partition +table, which in turn carries a partition of special type and which contains a +special header. The rest of partitions in the DOS partition table can be used +by the user. + +To prepare such partition, use your favourite partitioning tool. The partition +must have the following parameters: + + * Start sector .......... sector 2048 + * Partition size ........ at least 1024 kb + * Partition type ........ 0x53 (sometimes "OnTrack DM6 Aux3") + +For example in Linux fdisk, the sequence for a clear card is the following: + + * o ..................... create a clear partition table + * n ..................... create new partition + * p ............. primary partition + * 1 ............. first partition + * 2048 .......... first sector is 2048 + * +1M ........... make the partition 1Mb big + * t 1 ................... change first partition ID + * 53 ............ change the ID to 0x53 (OnTrack DM6 Aux3) + * <create other partitions> + * w ..................... write partition table to disk + +The partition layout is ready, next the special partition must be filled with +proper contents. The contents is generated by running the following command (see +chapter 2)): + + $ ./tools/mxsboot sd u-boot.sb u-boot.sd + +The resulting file, "u-boot.sd", shall then be written to the partition. In this +case, we assume the first partition of the SD card is /dev/mmcblk0p1: + + $ dd if=u-boot.sd of=/dev/mmcblk0p1 + +Last step is to insert the card into M28EVK and boot. + +NOTE: If the user needs to adjust the start sector, the "mxsboot" tool contains + a "-p" switch for that purpose. The "-p" switch takes the sector number as + an argument. + +4) Installation of U-Boot for M28 to NAND flash +----------------------------------------------- + +To boot an M28 from NAND, set the boot mode DIP switches according to i.MX28 +manual chapter 12.2.1 (Table 12-2), PORT=GPMI, NAND 1.8 V. + +There are two possibilities when preparing an image writable to NAND flash. + + I) The NAND wasn't written at all yet or the BCB is broken + ---------------------------------------------------------- + In this case, both BCB (FCB and DBBT) and firmware needs to be + written to NAND. To generate NAND image containing all these, + there is a tool called "mxsboot" in the "tools/" directory. The tool + is invoked on "u-boot.sb" file from chapter 2): + + $ ./tools/mxsboot nand u-boot.sb u-boot.nand + + NOTE: The above invokation works for NAND flash with geometry of + 2048b per page, 64b OOB data, 128kb erase size. If your chip + has a different geometry, please use: + + -w <size> change page size (default 2048 b) + -o <size> change oob size (default 64 b) + -e <size> change erase size (default 131072 b) + + The geometry information can be obtained from running U-Boot + on M28 by issuing the "nand info" command. + + The resulting file, "u-boot.nand" can be written directly to NAND + from the U-Boot prompt. To simplify the process, the U-Boot default + environment contains script "update_nand_full" to update the system. + + This script expects a working TFTP server containing the file + "u-boot.nand" in it's root directory. This can be changed by + adjusting the "update_nand_full_filename" varible. + + To update the system, run the following in U-Boot prompt: + + => run update_nand_full + + In case you would only need to update the bootloader in future, + see II) below. + + II) The NAND was already written with a good BCB + ------------------------------------------------ + This part applies after the part I) above was done at least once. + + If part I) above was done correctly already, there is no need to + write the FCB and DBBT parts of NAND again. It's possible to upgrade + only the bootloader image. + + To simplify the process of firmware update, the U-Boot default + environment contains script "update_nand_firmware" to update only + the firmware, without rewriting FCB and DBBT. + + This script expects a working TFTP server containing the file + "u-boot.sb" in it's root directory. This can be changed by + adjusting the "update_nand_firmware_filename" varible. + + To update the system, run the following in U-Boot prompt: + + => run update_nand_firmware + + III) Special settings for the update scripts + -------------------------------------------- + There is a slight possibility of the user wanting to adjust the + STRIDE and COUNT options of the NAND boot. For description of these, + see i.MX28 manual section 12.12.1.2 and 12.12.1.3. + + The update scripts take this possibility into account. In case the + user changes STRIDE by blowing fuses, the user also has to change + "update_nand_stride" variable. In case the user changes COUNT by + blowing fuses, the user also has to change "update_nand_count" + variable for the update scripts to work correctly. + + In case the user needs to boot a firmware image bigger than 1Mb, the + user has to adjust the "update_nand_firmware_maxsz" variable for the + update scripts to work properly.
Signature · 1 line
1.7.7.1
PATCH 15/20 M28: Add doc/README.m28 documentation
Quoted 228 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- doc/README.m28 | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 223 insertions(+), 0 deletions(-) create mode 100644 doc/README.m28doc/README.m28 new file +213
-0@@ -0,0 +1,223 @@ +DENX M28EVK +=========== + +This document describes the DENX M28/M28EVK U-Boot port. This document mostly +covers topics related to making the module/board bootable. + +Terminology +----------- + +The dollar symbol ($) introduces a snipped of shell code. This shall be typed +into the unix command prompt in U-Boot source code root directory. + +The (=>) introduces a snipped of code that should by typed into U-Boot command +prompt. + +Contents +-------- + +0) Files of the M28/M28EVK port +1) Prerequisites +2) Compiling U-Boot for M28 +3) Installation of U-Boot for M28EVK to SD card +4) Installation of U-Boot for M28 to NAND flash + +0) Files of the M28/M28EVK port +------------------------------- + +arch/arm/cpu/arm926ejs/mx28/ - The CPU support code for the Freescale i.MX28 +arch/arm/include/asm/arch-mx28/ - Header files for the Freescale i.MX28 +board/denx/m28evk/ - M28EVK board specific files +include/configs/m28evk.h - M28EVK configuration file + +1) Prerequisites +---------------- + +To make the M28 module or the M28 module or M28EVK board bootable, some tools +are necessary. The first one is the "elftosb" tool distributed by Freescale +Semiconductor. The other tool is the "mxsboot" tool found in U-Boot source tree. + +Firstly, obtain the elftosb archive from the following location: + + http://foss.doredevelopment.dk/mirrors/imx/elftosb-10.12.01.tar.gz + +We use a $VER variable here to denote the current version. At the time of +writing of this document, that is "10.12.01". To obtain the file from command +line, use: + + $ VER="10.12.01" + $ wget http://foss.doredevelopment.dk/mirrors/imx/elftosb-${VER}.tar.gz + +Extract the file: + + $ tar xzf elftosb-${VER}.tar.gz + +Compile the file. We need to manually tell the linker to use also libm: + + $ cd elftosb-${VER}/ + $ make LIBS="-lstdc++ -lm" elftosb + +Optionally, remove debugging symbols from elftosb: + + $ strip bld/linux/elftosb + +Finally, install the "elftosb" binary. The "install" target is missing, so just +copy the binary by hand: + + $ sudo cp bld/linux/elftosb /usr/local/bin/ + +Make sure the "elftosb" binary can be found in your $PATH, in this case this +means "/usr/local/bin/" has to be in your $PATH. + +2) Compiling U-Boot for M28 +--------------------------- + +Compiling the U-Boot for M28 is straightforward and done as compiling U-Boot +for any other ARM device. For cross-compiler setup, please refer to ELDK5.0 +documentation. First, clean up the source code: + + $ make mrproper + +Next, configure U-Boot for M28EVK: + + $ make m28evk_config + +Lastly, compile U-Boot and prepare a "BootStream". The "BootStream" is a special +type of file, which the i.MX28 CPU can boot. This is handled by the following +command: + + $ make u-boot.sb + +HINT: To speed-up the build process, you can add -j<N>, where N is number of + compiler instances that'll run in parallel. + +The code produces "u-boot.sb" file. This file needs to be augmented with a +proper header to allow successful boot from SD or NAND. Adding the header is +discussed in the following chapters. + +3) Installation of U-Boot for M28EVK to SD card +----------------------------------------------- + +To boot an M28 from SD, set the boot mode DIP switches according to i.MX28 +manual chapter 12.2.1 (Table 12-2), PORT=SSP0, SD/MMC master on SSP0, 3.3V. + +An SD card the i.MX28 CPU can use to boot U-Boot must contain a DOS partition +table, which in turn carries a partition of special type and which contains a +special header. The rest of partitions in the DOS partition table can be used +by the user. + +To prepare such partition, use your favourite partitioning tool. The partition +must have the following parameters: + + * Start sector .......... sector 2048 + * Partition size ........ at least 1024 kb + * Partition type ........ 0x53 (sometimes "OnTrack DM6 Aux3") + +For example in Linux fdisk, the sequence for a clear card is the following: + + * o ..................... create a clear partition table + * n ..................... create new partition + * p ............. primary partition + * 1 ............. first partition + * 2048 .......... first sector is 2048 + * +1M ........... make the partition 1Mb big + * t 1 ................... change first partition ID + * 53 ............ change the ID to 0x53 (OnTrack DM6 Aux3) + * <create other partitions> + * w ..................... write partition table to disk + +The partition layout is ready, next the special partition must be filled with +proper contents. The contents is generated by running the following command (see +chapter 2)): + + $ ./tools/mxsboot sd u-boot.sb u-boot.sd + +The resulting file, "u-boot.sd", shall then be written to the partition. In this +case, we assume the first partition of the SD card is /dev/mmcblk0p1: + + $ dd if=u-boot.sd of=/dev/mmcblk0p1 + +Last step is to insert the card into M28EVK and boot. + +NOTE: If the user needs to adjust the start sector, the "mxsboot" tool contains + a "-p" switch for that purpose. The "-p" switch takes the sector number as + an argument. + +4) Installation of U-Boot for M28 to NAND flash +----------------------------------------------- + +To boot an M28 from NAND, set the boot mode DIP switches according to i.MX28 +manual chapter 12.2.1 (Table 12-2), PORT=GPMI, NAND 1.8 V. + +There are two possibilities when preparing an image writable to NAND flash. + + I) The NAND wasn't written at all yet or the BCB is broken + ---------------------------------------------------------- + In this case, both BCB (FCB and DBBT) and firmware needs to be + written to NAND. To generate NAND image containing all these, + there is a tool called "mxsboot" in the "tools/" directory. The tool + is invoked on "u-boot.sb" file from chapter 2): + + $ ./tools/mxsboot nand u-boot.sb u-boot.nand + + NOTE: The above invokation works for NAND flash with geometry of + 2048b per page, 64b OOB data, 128kb erase size. If your chip + has a different geometry, please use: + + -w <size> change page size (default 2048 b) + -o <size> change oob size (default 64 b) + -e <size> change erase size (default 131072 b) + + The geometry information can be obtained from running U-Boot + on M28 by issuing the "nand info" command. + + The resulting file, "u-boot.nand" can be written directly to NAND + from the U-Boot prompt. To simplify the process, the U-Boot default + environment contains script "update_nand_full" to update the system. + + This script expects a working TFTP server containing the file + "u-boot.nand" in it's root directory. This can be changed by + adjusting the "update_nand_full_filename" varible. + + To update the system, run the following in U-Boot prompt: + + => run update_nand_full + + In case you would only need to update the bootloader in future, + see II) below. + + II) The NAND was already written with a good BCB + ------------------------------------------------ + This part applies after the part I) above was done at least once. + + If part I) above was done correctly already, there is no need to + write the FCB and DBBT parts of NAND again. It's possible to upgrade + only the bootloader image. + + To simplify the process of firmware update, the U-Boot default + environment contains script "update_nand_firmware" to update only + the firmware, without rewriting FCB and DBBT. + + This script expects a working TFTP server containing the file + "u-boot.sb" in it's root directory. This can be changed by + adjusting the "update_nand_firmware_filename" varible. + + To update the system, run the following in U-Boot prompt: + + => run update_nand_firmware + + III) Special settings for the update scripts + -------------------------------------------- + There is a slight possibility of the user wanting to adjust the + STRIDE and COUNT options of the NAND boot. For description of these, + see i.MX28 manual section 12.12.1.2 and 12.12.1.3.
doc/README.m28 line 223
Quoted 10 lines
doc/README.m28 new file +10
-0+ + The update scripts take this possibility into account. In case the + user changes STRIDE by blowing fuses, the user also has to change + "update_nand_stride" variable. In case the user changes COUNT by + blowing fuses, the user also has to change "update_nand_count" + variable for the update scripts to work correctly. + + In case the user needs to boot a firmware image bigger than 1Mb, the + user has to adjust the "update_nand_firmware_maxsz" variable for the + update scripts to work properly.
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 16/20 iMX28: Fix ARM vector handling
In reply to Marek VasutThis patch introduces proper ARM vector handling for i.MX28 CPU. This issue wasn't addressed because the interrupts weren't enabled on any ARMv5 core, therefore the issue wasn't noticed earlier.
In previous implementation, the vectoring code used by i.MX28 CPU when an exception happened was that of the SPL. With this change, the branch target when an exception happens can be reconfigured by U-Boot.
--- arch/arm/cpu/arm926ejs/mx28/mx28.c | 22 +++ board/denx/m28evk/start.S | 264 +++++++----------------------------- include/configs/m28evk.h | 1 + 3 files changed, 74 insertions(+), 213 deletions(-)
arch/arm/cpu/arm926ejs/mx28/mx28.c +22 -0
@@ -35,6 +35,8 @@#include <asm/arch/imx-regs.h> #include <asm/arch/sys_proto.h> +DECLARE_GLOBAL_DATA_PTR ; +/* 1 second delay should be plenty of time for block reset. */ #define RESET_MAX_TIMEOUT 1000000
@@ -116,11 +118,31 @@ int mx28_reset_block(struct mx28_register *reg)return 0 ; } +void mx28_fixup_vt (uint32_t start_addr) +{ +uint32_t *vt = (uint32_t *)0x20 ; +int i; + +for (i =0 ; i <8 ; i++) + vt[i] = start_addr + (4 * i); +} + +#ifdef CONFIG_ARCH_MISC_INIT +int arch_misc_init (void ) +{ +mx28_fixup_vt (gd->relocaddr); +return 0 ; +} +#endif +#ifdef CONFIG_ARCH_CPU_INIT int arch_cpu_init (void ) {struct mx28_clkctrl_regs *clkctrl_regs = (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; +extern uint32_t _start; + +mx28_fixup_vt ((uint32_t )&_start);/* * Enable NAND clock
board/denx/m28evk/start.S +51 -213
289 lines not on this page · raw message
include/configs/m28evk.h +1 -0
@@ -41,6 +41,7 @@#define CONFIG_SYS_DCACHE_OFF #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_ARCH_CPU_INIT +#define CONFIG_ARCH_MISC_INIT /* * SPL
Signature · 1 line
1.7.7.1
PATCH 16/20 iMX28: Fix ARM vector handling
Quoted 365 lines · Marek Vasut
This patch introduces proper ARM vector handling for i.MX28 CPU. This issue wasn't addressed because the interrupts weren't enabled on any ARMv5 core, therefore the issue wasn't noticed earlier.
In previous implementation, the vectoring code used by i.MX28 CPU when an exception happened was that of the SPL. With this change, the branch target when an exception happens can be reconfigured by U-Boot.
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- arch/arm/cpu/arm926ejs/mx28/mx28.c | 22 +++ board/denx/m28evk/start.S | 264 +++++++----------------------------- include/configs/m28evk.h | 1 + 3 files changed, 74 insertions(+), 213 deletions(-)arch/arm/cpu/arm926ejs/mx28/mx28.c +22
-0@@ -35,6 +35,8 @@#include <asm/arch/imx-regs.h> #include <asm/arch/sys_proto.h> +DECLARE_GLOBAL_DATA_PTR ; +/* 1 second delay should be plenty of time for block reset. */ #define RESET_MAX_TIMEOUT 1000000@@ -116,11 +118,31 @@ int mx28_reset_block(struct mx28_register *reg)return 0 ; } +void mx28_fixup_vt (uint32_t start_addr) +{ +uint32_t *vt = (uint32_t *)0x20 ; +int i; + +for (i =0 ; i <8 ; i++) + vt[i] = start_addr + (4 * i); +} + +#ifdef CONFIG_ARCH_MISC_INIT +int arch_misc_init (void ) +{ +mx28_fixup_vt (gd->relocaddr); +return 0 ; +} +#endif +#ifdef CONFIG_ARCH_CPU_INIT int arch_cpu_init (void ) {struct mx28_clkctrl_regs *clkctrl_regs = (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; +extern uint32_t _start; + +mx28_fixup_vt ((uint32_t )&_start);/* * Enable NAND clock board/denx/m28evk/start.S +51
-213@@ -58,54 +58,58 @@ .globl _start _start: b reset -#ifdef CONFIG_SPL_BUILD -/* No exception handlers in preloader */ - ldr pc, _hang - ldr pc, _hang - ldr pc, _hang - ldr pc, _hang - b reset - ldr pc, _hang - ldr pc, _hang + b undefined_instruction + b software_interrupt + b prefetch_abort + b data_abort + b not_used + b irq + b fiq -_hang: - .word do_hang -/* pad to 64 byte boundary */ - .word 0x12345678 - .word 0x12345678 - .word 0x12345678 - .word 0x12345678 - .word 0x12345678 - .word 0x12345678 - .word 0x12345678 -#else - ldr pc, _undefined_instruction - ldr pc, _software_interrupt - ldr pc, _prefetch_abort - ldr pc, _data_abort - ldr pc, _not_used - ldr pc, _irq - ldr pc, _fiq +/* + * Vector table, located at address 0x20. + * This table allows the code running AFTER SPL, the U-Boot, to install it's + * interrupt handlers here. The problem is that the U-Boot is loaded into RAM, + * including it's interrupt vectoring table and the table at 0x0 is still the + * SPLs. So if interrupt happens in U-Boot, the SPLs interrupt vectoring table + * is still used. + */ +_vt_reset: + .word _reset +_vt_undefined_instruction: + .word _hang +_vt_software_interrupt: + .word _hang +_vt_prefetch_abort: + .word _hang +_vt_data_abort: + .word _hang +_vt_not_used: + .word _reset +_vt_irq: + .word _hang +_vt_fiq: + .word _hang -_undefined_instruction: - .word undefined_instruction -_software_interrupt: - .word software_interrupt -_prefetch_abort: - .word prefetch_abort -_data_abort: - .word data_abort -_not_used: - .word not_used -_irq: - .word irq -_fiq: - .word fiq +reset: + ldr pc, _vt_reset +undefined_instruction: + ldr pc, _vt_undefined_instruction +software_interrupt: + ldr pc, _vt_software_interrupt +prefetch_abort: + ldr pc, _vt_prefetch_abort +data_abort: + ldr pc, _vt_data_abort +not_used: + ldr pc, _vt_not_used +irq: + ldr pc, _vt_irq +fiq: + ldr pc, _vt_fiq -#endif /* CONFIG_SPL_BUILD */ .balignl 16,0xdeadbeef - /* ************************************************************************* *@@ -162,7 +166,7 @@ IRQ_STACK_START_IN: * the actual reset code */ -reset: +_reset: /* * Store all registers on old stack pointer, this will allow us later to * return to the BootROM and let the BootROM load U-Boot into RAM.@@ -220,177 +224,11 @@ cpu_init_crit: mcr p15, 0, r0, c1, c0, 0 mov pc, lr /* back to my caller */ -#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ - -#ifndef CONFIG_SPL_BUILD -/* - ************************************************************************* - * - * Interrupt handling - * - ************************************************************************* - */ - -@ -@ IRQ stack frame. -@ -#define S_FRAME_SIZE 72 - -#define S_OLD_R0 68 -#define S_PSR 64 -#define S_PC 60 -#define S_LR 56 -#define S_SP 52 - -#define S_IP 48 -#define S_FP 44 -#define S_R10 40 -#define S_R9 36 -#define S_R8 32 -#define S_R7 28 -#define S_R6 24 -#define S_R5 20 -#define S_R4 16 -#define S_R3 12 -#define S_R2 8 -#define S_R1 4 -#define S_R0 0 - -#define MODE_SVC 0x13 -#define I_BIT 0x80 - -/* - * use bad_save_user_regs for abort/prefetch/undef/swi ... - * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling - */ - - .macro bad_save_user_regs - @ carve out a frame on current user stack - sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 - ldr r2, IRQ_STACK_START_IN - @ get values for "aborted" pc and cpsr (into parm regs) - ldmia r2, {r2 - r3} - add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack - add r5, sp, #S_SP - mov r1, lr - stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr - mov r0, sp @ save current stack into r0 (param register) - .endm - - .macro irq_save_user_regs - sub sp, sp, #S_FRAME_SIZE - stmia sp, {r0 - r12} @ Calling r0-r12 - @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. - add r8, sp, #S_PC - stmdb r8, {sp, lr}^ @ Calling SP, LR - str lr, [r8, #0] @ Save calling PC - mrs r6, spsr - str r6, [r8, #4] @ Save CPSR - str r0, [r8, #8] @ Save OLD_R0 - mov r0, sp - .endm - - .macro irq_restore_user_regs - ldmia sp, {r0 - lr}^ @ Calling r0 - lr - mov r0, r0 - ldr lr, [sp, #S_PC] @ Get PC - add sp, sp, #S_FRAME_SIZE - subs pc, lr, #4 @ return & move spsr_svc into cpsr - .endm - - .macro get_bad_stack - ldr r13, IRQ_STACK_START_IN @ setup our mode stack - - str lr, [r13] @ save caller lr in position 0 of saved stack - mrs lr, spsr @ get the spsr - str lr, [r13, #4] @ save spsr in position 1 of saved stack - mov r13, #MODE_SVC @ prepare SVC-Mode - @ msr spsr_c, r13 - msr spsr, r13 @ switch modes, make sure moves will execute - mov lr, pc @ capture return pc - movs pc, lr @ jump to next instruction & switch modes. - .endm - - .macro get_irq_stack @ setup IRQ stack - ldr sp, IRQ_STACK_START - .endm - - .macro get_fiq_stack @ setup FIQ stack - ldr sp, FIQ_STACK_START - .endm -#endif /* CONFIG_SPL_BUILD */ -/* - * exception handlers - */ -#ifdef CONFIG_SPL_BUILD .align 5 -do_hang: +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + +_hang: ldr sp, _TEXT_BASE /* switch to abort stack */ 1: bl 1b /* hang and never return */ -#else /* !CONFIG_SPL_BUILD */ - .align 5 -undefined_instruction: - get_bad_stack - bad_save_user_regs - bl do_undefined_instruction - - .align 5 -software_interrupt: - get_bad_stack - bad_save_user_regs - bl do_software_interrupt - - .align 5 -prefetch_abort: - get_bad_stack - bad_save_user_regs - bl do_prefetch_abort - - .align 5 -data_abort: - get_bad_stack - bad_save_user_regs - bl do_data_abort - - .align 5 -not_used: - get_bad_stack - bad_save_user_regs - bl do_not_used - -#ifdef CONFIG_USE_IRQ - - .align 5 -irq: - get_irq_stack - irq_save_user_regs - bl do_irq - irq_restore_user_regs - - .align 5 -fiq: - get_fiq_stack - /* someone ought to write a more effiction fiq_save_user_regs */ - irq_save_user_regs - bl do_fiq - irq_restore_user_regs - -#else - - .align 5 -irq: - get_bad_stack - bad_save_user_regs - bl do_irq - - .align 5 -fiq: - get_bad_stack - bad_save_user_regs - bl do_fiq - -#endif -#endif /* CONFIG_SPL_BUILD */include/configs/m28evk.h +0
-0
include/configs/m28evk.h line 47
Quoted 7 lines
include/configs/m28evk.h +1
-0@@ -41,6 +41,7 @@#define CONFIG_SYS_DCACHE_OFF #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_ARCH_CPU_INIT +#define CONFIG_ARCH_MISC_INIT /* * SPL
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 17/20 M28: Add memory detection into SPL
In reply to Marek VasutThis code allows the DDR DRAM size to be detected at runtime. The RAM size is stored into two scratch registers, from which it is then fetched in U-Boot.
--- board/denx/m28evk/Makefile | 7 ++++++- board/denx/m28evk/m28evk.c | 18 ++++++++++++++++-- board/denx/m28evk/mem_init.c | 27 +++++++++++++++++++++++++++ include/configs/m28evk.h | 2 +- 4 files changed, 50 insertions(+), 4 deletions(-)
board/denx/m28evk/Makefile +6 -1
@@ -30,7 +30,7 @@ COBJS := m28evk.o endif ifdef CONFIG_SPL_BUILD -COBJS := mem_init.o mmc_boot.o power_init.o +COBJS := mem_init.o mmc_boot.o power_init.o memsize.o endif SRCS := $(COBJS:.o=.c)
@@ -41,6 +41,11 @@ $(LIB): $(obj).depend $(OBJS) all: $(ALL) +ifdef CONFIG_SPL_BUILD +memsize.c: + ln -sf $(TOPDIR)/common/memsize.c $@ +endif + ######################################################################### # defines $(obj).depend target
board/denx/m28evk/m28evk.c +16 -2
@@ -63,10 +63,24 @@ int board_init(void)return 0 ; } +#define HW_DIGCTRL_SCRATCH0 0x8001c280 +#define HW_DIGCTRL_SCRATCH1 0x8001c290int dram_init (void ) { -/* dram_init must store complete ramsize in gd->ram_size */ - gd->ram_size =get_ram_size ((long *)PHYS_SDRAM_1 ,PHYS_SDRAM_1_SIZE ); +uint32_t sz[2 ]; + + sz[0 ] =readl (HW_DIGCTRL_SCRATCH0 ); + sz[1 ] =readl (HW_DIGCTRL_SCRATCH1 ); + +if (sz[0 ] != sz[1 ]) { +printf ("MX28:\n" +"Error, the RAM size in HW_DIGCTRL_SCRATCH0 and\n" +"HW_DIGCTRL_SCRATCH1 is not the same. Please\n" +"verify these two registers contain valid RAM size!\n" ); +hang (); + } + + gd->ram_size = sz[0 ];return 0 ; }
board/denx/m28evk/mem_init.c +27 -0
@@ -165,6 +165,31 @@ void mx28_mem_setup_vddd(void) &power_regs->hw_power_vdddctrl); } +#define HW_DIGCTRL_SCRATCH0 0x8001c280 +#define HW_DIGCTRL_SCRATCH1 0x8001c290 +void data_abort_memdetect_handler (void ) __attribute__((naked)); +void data_abort_memdetect_handler (void ) +{ + asmvolatile ("subs pc, r14, #4" ); +} + +void mx28_mem_get_size (void ) +{ +uint32_t sz, da; +uint32_t *vt = (uint32_t *)0x20 ; + +/* Replace the DABT handler. */ + da = vt[4 ]; + vt[4 ] = (uint32_t )&data_abort_memdetect_handler; + + sz =get_ram_size ((long *)PHYS_SDRAM_1 ,PHYS_SDRAM_1_SIZE ); +writel (sz,HW_DIGCTRL_SCRATCH0 ); +writel (sz,HW_DIGCTRL_SCRATCH1 ); + +/* Restore the old DABT handler. */ + vt[4 ] = da; +} +void mx28_mem_init (void ) { struct mx28_clkctrl_regs *clkctrl_regs =
@@ -210,4 +235,6 @@ void mx28_mem_init(void)early_delay (10000 );mx28_mem_setup_cpu_and_hbus (); + +mx28_mem_get_size (); }
include/configs/m28evk.h +1 -1
@@ -81,7 +81,7 @@*/ #define CONFIG_NR_DRAM_BANKS 1/* 2 banks of DRAM */ #define PHYS_SDRAM_1 0x40000000/* Base address */ -#define PHYS_SDRAM_1_SIZE 0x08000000/* 128 MB */ +#define PHYS_SDRAM_1_SIZE 0x40000000/* Max 1 GB RAM */ #define CONFIG_STACKSIZE 0x00010000/* 128 KB stack */ #define CONFIG_SYS_MALLOC_LEN 0x00400000/* 4 MB for malloc */ #define CONFIG_SYS_GBL_DATA_SIZE 128/* Initial data */
Signature · 1 line
1.7.7.1
PATCH 17/20 M28: Add memory detection into SPL
Quoted 119 lines · Marek Vasut
This code allows the DDR DRAM size to be detected at runtime. The RAM size is stored into two scratch registers, from which it is then fetched in U-Boot.
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>--- board/denx/m28evk/Makefile | 7 ++++++- board/denx/m28evk/m28evk.c | 18 ++++++++++++++++-- board/denx/m28evk/mem_init.c | 27 +++++++++++++++++++++++++++ include/configs/m28evk.h | 2 +- 4 files changed, 50 insertions(+), 4 deletions(-)board/denx/m28evk/Makefile +6
-1@@ -30,7 +30,7 @@ COBJS := m28evk.o endif ifdef CONFIG_SPL_BUILD -COBJS := mem_init.o mmc_boot.o power_init.o +COBJS := mem_init.o mmc_boot.o power_init.o memsize.o endif SRCS := $(COBJS:.o=.c)@@ -41,6 +41,11 @@ $(LIB): $(obj).depend $(OBJS) all: $(ALL) +ifdef CONFIG_SPL_BUILD +memsize.c: + ln -sf $(TOPDIR)/common/memsize.c $@ +endif + ######################################################################### # defines $(obj).depend targetboard/denx/m28evk/m28evk.c +16
-2@@ -63,10 +63,24 @@ int board_init(void)return 0 ; } +#define HW_DIGCTRL_SCRATCH0 0x8001c280 +#define HW_DIGCTRL_SCRATCH1 0x8001c290int dram_init (void ) { -/* dram_init must store complete ramsize in gd->ram_size */ - gd->ram_size =get_ram_size ((long *)PHYS_SDRAM_1 ,PHYS_SDRAM_1_SIZE ); +uint32_t sz[2 ]; + + sz[0 ] =readl (HW_DIGCTRL_SCRATCH0 ); + sz[1 ] =readl (HW_DIGCTRL_SCRATCH1 ); + +if (sz[0 ] != sz[1 ]) { +printf ("MX28:\n" +"Error, the RAM size in HW_DIGCTRL_SCRATCH0 and\n" +"HW_DIGCTRL_SCRATCH1 is not the same. Please\n" +"verify these two registers contain valid RAM size!\n" ); +hang (); + } + + gd->ram_size = sz[0 ];return 0 ; }board/denx/m28evk/mem_init.c +27
-0@@ -165,6 +165,31 @@ void mx28_mem_setup_vddd(void) &power_regs->hw_power_vdddctrl); } +#define HW_DIGCTRL_SCRATCH0 0x8001c280 +#define HW_DIGCTRL_SCRATCH1 0x8001c290 +void data_abort_memdetect_handler (void ) __attribute__((naked)); +void data_abort_memdetect_handler (void ) +{ + asmvolatile ("subs pc, r14, #4" ); +} + +void mx28_mem_get_size (void ) +{ +uint32_t sz, da; +uint32_t *vt = (uint32_t *)0x20 ; + +/* Replace the DABT handler. */ + da = vt[4 ]; + vt[4 ] = (uint32_t )&data_abort_memdetect_handler; + + sz =get_ram_size ((long *)PHYS_SDRAM_1 ,PHYS_SDRAM_1_SIZE ); +writel (sz,HW_DIGCTRL_SCRATCH0 ); +writel (sz,HW_DIGCTRL_SCRATCH1 ); + +/* Restore the old DABT handler. */ + vt[4 ] = da; +} +void mx28_mem_init (void ) { struct mx28_clkctrl_regs *clkctrl_regs =@@ -210,4 +235,6 @@ void mx28_mem_init(void)early_delay (10000 );mx28_mem_setup_cpu_and_hbus (); + +mx28_mem_get_size (); }include/configs/m28evk.h +0
-0
include/configs/m28evk.h line 87
Quoted 8 lines
include/configs/m28evk.h +1
-1@@ -81,7 +81,7 @@*/ #define CONFIG_NR_DRAM_BANKS 1/* 2 banks of DRAM */ #define PHYS_SDRAM_1 0x40000000/* Base address */ -#define PHYS_SDRAM_1_SIZE 0x08000000/* 128 MB */ +#define PHYS_SDRAM_1_SIZE 0x40000000/* Max 1 GB RAM */ #define CONFIG_STACKSIZE 0x00010000/* 128 KB stack */ #define CONFIG_SYS_MALLOC_LEN 0x00400000/* 4 MB for malloc */ #define CONFIG_SYS_GBL_DATA_SIZE 128/* Initial data */
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 18/20 iMX28: Add USB and USB PHY register definitions
In reply to Marek Vasut--- arch/arm/include/asm/arch-mx28/regs-usb.h | 178 ++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx28/regs-usbphy.h | 151 ++++++++++++++++++++++ 2 files changed, 329 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch-mx28/regs-usb.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-usbphy.h
arch/arm/include/asm/arch-mx28/regs-usb.h new file +178 -0
@@ -0,0 +1,178 @@ +/* +* Freescale i.MX28 USB OTG Register Definitions +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 __REGS_USB_H__ +#define __REGS_USB_H__ + +struct mx28_usb_regs { +uint32_t hw_usbctrl_id;/* 0x000 */ +uint32_t hw_usbctrl_hwgeneral;/* 0x004 */ +uint32_t hw_usbctrl_hwhost;/* 0x008 */ +uint32_t hw_usbctrl_hwdevice;/* 0x00c */ +uint32_t hw_usbctrl_hwtxbuf;/* 0x010 */ +uint32_t hw_usbctrl_hwrxbuf;/* 0x014 */ + +uint32_t reserved1[26 ]; + +uint32_t hw_usbctrl_gptimer0ld;/* 0x080 */ +uint32_t hw_usbctrl_gptimer0ctrl;/* 0x084 */ +uint32_t hw_usbctrl_gptimer1ld;/* 0x088 */ +uint32_t hw_usbctrl_gptimer1ctrl;/* 0x08c */ +uint32_t hw_usbctrl_sbuscfg;/* 0x090 */ + +uint32_t reserved2[27 ]; + +uint32_t hw_usbctrl_caplength;/* 0x100 */ +uint32_t hw_usbctrl_hcsparams;/* 0x104 */ +uint32_t hw_usbctrl_hccparams;/* 0x108 */ + +uint32_t reserved3[5 ]; + +uint32_t hw_usbctrl_dciversion;/* 0x120 */ +uint32_t hw_usbctrl_dccparams;/* 0x124 */ + +uint32_t reserved4[6 ]; + +uint32_t hw_usbctrl_usbcmd;/* 0x140 */ +uint32_t hw_usbctrl_usbsts;/* 0x144 */ +uint32_t hw_usbctrl_usbintr;/* 0x148 */ +uint32_t hw_usbctrl_frindex;/* 0x14c */ + +uint32_t reserved5; + +union { +uint32_t hw_usbctrl_periodiclistbase;/* 0x154 */ +uint32_t hw_usbctrl_deviceaddr;/* 0x154 */ + }; +union { +uint32_t hw_usbctrl_asynclistaddr;/* 0x158 */ +uint32_t hw_usbctrl_endpointlistaddr;/* 0x158 */ + }; + +uint32_t hw_usbctrl_ttctrl;/* 0x15c */ +uint32_t hw_usbctrl_burstsize;/* 0x160 */ +uint32_t hw_usbctrl_txfilltuning;/* 0x164 */ + +uint32_t reserved6; + +uint32_t hw_usbctrl_ic_usb;/* 0x16c */ +uint32_t hw_usbctrl_ulpi;/* 0x170 */ + +uint32_t reserved7; + +uint32_t hw_usbctrl_endptnak;/* 0x178 */ +uint32_t hw_usbctrl_endptnaken;/* 0x17c */ + +uint32_t reserved8; + +uint32_t hw_usbctrl_portsc1;/* 0x184 */ + +uint32_t reserved9[7 ]; + +uint32_t hw_usbctrl_otgsc;/* 0x1a4 */ +uint32_t hw_usbctrl_usbmode;/* 0x1a8 */ +uint32_t hw_usbctrl_endptsetupstat;/* 0x1ac */ +uint32_t hw_usbctrl_endptprime;/* 0x1b0 */ +uint32_t hw_usbctrl_endptflush;/* 0x1b4 */ +uint32_t hw_usbctrl_endptstat;/* 0x1b8 */ +uint32_t hw_usbctrl_endptcomplete;/* 0x1bc */ +uint32_t hw_usbctrl_endptctrl0;/* 0x1c0 */ +uint32_t hw_usbctrl_endptctrl1;/* 0x1c4 */ +uint32_t hw_usbctrl_endptctrl2;/* 0x1c8 */ +uint32_t hw_usbctrl_endptctrl3;/* 0x1cc */ +uint32_t hw_usbctrl_endptctrl4;/* 0x1d0 */ +uint32_t hw_usbctrl_endptctrl5;/* 0x1d4 */ +uint32_t hw_usbctrl_endptctrl6;/* 0x1d8 */ +uint32_t hw_usbctrl_endptctrl7;/* 0x1dc */ +}; + +#define CLKCTRL_PLL0CTRL0_LFR_SEL_MASK (0x3 << 28) + +#define HW_USBCTRL_ID_CIVERSION_OFFSET 29 +#define HW_USBCTRL_ID_CIVERSION_MASK (0x7 << 29) +#define HW_USBCTRL_ID_VERSION_OFFSET 25 +#define HW_USBCTRL_ID_VERSION_MASK (0xf << 25) +#define HW_USBCTRL_ID_REVISION_OFFSET 21 +#define HW_USBCTRL_ID_REVISION_MASK (0xf << 21) +#define HW_USBCTRL_ID_TAG_OFFSET 16 +#define HW_USBCTRL_ID_TAG_MASK (0x1f << 16) +#define HW_USBCTRL_ID_NID_OFFSET 8 +#define HW_USBCTRL_ID_NID_MASK (0x3f << 8) +#define HW_USBCTRL_ID_ID_OFFSET 0 +#define HW_USBCTRL_ID_ID_MASK (0x3f << 0) + +#define HW_USBCTRL_HWGENERAL_SM_OFFSET 9 +#define HW_USBCTRL_HWGENERAL_SM_MASK (0x3 << 9) +#define HW_USBCTRL_HWGENERAL_PHYM_OFFSET 6 +#define HW_USBCTRL_HWGENERAL_PHYM_MASK (0x7 << 6) +#define HW_USBCTRL_HWGENERAL_PHYW_OFFSET 4 +#define HW_USBCTRL_HWGENERAL_PHYW_MASK (0x3 << 4) +#define HW_USBCTRL_HWGENERAL_BWT (1 << 3) +#define HW_USBCTRL_HWGENERAL_CLKC_OFFSET 1 +#define HW_USBCTRL_HWGENERAL_CLKC_MASK (0x3 << 1) +#define HW_USBCTRL_HWGENERAL_RT (1 << 0) + +#define HW_USBCTRL_HWHOST_TTPER_OFFSET 24 +#define HW_USBCTRL_HWHOST_TTPER_MASK (0xff << 24) +#define HW_USBCTRL_HWHOST_TTASY_OFFSET 16 +#define HW_USBCTRL_HWHOST_TTASY_MASK (0xff << 19) +#define HW_USBCTRL_HWHOST_NPORT_OFFSET 1 +#define HW_USBCTRL_HWHOST_NPORT_MASK (0x7 << 1) +#define HW_USBCTRL_HWHOST_HC (1 << 0) + +#define HW_USBCTRL_HWDEVICE_DEVEP_OFFSET 1 +#define HW_USBCTRL_HWDEVICE_DEVEP_MASK (0x1f << 1) +#define HW_USBCTRL_HWDEVICE_DC (1 << 0) + +#define HW_USBCTRL_HWTXBUF_TXLCR (1 << 31) +#define HW_USBCTRL_HWTXBUF_TXCHANADD_OFFSET 16 +#define HW_USBCTRL_HWTXBUF_TXCHANADD_MASK (0xff << 16) +#define HW_USBCTRL_HWTXBUF_TXADD_OFFSET 8 +#define HW_USBCTRL_HWTXBUF_TXADD_MASK (0xff << 8) +#define HW_USBCTRL_HWTXBUF_TXBURST_OFFSET 0 +#define HW_USBCTRL_HWTXBUF_TXBURST_MASK 0xff + +#define HW_USBCTRL_HWRXBUF_RXADD_OFFSET 8 +#define HW_USBCTRL_HWRXBUF_RXADD_MASK (0xff << 8) +#define HW_USBCTRL_HWRXBUF_RXBURST_OFFSET 0 +#define HW_USBCTRL_HWRXBUF_RXBURST_MASK 0xff + +#define HW_USBCTRL_GPTIMERLD_GPTLD_OFFSET 0 +#define HW_USBCTRL_GPTIMERLD_GPTLD_MASK 0xffffff + +#define HW_USBCTRL_GPTIMERCTRL_GPTRUN (1 << 31) +#define HW_USBCTRL_GPTIMERCTRL_GPTRST (1 << 30) +#define HW_USBCTRL_GPTIMERCTRL_GPTMODE (1 << 24) +#define HW_USBCTRL_GPTIMERCTRL_GPTCNT_OFFSET 0 +#define HW_USBCTRL_GPTIMERCTRL_GPTCNT_MASK 0xffffff + +#define HW_USBCTRL_SBUSCFG_AHBBURST_OFFSET 0 +#define HW_USBCTRL_SBUSCFG_AHBBURST_MASK 0x7 +#define HW_USBCTRL_SBUSCFG_AHBBURST_U_INCR 0x0 +#define HW_USBCTRL_SBUSCFG_AHBBURST_S_INCR4 0x1 +#define HW_USBCTRL_SBUSCFG_AHBBURST_S_INCR8 0x2 +#define HW_USBCTRL_SBUSCFG_AHBBURST_S_INCR16 0x3 +#define HW_USBCTRL_SBUSCFG_AHBBURST_U_INCR4 0x5 +#define HW_USBCTRL_SBUSCFG_AHBBURST_U_INCR8 0x6 +#define HW_USBCTRL_SBUSCFG_AHBBURST_U_INCR16 0x7 + +#endif /* __REGS_USB_H__ */
arch/arm/include/asm/arch-mx28/regs-usbphy.h new file +151 -0
151 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 18/20 iMX28: Add USB and USB PHY register definitions
Quoted 343 lines · Marek Vasut
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>Cc Remy Bohmer <[email protected]>--- arch/arm/include/asm/arch-mx28/regs-usb.h | 178 ++++++++++++++++++++++++++ arch/arm/include/asm/arch-mx28/regs-usbphy.h | 151 ++++++++++++++++++++++ 2 files changed, 329 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch-mx28/regs-usb.h create mode 100644 arch/arm/include/asm/arch-mx28/regs-usbphy.harch/arm/include/asm/arch-mx28/regs-usb.h new file +178
-0@@ -0,0 +1,178 @@ +/* +* Freescale i.MX28 USB OTG Register Definitions +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 __REGS_USB_H__ +#define __REGS_USB_H__ + +struct mx28_usb_regs { +uint32_t hw_usbctrl_id;/* 0x000 */ +uint32_t hw_usbctrl_hwgeneral;/* 0x004 */ +uint32_t hw_usbctrl_hwhost;/* 0x008 */ +uint32_t hw_usbctrl_hwdevice;/* 0x00c */ +uint32_t hw_usbctrl_hwtxbuf;/* 0x010 */ +uint32_t hw_usbctrl_hwrxbuf;/* 0x014 */ + +uint32_t reserved1[26 ]; + +uint32_t hw_usbctrl_gptimer0ld;/* 0x080 */ +uint32_t hw_usbctrl_gptimer0ctrl;/* 0x084 */ +uint32_t hw_usbctrl_gptimer1ld;/* 0x088 */ +uint32_t hw_usbctrl_gptimer1ctrl;/* 0x08c */ +uint32_t hw_usbctrl_sbuscfg;/* 0x090 */ + +uint32_t reserved2[27 ]; + +uint32_t hw_usbctrl_caplength;/* 0x100 */ +uint32_t hw_usbctrl_hcsparams;/* 0x104 */ +uint32_t hw_usbctrl_hccparams;/* 0x108 */ + +uint32_t reserved3[5 ]; + +uint32_t hw_usbctrl_dciversion;/* 0x120 */ +uint32_t hw_usbctrl_dccparams;/* 0x124 */ + +uint32_t reserved4[6 ]; + +uint32_t hw_usbctrl_usbcmd;/* 0x140 */ +uint32_t hw_usbctrl_usbsts;/* 0x144 */ +uint32_t hw_usbctrl_usbintr;/* 0x148 */ +uint32_t hw_usbctrl_frindex;/* 0x14c */ + +uint32_t reserved5; + +union { +uint32_t hw_usbctrl_periodiclistbase;/* 0x154 */ +uint32_t hw_usbctrl_deviceaddr;/* 0x154 */ + }; +union { +uint32_t hw_usbctrl_asynclistaddr;/* 0x158 */ +uint32_t hw_usbctrl_endpointlistaddr;/* 0x158 */ + }; + +uint32_t hw_usbctrl_ttctrl;/* 0x15c */ +uint32_t hw_usbctrl_burstsize;/* 0x160 */ +uint32_t hw_usbctrl_txfilltuning;/* 0x164 */ + +uint32_t reserved6; + +uint32_t hw_usbctrl_ic_usb;/* 0x16c */ +uint32_t hw_usbctrl_ulpi;/* 0x170 */ + +uint32_t reserved7; + +uint32_t hw_usbctrl_endptnak;/* 0x178 */ +uint32_t hw_usbctrl_endptnaken;/* 0x17c */ + +uint32_t reserved8; + +uint32_t hw_usbctrl_portsc1;/* 0x184 */ + +uint32_t reserved9[7 ]; + +uint32_t hw_usbctrl_otgsc;/* 0x1a4 */ +uint32_t hw_usbctrl_usbmode;/* 0x1a8 */ +uint32_t hw_usbctrl_endptsetupstat;/* 0x1ac */ +uint32_t hw_usbctrl_endptprime;/* 0x1b0 */ +uint32_t hw_usbctrl_endptflush;/* 0x1b4 */ +uint32_t hw_usbctrl_endptstat;/* 0x1b8 */ +uint32_t hw_usbctrl_endptcomplete;/* 0x1bc */ +uint32_t hw_usbctrl_endptctrl0;/* 0x1c0 */ +uint32_t hw_usbctrl_endptctrl1;/* 0x1c4 */ +uint32_t hw_usbctrl_endptctrl2;/* 0x1c8 */ +uint32_t hw_usbctrl_endptctrl3;/* 0x1cc */ +uint32_t hw_usbctrl_endptctrl4;/* 0x1d0 */ +uint32_t hw_usbctrl_endptctrl5;/* 0x1d4 */ +uint32_t hw_usbctrl_endptctrl6;/* 0x1d8 */ +uint32_t hw_usbctrl_endptctrl7;/* 0x1dc */ +}; + +#define CLKCTRL_PLL0CTRL0_LFR_SEL_MASK (0x3 << 28) + +#define HW_USBCTRL_ID_CIVERSION_OFFSET 29 +#define HW_USBCTRL_ID_CIVERSION_MASK (0x7 << 29) +#define HW_USBCTRL_ID_VERSION_OFFSET 25 +#define HW_USBCTRL_ID_VERSION_MASK (0xf << 25) +#define HW_USBCTRL_ID_REVISION_OFFSET 21 +#define HW_USBCTRL_ID_REVISION_MASK (0xf << 21) +#define HW_USBCTRL_ID_TAG_OFFSET 16 +#define HW_USBCTRL_ID_TAG_MASK (0x1f << 16) +#define HW_USBCTRL_ID_NID_OFFSET 8 +#define HW_USBCTRL_ID_NID_MASK (0x3f << 8) +#define HW_USBCTRL_ID_ID_OFFSET 0 +#define HW_USBCTRL_ID_ID_MASK (0x3f << 0) + +#define HW_USBCTRL_HWGENERAL_SM_OFFSET 9 +#define HW_USBCTRL_HWGENERAL_SM_MASK (0x3 << 9) +#define HW_USBCTRL_HWGENERAL_PHYM_OFFSET 6 +#define HW_USBCTRL_HWGENERAL_PHYM_MASK (0x7 << 6) +#define HW_USBCTRL_HWGENERAL_PHYW_OFFSET 4 +#define HW_USBCTRL_HWGENERAL_PHYW_MASK (0x3 << 4) +#define HW_USBCTRL_HWGENERAL_BWT (1 << 3) +#define HW_USBCTRL_HWGENERAL_CLKC_OFFSET 1 +#define HW_USBCTRL_HWGENERAL_CLKC_MASK (0x3 << 1) +#define HW_USBCTRL_HWGENERAL_RT (1 << 0) + +#define HW_USBCTRL_HWHOST_TTPER_OFFSET 24 +#define HW_USBCTRL_HWHOST_TTPER_MASK (0xff << 24) +#define HW_USBCTRL_HWHOST_TTASY_OFFSET 16 +#define HW_USBCTRL_HWHOST_TTASY_MASK (0xff << 19) +#define HW_USBCTRL_HWHOST_NPORT_OFFSET 1 +#define HW_USBCTRL_HWHOST_NPORT_MASK (0x7 << 1) +#define HW_USBCTRL_HWHOST_HC (1 << 0) + +#define HW_USBCTRL_HWDEVICE_DEVEP_OFFSET 1 +#define HW_USBCTRL_HWDEVICE_DEVEP_MASK (0x1f << 1) +#define HW_USBCTRL_HWDEVICE_DC (1 << 0) + +#define HW_USBCTRL_HWTXBUF_TXLCR (1 << 31) +#define HW_USBCTRL_HWTXBUF_TXCHANADD_OFFSET 16 +#define HW_USBCTRL_HWTXBUF_TXCHANADD_MASK (0xff << 16) +#define HW_USBCTRL_HWTXBUF_TXADD_OFFSET 8 +#define HW_USBCTRL_HWTXBUF_TXADD_MASK (0xff << 8) +#define HW_USBCTRL_HWTXBUF_TXBURST_OFFSET 0 +#define HW_USBCTRL_HWTXBUF_TXBURST_MASK 0xff + +#define HW_USBCTRL_HWRXBUF_RXADD_OFFSET 8 +#define HW_USBCTRL_HWRXBUF_RXADD_MASK (0xff << 8) +#define HW_USBCTRL_HWRXBUF_RXBURST_OFFSET 0 +#define HW_USBCTRL_HWRXBUF_RXBURST_MASK 0xff + +#define HW_USBCTRL_GPTIMERLD_GPTLD_OFFSET 0 +#define HW_USBCTRL_GPTIMERLD_GPTLD_MASK 0xffffff + +#define HW_USBCTRL_GPTIMERCTRL_GPTRUN (1 << 31) +#define HW_USBCTRL_GPTIMERCTRL_GPTRST (1 << 30) +#define HW_USBCTRL_GPTIMERCTRL_GPTMODE (1 << 24) +#define HW_USBCTRL_GPTIMERCTRL_GPTCNT_OFFSET 0 +#define HW_USBCTRL_GPTIMERCTRL_GPTCNT_MASK 0xffffff + +#define HW_USBCTRL_SBUSCFG_AHBBURST_OFFSET 0 +#define HW_USBCTRL_SBUSCFG_AHBBURST_MASK 0x7 +#define HW_USBCTRL_SBUSCFG_AHBBURST_U_INCR 0x0 +#define HW_USBCTRL_SBUSCFG_AHBBURST_S_INCR4 0x1 +#define HW_USBCTRL_SBUSCFG_AHBBURST_S_INCR8 0x2 +#define HW_USBCTRL_SBUSCFG_AHBBURST_S_INCR16 0x3 +#define HW_USBCTRL_SBUSCFG_AHBBURST_U_INCR4 0x5 +#define HW_USBCTRL_SBUSCFG_AHBBURST_U_INCR8 0x6 +#define HW_USBCTRL_SBUSCFG_AHBBURST_U_INCR16 0x7 + +#endif /* __REGS_USB_H__ */ arch/arm/include/asm/arch-mx28/regs-usbphy.h new file +141
-0@@ -0,0 +1,151 @@ +/* +* Freescale i.MX28 USB PHY Register Definitions +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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 __REGS_USBPHY_H__ +#define __REGS_USBPHY_H__ + +struct mx28_usbphy_regs { + mx28_reg(hw_usbphy_pwd) + mx28_reg(hw_usbphy_tx) + mx28_reg(hw_usbphy_rx) + mx28_reg(hw_usbphy_ctrl) + mx28_reg(hw_usbphy_status) + mx28_reg(hw_usbphy_debug) + mx28_reg(hw_usbphy_debug0_status) + mx28_reg(hw_usbphy_debug1) + mx28_reg(hw_usbphy_version) + mx28_reg(hw_usbphy_ip) +}; + +#define USBPHY_PWD_RXPWDRX (1 << 20) +#define USBPHY_PWD_RXPWDDIFF (1 << 19) +#define USBPHY_PWD_RXPWD1PT1 (1 << 18) +#define USBPHY_PWD_RXPWDENV (1 << 17) +#define USBPHY_PWD_TXPWDV2I (1 << 12) +#define USBPHY_PWD_TXPWDIBIAS (1 << 11) +#define USBPHY_PWD_TXPWDFS (1 << 10) + +#define USBPHY_TX_USBPHY_TX_EDGECTRL_OFFSET 26 +#define USBPHY_TX_USBPHY_TX_EDGECTRL_MASK (0x7 << 26) +#define USBPHY_TX_USBPHY_TX_SYNC_INVERT (1 << 25) +#define USBPHY_TX_USBPHY_TX_SYNC_MUX (1 << 24) +#define USBPHY_TX_TXENCAL45DP (1 << 21) +#define USBPHY_TX_TXCAL45DP_OFFSET 16 +#define USBPHY_TX_TXCAL45DP_MASK (0xf << 16) +#define USBPHY_TX_TXENCAL45DM (1 << 13) +#define USBPHY_TX_TXCAL45DM_OFFSET 8 +#define USBPHY_TX_TXCAL45DM_MASK (0xf << 8) +#define USBPHY_TX_D_CAL_OFFSET 0 +#define USBPHY_TX_D_CAL_MASK 0xf + +#define USBPHY_RX_RXDBYPASS (1 << 22) +#define USBPHY_RX_DISCONADJ_OFFSET 4 +#define USBPHY_RX_DISCONADJ_MASK (0x7 << 4) +#define USBPHY_RX_ENVADJ_OFFSET 0 +#define USBPHY_RX_ENVADJ_MASK 0x7 + +#define USBPHY_CTRL_SFTRST (1 << 31) +#define USBPHY_CTRL_CLKGATE (1 << 30) +#define USBPHY_CTRL_UTMI_SUSPENDM (1 << 29) +#define USBPHY_CTRL_HOST_FORCE_LS_SE0 (1 << 28) +#define USBPHY_CTRL_ENAUTOSET_USBCLKS (1 << 26) +#define USBPHY_CTRL_ENAUTOCLR_USBCLKGATE (1 << 25) +#define USBPHY_CTRL_FSDLL_RST_EN (1 << 24) +#define USBPHY_CTRL_ENVBUSCHG_WKUP (1 << 23) +#define USBPHY_CTRL_ENIDCHG_WKUP (1 << 22) +#define USBPHY_CTRL_ENDPDMCHG_WKUP (1 << 21) +#define USBPHY_CTRL_ENAUTOCLR_PHY_PWD (1 << 20) +#define USBPHY_CTRL_ENAUTOCLR_CLKGATE (1 << 19) +#define USBPHY_CTRL_ENAUTO_PWRON_PLL (1 << 18) +#define USBPHY_CTRL_WAKEUP_IRQ (1 << 17) +#define USBPHY_CTRL_ENIRQWAKEUP (1 << 16) +#define USBPHY_CTRL_ENUTMILEVEL3 (1 << 15) +#define USBPHY_CTRL_ENUTMILEVEL2 (1 << 14) +#define USBPHY_CTRL_DATA_ON_LRADC (1 << 13) +#define USBPHY_CTRL_DEVPLUGIN_IRQ (1 << 12) +#define USBPHY_CTRL_ENIRQDEVPLUGIN (1 << 11) +#define USBPHY_CTRL_RESUME_IRQ (1 << 10) +#define USBPHY_CTRL_ENIRQRESUMEDETECT (1 << 9) +#define USBPHY_CTRL_RESUMEIRQSTICKY (1 << 8) +#define USBPHY_CTRL_ENOTGIDDETECT (1 << 7) +#define USBPHY_CTRL_DEVPLUGIN_POLARITY (1 << 5) +#define USBPHY_CTRL_ENDEVPLUGINDETECT (1 << 4) +#define USBPHY_CTRL_HOSTDISCONDETECT_IRQ (1 << 3) +#define USBPHY_CTRL_ENIRQHOSTDISCON (1 << 2) +#define USBPHY_CTRL_ENHOSTDISCONDETECT (1 << 1) + +#define USBPHY_STATUS_RESUME_STATUS (1 << 10) +#define USBPHY_STATUS_OTGID_STATUS (1 << 8) +#define USBPHY_STATUS_DEVPLUGIN_STATUS (1 << 6) +#define USBPHY_STATUS_HOSTDISCONDETECT_STATUS (1 << 3) + +#define USBPHY_DEBUG_CLKGATE (1 << 30) +#define USBPHY_DEBUG_HOST_RESUME_DEBUG (1 << 29) +#define USBPHY_DEBUG_SQUELCHRESETLENGTH_OFFSET 25 +#define USBPHY_DEBUG_SQUELCHRESETLENGTH_MASK (0xf << 25) +#define USBPHY_DEBUG_ENSQUELCHRESET (1 << 24) +#define USBPHY_DEBUG_SQUELCHRESETCOUNT_OFFSET 16 +#define USBPHY_DEBUG_SQUELCHRESETCOUNT_MASK (0x1f << 16) +#define USBPHY_DEBUG_ENTX2RXCOUNT (1 << 12) +#define USBPHY_DEBUG_TX2RXCOUNT_OFFSET 8 +#define USBPHY_DEBUG_TX2RXCOUNT_MASK (0xf << 8) +#define USBPHY_DEBUG_ENHSTPULLDOWN_OFFSET 4 +#define USBPHY_DEBUG_ENHSTPULLDOWN_MASK (0x3 << 4) +#define USBPHY_DEBUG_HSTPULLDOWN_OFFSET 2 +#define USBPHY_DEBUG_HSTPULLDOWN_MASK (0x3 << 2) +#define USBPHY_DEBUG_DEBUG_INTERFACE_HOLD (1 << 1) +#define USBPHY_DEBUG_OTGIDPIDLOCK (1 << 0) + +#define USBPHY_DEBUG0_STATUS_SQUELCH_COUNT_OFFSET 26 +#define USBPHY_DEBUG0_STATUS_SQUELCH_COUNT_MASK (0x3f << 26) +#define USBPHY_DEBUG0_STATUS_UTMI_RXERROR_OFFSET 16 +#define USBPHY_DEBUG0_STATUS_UTMI_RXERROR_MASK (0x3ff << 16) +#define USBPHY_DEBUG0_STATUS_LOOP_BACK_OFFSET 0 +#define USBPHY_DEBUG0_STATUS_LOOP_BACK_MASK 0xffff + +#define USBPHY_DEBUG1_ENTAILADJVD_OFFSET 13 +#define USBPHY_DEBUG1_ENTAILADJVD_MASK (0x3 << 13) +#define USBPHY_DEBUG1_ENTX2TX (1 << 12) +#define USBPHY_DEBUG1_DBG_ADDRESS_OFFSET 0 +#define USBPHY_DEBUG1_DBG_ADDRESS_MASK 0xf + +#define USBPHY_VERSION_MAJOR_MASK (0xff << 24) +#define USBPHY_VERSION_MAJOR_OFFSET 24 +#define USBPHY_VERSION_MINOR_MASK (0xff << 16) +#define USBPHY_VERSION_MINOR_OFFSET 16 +#define USBPHY_VERSION_STEP_MASK 0xffff +#define USBPHY_VERSION_STEP_OFFSET 0 + +#define USBPHY_IP_DIV_SEL_OFFSET 23 +#define USBPHY_IP_DIV_SEL_MASK (0x3 << 23) +#define USBPHY_IP_LFR_SEL_OFFSET 21 +#define USBPHY_IP_LFR_SEL_MASK (0x3 << 21)
arch/arm/include/asm/arch-mx28/regs-usbphy.h line 151
Quoted 10 lines
arch/arm/include/asm/arch-mx28/regs-usbphy.h new file +10
-0+#define USBPHY_IP_CP_SEL_OFFSET 19 +#define USBPHY_IP_CP_SEL_MASK (0x3 << 19) +#define USBPHY_IP_TSTI_TX_DP (1 << 18) +#define USBPHY_IP_TSTI_TX_DM (1 << 17) +#define USBPHY_IP_ANALOG_TESTMODE (1 << 16) +#define USBPHY_IP_EN_USB_CLKS (1 << 2) +#define USBPHY_IP_PLL_LOCKED (1 << 1) +#define USBPHY_IP_PLL_POWER (1 << 0) + +#endif /* __REGS_USBPHY_H__ */
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 19/20 iMX28: Add USB HOST driver
In reply to Marek VasutThis driver supports both EHCI ports on the i.MX28 CPU.
--- drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-mxs.c | 154 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 0 deletions(-) create mode 100644 drivers/usb/host/ehci-mxs.c
drivers/usb/host/Makefile +1 -0
@@ -41,6 +41,7 @@ else COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o endif COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o +COBJS-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o COBJS-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o COBJS-$(CONFIG_USB_EHCI_KIRKWOOD) += ehci-kirkwood.o
drivers/usb/host/ehci-mxs.c new file +154 -0
154 lines not on this page · raw message
Signature · 1 line
1.7.7.1
PATCH 19/20 iMX28: Add USB HOST driver
Quoted 175 lines · Marek Vasut
This driver supports both EHCI ports on the i.MX28 CPU.
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>Cc Remy Bohmer <[email protected]>--- drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-mxs.c | 154 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+), 0 deletions(-) create mode 100644 drivers/usb/host/ehci-mxs.cdrivers/usb/host/Makefile +1
-0@@ -41,6 +41,7 @@ else COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o endif COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o +COBJS-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o COBJS-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o COBJS-$(CONFIG_USB_EHCI_KIRKWOOD) += ehci-kirkwood.odrivers/usb/host/ehci-mxs.c new file +144
-0@@ -0,0 +1,154 @@ +/* +* Freescale i.MX28 USB Host driver +* +* Copyright (C) 2011 Marek Vasut <[email protected]> +* on behalf of DENX Software Engineering GmbH +* +* 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/regs-common.h> +#include <asm/arch/regs-base.h> +#include <asm/arch/regs-clkctrl.h> +#include <asm/arch/regs-usb.h> +#include <asm/arch/regs-usbphy.h> + +#include "ehci-core.h" +#include "ehci.h" + +#if (CONFIG_EHCI_MXS_PORT !=0 ) && (CONFIG_EHCI_MXS_PORT !=1 ) +#error "MXS EHCI: Invalid port selected!" +#endif + +#ifndef CONFIG_EHCI_MXS_PORT +#error "MXS EHCI: Please define correct port using CONFIG_EHCI_MXS_PORT!" +#endif + +static struct ehci_mxs { +struct mx28_usb_regs *usb_regs; +struct mx28_usbphy_regs *phy_regs; +} ehci_mxs; + +int mxs_ehci_get_port (struct ehci_mxs *mxs_usb,int port) +{ +uint32_t usb_base, phy_base; +switch (port) { +case 0 : + usb_base =MXS_USBCTRL0_BASE ; + phy_base =MXS_USBPHY0_BASE ; +break ; +case 1 : + usb_base =MXS_USBCTRL1_BASE ; + phy_base =MXS_USBPHY1_BASE ; +break ; +default : +printf ("CONFIG_EHCI_MXS_PORT (port = %d)\n" , port); +return -1 ; + } + + mxs_usb->usb_regs = (struct mx28_usb_regs *)usb_base; + mxs_usb->phy_regs = (struct mx28_usbphy_regs *)phy_base; +return 0 ; +} + +/* This DIGCTL register ungates clock to USB */ +#define HW_DIGCTL_CTRL 0x8001c000 +#define HW_DIGCTL_CTRL_USB0_CLKGATE (1 << 2) +#define HW_DIGCTL_CTRL_USB1_CLKGATE (1 << 16) + +int ehci_hcd_init (void ) +{ + +int ret; +uint32_t usb_base, cap_base; +struct mx28_register *digctl_ctrl = + (struct mx28_register *)HW_DIGCTL_CTRL ; +struct mx28_clkctrl_regs *clkctrl_regs = + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; + + ret =mxs_ehci_get_port (&ehci_mxs,CONFIG_EHCI_MXS_PORT ); +if (ret) +return ret; + +/* Reset the PHY block */ +writel (USBPHY_CTRL_SFTRST , &ehci_mxs.phy_regs->hw_usbphy_ctrl_set); +udelay (10 ); +writel (USBPHY_CTRL_SFTRST |USBPHY_CTRL_CLKGATE , + &ehci_mxs.phy_regs->hw_usbphy_ctrl_clr); + +/* Enable USB clock */ +writel (CLKCTRL_PLL0CTRL0_EN_USB_CLKS |CLKCTRL_PLL0CTRL0_POWER , + &clkctrl_regs->hw_clkctrl_pll0ctrl0_set); +writel (CLKCTRL_PLL1CTRL0_EN_USB_CLKS |CLKCTRL_PLL1CTRL0_POWER , + &clkctrl_regs->hw_clkctrl_pll1ctrl0_set); + +writel (HW_DIGCTL_CTRL_USB0_CLKGATE |HW_DIGCTL_CTRL_USB1_CLKGATE , + &digctl_ctrl->reg_clr); + +/* Start USB PHY */ +writel (0 , &ehci_mxs.phy_regs->hw_usbphy_pwd); + +/* Enable UTMI+ Level 2 and Level 3 compatibility */ +writel (USBPHY_CTRL_ENUTMILEVEL3 |USBPHY_CTRL_ENUTMILEVEL2 |1 , + &ehci_mxs.phy_regs->hw_usbphy_ctrl_set); + + usb_base = ((uint32_t )ehci_mxs.usb_regs) +0x100 ; + hccr = (struct ehci_hccr *)usb_base; + + cap_base =ehci_readl (&hccr->cr_capbase); + hcor = (struct ehci_hcor *)(usb_base +HC_LENGTH (cap_base)); + +return 0 ; +} + +int ehci_hcd_stop (void ) +{ +int ret; +uint32_t tmp; +struct mx28_register *digctl_ctrl = + (struct mx28_register *)HW_DIGCTL_CTRL ; +struct mx28_clkctrl_regs *clkctrl_regs = + (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE ; + + ret =mxs_ehci_get_port (&ehci_mxs,CONFIG_EHCI_MXS_PORT ); +if (ret) +return ret; + +/* Stop the USB port */ + tmp =ehci_readl (&hcor->or_usbcmd); + tmp &= ~CMD_RUN ; +ehci_writel (tmp, &hcor->or_usbcmd); + +/* Disable the PHY */ + tmp =USBPHY_PWD_RXPWDRX |USBPHY_PWD_RXPWDDIFF | +USBPHY_PWD_RXPWD1PT1 |USBPHY_PWD_RXPWDENV | +USBPHY_PWD_TXPWDV2I |USBPHY_PWD_TXPWDIBIAS | +USBPHY_PWD_TXPWDFS ; +writel (tmp, &ehci_mxs.phy_regs->hw_usbphy_pwd); + +/* Disable USB clock */ + writel(CLKCTRL_PLL0CTRL0_EN_USB_CLKS,
drivers/usb/host/ehci-mxs.c line 154
Quoted 10 lines
drivers/usb/host/ehci-mxs.c new file +10
-0+ &clkctrl_regs->hw_clkctrl_pll0ctrl0_clr); +writel (CLKCTRL_PLL1CTRL0_EN_USB_CLKS , + &clkctrl_regs->hw_clkctrl_pll1ctrl0_clr); + +/* Gate off the USB clock */ +writel (HW_DIGCTL_CTRL_USB0_CLKGATE |HW_DIGCTL_CTRL_USB1_CLKGATE , + &digctl_ctrl->reg_set); + +return 0 ; +}
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 20/20 M28EVK: Enable USB HOST support
In reply to Marek VasutThis enables the second port, aka. the port with the USB connector on the M28EVK.
--- board/denx/m28evk/m28evk.c | 7 +++++++ include/configs/m28evk.h | 12 ++++++++++++ 2 files changed, 19 insertions(+), 0 deletions(-)
board/denx/m28evk/m28evk.c +7 -0
@@ -52,6 +52,13 @@ int board_early_init_f(void)/* SSP2 clock at 96MHz */ mx28_set_sspclk (MXC_SSPCLK2 ,96000 ,0 ); +#ifdef CONFIG_CMD_USB +mxs_iomux_setup_pad (MX28_PAD_SSP2_SS1__USB1_OVERCURRENT ); +mxs_iomux_setup_pad (MX28_PAD_AUART3_TX__GPIO_3_13 | +MXS_PAD_12MA |MXS_PAD_3V3 |MXS_PAD_PULLUP ); +gpio_direction_output (MX28_PAD_AUART3_TX__GPIO_3_13 ,0 ); +#endif +return 0 ; }
include/configs/m28evk.h +12 -0
@@ -75,6 +75,7 @@#define CONFIG_CMD_SETEXPR #define CONFIG_CMD_SF #define CONFIG_CMD_SPI +#define CONFIG_CMD_USB /* * Memory configurations
@@ -218,6 +219,17 @@#endif /* +* USB +*/ +#ifdef CONFIG_CMD_USB +#define CONFIG_USB_EHCI +#define CONFIG_USB_EHCI_MXS +#define CONFIG_EHCI_MXS_PORT 1 +#define CONFIG_EHCI_IS_TDI +#define CONFIG_USB_STORAGE +#endif + +/* * SPI */ #ifdef CONFIG_CMD_SPI
Signature · 1 line
1.7.7.1
PATCH 20/20 M28EVK: Enable USB HOST support
Quoted 51 lines · Marek Vasut
This enables the second port, aka. the port with the USB connector on the M28EVK.
Signed-off-by Marek Vasut <[email protected]>Cc Stefano Babic <[email protected]>Cc Wolfgang Denk <[email protected]>Cc Detlev Zundel <[email protected]>Cc Remy Bohmer <[email protected]>--- board/denx/m28evk/m28evk.c | 7 +++++++ include/configs/m28evk.h | 12 ++++++++++++ 2 files changed, 19 insertions(+), 0 deletions(-)board/denx/m28evk/m28evk.c +7
-0@@ -52,6 +52,13 @@ int board_early_init_f(void)/* SSP2 clock at 96MHz */ mx28_set_sspclk (MXC_SSPCLK2 ,96000 ,0 ); +#ifdef CONFIG_CMD_USB +mxs_iomux_setup_pad (MX28_PAD_SSP2_SS1__USB1_OVERCURRENT ); +mxs_iomux_setup_pad (MX28_PAD_AUART3_TX__GPIO_3_13 | +MXS_PAD_12MA |MXS_PAD_3V3 |MXS_PAD_PULLUP ); +gpio_direction_output (MX28_PAD_AUART3_TX__GPIO_3_13 ,0 ); +#endif +return 0 ; }include/configs/m28evk.h +5
-0@@ -75,6 +75,7 @@#define CONFIG_CMD_SETEXPR #define CONFIG_CMD_SF #define CONFIG_CMD_SPI +#define CONFIG_CMD_USB /* * Memory configurations @@ -218,6 +219,17 @@#endif /* +* USB +*/ +#ifdef CONFIG_CMD_USB +#define CONFIG_USB_EHCI
include/configs/m28evk.h line 235
Quoted 10 lines
include/configs/m28evk.h +7
-0+#define CONFIG_USB_EHCI_MXS +#define CONFIG_EHCI_MXS_PORT 1 +#define CONFIG_EHCI_IS_TDI +#define CONFIG_USB_STORAGE +#endif + +/* * SPI */ #ifdef CONFIG_CMD_SPI
Applied to u-boot-imx, thanks.
Best regards,
Stefano Babic
Signature · 5 lines
===================================================================== 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 at denx.de =====================================================================
PATCH 20/20 M28EVK: Enable USB HOST support
In reply to Marek VasutHi Marek,
Quoted 2 lines · Marek Vasut
This enables the second port, aka. the port with the USB connector on the M28EVK.
Which version of GCC you are using? I noticed that "usb start" freezes after message "scanning bus for devices..." if I had memory stick connected. I used GCC 4.6.1 that comes with Yocto 1.1. Without stick I did not have any such problems. The board is very similar to M28EVK. With GCC 4.3.4 it works fine.
I also tested both compilers on our Atmel AT91SAM9260 based device but I didn't have such problems.
Any ideas how to debug this further? I noticed some comments related to GCC in common/usb.c before usb_set_maxpacket_ep function. I also printed out i and ii in usb_set_maxpacket. Results were something that I didn't expect:
i: 0, ii: 0
i: 0, ii: 1
i: 4, ii: -30879
i: 4, ii: -30878
--
Veli-Pekka Peltola
PATCH 20/20 M28EVK: Enable USB HOST support
Quoted 24 lines
Hi Marek,
Quoted 2 lines · Marek Vasut
This enables the second port, aka. the port with the USB connector on the M28EVK.
Which version of GCC you are using? I noticed that "usb start" freezes after message "scanning bus for devices..." if I had memory stick connected. I used GCC 4.6.1 that comes with Yocto 1.1. Without stick I did not have any such problems. The board is very similar to M28EVK. With GCC 4.3.4 it works fine.
I also tested both compilers on our Atmel AT91SAM9260 based device but I didn't have such problems.
Any ideas how to debug this further? I noticed some comments related to GCC in
common/usb.cbeforeusb_set_maxpacket_epfunction. I also printed out i and ii inusb_set_maxpacket. Results were something that I didn't expect:
i: 0, ii: 0
i: 0, ii: 1
i: 4, ii: -30879
i: 4, ii: -30878
Quoted 2 lines
--
Veli-Pekka Peltola
Can you try this patch please:
Subject: [PATCH] GCC4.6: Fix common/usb.c on xscale
Message-Id: <[email protected]>
I had the same issue with gcc4.6 on xscale, if it fixes your problem, can you also try with 3.4.3 and give me your ACK?
M