diff options
Diffstat (limited to 'arch/arm/imx-common')
-rw-r--r-- | arch/arm/imx-common/Makefile | 95 | ||||
-rw-r--r-- | arch/arm/imx-common/cmd_bmode.c | 122 | ||||
-rw-r--r-- | arch/arm/imx-common/cmd_hdmidet.c | 37 | ||||
-rw-r--r-- | arch/arm/imx-common/cpu.c | 196 | ||||
-rw-r--r-- | arch/arm/imx-common/i2c-mxv7.c | 99 | ||||
-rw-r--r-- | arch/arm/imx-common/iomux-v3.c | 69 | ||||
-rw-r--r-- | arch/arm/imx-common/misc.c | 84 | ||||
-rw-r--r-- | arch/arm/imx-common/speed.c | 61 | ||||
-rw-r--r-- | arch/arm/imx-common/timer.c | 137 |
9 files changed, 900 insertions, 0 deletions
diff --git a/arch/arm/imx-common/Makefile b/arch/arm/imx-common/Makefile new file mode 100644 index 0000000..9492326 --- /dev/null +++ b/arch/arm/imx-common/Makefile @@ -0,0 +1,95 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2011 Freescale Semiconductor, Inc. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)libimx-common.o + +ifeq ($(SOC),$(filter $(SOC),mx25 mx35 mx5 mx6 vf610)) +COBJS-y = iomux-v3.o +endif +ifeq ($(SOC),$(filter $(SOC),mx5 mx6)) +COBJS-y += timer.o cpu.o speed.o +COBJS-$(CONFIG_I2C_MXC) += i2c-mxv7.o +endif +ifeq ($(SOC),$(filter $(SOC),mx6 mxs)) +COBJS-y += misc.o +endif +COBJS-$(CONFIG_CMD_BMODE) += cmd_bmode.o +COBJS-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o +COBJS := $(sort $(COBJS-y)) + +SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +$(OBJTREE)/$(patsubst "%",%,$(CONFIG_IMX_CONFIG)).cfgtmp: $(OBJTREE)/%.cfgtmp : $(SRCTREE)/% + mkdir -p $(dir $@) + $(CC) -E -x c $< $(CPPFLAGS) -o $@ + +$(OBJTREE)/u-boot.imx: $(OBJTREE)/u-boot.bin $(OBJTREE)/$(patsubst "%",%,$(CONFIG_IMX_CONFIG)).cfgtmp + $(OBJTREE)/tools/mkimage -n $(filter-out %.bin,$^) -T imximage \ + -e $(CONFIG_SYS_TEXT_BASE) -d $< $@ + +$(OBJTREE)/SPL: $(OBJTREE)/spl/u-boot-spl.bin $(OBJTREE)/$(patsubst "%",%,$(CONFIG_IMX_CONFIG)).cfgtmp + $(OBJTREE)/tools/mkimage -n $(filter-out %.bin,$^) -T imximage \ + -e $(CONFIG_SPL_TEXT_BASE) -d $< $@ + +$(OBJTREE)/u-boot-with-spl.imx: $(OBJTREE)/SPL $(OBJTREE)/u-boot.bin + $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(CONFIG_SPL_PAD_TO) \ + -I binary -O binary $< $(OBJTREE)/spl/u-boot-spl-pad.imx + $(OBJTREE)/tools/mkimage -A arm -O U-Boot -a $(CONFIG_SYS_TEXT_BASE) \ + -e $(CONFIG_SYS_TEXT_BASE) -C none -d $(OBJTREE)/u-boot.bin \ + $(OBJTREE)/u-boot.uim + cat $(OBJTREE)/spl/u-boot-spl-pad.imx $(OBJTREE)/u-boot.uim > $@ + rm $(OBJTREE)/spl/u-boot-spl-pad.imx $(OBJTREE)/u-boot.uim + +$(OBJTREE)/u-boot-with-nand-spl.imx: $(OBJTREE)/SPL $(OBJTREE)/u-boot.bin + (echo -ne '\x00\x00\x00\x00\x46\x43\x42\x20\x01' && \ + dd bs=1015 count=1 if=/dev/zero 2>/dev/null) | \ + cat - $< > $(OBJTREE)/spl/u-boot-nand-spl.imx + $(OBJCOPY) ${OBJCFLAGS} --pad-to=$(CONFIG_SPL_PAD_TO) \ + -I binary -O binary $(OBJTREE)/spl/u-boot-nand-spl.imx \ + $(OBJTREE)/spl/u-boot-nand-spl-pad.imx + rm $(OBJTREE)/spl/u-boot-nand-spl.imx + $(OBJTREE)/tools/mkimage -A arm -O U-Boot -a $(CONFIG_SYS_TEXT_BASE) \ + -e $(CONFIG_SYS_TEXT_BASE) -C none -d $(OBJTREE)/u-boot.bin \ + $(OBJTREE)/u-boot.uim + cat $(OBJTREE)/spl/u-boot-nand-spl-pad.imx $(OBJTREE)/u-boot.uim > $@ + rm $(OBJTREE)/spl/u-boot-nand-spl-pad.imx $(OBJTREE)/u-boot.uim + + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/arm/imx-common/cmd_bmode.c b/arch/arm/imx-common/cmd_bmode.c new file mode 100644 index 0000000..ddc14b0 --- /dev/null +++ b/arch/arm/imx-common/cmd_bmode.c @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2012 Boundary Devices Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/imx-common/boot_mode.h> +#include <malloc.h> +#include <command.h> + +static const struct boot_mode *modes[2]; + +static const struct boot_mode *search_modes(char *arg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(modes); i++) { + const struct boot_mode *p = modes[i]; + if (p) { + while (p->name) { + if (!strcmp(p->name, arg)) + return p; + p++; + } + } + } + return NULL; +} + +static int create_usage(char *dest) +{ + int i; + int size = 0; + + for (i = 0; i < ARRAY_SIZE(modes); i++) { + const struct boot_mode *p = modes[i]; + if (p) { + while (p->name) { + int len = strlen(p->name); + if (dest) { + memcpy(dest, p->name, len); + dest += len; + *dest++ = '|'; + } + size += len + 1; + p++; + } + } + } + if (dest) + memcpy(dest - 1, " [noreset]", 11); /* include trailing 0 */ + size += 10; + return size; +} + +static int do_boot_mode(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + const struct boot_mode *p; + int reset_requested = 1; + + if (argc < 2) + return CMD_RET_USAGE; + p = search_modes(argv[1]); + if (!p) + return CMD_RET_USAGE; + if (argc == 3) { + if (strcmp(argv[2], "noreset")) + return CMD_RET_USAGE; + reset_requested = 0; + } + + boot_mode_apply(p->cfg_val); + if (reset_requested && p->cfg_val) + do_reset(NULL, 0, 0, NULL); + return 0; +} + +U_BOOT_CMD( + bmode, 3, 0, do_boot_mode, + NULL, + ""); + +void add_board_boot_modes(const struct boot_mode *p) +{ + int size; + char *dest; + + cmd_tbl_t *entry = ll_entry_get(cmd_tbl_t, bmode, cmd); + + if (entry->usage) { + free(entry->usage); + entry->usage = NULL; + } + + modes[0] = p; + modes[1] = soc_boot_modes; + size = create_usage(NULL); + dest = malloc(size); + if (dest) { + create_usage(dest); + entry->usage = dest; + } +} diff --git a/arch/arm/imx-common/cmd_hdmidet.c b/arch/arm/imx-common/cmd_hdmidet.c new file mode 100644 index 0000000..794bf50 --- /dev/null +++ b/arch/arm/imx-common/cmd_hdmidet.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2012 Boundary Devices Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/mxc_hdmi.h> +#include <asm/io.h> + +static int do_hdmidet(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct hdmi_regs *hdmi = (struct hdmi_regs *)HDMI_ARB_BASE_ADDR; + u8 reg = readb(&hdmi->phy_stat0) & HDMI_PHY_HPD; + return (reg&HDMI_PHY_HPD) ? 0 : 1; +} + +U_BOOT_CMD(hdmidet, 1, 1, do_hdmidet, + "detect HDMI monitor", + "" +); diff --git a/arch/arm/imx-common/cpu.c b/arch/arm/imx-common/cpu.c new file mode 100644 index 0000000..a9b86c1 --- /dev/null +++ b/arch/arm/imx-common/cpu.c @@ -0,0 +1,196 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (C) Copyright 2009 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/crm_regs.h> +#include <ipu_pixfmt.h> + +#ifdef CONFIG_FSL_ESDHC +#include <fsl_esdhc.h> +#endif + +char *get_reset_cause(void) +{ + u32 cause; + struct src *src_regs = (struct src *)SRC_BASE_ADDR; + + cause = readl(&src_regs->srsr); + writel(cause, &src_regs->srsr); + + switch (cause) { + case 0x00001: + case 0x00011: + return "POR"; + case 0x00004: + return "CSU"; + case 0x00008: + return "IPP USER"; + case 0x00010: + return "WDOG"; + case 0x00020: + return "JTAG HIGH-Z"; + case 0x00040: + return "JTAG SW"; + case 0x10000: + return "WARM BOOT"; + default: + return "unknown reset"; + } +} + +#if defined(CONFIG_MX53) || defined(CONFIG_MX6) +#if defined(CONFIG_MX53) +#define MEMCTL_BASE ESDCTL_BASE_ADDR; +#else +#define MEMCTL_BASE MMDC_P0_BASE_ADDR; +#endif +static const unsigned char col_lookup[] = {9, 10, 11, 8, 12, 9, 9, 9}; +static const unsigned char bank_lookup[] = {3, 2}; + +struct esd_mmdc_regs { + uint32_t ctl; + uint32_t pdc; + uint32_t otc; + uint32_t cfg0; + uint32_t cfg1; + uint32_t cfg2; + uint32_t misc; + uint32_t scr; + uint32_t ref; + uint32_t rsvd1; + uint32_t rsvd2; + uint32_t rwd; + uint32_t or; + uint32_t mrr; + uint32_t cfg3lp; + uint32_t mr4; +}; + +#define ESD_MMDC_CTL_GET_ROW(mdctl) ((ctl >> 24) & 7) +#define ESD_MMDC_CTL_GET_COLUMN(mdctl) ((ctl >> 20) & 7) +#define ESD_MMDC_CTL_GET_WIDTH(mdctl) ((ctl >> 16) & 3) +#define ESD_MMDC_CTL_GET_CS1(mdctl) ((ctl >> 30) & 1) +#define ESD_MMDC_MISC_GET_BANK(mdmisc) ((misc >> 5) & 1) + +unsigned imx_ddr_size(void) +{ + struct esd_mmdc_regs *mem = (struct esd_mmdc_regs *)MEMCTL_BASE; + unsigned ctl = readl(&mem->ctl); + unsigned misc = readl(&mem->misc); + int bits = 11 + 0 + 0 + 1; /* row + col + bank + width */ + + bits += ESD_MMDC_CTL_GET_ROW(ctl); + bits += col_lookup[ESD_MMDC_CTL_GET_COLUMN(ctl)]; + bits += bank_lookup[ESD_MMDC_MISC_GET_BANK(misc)]; + bits += ESD_MMDC_CTL_GET_WIDTH(ctl); + bits += ESD_MMDC_CTL_GET_CS1(ctl); + return 1 << bits; +} +#endif + +#if defined(CONFIG_DISPLAY_CPUINFO) + +const char *get_imx_type(u32 imxtype) +{ + switch (imxtype) { + case MXC_CPU_MX6Q: + return "6Q"; /* Quad-core version of the mx6 */ + case MXC_CPU_MX6DL: + return "6DL"; /* Dual Lite version of the mx6 */ + case MXC_CPU_MX6SOLO: + return "6SOLO"; /* Solo version of the mx6 */ + case MXC_CPU_MX6SL: + return "6SL"; /* Solo-Lite version of the mx6 */ + case MXC_CPU_MX51: + return "51"; + case MXC_CPU_MX53: + return "53"; + default: + return "??"; + } +} + +int print_cpuinfo(void) +{ + u32 cpurev; + + cpurev = get_cpu_rev(); + + printf("CPU: Freescale i.MX%s rev%d.%d at %d MHz\n", + get_imx_type((cpurev & 0xFF000) >> 12), + (cpurev & 0x000F0) >> 4, + (cpurev & 0x0000F) >> 0, + mxc_get_clock(MXC_ARM_CLK) / 1000000); + printf("Reset cause: %s\n", get_reset_cause()); + return 0; +} +#endif + +int cpu_eth_init(bd_t *bis) +{ + int rc = -ENODEV; + +#if defined(CONFIG_FEC_MXC) + rc = fecmxc_initialize(bis); +#endif + + return rc; +} + +#ifdef CONFIG_FSL_ESDHC +/* + * Initializes on-chip MMC controllers. + * to override, implement board_mmc_init() + */ +int cpu_mmc_init(bd_t *bis) +{ + return fsl_esdhc_mmc_init(bis); +} +#endif + +u32 get_ahb_clk(void) +{ + struct mxc_ccm_reg *imx_ccm = (struct mxc_ccm_reg *)CCM_BASE_ADDR; + u32 reg, ahb_podf; + + reg = __raw_readl(&imx_ccm->cbcdr); + reg &= MXC_CCM_CBCDR_AHB_PODF_MASK; + ahb_podf = reg >> MXC_CCM_CBCDR_AHB_PODF_OFFSET; + + return get_periph_clk() / (ahb_podf + 1); +} + +#if defined(CONFIG_VIDEO_IPUV3) +void arch_preboot_os(void) +{ + /* disable video before launching O/S */ + ipuv3_fb_shutdown(); +} +#endif diff --git a/arch/arm/imx-common/i2c-mxv7.c b/arch/arm/imx-common/i2c-mxv7.c new file mode 100644 index 0000000..da2b26f --- /dev/null +++ b/arch/arm/imx-common/i2c-mxv7.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2012 Boundary Devices Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <asm/errno.h> +#include <asm/gpio.h> +#include <asm/imx-common/mxc_i2c.h> +#include <watchdog.h> + +static int force_idle_bus(void *priv) +{ + int i; + int sda, scl; + ulong elapsed, start_time; + struct i2c_pads_info *p = (struct i2c_pads_info *)priv; + int ret = 0; + + gpio_direction_input(p->sda.gp); + gpio_direction_input(p->scl.gp); + + imx_iomux_v3_setup_pad(p->sda.gpio_mode); + imx_iomux_v3_setup_pad(p->scl.gpio_mode); + + sda = gpio_get_value(p->sda.gp); + scl = gpio_get_value(p->scl.gp); + if ((sda & scl) == 1) + goto exit; /* Bus is idle already */ + + printf("%s: sda=%d scl=%d sda.gp=0x%x scl.gp=0x%x\n", __func__, + sda, scl, p->sda.gp, p->scl.gp); + /* Send high and low on the SCL line */ + for (i = 0; i < 9; i++) { + gpio_direction_output(p->scl.gp, 0); + udelay(50); + gpio_direction_input(p->scl.gp); + udelay(50); + } + start_time = get_timer(0); + for (;;) { + sda = gpio_get_value(p->sda.gp); + scl = gpio_get_value(p->scl.gp); + if ((sda & scl) == 1) + break; + WATCHDOG_RESET(); + elapsed = get_timer(start_time); + if (elapsed > (CONFIG_SYS_HZ / 5)) { /* .2 seconds */ + ret = -EBUSY; + printf("%s: failed to clear bus, sda=%d scl=%d\n", + __func__, sda, scl); + break; + } + } +exit: + imx_iomux_v3_setup_pad(p->sda.i2c_mode); + imx_iomux_v3_setup_pad(p->scl.i2c_mode); + return ret; +} + +static void * const i2c_bases[] = { + (void *)I2C1_BASE_ADDR, + (void *)I2C2_BASE_ADDR, +#ifdef I2C3_BASE_ADDR + (void *)I2C3_BASE_ADDR, +#endif +}; + +/* i2c_index can be from 0 - 2 */ +void setup_i2c(unsigned i2c_index, int speed, int slave_addr, + struct i2c_pads_info *p) +{ + if (i2c_index >= ARRAY_SIZE(i2c_bases)) + return; + /* Enable i2c clock */ + enable_i2c_clk(1, i2c_index); + /* Make sure bus is idle */ + force_idle_bus(p); + bus_i2c_init(i2c_bases[i2c_index], speed, slave_addr, + force_idle_bus, p); +} diff --git a/arch/arm/imx-common/iomux-v3.c b/arch/arm/imx-common/iomux-v3.c new file mode 100644 index 0000000..35880c7 --- /dev/null +++ b/arch/arm/imx-common/iomux-v3.c @@ -0,0 +1,69 @@ +/* + * Based on the iomux-v3.c from Linux kernel: + * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de> + * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH, + * <armlinux@phytec.de> + * + * Copyright (C) 2004-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ +#include <common.h> +#include <asm/io.h> +#include <asm/arch/imx-regs.h> +#include <asm/imx-common/iomux-v3.h> + +static void *base = (void *)IOMUXC_BASE_ADDR; + +/* + * configures a single pad in the iomuxer + */ +void imx_iomux_v3_setup_pad(iomux_v3_cfg_t pad) +{ + u32 mux_ctrl_ofs = (pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT; + u32 mux_mode = (pad & MUX_MODE_MASK) >> MUX_MODE_SHIFT; + u32 sel_input_ofs = + (pad & MUX_SEL_INPUT_OFS_MASK) >> MUX_SEL_INPUT_OFS_SHIFT; + u32 sel_input = + (pad & MUX_SEL_INPUT_MASK) >> MUX_SEL_INPUT_SHIFT; + u32 pad_ctrl_ofs = + (pad & MUX_PAD_CTRL_OFS_MASK) >> MUX_PAD_CTRL_OFS_SHIFT; + u32 pad_ctrl = (pad & MUX_PAD_CTRL_MASK) >> MUX_PAD_CTRL_SHIFT; + + if (mux_ctrl_ofs) + __raw_writel(mux_mode, base + mux_ctrl_ofs); + + if (sel_input_ofs) + __raw_writel(sel_input, base + sel_input_ofs); + +#ifdef CONFIG_IOMUX_SHARE_CONF_REG + if (!(pad_ctrl & NO_PAD_CTRL)) + __raw_writel((mux_mode << PAD_MUX_MODE_SHIFT) | pad_ctrl, + base + pad_ctrl_ofs); +#else + if (!(pad_ctrl & NO_PAD_CTRL) && pad_ctrl_ofs) + __raw_writel(pad_ctrl, base + pad_ctrl_ofs); +#endif +} + +void imx_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t const *pad_list, + unsigned count) +{ + iomux_v3_cfg_t const *p = pad_list; + int i; + + for (i = 0; i < count; i++) + imx_iomux_v3_setup_pad(*p++); +} diff --git a/arch/arm/imx-common/misc.c b/arch/arm/imx-common/misc.c new file mode 100644 index 0000000..220785c --- /dev/null +++ b/arch/arm/imx-common/misc.c @@ -0,0 +1,84 @@ +/* + * Copyright 2013 Stefan Roese <sr@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. + */ + +#include <common.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/imx-common/regs-common.h> + +/* 1 second delay should be plenty of time for block reset. */ +#define RESET_MAX_TIMEOUT 1000000 + +#define MXS_BLOCK_SFTRST (1 << 31) +#define MXS_BLOCK_CLKGATE (1 << 30) + +int mxs_wait_mask_set(struct mxs_register_32 *reg, uint32_t mask, unsigned + int timeout) +{ + while (--timeout) { + if ((readl(®->reg) & mask) == mask) + break; + udelay(1); + } + + return !timeout; +} + +int mxs_wait_mask_clr(struct mxs_register_32 *reg, uint32_t mask, unsigned + int timeout) +{ + while (--timeout) { + if ((readl(®->reg) & mask) == 0) + break; + udelay(1); + } + + return !timeout; +} + +int mxs_reset_block(struct mxs_register_32 *reg) +{ + /* Clear SFTRST */ + writel(MXS_BLOCK_SFTRST, ®->reg_clr); + + if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) + return 1; + + /* Clear CLKGATE */ + writel(MXS_BLOCK_CLKGATE, ®->reg_clr); + + /* Set SFTRST */ + writel(MXS_BLOCK_SFTRST, ®->reg_set); + + /* Wait for CLKGATE being set */ + if (mxs_wait_mask_set(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT)) + return 1; + + /* Clear SFTRST */ + writel(MXS_BLOCK_SFTRST, ®->reg_clr); + + if (mxs_wait_mask_clr(reg, MXS_BLOCK_SFTRST, RESET_MAX_TIMEOUT)) + return 1; + + /* Clear CLKGATE */ + writel(MXS_BLOCK_CLKGATE, ®->reg_clr); + + if (mxs_wait_mask_clr(reg, MXS_BLOCK_CLKGATE, RESET_MAX_TIMEOUT)) + return 1; + + return 0; +} diff --git a/arch/arm/imx-common/speed.c b/arch/arm/imx-common/speed.c new file mode 100644 index 0000000..638ee1a --- /dev/null +++ b/arch/arm/imx-common/speed.c @@ -0,0 +1,61 @@ +/* + * (C) Copyright 2000-2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. + * TsiChung Liew (Tsi-Chung.Liew@freescale.com) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> + +#ifdef CONFIG_FSL_ESDHC +DECLARE_GLOBAL_DATA_PTR; +#endif + +int get_clocks(void) +{ +#ifdef CONFIG_FSL_ESDHC +#ifdef CONFIG_FSL_USDHC +#if CONFIG_SYS_FSL_ESDHC_ADDR == USDHC2_BASE_ADDR + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); +#elif CONFIG_SYS_FSL_ESDHC_ADDR == USDHC3_BASE_ADDR + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); +#elif CONFIG_SYS_FSL_ESDHC_ADDR == USDHC4_BASE_ADDR + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK); +#else + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); +#endif +#else +#if CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC2_BASE_ADDR + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC2_CLK); +#elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC3_BASE_ADDR + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC3_CLK); +#elif CONFIG_SYS_FSL_ESDHC_ADDR == MMC_SDHC4_BASE_ADDR + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC4_CLK); +#else + gd->arch.sdhc_clk = mxc_get_clock(MXC_ESDHC_CLK); +#endif +#endif +#endif + return 0; +} diff --git a/arch/arm/imx-common/timer.c b/arch/arm/imx-common/timer.c new file mode 100644 index 0000000..1dbc413 --- /dev/null +++ b/arch/arm/imx-common/timer.c @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2007 + * Sascha Hauer, Pengutronix + * + * (C) Copyright 2009 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <div64.h> +#include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> + +/* General purpose timers registers */ +struct mxc_gpt { + unsigned int control; + unsigned int prescaler; + unsigned int status; + unsigned int nouse[6]; + unsigned int counter; +}; + +static struct mxc_gpt *cur_gpt = (struct mxc_gpt *)GPT1_BASE_ADDR; + +/* General purpose timers bitfields */ +#define GPTCR_SWR (1 << 15) /* Software reset */ +#define GPTCR_FRR (1 << 9) /* Freerun / restart */ +#define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source */ +#define GPTCR_TEN 1 /* Timer enable */ + +DECLARE_GLOBAL_DATA_PTR; + +static inline unsigned long long tick_to_time(unsigned long long tick) +{ + tick *= CONFIG_SYS_HZ; + do_div(tick, MXC_CLK32); + + return tick; +} + +static inline unsigned long long us_to_tick(unsigned long long usec) +{ + usec = usec * MXC_CLK32 + 999999; + do_div(usec, 1000000); + + return usec; +} + +int timer_init(void) +{ + int i; + + /* setup GP Timer 1 */ + __raw_writel(GPTCR_SWR, &cur_gpt->control); + + /* We have no udelay by now */ + for (i = 0; i < 100; i++) + __raw_writel(0, &cur_gpt->control); + + __raw_writel(0, &cur_gpt->prescaler); /* 32Khz */ + + /* Freerun Mode, PERCLK1 input */ + i = __raw_readl(&cur_gpt->control); + __raw_writel(i | GPTCR_CLKSOURCE_32 | GPTCR_TEN, &cur_gpt->control); + + gd->arch.tbl = __raw_readl(&cur_gpt->counter); + gd->arch.tbu = 0; + + return 0; +} + +unsigned long long get_ticks(void) +{ + ulong now = __raw_readl(&cur_gpt->counter); /* current tick value */ + + /* increment tbu if tbl has rolled over */ + if (now < gd->arch.tbl) + gd->arch.tbu++; + gd->arch.tbl = now; + return (((unsigned long long)gd->arch.tbu) << 32) | gd->arch.tbl; +} + +ulong get_timer_masked(void) +{ + /* + * get_ticks() returns a long long (64 bit), it wraps in + * 2^64 / MXC_CLK32 = 2^64 / 2^15 = 2^49 ~ 5 * 10^14 (s) ~ + * 5 * 10^9 days... and get_ticks() * CONFIG_SYS_HZ wraps in + * 5 * 10^6 days - long enough. + */ + return tick_to_time(get_ticks()); +} + +ulong get_timer(ulong base) +{ + return get_timer_masked() - base; +} + +/* delay x useconds AND preserve advance timstamp value */ +void __udelay(unsigned long usec) +{ + unsigned long long tmp; + ulong tmo; + + tmo = us_to_tick(usec); + tmp = get_ticks() + tmo; /* get current timestamp */ + + while (get_ticks() < tmp) /* loop till event */ + /*NOP*/; +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return MXC_CLK32; +} |