summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorWolfgang Denk <wd@denx.de>2011-02-02 21:57:19 +0100
committerWolfgang Denk <wd@denx.de>2011-02-02 21:57:19 +0100
commitbe9db564de898240034151c48cf9e0d03ece3f35 (patch)
treef87b02a573c61fdab3f190de09e6b0c8061f446b /drivers
parent89ffa8dbb5bd0552f5f3399f4430a4c97f4d50d4 (diff)
parent9e40808c3fe0237a8d49f10394d3a8e4e29540a6 (diff)
downloadu-boot-imx-be9db564de898240034151c48cf9e0d03ece3f35.zip
u-boot-imx-be9db564de898240034151c48cf9e0d03ece3f35.tar.gz
u-boot-imx-be9db564de898240034151c48cf9e0d03ece3f35.tar.bz2
Merge branch 'master' of /home/wd/git/u-boot/custodians
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/mxc_ata.c146
-rw-r--r--drivers/gpio/mxc_gpio.c9
-rw-r--r--drivers/i2c/mxc_i2c.c172
-rw-r--r--drivers/misc/Makefile5
-rw-r--r--drivers/misc/fsl_pmic.c45
-rw-r--r--drivers/misc/mc9sdz60.c51
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/davinci_mmc.c404
-rw-r--r--drivers/mtd/nand/mxc_nand.c6
-rw-r--r--drivers/net/davinci_emac.c15
-rw-r--r--drivers/net/fec_mxc.c2
-rw-r--r--drivers/net/fec_mxc.h4
-rw-r--r--drivers/serial/serial_mxc.c9
-rw-r--r--drivers/serial/serial_s5p.c2
-rw-r--r--drivers/spi/mxc_spi.c200
16 files changed, 920 insertions, 152 deletions
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index e27175b..aa7dc87 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -31,6 +31,7 @@ COBJS-$(CONFIG_FSL_SATA) += fsl_sata.o
COBJS-$(CONFIG_LIBATA) += libata.o
COBJS-$(CONFIG_CMD_MG_DISK) += mg_disk.o
COBJS-$(CONFIG_MVSATA_IDE) += mvsata_ide.o
+COBJS-$(CONFIG_MX51_PATA) += mxc_ata.o
COBJS-$(CONFIG_PATA_BFIN) += pata_bfin.o
COBJS-$(CONFIG_SATA_DWC) += sata_dwc.o
COBJS-$(CONFIG_SATA_SIL3114) += sata_sil3114.o
diff --git a/drivers/block/mxc_ata.c b/drivers/block/mxc_ata.c
new file mode 100644
index 0000000..f22f4f4
--- /dev/null
+++ b/drivers/block/mxc_ata.c
@@ -0,0 +1,146 @@
+/*
+ * Freescale iMX51 ATA driver
+ *
+ * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
+ *
+ * Based on code by:
+ * Mahesh Mahadevan <mahesh.mahadevan@freescale.com>
+ *
+ * Based on code from original FSL ATA driver, which is
+ * part of eCos, the Embedded Configurable Operating System.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <config.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <ide.h>
+
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+
+/* MXC ATA register offsets */
+struct mxc_ata_config_regs {
+ u8 time_off; /* 0x00 */
+ u8 time_on;
+ u8 time_1;
+ u8 time_2w;
+ u8 time_2r;
+ u8 time_ax;
+ u8 time_pio_rdx;
+ u8 time_4;
+ u8 time_9;
+ u8 time_m;
+ u8 time_jn;
+ u8 time_d;
+ u8 time_k;
+ u8 time_ack;
+ u8 time_env;
+ u8 time_udma_rdx;
+ u8 time_zah; /* 0x10 */
+ u8 time_mlix;
+ u8 time_dvh;
+ u8 time_dzfs;
+ u8 time_dvs;
+ u8 time_cvh;
+ u8 time_ss;
+ u8 time_cyc;
+ u32 fifo_data_32; /* 0x18 */
+ u32 fifo_data_16;
+ u32 fifo_fill;
+ u32 ata_control;
+ u32 interrupt_pending;
+ u32 interrupt_enable;
+ u32 interrupt_clear;
+ u32 fifo_alarm;
+};
+
+struct mxc_data_hdd_regs {
+ u32 drive_data; /* 0xa0 */
+ u32 drive_features;
+ u32 drive_sector_count;
+ u32 drive_sector_num;
+ u32 drive_cyl_low;
+ u32 drive_cyl_high;
+ u32 drive_dev_head;
+ u32 command;
+ u32 status;
+ u32 alt_status;
+};
+
+/* PIO timing table */
+#define NR_PIO_SPECS 5
+static uint16_t pio_t1[NR_PIO_SPECS] = { 70, 50, 30, 30, 25 };
+static uint16_t pio_t2_8[NR_PIO_SPECS] = { 290, 290, 290, 80, 70 };
+static uint16_t pio_t4[NR_PIO_SPECS] = { 30, 20, 15, 10, 10 };
+static uint16_t pio_t9[NR_PIO_SPECS] = { 20, 15, 10, 10, 10 };
+static uint16_t pio_tA[NR_PIO_SPECS] = { 50, 50, 50, 50, 50 };
+
+#define REG2OFF(reg) ((((uint32_t)reg) & 0x3) * 8)
+static void set_ata_bus_timing(unsigned char mode)
+{
+ uint32_t val;
+ uint32_t T = 1000000000 / mxc_get_clock(MXC_IPG_CLK);
+
+ struct mxc_ata_config_regs *ata_regs;
+ ata_regs = (struct mxc_ata_config_regs *)CONFIG_SYS_ATA_BASE_ADDR;
+
+ if (mode >= NR_PIO_SPECS)
+ return;
+
+ /* Write TIME_OFF/ON/1/2W */
+ val = (3 << REG2OFF(&ata_regs->time_off)) |
+ (3 << REG2OFF(&ata_regs->time_on)) |
+ (((pio_t1[mode] + T) / T) << REG2OFF(&ata_regs->time_1)) |
+ (((pio_t2_8[mode] + T) / T) << REG2OFF(&ata_regs->time_2w));
+ writel(val, &ata_regs->time_off);
+
+ /* Write TIME_2R/AX/RDX/4 */
+ val = (((pio_t2_8[mode] + T) / T) << REG2OFF(&ata_regs->time_2r)) |
+ (((pio_tA[mode] + T) / T + 2) << REG2OFF(&ata_regs->time_ax)) |
+ (1 << REG2OFF(&ata_regs->time_pio_rdx)) |
+ (((pio_t4[mode] + T) / T) << REG2OFF(&ata_regs->time_4));
+ writel(val, &ata_regs->time_2r);
+
+ /* Write TIME_9 ; the rest of timing registers is irrelevant for PIO */
+ val = (((pio_t9[mode] + T) / T) << REG2OFF(&ata_regs->time_9));
+ writel(val, &ata_regs->time_9);
+}
+
+int ide_preinit(void)
+{
+ struct mxc_ata_config_regs *ata_regs;
+ ata_regs = (struct mxc_ata_config_regs *)CONFIG_SYS_ATA_BASE_ADDR;
+
+ /* 46.3.3.4 @ FSL iMX51 manual */
+ /* FIFO normal op., drive reset */
+ writel(0x80, &ata_regs->ata_control);
+ /* FIFO normal op., drive not reset */
+ writel(0xc0, &ata_regs->ata_control);
+
+ /* Configure the PIO timing */
+ set_ata_bus_timing(CONFIG_MXC_ATA_PIO_MODE);
+
+ /* 46.3.3.4 @ FSL iMX51 manual */
+ /* Drive not reset, IORDY handshake */
+ writel(0x41, &ata_regs->ata_control);
+
+ return 0;
+}
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
index 663141f..53a0673 100644
--- a/drivers/gpio/mxc_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -24,7 +24,7 @@
#ifdef CONFIG_MX31
#include <asm/arch/mx31-regs.h>
#endif
-#ifdef CONFIG_MX51
+#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
#include <asm/arch/imx-regs.h>
#endif
#include <asm/io.h>
@@ -35,9 +35,14 @@ static unsigned long gpio_ports[] = {
[0] = GPIO1_BASE_ADDR,
[1] = GPIO2_BASE_ADDR,
[2] = GPIO3_BASE_ADDR,
-#ifdef CONFIG_MX51
+#if defined(CONFIG_MX51) || defined(CONFIG_MX53)
[3] = GPIO4_BASE_ADDR,
#endif
+#if defined(CONFIG_MX53)
+ [4] = GPIO5_BASE_ADDR,
+ [5] = GPIO6_BASE_ADDR,
+ [6] = GPIO7_BASE_ADDR,
+#endif
};
int mxc_gpio_direction(unsigned int gpio, enum mxc_gpio_direction direction)
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 8e10fbb..c5ec486 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -23,11 +23,17 @@
*/
#include <common.h>
+#include <asm/io.h>
#if defined(CONFIG_HARD_I2C)
+#if defined(CONFIG_MX31)
#include <asm/arch/mx31.h>
#include <asm/arch/mx31-regs.h>
+#else
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+#endif
#define IADR 0x00
#define IFDR 0x04
@@ -47,7 +53,7 @@
#define I2SR_IIF (1 << 1)
#define I2SR_RX_NO_AK (1 << 0)
-#ifdef CONFIG_SYS_I2C_MX31_PORT1
+#if defined(CONFIG_SYS_I2C_MX31_PORT1)
#define I2C_BASE 0x43f80000
#define I2C_CLK_OFFSET 26
#elif defined (CONFIG_SYS_I2C_MX31_PORT2)
@@ -56,130 +62,205 @@
#elif defined (CONFIG_SYS_I2C_MX31_PORT3)
#define I2C_BASE 0x43f84000
#define I2C_CLK_OFFSET 30
+#elif defined(CONFIG_SYS_I2C_MX53_PORT1)
+#define I2C_BASE I2C1_BASE_ADDR
+#elif defined(CONFIG_SYS_I2C_MX53_PORT2)
+#define I2C_BASE I2C2_BASE_ADDR
+#elif defined(CONFIG_SYS_I2C_MX35_PORT1)
+#define I2C_BASE I2C_BASE_ADDR
#else
-#error "define CONFIG_SYS_I2C_MX31_PORTx to use the mx31 I2C driver"
+#error "define CONFIG_SYS_I2C_MX<Processor>_PORTx to use the mx I2C driver"
#endif
-#ifdef DEBUG
-#define DPRINTF(args...) printf(args)
-#else
-#define DPRINTF(args...)
-#endif
+#define I2C_MAX_TIMEOUT 10000
+#define I2C_MAX_RETRIES 3
static u16 div[] = { 30, 32, 36, 42, 48, 52, 60, 72, 80, 88, 104, 128, 144,
160, 192, 240, 288, 320, 384, 480, 576, 640, 768, 960,
1152, 1280, 1536, 1920, 2304, 2560, 3072, 3840};
+static inline void i2c_reset(void)
+{
+ writew(0, I2C_BASE + I2CR); /* Reset module */
+ writew(0, I2C_BASE + I2SR);
+ writew(I2CR_IEN, I2C_BASE + I2CR);
+}
+
void i2c_init(int speed, int unused)
{
- int freq = mx31_get_ipg_clk();
+ int freq;
int i;
+#if defined(CONFIG_MX31)
+ struct clock_control_regs *sc_regs =
+ (struct clock_control_regs *)CCM_BASE;
+
+ freq = mx31_get_ipg_clk();
/* start the required I2C clock */
- __REG(CCM_CGR0) = __REG(CCM_CGR0) | (3 << I2C_CLK_OFFSET);
+ writel(readl(&sc_regs->cgr0) | (3 << I2C_CLK_OFFSET),
+ &sc_regs->cgr0);
+#else
+ freq = mxc_get_clock(MXC_IPG_PERCLK);
+#endif
for (i = 0; i < 0x1f; i++)
if (freq / div[i] <= speed)
break;
- DPRINTF("%s: speed: %d\n",__FUNCTION__, speed);
+ debug("%s: speed: %d\n", __func__, speed);
- __REG16(I2C_BASE + I2CR) = 0; /* Reset module */
- __REG16(I2C_BASE + IFDR) = i;
- __REG16(I2C_BASE + I2CR) = I2CR_IEN;
- __REG16(I2C_BASE + I2SR) = 0;
+ writew(i, I2C_BASE + IFDR);
+ i2c_reset();
+}
+
+static int wait_idle(void)
+{
+ int timeout = I2C_MAX_TIMEOUT;
+
+ while ((readw(I2C_BASE + I2SR) & I2SR_IBB) && --timeout) {
+ writew(0, I2C_BASE + I2SR);
+ udelay(1);
+ }
+ return timeout ? timeout : (!(readw(I2C_BASE + I2SR) & I2SR_IBB));
}
static int wait_busy(void)
{
- int timeout = 10000;
+ int timeout = I2C_MAX_TIMEOUT;
- while (!(__REG16(I2C_BASE + I2SR) & I2SR_IIF) && --timeout)
+ while (!(readw(I2C_BASE + I2SR) & I2SR_IBB) && --timeout)
udelay(1);
- __REG16(I2C_BASE + I2SR) = 0; /* clear interrupt */
+ writew(0, I2C_BASE + I2SR); /* clear interrupt */
return timeout;
}
+static int wait_complete(void)
+{
+ int timeout = I2C_MAX_TIMEOUT;
+
+ while ((!(readw(I2C_BASE + I2SR) & I2SR_ICF)) && (--timeout)) {
+ writew(0, I2C_BASE + I2SR);
+ udelay(1);
+ }
+ udelay(200);
+
+ writew(0, I2C_BASE + I2SR); /* clear interrupt */
+
+ return timeout;
+}
+
+
static int tx_byte(u8 byte)
{
- __REG16(I2C_BASE + I2DR) = byte;
+ writew(byte, I2C_BASE + I2DR);
- if (!wait_busy() || __REG16(I2C_BASE + I2SR) & I2SR_RX_NO_AK)
+ if (!wait_complete() || readw(I2C_BASE + I2SR) & I2SR_RX_NO_AK)
return -1;
return 0;
}
-static int rx_byte(void)
+static int rx_byte(int last)
{
- if (!wait_busy())
+ if (!wait_complete())
return -1;
- return __REG16(I2C_BASE + I2DR);
+ if (last)
+ writew(I2CR_IEN, I2C_BASE + I2CR);
+
+ return readw(I2C_BASE + I2DR);
}
int i2c_probe(uchar chip)
{
int ret;
- __REG16(I2C_BASE + I2CR) = 0; /* Reset module */
- __REG16(I2C_BASE + I2CR) = I2CR_IEN;
+ writew(0, I2C_BASE + I2CR); /* Reset module */
+ writew(I2CR_IEN, I2C_BASE + I2CR);
- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_MTX;
+ writew(I2CR_IEN | I2CR_MSTA | I2CR_MTX, I2C_BASE + I2CR);
ret = tx_byte(chip << 1);
- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MTX;
+ writew(I2CR_IEN | I2CR_MTX, I2C_BASE + I2CR);
return ret;
}
static int i2c_addr(uchar chip, uint addr, int alen)
{
- __REG16(I2C_BASE + I2SR) = 0; /* clear interrupt */
- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_MTX;
+ int i, retry = 0;
+ for (retry = 0; retry < 3; retry++) {
+ if (wait_idle())
+ break;
+ i2c_reset();
+ for (i = 0; i < I2C_MAX_TIMEOUT; i++)
+ udelay(1);
+ }
+ if (retry >= I2C_MAX_RETRIES) {
+ debug("%s:bus is busy(%x)\n",
+ __func__, readw(I2C_BASE + I2SR));
+ return -1;
+ }
+ writew(I2CR_IEN | I2CR_MSTA | I2CR_MTX, I2C_BASE + I2CR);
- if (tx_byte(chip << 1))
+ if (!wait_busy()) {
+ debug("%s:trigger start fail(%x)\n",
+ __func__, readw(I2C_BASE + I2SR));
return -1;
+ }
+ if (tx_byte(chip << 1) || (readw(I2C_BASE + I2SR) & I2SR_RX_NO_AK)) {
+ debug("%s:chip address cycle fail(%x)\n",
+ __func__, readw(I2C_BASE + I2SR));
+ return -1;
+ }
while (alen--)
- if (tx_byte((addr >> (alen * 8)) & 0xff))
+ if (tx_byte((addr >> (alen * 8)) & 0xff) ||
+ (readw(I2C_BASE + I2SR) & I2SR_RX_NO_AK)) {
+ debug("%s:device address cycle fail(%x)\n",
+ __func__, readw(I2C_BASE + I2SR));
return -1;
+ }
return 0;
}
int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
{
- int timeout = 10000;
+ int timeout = I2C_MAX_TIMEOUT;
int ret;
- DPRINTF("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n",__FUNCTION__, chip, addr, alen, len);
+ debug("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n",
+ __func__, chip, addr, alen, len);
if (i2c_addr(chip, addr, alen)) {
printf("i2c_addr failed\n");
return -1;
}
- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_MTX | I2CR_RSTA;
+ writew(I2CR_IEN | I2CR_MSTA | I2CR_MTX | I2CR_RSTA, I2C_BASE + I2CR);
if (tx_byte(chip << 1 | 1))
return -1;
- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | ((len == 1) ? I2CR_TX_NO_AK : 0);
+ writew(I2CR_IEN | I2CR_MSTA |
+ ((len == 1) ? I2CR_TX_NO_AK : 0),
+ I2C_BASE + I2CR);
- ret = __REG16(I2C_BASE + I2DR);
+ ret = readw(I2C_BASE + I2DR);
while (len--) {
- if ((ret = rx_byte()) < 0)
+ ret = rx_byte(len == 0);
+ if (ret < 0)
return -1;
*buf++ = ret;
if (len <= 1)
- __REG16(I2C_BASE + I2CR) = I2CR_IEN | I2CR_MSTA | I2CR_TX_NO_AK;
+ writew(I2CR_IEN | I2CR_MSTA |
+ I2CR_TX_NO_AK,
+ I2C_BASE + I2CR);
}
- wait_busy();
-
- __REG16(I2C_BASE + I2CR) = I2CR_IEN;
+ writew(I2CR_IEN, I2C_BASE + I2CR);
- while (__REG16(I2C_BASE + I2SR) & I2SR_IBB && --timeout)
+ while (readw(I2C_BASE + I2SR) & I2SR_IBB && --timeout)
udelay(1);
return 0;
@@ -187,8 +268,9 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
{
- int timeout = 10000;
- DPRINTF("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n",__FUNCTION__, chip, addr, alen, len);
+ int timeout = I2C_MAX_TIMEOUT;
+ debug("%s chip: 0x%02x addr: 0x%04x alen: %d len: %d\n",
+ __func__, chip, addr, alen, len);
if (i2c_addr(chip, addr, alen))
return -1;
@@ -197,9 +279,9 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
if (tx_byte(*buf++))
return -1;
- __REG16(I2C_BASE + I2CR) = I2CR_IEN;
+ writew(I2CR_IEN, I2C_BASE + I2CR);
- while (__REG16(I2C_BASE + I2SR) & I2SR_IBB && --timeout)
+ while (readw(I2C_BASE + I2SR) & I2SR_IBB && --timeout)
udelay(1);
return 0;
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index a76bd4e..b152486 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -28,12 +28,13 @@ LIB := $(obj)libmisc.o
COBJS-$(CONFIG_ALI152X) += ali512x.o
COBJS-$(CONFIG_DS4510) += ds4510.o
COBJS-$(CONFIG_FSL_LAW) += fsl_law.o
+COBJS-$(CONFIG_FSL_PMIC) += fsl_pmic.o
COBJS-$(CONFIG_GPIO_LED) += gpio_led.o
+COBJS-$(CONFIG_FSL_MC9SDZ60) += mc9sdz60.o
COBJS-$(CONFIG_NS87308) += ns87308.o
+COBJS-$(CONFIG_PDSP188x) += pdsp188x.o
COBJS-$(CONFIG_STATUS_LED) += status_led.o
COBJS-$(CONFIG_TWL4030_LED) += twl4030_led.o
-COBJS-$(CONFIG_FSL_PMIC) += fsl_pmic.o
-COBJS-$(CONFIG_PDSP188x) += pdsp188x.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/misc/fsl_pmic.c b/drivers/misc/fsl_pmic.c
index 5ee1de1..ef80ad9 100644
--- a/drivers/misc/fsl_pmic.c
+++ b/drivers/misc/fsl_pmic.c
@@ -22,11 +22,48 @@
#include <config.h>
#include <common.h>
-#include <spi.h>
#include <asm/errno.h>
#include <linux/types.h>
#include <fsl_pmic.h>
+static int check_param(u32 reg, u32 write)
+{
+ if (reg > 63 || write > 1) {
+ printf("<reg num> = %d is invalid. Should be less then 63\n",
+ reg);
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_FSL_PMIC_I2C
+#include <i2c.h>
+
+u32 pmic_reg(u32 reg, u32 val, u32 write)
+{
+ unsigned char buf[4] = { 0 };
+ u32 ret_val = 0;
+
+ if (check_param(reg, write))
+ return -1;
+
+ if (write) {
+ buf[0] = (val >> 16) & 0xff;
+ buf[1] = (val >> 8) & 0xff;
+ buf[2] = (val) & 0xff;
+ if (i2c_write(CONFIG_SYS_FSL_PMIC_I2C_ADDR, reg, 1, buf, 3))
+ return -1;
+ } else {
+ if (i2c_read(CONFIG_SYS_FSL_PMIC_I2C_ADDR, reg, 1, buf, 3))
+ return -1;
+ ret_val = buf[0] << 16 | buf[1] << 8 | buf[2];
+ }
+
+ return ret_val;
+}
+#else /* SPI interface */
+#include <spi.h>
static struct spi_slave *slave;
struct spi_slave *pmic_spi_probe(void)
@@ -55,11 +92,8 @@ u32 pmic_reg(u32 reg, u32 val, u32 write)
return -1;
}
- if (reg > 63 || write > 1) {
- printf("<reg num> = %d is invalid. Should be less then 63\n",
- reg);
+ if (check_param(reg, write))
return -1;
- }
if (spi_claim_bus(slave))
return -1;
@@ -87,6 +121,7 @@ u32 pmic_reg(u32 reg, u32 val, u32 write)
spi_release_bus(slave);
return cpu_to_be32(pmic_rx);
}
+#endif
void pmic_reg_write(u32 reg, u32 value)
{
diff --git a/drivers/misc/mc9sdz60.c b/drivers/misc/mc9sdz60.c
new file mode 100644
index 0000000..439d5a6
--- /dev/null
+++ b/drivers/misc/mc9sdz60.c
@@ -0,0 +1,51 @@
+/*
+ * (C) Copyright 2010 Stefano Babic <sbabic@denx.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#include <config.h>
+#include <common.h>
+#include <asm/errno.h>
+#include <linux/types.h>
+#include <i2c.h>
+#include <mc9sdz60.h>
+
+#ifndef CONFIG_SYS_FSL_MC9SDZ60_I2C_ADDR
+#error "You have to configure I2C address for MC9SDZ60"
+#endif
+
+
+u8 mc9sdz60_reg_read(enum mc9sdz60_reg reg)
+{
+ u8 val;
+
+ if (i2c_read(CONFIG_SYS_FSL_MC9SDZ60_I2C_ADDR, reg, 1, &val, 1)) {
+ puts("Error reading MC9SDZ60 register\n");
+ return -1;
+ }
+
+ return val;
+}
+
+void mc9sdz60_reg_write(enum mc9sdz60_reg reg, u8 val)
+{
+ i2c_write(CONFIG_SYS_FSL_MC9SDZ60_I2C_ADDR, reg, 1, &val, 1);
+}
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 68afd30..3496f0a 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -27,6 +27,7 @@ LIB := $(obj)libmmc.o
COBJS-$(CONFIG_ATMEL_MCI) += atmel_mci.o
COBJS-$(CONFIG_BFIN_SDH) += bfin_sdh.o
+COBJS-$(CONFIG_DAVINCI_MMC) += davinci_mmc.o
COBJS-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
COBJS-$(CONFIG_GENERIC_MMC) += mmc.o
COBJS-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
diff --git a/drivers/mmc/davinci_mmc.c b/drivers/mmc/davinci_mmc.c
new file mode 100644
index 0000000..4e572dc
--- /dev/null
+++ b/drivers/mmc/davinci_mmc.c
@@ -0,0 +1,404 @@
+/*
+ * Davinci MMC Controller Driver
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <command.h>
+#include <mmc.h>
+#include <part.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/arch/sdmmc_defs.h>
+
+#define DAVINCI_MAX_BLOCKS (32)
+#define WATCHDOG_COUNT (100000)
+
+#define get_val(addr) REG(addr)
+#define set_val(addr, val) REG(addr) = (val)
+#define set_bit(addr, val) set_val((addr), (get_val(addr) | (val)))
+#define clear_bit(addr, val) set_val((addr), (get_val(addr) & ~(val)))
+
+/* Set davinci clock prescalar value based on the required clock in HZ */
+static void dmmc_set_clock(struct mmc *mmc, uint clock)
+{
+ struct davinci_mmc *host = mmc->priv;
+ struct davinci_mmc_regs *regs = host->reg_base;
+ uint clkrt, sysclk2, act_clock;
+
+ if (clock < mmc->f_min)
+ clock = mmc->f_min;
+ if (clock > mmc->f_max)
+ clock = mmc->f_max;
+
+ set_val(&regs->mmcclk, 0);
+ sysclk2 = host->input_clk;
+ clkrt = (sysclk2 / (2 * clock)) - 1;
+
+ /* Calculate the actual clock for the divider used */
+ act_clock = (sysclk2 / (2 * (clkrt + 1)));
+
+ /* Adjust divider if actual clock exceeds the required clock */
+ if (act_clock > clock)
+ clkrt++;
+
+ /* check clock divider boundary and correct it */
+ if (clkrt > 0xFF)
+ clkrt = 0xFF;
+
+ set_val(&regs->mmcclk, (clkrt | MMCCLK_CLKEN));
+}
+
+/* Status bit wait loop for MMCST1 */
+static int
+dmmc_wait_fifo_status(volatile struct davinci_mmc_regs *regs, uint status)
+{
+ uint mmcstatus1, wdog = WATCHDOG_COUNT;
+ mmcstatus1 = get_val(&regs->mmcst1);
+ while (--wdog && ((get_val(&regs->mmcst1) & status) != status))
+ udelay(10);
+
+ if (!(get_val(&regs->mmcctl) & MMCCTL_WIDTH_4_BIT))
+ udelay(100);
+
+ if (wdog == 0)
+ return COMM_ERR;
+
+ return 0;
+}
+
+/* Busy bit wait loop for MMCST1 */
+static int dmmc_busy_wait(volatile struct davinci_mmc_regs *regs)
+{
+ uint mmcstatus1, wdog = WATCHDOG_COUNT;
+
+ mmcstatus1 = get_val(&regs->mmcst1);
+ while (--wdog && (get_val(&regs->mmcst1) & MMCST1_BUSY))
+ udelay(10);
+
+ if (wdog == 0)
+ return COMM_ERR;
+
+ return 0;
+}
+
+/* Status bit wait loop for MMCST0 - Checks for error bits as well */
+static int dmmc_check_status(volatile struct davinci_mmc_regs *regs,
+ uint *cur_st, uint st_ready, uint st_error)
+{
+ uint wdog = WATCHDOG_COUNT;
+ uint mmcstatus = *cur_st;
+
+ while (wdog--) {
+ if (mmcstatus & st_ready) {
+ *cur_st = mmcstatus;
+ mmcstatus = get_val(&regs->mmcst1);
+ return 0;
+ } else if (mmcstatus & st_error) {
+ if (mmcstatus & MMCST0_TOUTRS)
+ return TIMEOUT;
+ printf("[ ST0 ERROR %x]\n", mmcstatus);
+ /*
+ * Ignore CRC errors as some MMC cards fail to
+ * initialize on DM365-EVM on the SD1 slot
+ */
+ if (mmcstatus & MMCST0_CRCRS)
+ return 0;
+ return COMM_ERR;
+ }
+ udelay(10);
+
+ mmcstatus = get_val(&regs->mmcst0);
+ }
+
+ printf("Status %x Timeout ST0:%x ST1:%x\n", st_ready, mmcstatus,
+ get_val(&regs->mmcst1));
+ return COMM_ERR;
+}
+
+/*
+ * Sends a command out on the bus. Takes the mmc pointer,
+ * a command pointer, and an optional data pointer.
+ */
+static int
+dmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+ struct davinci_mmc *host = mmc->priv;
+ volatile struct davinci_mmc_regs *regs = host->reg_base;
+ uint mmcstatus, status_rdy, status_err;
+ uint i, cmddata, bytes_left = 0;
+ int fifo_words, fifo_bytes, err;
+ char *data_buf = NULL;
+
+ /* Clear status registers */
+ mmcstatus = get_val(&regs->mmcst0);
+ fifo_words = (host->version == MMC_CTLR_VERSION_2) ? 16 : 8;
+ fifo_bytes = fifo_words << 2;
+
+ /* Wait for any previous busy signal to be cleared */
+ dmmc_busy_wait(regs);
+
+ cmddata = cmd->cmdidx;
+ cmddata |= MMCCMD_PPLEN;
+
+ /* Send init clock for CMD0 */
+ if (cmd->cmdidx == MMC_CMD_GO_IDLE_STATE)
+ cmddata |= MMCCMD_INITCK;
+
+ switch (cmd->resp_type) {
+ case MMC_RSP_R1b:
+ cmddata |= MMCCMD_BSYEXP;
+ /* Fall-through */
+ case MMC_RSP_R1: /* R1, R1b, R5, R6, R7 */
+ cmddata |= MMCCMD_RSPFMT_R1567;
+ break;
+ case MMC_RSP_R2:
+ cmddata |= MMCCMD_RSPFMT_R2;
+ break;
+ case MMC_RSP_R3: /* R3, R4 */
+ cmddata |= MMCCMD_RSPFMT_R3;
+ break;
+ }
+
+ set_val(&regs->mmcim, 0);
+
+ if (data) {
+ /* clear previous data transfer if any and set new one */
+ bytes_left = (data->blocksize * data->blocks);
+
+ /* Reset FIFO - Always use 32 byte fifo threshold */
+ set_val(&regs->mmcfifoctl,
+ (MMCFIFOCTL_FIFOLEV | MMCFIFOCTL_FIFORST));
+
+ if (host->version == MMC_CTLR_VERSION_2)
+ cmddata |= MMCCMD_DMATRIG;
+
+ cmddata |= MMCCMD_WDATX;
+ if (data->flags == MMC_DATA_READ) {
+ set_val(&regs->mmcfifoctl, MMCFIFOCTL_FIFOLEV);
+ } else if (data->flags == MMC_DATA_WRITE) {
+ set_val(&regs->mmcfifoctl,
+ (MMCFIFOCTL_FIFOLEV |
+ MMCFIFOCTL_FIFODIR));
+ cmddata |= MMCCMD_DTRW;
+ }
+
+ set_val(&regs->mmctod, 0xFFFF);
+ set_val(&regs->mmcnblk, (data->blocks & MMCNBLK_NBLK_MASK));
+ set_val(&regs->mmcblen, (data->blocksize & MMCBLEN_BLEN_MASK));
+
+ if (data->flags == MMC_DATA_WRITE) {
+ uint val;
+ data_buf = (char *)data->src;
+ /* For write, fill FIFO with data before issue of CMD */
+ for (i = 0; (i < fifo_words) && bytes_left; i++) {
+ memcpy((char *)&val, data_buf, 4);
+ set_val(&regs->mmcdxr, val);
+ data_buf += 4;
+ bytes_left -= 4;
+ }
+ }
+ } else {
+ set_val(&regs->mmcblen, 0);
+ set_val(&regs->mmcnblk, 0);
+ }
+
+ set_val(&regs->mmctor, 0x1FFF);
+
+ /* Send the command */
+ set_val(&regs->mmcarghl, cmd->cmdarg);
+ set_val(&regs->mmccmd, cmddata);
+
+ status_rdy = MMCST0_RSPDNE;
+ status_err = (MMCST0_TOUTRS | MMCST0_TOUTRD |
+ MMCST0_CRCWR | MMCST0_CRCRD);
+ if (cmd->resp_type & MMC_RSP_CRC)
+ status_err |= MMCST0_CRCRS;
+
+ mmcstatus = get_val(&regs->mmcst0);
+ err = dmmc_check_status(regs, &mmcstatus, status_rdy, status_err);
+ if (err)
+ return err;
+
+ /* For R1b wait for busy done */
+ if (cmd->resp_type == MMC_RSP_R1b)
+ dmmc_busy_wait(regs);
+
+ /* Collect response from controller for specific commands */
+ if (mmcstatus & MMCST0_RSPDNE) {
+ /* Copy the response to the response buffer */
+ if (cmd->resp_type & MMC_RSP_136) {
+ cmd->response[0] = get_val(&regs->mmcrsp67);
+ cmd->response[1] = get_val(&regs->mmcrsp45);
+ cmd->response[2] = get_val(&regs->mmcrsp23);
+ cmd->response[3] = get_val(&regs->mmcrsp01);
+ } else if (cmd->resp_type & MMC_RSP_PRESENT) {
+ cmd->response[0] = get_val(&regs->mmcrsp67);
+ }
+ }
+
+ if (data == NULL)
+ return 0;
+
+ if (data->flags == MMC_DATA_READ) {
+ /* check for DATDNE along with DRRDY as the controller might
+ * set the DATDNE without DRRDY for smaller transfers with
+ * less than FIFO threshold bytes
+ */
+ status_rdy = MMCST0_DRRDY | MMCST0_DATDNE;
+ status_err = MMCST0_TOUTRD | MMCST0_CRCRD;
+ data_buf = data->dest;
+ } else {
+ status_rdy = MMCST0_DXRDY | MMCST0_DATDNE;
+ status_err = MMCST0_CRCWR;
+ }
+
+ /* Wait until all of the blocks are transferred */
+ while (bytes_left) {
+ err = dmmc_check_status(regs, &mmcstatus, status_rdy,
+ status_err);
+ if (err)
+ return err;
+
+ if (data->flags == MMC_DATA_READ) {
+ /*
+ * MMC controller sets the Data receive ready bit
+ * (DRRDY) in MMCST0 even before the entire FIFO is
+ * full. This results in erratic behavior if we start
+ * reading the FIFO soon after DRRDY. Wait for the
+ * FIFO full bit in MMCST1 for proper FIFO clearing.
+ */
+ if (bytes_left > fifo_bytes)
+ dmmc_wait_fifo_status(regs, 0x4a);
+ else if (bytes_left == fifo_bytes)
+ dmmc_wait_fifo_status(regs, 0x40);
+
+ for (i = 0; bytes_left && (i < fifo_words); i++) {
+ cmddata = get_val(&regs->mmcdrr);
+ memcpy(data_buf, (char *)&cmddata, 4);
+ data_buf += 4;
+ bytes_left -= 4;
+ }
+ } else {
+ /*
+ * MMC controller sets the Data transmit ready bit
+ * (DXRDY) in MMCST0 even before the entire FIFO is
+ * empty. This results in erratic behavior if we start
+ * writing the FIFO soon after DXRDY. Wait for the
+ * FIFO empty bit in MMCST1 for proper FIFO clearing.
+ */
+ dmmc_wait_fifo_status(regs, MMCST1_FIFOEMP);
+ for (i = 0; bytes_left && (i < fifo_words); i++) {
+ memcpy((char *)&cmddata, data_buf, 4);
+ set_val(&regs->mmcdxr, cmddata);
+ data_buf += 4;
+ bytes_left -= 4;
+ }
+ dmmc_busy_wait(regs);
+ }
+ }
+
+ err = dmmc_check_status(regs, &mmcstatus, MMCST0_DATDNE, status_err);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+/* Initialize Davinci MMC controller */
+static int dmmc_init(struct mmc *mmc)
+{
+ struct davinci_mmc *host = mmc->priv;
+ struct davinci_mmc_regs *regs = host->reg_base;
+
+ /* Clear status registers explicitly - soft reset doesn't clear it
+ * If Uboot is invoked from UBL with SDMMC Support, the status
+ * registers can have uncleared bits
+ */
+ get_val(&regs->mmcst0);
+ get_val(&regs->mmcst1);
+
+ /* Hold software reset */
+ set_bit(&regs->mmcctl, MMCCTL_DATRST);
+ set_bit(&regs->mmcctl, MMCCTL_CMDRST);
+ udelay(10);
+
+ set_val(&regs->mmcclk, 0x0);
+ set_val(&regs->mmctor, 0x1FFF);
+ set_val(&regs->mmctod, 0xFFFF);
+
+ /* Clear software reset */
+ clear_bit(&regs->mmcctl, MMCCTL_DATRST);
+ clear_bit(&regs->mmcctl, MMCCTL_CMDRST);
+
+ udelay(10);
+
+ /* Reset FIFO - Always use the maximum fifo threshold */
+ set_val(&regs->mmcfifoctl, (MMCFIFOCTL_FIFOLEV | MMCFIFOCTL_FIFORST));
+ set_val(&regs->mmcfifoctl, MMCFIFOCTL_FIFOLEV);
+
+ return 0;
+}
+
+/* Set buswidth or clock as indicated by the GENERIC_MMC framework */
+static void dmmc_set_ios(struct mmc *mmc)
+{
+ struct davinci_mmc *host = mmc->priv;
+ struct davinci_mmc_regs *regs = host->reg_base;
+
+ /* Set the bus width */
+ if (mmc->bus_width == 4)
+ set_bit(&regs->mmcctl, MMCCTL_WIDTH_4_BIT);
+ else
+ clear_bit(&regs->mmcctl, MMCCTL_WIDTH_4_BIT);
+
+ /* Set clock speed */
+ if (mmc->clock)
+ dmmc_set_clock(mmc, mmc->clock);
+}
+
+/* Called from board_mmc_init during startup. Can be called multiple times
+ * depending on the number of slots available on board and controller
+ */
+int davinci_mmc_init(bd_t *bis, struct davinci_mmc *host)
+{
+ struct mmc *mmc;
+
+ mmc = malloc(sizeof(struct mmc));
+ memset(mmc, 0, sizeof(struct mmc));
+
+ sprintf(mmc->name, "davinci");
+ mmc->priv = host;
+ mmc->send_cmd = dmmc_send_cmd;
+ mmc->set_ios = dmmc_set_ios;
+ mmc->init = dmmc_init;
+
+ mmc->f_min = 200000;
+ mmc->f_max = 25000000;
+ mmc->voltages = host->voltages;
+ mmc->host_caps = host->host_caps;
+
+#ifdef CONFIG_MMC_MBLOCK
+ mmc->b_max = DAVINCI_MAX_BLOCKS;
+#endif
+ mmc_register(mmc);
+
+ return 0;
+}
+
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index ec71cfc..2a8dd7e 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -22,7 +22,7 @@
#include <nand.h>
#include <linux/err.h>
#include <asm/io.h>
-#if defined(CONFIG_MX25) || defined(CONFIG_MX27)
+#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX35)
#include <asm/arch/imx-regs.h>
#endif
@@ -50,7 +50,7 @@
*/
#if defined(CONFIG_MX31) || defined(CONFIG_MX27)
#define MXC_NFC_V1
-#elif defined(CONFIG_MX25)
+#elif defined(CONFIG_MX25) || defined(CONFIG_MX35)
#define MXC_NFC_V1_1
#else
#warning "MXC NFC version not defined"
@@ -265,7 +265,7 @@ static int is_16bit_nand(void)
else
return 0;
}
-#elif defined(CONFIG_MX25)
+#elif defined(CONFIG_MX25) || defined(CONFIG_MX35)
static int is_16bit_nand(void)
{
struct ccm_regs *ccm =
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 56cd2aa..c359f54 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -322,9 +322,10 @@ static void __attribute__((unused)) davinci_eth_gigabit_enable(void)
* Check if link detected is giga-bit
* If Gigabit mode detected, enable gigbit in MAC
*/
- writel(EMAC_MACCONTROL_GIGFORCE |
- EMAC_MACCONTROL_GIGABIT_ENABLE,
- &adap_emac->MACCONTROL);
+ writel(readl(&adap_emac->MACCONTROL) |
+ EMAC_MACCONTROL_GIGFORCE |
+ EMAC_MACCONTROL_GIGABIT_ENABLE,
+ &adap_emac->MACCONTROL);
}
}
}
@@ -666,6 +667,7 @@ int davinci_emac_initialize(void)
return -1;
memset(dev, 0, sizeof *dev);
+ sprintf(dev->name, "DaVinci-EMAC");
dev->iobase = 0;
dev->init = davinci_eth_open;
@@ -723,6 +725,13 @@ int davinci_emac_initialize(void)
phy.get_link_speed = dp83848_get_link_speed;
phy.auto_negotiate = dp83848_auto_negotiate;
break;
+ case PHY_ET1011C:
+ sprintf(phy.name, "ET1011C @ 0x%02x", active_phy_addr);
+ phy.init = gen_init_phy;
+ phy.is_phy_connected = gen_is_phy_connected;
+ phy.get_link_speed = et1011c_get_link_speed;
+ phy.auto_negotiate = gen_auto_negotiate;
+ break;
default:
sprintf(phy.name, "GENERIC @ 0x%02x", active_phy_addr);
phy.init = gen_init_phy;
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index c438962..4e4cd27 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -354,7 +354,7 @@ static int fec_open(struct eth_device *edev)
*/
writel(readl(&fec->eth->ecntrl) | FEC_ECNTRL_ETHER_EN,
&fec->eth->ecntrl);
-#ifdef CONFIG_MX25
+#if defined(CONFIG_MX25) || defined(CONFIG_MX53)
udelay(100);
/*
* setup the MII gasket for RMII mode
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
index 5d0d69d..1ba5161 100644
--- a/drivers/net/fec_mxc.h
+++ b/drivers/net/fec_mxc.h
@@ -147,7 +147,7 @@ struct ethernet_regs {
uint32_t res14[7]; /* MBAR_ETH + 0x2E4-2FC */
-#ifdef CONFIG_MX25
+#if defined(CONFIG_MX25) || defined(CONFIG_MX53)
uint16_t miigsk_cfgr; /* MBAR_ETH + 0x300 */
uint16_t res15[3]; /* MBAR_ETH + 0x302-306 */
uint16_t miigsk_enr; /* MBAR_ETH + 0x308 */
@@ -204,7 +204,7 @@ struct ethernet_regs {
#define FEC_ECNTRL_RESET 0x00000001 /* reset the FEC */
#define FEC_ECNTRL_ETHER_EN 0x00000002 /* enable the FEC */
-#ifdef CONFIG_MX25
+#if defined(CONFIG_MX25) || defined(CONFIG_MX53)
/* defines for MIIGSK */
/* RMII frequency control: 0=50MHz, 1=5MHz */
#define MIIGSK_CFGR_FRCONT (1 << 6)
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c
index f96b21f..b9cf9de 100644
--- a/drivers/serial/serial_mxc.c
+++ b/drivers/serial/serial_mxc.c
@@ -50,11 +50,14 @@
#define UART_PHYS 0x1001b000
#elif defined(CONFIG_SYS_MX27_UART6)
#define UART_PHYS 0x1001c000
-#elif defined(CONFIG_SYS_MX51_UART1)
+#elif defined(CONFIG_SYS_MX35_UART1) || defined(CONFIG_SYS_MX51_UART1) || \
+ defined(CONFIG_SYS_MX53_UART1)
#define UART_PHYS UART1_BASE_ADDR
-#elif defined(CONFIG_SYS_MX51_UART2)
+#elif defined(CONFIG_SYS_MX35_UART2) || defined(CONFIG_SYS_MX51_UART2) || \
+ defined(CONFIG_SYS_MX53_UART2)
#define UART_PHYS UART2_BASE_ADDR
-#elif defined(CONFIG_SYS_MX51_UART3)
+#elif defined(CONFIG_SYS_MX35_UART3) || defined(CONFIG_SYS_MX51_UART3) || \
+ defined(CONFIG_SYS_MX53_UART3)
#define UART_PHYS UART3_BASE_ADDR
#else
#error "define CONFIG_SYS_MXxx_UARTx to use the MXC UART driver"
diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c
index 9c1cbf4..f1ffa29 100644
--- a/drivers/serial/serial_s5p.c
+++ b/drivers/serial/serial_s5p.c
@@ -72,7 +72,7 @@ void serial_setbrg_dev(const int dev_index)
writel(val / 16 - 1, &uart->ubrdiv);
- if (use_divslot)
+ if (s5p_uart_divslot())
writew(udivslot[val % 16], &uart->rest.slot);
else
writeb(val % 16, &uart->rest.value);
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index d558137..6474eb8 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -36,16 +36,6 @@
#include <asm/arch/mx31.h>
-#define MXC_CSPIRXDATA 0x00
-#define MXC_CSPITXDATA 0x04
-#define MXC_CSPICTRL 0x08
-#define MXC_CSPIINT 0x0C
-#define MXC_CSPIDMA 0x10
-#define MXC_CSPISTAT 0x14
-#define MXC_CSPIPERIOD 0x18
-#define MXC_CSPITEST 0x1C
-#define MXC_CSPIRESET 0x00
-
#define MXC_CSPICTRL_EN (1 << 0)
#define MXC_CSPICTRL_MODE (1 << 1)
#define MXC_CSPICTRL_XCH (1 << 2)
@@ -70,19 +60,12 @@ static unsigned long spi_bases[] = {
0x53f84000,
};
+#define mxc_get_clock(x) mx31_get_ipg_clk()
+
#elif defined(CONFIG_MX51)
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
-#define MXC_CSPIRXDATA 0x00
-#define MXC_CSPITXDATA 0x04
-#define MXC_CSPICTRL 0x08
-#define MXC_CSPICON 0x0C
-#define MXC_CSPIINT 0x10
-#define MXC_CSPIDMA 0x14
-#define MXC_CSPISTAT 0x18
-#define MXC_CSPIPERIOD 0x1C
-#define MXC_CSPIRESET 0x00
#define MXC_CSPICTRL_EN (1 << 0)
#define MXC_CSPICTRL_MODE (1 << 1)
#define MXC_CSPICTRL_XCH (1 << 2)
@@ -111,12 +94,44 @@ static unsigned long spi_bases[] = {
CSPI2_BASE_ADDR,
CSPI3_BASE_ADDR,
};
+
+#elif defined(CONFIG_MX35)
+
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+
+#define MXC_CSPICTRL_EN (1 << 0)
+#define MXC_CSPICTRL_MODE (1 << 1)
+#define MXC_CSPICTRL_XCH (1 << 2)
+#define MXC_CSPICTRL_SMC (1 << 3)
+#define MXC_CSPICTRL_POL (1 << 4)
+#define MXC_CSPICTRL_PHA (1 << 5)
+#define MXC_CSPICTRL_SSCTL (1 << 6)
+#define MXC_CSPICTRL_SSPOL (1 << 7)
+#define MXC_CSPICTRL_CHIPSELECT(x) (((x) & 0x3) << 12)
+#define MXC_CSPICTRL_BITCOUNT(x) (((x) & 0xfff) << 20)
+#define MXC_CSPICTRL_DATARATE(x) (((x) & 0x7) << 16)
+#define MXC_CSPICTRL_TC (1 << 7)
+#define MXC_CSPICTRL_RXOVF (1 << 6)
+#define MXC_CSPICTRL_MAXBITS 0xfff
+
+#define MXC_CSPIPERIOD_32KHZ (1 << 15)
+#define MAX_SPI_BYTES 4
+
+static unsigned long spi_bases[] = {
+ 0x43fa4000,
+ 0x50010000,
+};
+
#else
#error "Unsupported architecture"
#endif
#define OUT MXC_GPIO_DIRECTION_OUT
+#define reg_read readl
+#define reg_write(a, v) writel(v, a)
+
struct mxc_spi_slave {
struct spi_slave slave;
unsigned long base;
@@ -133,16 +148,6 @@ static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave)
return container_of(slave, struct mxc_spi_slave, slave);
}
-static inline u32 reg_read(unsigned long addr)
-{
- return *(volatile unsigned long*)addr;
-}
-
-static inline void reg_write(unsigned long addr, u32 val)
-{
- *(volatile unsigned long*)addr = val;
-}
-
void spi_cs_activate(struct spi_slave *slave)
{
struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
@@ -158,24 +163,73 @@ void spi_cs_deactivate(struct spi_slave *slave)
!(mxcs->ss_pol));
}
-#ifdef CONFIG_MX51
-static s32 spi_cfg(struct mxc_spi_slave *mxcs, unsigned int cs,
+u32 get_cspi_div(u32 div)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ if (div <= (4 << i))
+ return i;
+ }
+ return i;
+}
+
+#if defined(CONFIG_MX31) || defined(CONFIG_MX35)
+static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ unsigned int ctrl_reg;
+ u32 clk_src;
+ u32 div;
+
+ clk_src = mxc_get_clock(MXC_CSPI_CLK);
+
+ div = clk_src / max_hz;
+ div = get_cspi_div(div);
+
+ debug("clk %d Hz, div %d, real clk %d Hz\n",
+ max_hz, div, clk_src / (4 << div));
+
+ ctrl_reg = MXC_CSPICTRL_CHIPSELECT(cs) |
+ MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS) |
+ MXC_CSPICTRL_DATARATE(div) |
+ MXC_CSPICTRL_EN |
+#ifdef CONFIG_MX35
+ MXC_CSPICTRL_SSCTL |
+#endif
+ MXC_CSPICTRL_MODE;
+
+ if (mode & SPI_CPHA)
+ ctrl_reg |= MXC_CSPICTRL_PHA;
+ if (mode & SPI_CPOL)
+ ctrl_reg |= MXC_CSPICTRL_POL;
+ if (mode & SPI_CS_HIGH)
+ ctrl_reg |= MXC_CSPICTRL_SSPOL;
+ mxcs->ctrl_reg = ctrl_reg;
+
+ return 0;
+}
+#endif
+
+#if defined(CONFIG_MX51)
+static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
unsigned int max_hz, unsigned int mode)
{
u32 clk_src = mxc_get_clock(MXC_CSPI_CLK);
s32 pre_div = 0, post_div = 0, i, reg_ctrl, reg_config;
u32 ss_pol = 0, sclkpol = 0, sclkpha = 0;
+ struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
if (max_hz == 0) {
printf("Error: desired clock is 0\n");
return -1;
}
- reg_ctrl = reg_read(mxcs->base + MXC_CSPICTRL);
+ reg_ctrl = reg_read(&regs->ctrl);
/* Reset spi */
- reg_write(mxcs->base + MXC_CSPICTRL, 0);
- reg_write(mxcs->base + MXC_CSPICTRL, (reg_ctrl | 0x1));
+ reg_write(&regs->ctrl, 0);
+ reg_write(&regs->ctrl, (reg_ctrl | 0x1));
/*
* The following computation is taken directly from Freescale's code.
@@ -223,11 +277,11 @@ static s32 spi_cfg(struct mxc_spi_slave *mxcs, unsigned int cs,
if (mode & SPI_CPHA)
sclkpha = 1;
- reg_config = reg_read(mxcs->base + MXC_CSPICON);
+ reg_config = reg_read(&regs->cfg);
/*
* Configuration register setup
- * The MX51 has support different setup for each SS
+ * The MX51 supports different setup for each SS
*/
reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_SSPOL))) |
(ss_pol << (cs + MXC_CSPICON_SSPOL));
@@ -237,18 +291,17 @@ static s32 spi_cfg(struct mxc_spi_slave *mxcs, unsigned int cs,
(sclkpha << (cs + MXC_CSPICON_PHA));
debug("reg_ctrl = 0x%x\n", reg_ctrl);
- reg_write(mxcs->base + MXC_CSPICTRL, reg_ctrl);
+ reg_write(&regs->ctrl, reg_ctrl);
debug("reg_config = 0x%x\n", reg_config);
- reg_write(mxcs->base + MXC_CSPICON, reg_config);
+ reg_write(&regs->cfg, reg_config);
/* save config register and control register */
mxcs->ctrl_reg = reg_ctrl;
mxcs->cfg_reg = reg_config;
/* clear interrupt reg */
- reg_write(mxcs->base + MXC_CSPIINT, 0);
- reg_write(mxcs->base + MXC_CSPISTAT,
- MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
+ reg_write(&regs->intr, 0);
+ reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
return 0;
}
@@ -260,6 +313,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
int nbytes = (bitlen + 7) / 8;
u32 data, cnt, i;
+ struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
debug("%s: bitlen %d dout 0x%x din 0x%x\n",
__func__, bitlen, (u32)dout, (u32)din);
@@ -268,14 +322,13 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
~MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS)) |
MXC_CSPICTRL_BITCOUNT(bitlen - 1);
- reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg | MXC_CSPICTRL_EN);
+ reg_write(&regs->ctrl, mxcs->ctrl_reg | MXC_CSPICTRL_EN);
#ifdef CONFIG_MX51
- reg_write(mxcs->base + MXC_CSPICON, mxcs->cfg_reg);
+ reg_write(&regs->cfg, mxcs->cfg_reg);
#endif
/* Clear interrupt register */
- reg_write(mxcs->base + MXC_CSPISTAT,
- MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
+ reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
/*
* The SPI controller works only with words,
@@ -292,7 +345,7 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
}
debug("Sending SPI 0x%x\n", data);
- reg_write(mxcs->base + MXC_CSPITXDATA, data);
+ reg_write(&regs->txdata, data);
nbytes -= cnt;
}
@@ -304,9 +357,8 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
/* Buffer is not 32-bit aligned */
if ((unsigned long)dout & 0x03) {
data = 0;
- for (i = 0; i < 4; i++, data <<= 8) {
+ for (i = 0; i < 4; i++)
data = (data << 8) | (*dout++ & 0xFF);
- }
} else {
data = *(u32 *)dout;
data = cpu_to_be32(data);
@@ -314,41 +366,40 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
dout += 4;
}
debug("Sending SPI 0x%x\n", data);
- reg_write(mxcs->base + MXC_CSPITXDATA, data);
+ reg_write(&regs->txdata, data);
nbytes -= 4;
}
/* FIFO is written, now starts the transfer setting the XCH bit */
- reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg |
+ reg_write(&regs->ctrl, mxcs->ctrl_reg |
MXC_CSPICTRL_EN | MXC_CSPICTRL_XCH);
/* Wait until the TC (Transfer completed) bit is set */
- while ((reg_read(mxcs->base + MXC_CSPISTAT) & MXC_CSPICTRL_TC) == 0)
+ while ((reg_read(&regs->stat) & MXC_CSPICTRL_TC) == 0)
;
/* Transfer completed, clear any pending request */
- reg_write(mxcs->base + MXC_CSPISTAT,
- MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
+ reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
nbytes = (bitlen + 7) / 8;
cnt = nbytes % 32;
if (bitlen % 32) {
- data = reg_read(mxcs->base + MXC_CSPIRXDATA);
+ data = reg_read(&regs->rxdata);
cnt = (bitlen % 32) / 8;
+ data = cpu_to_be32(data) >> ((sizeof(data) - cnt) * 8);
debug("SPI Rx unaligned: 0x%x\n", data);
if (din) {
- for (i = 0; i < cnt; i++, data >>= 8) {
- *din++ = data & 0xFF;
- }
+ memcpy(din, &data, cnt);
+ din += cnt;
}
nbytes -= cnt;
}
while (nbytes > 0) {
u32 tmp;
- tmp = reg_read(mxcs->base + MXC_CSPIRXDATA);
+ tmp = reg_read(&regs->rxdata);
data = cpu_to_be32(tmp);
debug("SPI Rx: 0x%x 0x%x\n", tmp, data);
cnt = min(nbytes, sizeof(data));
@@ -363,7 +414,6 @@ int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
}
-
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
void *din, unsigned long flags)
{
@@ -381,7 +431,6 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
spi_cs_activate(slave);
while (n_bytes > 0) {
-
if (n_bytes < MAX_SPI_BYTES)
blk_size = n_bytes;
else
@@ -441,7 +490,6 @@ static int decode_cs(struct mxc_spi_slave *mxcs, unsigned int cs)
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
unsigned int max_hz, unsigned int mode)
{
- unsigned int ctrl_reg;
struct mxc_spi_slave *mxcs;
int ret;
@@ -467,30 +515,12 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
mxcs->base = spi_bases[bus];
mxcs->ss_pol = (mode & SPI_CS_HIGH) ? 1 : 0;
-#ifdef CONFIG_MX51
- /* Can be used for i.MX31 too ? */
- ctrl_reg = 0;
- ret = spi_cfg(mxcs, cs, max_hz, mode);
+ ret = spi_cfg_mxc(mxcs, cs, max_hz, mode);
if (ret) {
printf("mxc_spi: cannot setup SPI controller\n");
free(mxcs);
return NULL;
}
-#else
- ctrl_reg = MXC_CSPICTRL_CHIPSELECT(cs) |
- MXC_CSPICTRL_BITCOUNT(31) |
- MXC_CSPICTRL_DATARATE(7) | /* FIXME: calculate data rate */
- MXC_CSPICTRL_EN |
- MXC_CSPICTRL_MODE;
-
- if (mode & SPI_CPHA)
- ctrl_reg |= MXC_CSPICTRL_PHA;
- if (mode & SPI_CPOL)
- ctrl_reg |= MXC_CSPICTRL_POL;
- if (mode & SPI_CS_HIGH)
- ctrl_reg |= MXC_CSPICTRL_SSPOL;
- mxcs->ctrl_reg = ctrl_reg;
-#endif
return &mxcs->slave;
}
@@ -504,13 +534,13 @@ void spi_free_slave(struct spi_slave *slave)
int spi_claim_bus(struct spi_slave *slave)
{
struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+ struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
- reg_write(mxcs->base + MXC_CSPIRESET, 1);
+ reg_write(&regs->rxdata, 1);
udelay(1);
- reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg);
- reg_write(mxcs->base + MXC_CSPIPERIOD,
- MXC_CSPIPERIOD_32KHZ);
- reg_write(mxcs->base + MXC_CSPIINT, 0);
+ reg_write(&regs->ctrl, mxcs->ctrl_reg);
+ reg_write(&regs->period, MXC_CSPIPERIOD_32KHZ);
+ reg_write(&regs->intr, 0);
return 0;
}