summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/sh_i2c.c139
-rw-r--r--drivers/input/i8042.c90
-rw-r--r--drivers/input/input.c102
-rw-r--r--drivers/mmc/Makefile2
-rw-r--r--drivers/mmc/dw_mmc.c385
-rw-r--r--drivers/mmc/mmc.c92
-rw-r--r--drivers/mmc/mmc_spi.c4
-rw-r--r--drivers/mmc/mxsmmc.c36
-rw-r--r--drivers/mmc/pxa_mmc.c643
-rw-r--r--drivers/mmc/s5p_sdhci.c3
-rw-r--r--drivers/mmc/sdhci.c12
-rw-r--r--drivers/net/fm/Makefile6
-rw-r--r--drivers/net/fm/eth.c39
-rw-r--r--drivers/net/fm/init.c18
-rw-r--r--drivers/net/fm/memac.c132
-rw-r--r--drivers/net/fm/memac_phy.c150
-rw-r--r--drivers/net/fm/t4240.c128
-rw-r--r--drivers/net/mcfmii.c4
-rw-r--r--drivers/pci/fsl_pci_init.c65
-rw-r--r--drivers/qe/qe.c21
-rw-r--r--drivers/serial/altera_jtag_uart.c8
-rw-r--r--drivers/serial/altera_uart.c9
-rw-r--r--drivers/serial/atmel_usart.c8
-rw-r--r--drivers/serial/lpc32xx_hsuart.c8
-rw-r--r--drivers/serial/mcfuart.c11
-rw-r--r--drivers/serial/ns9750_serial.c15
-rw-r--r--drivers/serial/opencores_yanu.c10
-rw-r--r--drivers/serial/s3c4510b_uart.c6
-rw-r--r--drivers/serial/s3c64xx.c8
-rw-r--r--drivers/serial/serial.c204
-rw-r--r--drivers/serial/serial_clps7111.c9
-rw-r--r--drivers/serial/serial_imx.c9
-rw-r--r--drivers/serial/serial_ixp.c9
-rw-r--r--drivers/serial/serial_ks8695.c9
-rw-r--r--drivers/serial/serial_lpc2292.c9
-rw-r--r--drivers/serial/serial_mxc.c9
-rw-r--r--drivers/serial/serial_netarm.c9
-rw-r--r--drivers/serial/serial_pl01x.c9
-rw-r--r--drivers/serial/serial_s3c44b0.c9
-rw-r--r--drivers/serial/serial_sa1100.c9
-rw-r--r--drivers/serial/serial_sh.c9
-rw-r--r--drivers/spi/fsl_espi.c6
-rw-r--r--drivers/usb/host/ehci-fsl.c22
43 files changed, 1452 insertions, 1033 deletions
diff --git a/drivers/i2c/sh_i2c.c b/drivers/i2c/sh_i2c.c
index 3147123bba..44ba90ef57 100644
--- a/drivers/i2c/sh_i2c.c
+++ b/drivers/i2c/sh_i2c.c
@@ -43,12 +43,18 @@ static struct sh_i2c *base;
#define SH_I2C_ICCR_SCP (1 << 0)
/* ICSR / ICIC */
-#define SH_IC_BUSY (1 << 3)
+#define SH_IC_BUSY (1 << 4)
#define SH_IC_TACK (1 << 2)
#define SH_IC_WAIT (1 << 1)
#define SH_IC_DTE (1 << 0)
-static u8 iccl, icch;
+#ifdef CONFIG_SH_I2C_8BIT
+/* store 8th bit of iccl and icch in ICIC register */
+#define SH_I2C_ICIC_ICCLB8 (1 << 7)
+#define SH_I2C_ICIC_ICCHB8 (1 << 6)
+#endif
+
+static u16 iccl, icch;
#define IRQ_WAIT 1000
@@ -63,6 +69,20 @@ static void irq_dte(struct sh_i2c *base)
}
}
+static int irq_dte_with_tack(struct sh_i2c *base)
+{
+ int i;
+
+ for (i = 0 ; i < IRQ_WAIT ; i++) {
+ if (SH_IC_DTE & readb(&base->icsr))
+ break;
+ if (SH_IC_TACK & readb(&base->icsr))
+ return -1;
+ udelay(10);
+ }
+ return 0;
+}
+
static void irq_busy(struct sh_i2c *base)
{
int i;
@@ -74,71 +94,97 @@ static void irq_busy(struct sh_i2c *base)
}
}
-static void i2c_set_addr(struct sh_i2c *base, u8 id, u8 reg, int stop)
+static int i2c_set_addr(struct sh_i2c *base, u8 id, u8 reg, int stop)
{
- writeb(readb(&base->iccr) & ~SH_I2C_ICCR_ICE, &base->iccr);
- writeb(readb(&base->iccr) | SH_I2C_ICCR_ICE, &base->iccr);
-
- writeb(iccl, &base->iccl);
- writeb(icch, &base->icch);
- writeb(0, &base->icic);
+ u8 icic = SH_IC_TACK;
+
+ clrbits_8(&base->iccr, SH_I2C_ICCR_ICE);
+ setbits_8(&base->iccr, SH_I2C_ICCR_ICE);
+
+ writeb(iccl & 0xff, &base->iccl);
+ writeb(icch & 0xff, &base->icch);
+#ifdef CONFIG_SH_I2C_8BIT
+ if (iccl > 0xff)
+ icic |= SH_I2C_ICIC_ICCLB8;
+ if (icch > 0xff)
+ icic |= SH_I2C_ICIC_ICCHB8;
+#endif
+ writeb(icic, &base->icic);
writeb((SH_I2C_ICCR_ICE|SH_I2C_ICCR_RTS|SH_I2C_ICCR_BUSY), &base->iccr);
irq_dte(base);
+ clrbits_8(&base->icsr, SH_IC_TACK);
writeb(id << 1, &base->icdr);
- irq_dte(base);
+ if (irq_dte_with_tack(base) != 0)
+ return -1;
writeb(reg, &base->icdr);
if (stop)
writeb((SH_I2C_ICCR_ICE|SH_I2C_ICCR_RTS), &base->iccr);
- irq_dte(base);
+ if (irq_dte_with_tack(base) != 0)
+ return -1;
+ return 0;
}
static void i2c_finish(struct sh_i2c *base)
{
writeb(0, &base->icsr);
- writeb(readb(&base->iccr) & ~SH_I2C_ICCR_ICE, &base->iccr);
+ clrbits_8(&base->iccr, SH_I2C_ICCR_ICE);
}
-static void i2c_raw_write(struct sh_i2c *base, u8 id, u8 reg, u8 val)
+static int i2c_raw_write(struct sh_i2c *base, u8 id, u8 reg, u8 val)
{
- i2c_set_addr(base, id, reg, 0);
+ int ret = -1;
+ if (i2c_set_addr(base, id, reg, 0) != 0)
+ goto exit0;
udelay(10);
writeb(val, &base->icdr);
- irq_dte(base);
+ if (irq_dte_with_tack(base) != 0)
+ goto exit0;
writeb((SH_I2C_ICCR_ICE | SH_I2C_ICCR_RTS), &base->iccr);
- irq_dte(base);
+ if (irq_dte_with_tack(base) != 0)
+ goto exit0;
irq_busy(base);
-
+ ret = 0;
+exit0:
i2c_finish(base);
+ return ret;
}
-static u8 i2c_raw_read(struct sh_i2c *base, u8 id, u8 reg)
+static int i2c_raw_read(struct sh_i2c *base, u8 id, u8 reg)
{
- u8 ret;
-
- i2c_set_addr(base, id, reg, 1);
+ int ret = -1;
+
+#if defined(CONFIG_SH73A0)
+ if (i2c_set_addr(base, id, reg, 0) != 0)
+ goto exit0;
+#else
+ if (i2c_set_addr(base, id, reg, 1) != 0)
+ goto exit0;
udelay(100);
+#endif
writeb((SH_I2C_ICCR_ICE|SH_I2C_ICCR_RTS|SH_I2C_ICCR_BUSY), &base->iccr);
irq_dte(base);
writeb(id << 1 | 0x01, &base->icdr);
- irq_dte(base);
+ if (irq_dte_with_tack(base) != 0)
+ goto exit0;
writeb((SH_I2C_ICCR_ICE|SH_I2C_ICCR_SCP), &base->iccr);
- irq_dte(base);
+ if (irq_dte_with_tack(base) != 0)
+ goto exit0;
- ret = readb(&base->icdr);
+ ret = readb(&base->icdr) & 0xff;
writeb((SH_I2C_ICCR_ICE|SH_I2C_ICCR_RACK), &base->iccr);
readb(&base->icdr); /* Dummy read */
irq_busy(base);
-
+exit0:
i2c_finish(base);
return ret;
@@ -166,6 +212,21 @@ int i2c_set_bus_num(unsigned int bus)
case 1:
base = (void *)CONFIG_SH_I2C_BASE1;
break;
+#ifdef CONFIG_SH_I2C_BASE2
+ case 2:
+ base = (void *)CONFIG_SH_I2C_BASE2;
+ break;
+#endif
+#ifdef CONFIG_SH_I2C_BASE3
+ case 3:
+ base = (void *)CONFIG_SH_I2C_BASE3;
+ break;
+#endif
+#ifdef CONFIG_SH_I2C_BASE4
+ case 4:
+ base = (void *)CONFIG_SH_I2C_BASE4;
+ break;
+#endif
default:
return -1;
}
@@ -206,18 +267,18 @@ void i2c_init(int speed, int slaveaddr)
denom = speed * (CONFIG_SH_I2C_DATA_HIGH + CONFIG_SH_I2C_DATA_LOW);
tmp = num * 10 / denom;
if (tmp % 10 >= 5)
- iccl = (u8)((num/denom) + 1);
+ iccl = (u16)((num/denom) + 1);
else
- iccl = (u8)(num/denom);
+ iccl = (u16)(num/denom);
/* Calculate the value for icch. From the data sheet:
icch = (p clock / transfer rate) * (H / (L + H)) */
num = CONFIG_SH_I2C_CLOCK * CONFIG_SH_I2C_DATA_HIGH;
tmp = num * 10 / denom;
if (tmp % 10 >= 5)
- icch = (u8)((num/denom) + 1);
+ icch = (u16)((num/denom) + 1);
else
- icch = (u8)(num/denom);
+ icch = (u16)(num/denom);
}
/*
@@ -235,10 +296,14 @@ void i2c_init(int speed, int slaveaddr)
*/
int i2c_read(u8 chip, u32 addr, int alen, u8 *buffer, int len)
{
+ int ret;
int i = 0;
- for (i = 0 ; i < len ; i++)
- buffer[i] = i2c_raw_read(base, chip, addr + i);
-
+ for (i = 0 ; i < len ; i++) {
+ ret = i2c_raw_read(base, chip, addr + i);
+ if (ret < 0)
+ return -1;
+ buffer[i] = ret & 0xff;
+ }
return 0;
}
@@ -259,8 +324,8 @@ int i2c_write(u8 chip, u32 addr, int alen, u8 *buffer, int len)
{
int i = 0;
for (i = 0; i < len ; i++)
- i2c_raw_write(base, chip, addr + i, buffer[i]);
-
+ if (i2c_raw_write(base, chip, addr + i, buffer[i]) != 0)
+ return -1;
return 0;
}
@@ -272,5 +337,9 @@ int i2c_write(u8 chip, u32 addr, int alen, u8 *buffer, int len)
*/
int i2c_probe(u8 chip)
{
- return 0;
+ int ret;
+
+ ret = i2c_set_addr(base, chip, 0, 1);
+ i2c_finish(base);
+ return ret;
}
diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c
index c3bc5360ca..26958aaa3e 100644
--- a/drivers/input/i8042.c
+++ b/drivers/input/i8042.c
@@ -26,6 +26,7 @@
/* includes */
#include <common.h>
+#include <linux/compiler.h>
#ifdef CONFIG_USE_CPCIDVI
extern u8 gt_cpcidvi_in8(u32 offset);
@@ -320,6 +321,54 @@ static int kbd_controller_present(void)
return in8(I8042_STATUS_REG) != 0xff;
}
+/*
+ * Implement a weak default function for boards that optionally
+ * need to skip the i8042 initialization.
+ */
+int __weak board_i8042_skip(void)
+{
+ /* As default, don't skip */
+ return 0;
+}
+
+void i8042_flush(void)
+{
+ int timeout;
+
+ /*
+ * The delay is to give the keyboard controller some time to fill the
+ * next byte.
+ */
+ while (1) {
+ timeout = 100; /* wait for no longer than 100us */
+ while (timeout > 0 && !(in8(I8042_STATUS_REG) & 0x01)) {
+ udelay(1);
+ timeout--;
+ }
+
+ /* Try to pull next byte if not timeout. */
+ if (in8(I8042_STATUS_REG) & 0x01)
+ in8(I8042_DATA_REG);
+ else
+ break;
+ }
+}
+
+int i8042_disable(void)
+{
+ if (kbd_input_empty() == 0)
+ return -1;
+
+ /* Disable keyboard */
+ out8(I8042_COMMAND_REG, 0xad);
+
+ if (kbd_input_empty() == 0)
+ return -1;
+
+ return 0;
+}
+
+
/*******************************************************************************
*
* i8042_kbd_init - reset keyboard and init state flags
@@ -329,7 +378,7 @@ int i8042_kbd_init(void)
int keymap, try;
char *penv;
- if (!kbd_controller_present())
+ if (!kbd_controller_present() || board_i8042_skip())
return -1;
#ifdef CONFIG_USE_CPCIDVI
@@ -607,11 +656,22 @@ static void kbd_led_set(void)
static int kbd_input_empty(void)
{
- int kbdTimeout = KBD_TIMEOUT;
+ int kbdTimeout = KBD_TIMEOUT * 1000;
+
+ while ((in8(I8042_STATUS_REG) & I8042_STATUS_IN_DATA) && kbdTimeout--)
+ udelay(1);
+
+ return kbdTimeout != -1;
+}
+
+/******************************************************************************/
+
+static int wait_until_kbd_output_full(void)
+{
+ int kbdTimeout = KBD_TIMEOUT * 1000;
- /* wait for input buf empty */
- while ((in8(I8042_STATUS_REG) & 0x02) && kbdTimeout--)
- udelay(1000);
+ while (((in8(I8042_STATUS_REG) & 0x01) == 0) && kbdTimeout--)
+ udelay(1);
return kbdTimeout != -1;
}
@@ -620,31 +680,39 @@ static int kbd_input_empty(void)
static int kbd_reset(void)
{
+ /* KB Reset */
if (kbd_input_empty() == 0)
return -1;
out8(I8042_DATA_REG, 0xff);
- udelay(250000);
+ if (wait_until_kbd_output_full() == 0)
+ return -1;
+
+ if (in8(I8042_DATA_REG) != 0xfa) /* ACK */
+ return -1;
+
+ if (wait_until_kbd_output_full() == 0)
+ return -1;
+
+ if (in8(I8042_DATA_REG) != 0xaa) /* Test Pass*/
+ return -1;
if (kbd_input_empty() == 0)
return -1;
-#ifdef CONFIG_USE_CPCIDVI
+ /* Set KBC mode */
out8(I8042_COMMAND_REG, 0x60);
-#else
- out8(I8042_DATA_REG, 0x60);
-#endif
if (kbd_input_empty() == 0)
return -1;
out8(I8042_DATA_REG, 0x45);
-
if (kbd_input_empty() == 0)
return -1;
+ /* Enable Keyboard */
out8(I8042_COMMAND_REG, 0xae);
if (kbd_input_empty() == 0)
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 5b2b4b0714..98006679b3 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -93,6 +93,22 @@ static unsigned char kbd_ctrl_xlate[] = {
'\r', 0xff, 0xff
};
+/*
+ * Scan key code to ANSI 3.64 escape sequence table. This table is
+ * incomplete in that it does not include all possible extra keys.
+ */
+static struct {
+ int kbd_scan_code;
+ char *escape;
+} kbd_to_ansi364[] = {
+ { KEY_UP, "\033[A"},
+ { KEY_DOWN, "\033[B"},
+ { KEY_RIGHT, "\033[C"},
+ { KEY_LEFT, "\033[D"},
+};
+
+/* Maximum number of output characters that an ANSI sequence expands to */
+#define ANSI_CHAR_MAX 3
int input_queue_ascii(struct input_config *config, int ch)
{
@@ -289,24 +305,67 @@ static int input_check_keycodes(struct input_config *config,
}
/**
+ * Checks and converts a special key code into ANSI 3.64 escape sequence.
+ *
+ * @param config Input state
+ * @param keycode Key code to examine
+ * @param output_ch Buffer to place output characters into. It should
+ * be at least ANSI_CHAR_MAX bytes long, to allow for
+ * an ANSI sequence.
+ * @param max_chars Maximum number of characters to add to output_ch
+ * @return number of characters output, if the key was converted, otherwise 0.
+ * This may be larger than max_chars, in which case the overflow
+ * characters are not output.
+ */
+static int input_keycode_to_ansi364(struct input_config *config,
+ int keycode, char output_ch[], int max_chars)
+{
+ const char *escape;
+ int ch_count;
+ int i;
+
+ for (i = ch_count = 0; i < ARRAY_SIZE(kbd_to_ansi364); i++) {
+ if (keycode != kbd_to_ansi364[i].kbd_scan_code)
+ continue;
+ for (escape = kbd_to_ansi364[i].escape; *escape; escape++) {
+ if (ch_count < max_chars)
+ output_ch[ch_count] = *escape;
+ ch_count++;
+ }
+ return ch_count;
+ }
+
+ return 0;
+}
+
+/**
+ * Converts and queues a list of key codes in escaped ASCII string form
* Convert a list of key codes into ASCII
*
* You must call input_check_keycodes() before this. It turns the keycode
- * list into a list of ASCII characters which are ready to send to the
- * input layer.
+ * list into a list of ASCII characters and sends them to the input layer.
*
* Characters which were seen last time do not generate fresh ASCII output.
+ * The output (calls to queue_ascii) may be longer than num_keycodes, if the
+ * keycode contains special keys that was encoded to longer escaped sequence.
*
* @param config Input state
* @param keycode List of key codes to examine
* @param num_keycodes Number of key codes
+ * @param output_ch Buffer to place output characters into. It should
+ * be at last ANSI_CHAR_MAX * num_keycodes, to allow for
+ * ANSI sequences.
+ * @param max_chars Maximum number of characters to add to output_ch
* @param same Number of key codes which are the same
+ * @return number of characters written into output_ch, or -1 if we would
+ * exceed max_chars chars.
*/
static int input_keycodes_to_ascii(struct input_config *config,
- int keycode[], int num_keycodes, char output_ch[], int same)
+ int keycode[], int num_keycodes, char output_ch[],
+ int max_chars, int same)
{
struct input_key_xlate *table;
- int ch_count;
+ int ch_count = 0;
int i;
table = &config->table[0];
@@ -321,19 +380,31 @@ static int input_keycodes_to_ascii(struct input_config *config,
}
}
- /* now find normal keys */
- for (i = ch_count = 0; i < num_keycodes; i++) {
+ /* Start conversion by looking for the first new keycode (by same). */
+ for (i = same; i < num_keycodes; i++) {
int key = keycode[i];
+ int ch = (key < table->num_entries) ? table->xlate[key] : 0xff;
- if (key < table->num_entries && i >= same) {
- int ch = table->xlate[key];
-
- /* If a normal key with an ASCII value, add it! */
- if (ch != 0xff)
- output_ch[ch_count++] = (uchar)ch;
+ /*
+ * For a normal key (with an ASCII value), add it; otherwise
+ * translate special key to escape sequence if possible.
+ */
+ if (ch != 0xff) {
+ if (ch_count < max_chars)
+ output_ch[ch_count] = (uchar)ch;
+ ch_count++;
+ } else {
+ ch_count += input_keycode_to_ansi364(config, key,
+ output_ch, max_chars);
}
}
+ if (ch_count > max_chars) {
+ debug("%s: Output char buffer overflow size=%d, need=%d\n",
+ __func__, max_chars, ch_count);
+ return -1;
+ }
+
/* ok, so return keys */
return ch_count;
}
@@ -341,7 +412,7 @@ static int input_keycodes_to_ascii(struct input_config *config,
int input_send_keycodes(struct input_config *config,
int keycode[], int num_keycodes)
{
- char ch[num_keycodes];
+ char ch[num_keycodes * ANSI_CHAR_MAX];
int count, i, same = 0;
int is_repeat = 0;
unsigned delay_ms;
@@ -363,7 +434,7 @@ int input_send_keycodes(struct input_config *config,
}
count = input_keycodes_to_ascii(config, keycode, num_keycodes,
- ch, is_repeat ? 0 : same);
+ ch, sizeof(ch), is_repeat ? 0 : same);
for (i = 0; i < count; i++)
input_queue_ascii(config, ch[i]);
delay_ms = is_repeat ?
@@ -371,7 +442,8 @@ int input_send_keycodes(struct input_config *config,
config->repeat_delay_ms;
config->next_repeat_ms = get_timer(0) + delay_ms;
- return 0;
+
+ return count;
}
int input_add_table(struct input_config *config, int left_keycode,
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 565ba6a383..a1dd7302bf 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -41,12 +41,12 @@ 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
COBJS-$(CONFIG_SDHCI) += sdhci.o
COBJS-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
COBJS-$(CONFIG_SH_MMCIF) += sh_mmcif.o
COBJS-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
+COBJS-$(CONFIG_DWMMC) += dw_mmc.o
COBJS := $(COBJS-y)
SRCS := $(COBJS:.o=.c)
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
new file mode 100644
index 0000000000..4070d4ea53
--- /dev/null
+++ b/drivers/mmc/dw_mmc.c
@@ -0,0 +1,385 @@
+/*
+ * (C) Copyright 2012 SAMSUNG Electronics
+ * Jaehoon Chung <jh80.chung@samsung.com>
+ * Rajeshawari Shinde <rajeshwari.s@samsung.com>
+ *
+ * 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 <dwmmc.h>
+#include <asm/arch/clk.h>
+#include <asm-generic/errno.h>
+
+#define PAGE_SIZE 4096
+
+static int dwmci_wait_reset(struct dwmci_host *host, u32 value)
+{
+ unsigned long timeout = 1000;
+ u32 ctrl;
+
+ dwmci_writel(host, DWMCI_CTRL, value);
+
+ while (timeout--) {
+ ctrl = dwmci_readl(host, DWMCI_CTRL);
+ if (!(ctrl & DWMCI_RESET_ALL))
+ return 1;
+ }
+ return 0;
+}
+
+static void dwmci_set_idma_desc(struct dwmci_idmac *idmac,
+ u32 desc0, u32 desc1, u32 desc2)
+{
+ struct dwmci_idmac *desc = idmac;
+
+ desc->flags = desc0;
+ desc->cnt = desc1;
+ desc->addr = desc2;
+ desc->next_addr = (unsigned int)desc + sizeof(struct dwmci_idmac);
+}
+
+static void dwmci_prepare_data(struct dwmci_host *host,
+ struct mmc_data *data)
+{
+ unsigned long ctrl;
+ unsigned int i = 0, flags, cnt, blk_cnt;
+ ulong data_start, data_end, start_addr;
+ ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, data->blocks);
+
+
+ blk_cnt = data->blocks;
+
+ dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET);
+
+ data_start = (ulong)cur_idmac;
+ dwmci_writel(host, DWMCI_DBADDR, (unsigned int)cur_idmac);
+
+ if (data->flags == MMC_DATA_READ)
+ start_addr = (unsigned int)data->dest;
+ else
+ start_addr = (unsigned int)data->src;
+
+ do {
+ flags = DWMCI_IDMAC_OWN | DWMCI_IDMAC_CH ;
+ flags |= (i == 0) ? DWMCI_IDMAC_FS : 0;
+ if (blk_cnt <= 8) {
+ flags |= DWMCI_IDMAC_LD;
+ cnt = data->blocksize * blk_cnt;
+ } else
+ cnt = data->blocksize * 8;
+
+ dwmci_set_idma_desc(cur_idmac, flags, cnt,
+ start_addr + (i * PAGE_SIZE));
+
+ if(blk_cnt < 8)
+ break;
+ blk_cnt -= 8;
+ cur_idmac++;
+ i++;
+ } while(1);
+
+ data_end = (ulong)cur_idmac;
+ flush_dcache_range(data_start, data_end + ARCH_DMA_MINALIGN);
+
+ ctrl = dwmci_readl(host, DWMCI_CTRL);
+ ctrl |= DWMCI_IDMAC_EN | DWMCI_DMA_EN;
+ dwmci_writel(host, DWMCI_CTRL, ctrl);
+
+ ctrl = dwmci_readl(host, DWMCI_BMOD);
+ ctrl |= DWMCI_BMOD_IDMAC_FB | DWMCI_BMOD_IDMAC_EN;
+ dwmci_writel(host, DWMCI_BMOD, ctrl);
+
+ dwmci_writel(host, DWMCI_BLKSIZ, data->blocksize);
+ dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks);
+}
+
+static int dwmci_set_transfer_mode(struct dwmci_host *host,
+ struct mmc_data *data)
+{
+ unsigned long mode;
+
+ mode = DWMCI_CMD_DATA_EXP;
+ if (data->flags & MMC_DATA_WRITE)
+ mode |= DWMCI_CMD_RW;
+
+ return mode;
+}
+
+static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
+ int flags = 0, i;
+ unsigned int timeout = 100000;
+ u32 retry = 10000;
+ u32 mask, ctrl;
+
+ while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
+ if (timeout == 0) {
+ printf("Timeout on data busy\n");
+ return TIMEOUT;
+ }
+ timeout--;
+ }
+
+ dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
+
+ if (data)
+ dwmci_prepare_data(host, data);
+
+
+ dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
+
+ if (data)
+ flags = dwmci_set_transfer_mode(host, data);
+
+ if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY))
+ return -1;
+
+ if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+ flags |= DWMCI_CMD_ABORT_STOP;
+ else
+ flags |= DWMCI_CMD_PRV_DAT_WAIT;
+
+ if (cmd->resp_type & MMC_RSP_PRESENT) {
+ flags |= DWMCI_CMD_RESP_EXP;
+ if (cmd->resp_type & MMC_RSP_136)
+ flags |= DWMCI_CMD_RESP_LENGTH;
+ }
+
+ if (cmd->resp_type & MMC_RSP_CRC)
+ flags |= DWMCI_CMD_CHECK_CRC;
+
+ flags |= (cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG);
+
+ debug("Sending CMD%d\n",cmd->cmdidx);
+
+ dwmci_writel(host, DWMCI_CMD, flags);
+
+ for (i = 0; i < retry; i++) {
+ mask = dwmci_readl(host, DWMCI_RINTSTS);
+ if (mask & DWMCI_INTMSK_CDONE) {
+ if (!data)
+ dwmci_writel(host, DWMCI_RINTSTS, mask);
+ break;
+ }
+ }
+
+ if (i == retry)
+ return TIMEOUT;
+
+ if (mask & DWMCI_INTMSK_RTO) {
+ debug("Response Timeout..\n");
+ return TIMEOUT;
+ } else if (mask & DWMCI_INTMSK_RE) {
+ debug("Response Error..\n");
+ return -1;
+ }
+
+
+ if (cmd->resp_type & MMC_RSP_PRESENT) {
+ if (cmd->resp_type & MMC_RSP_136) {
+ cmd->response[0] = dwmci_readl(host, DWMCI_RESP3);
+ cmd->response[1] = dwmci_readl(host, DWMCI_RESP2);
+ cmd->response[2] = dwmci_readl(host, DWMCI_RESP1);
+ cmd->response[3] = dwmci_readl(host, DWMCI_RESP0);
+ } else {
+ cmd->response[0] = dwmci_readl(host, DWMCI_RESP0);
+ }
+ }
+
+ if (data) {
+ do {
+ mask = dwmci_readl(host, DWMCI_RINTSTS);
+ if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) {
+ debug("DATA ERROR!\n");
+ return -1;
+ }
+ } while (!(mask & DWMCI_INTMSK_DTO));
+
+ dwmci_writel(host, DWMCI_RINTSTS, mask);
+
+ ctrl = dwmci_readl(host, DWMCI_CTRL);
+ ctrl &= ~(DWMCI_DMA_EN);
+ dwmci_writel(host, DWMCI_CTRL, ctrl);
+ }
+
+ udelay(100);
+
+ return 0;
+}
+
+static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
+{
+ u32 div, status;
+ int timeout = 10000;
+ unsigned long sclk;
+
+ if (freq == host->clock)
+ return 0;
+
+ /*
+ * If host->mmc_clk didn't define,
+ * then assume that host->bus_hz is source clock value.
+ * host->bus_hz should be set from user.
+ */
+ if (host->mmc_clk)
+ sclk = host->mmc_clk(host->dev_index);
+ else if (host->bus_hz)
+ sclk = host->bus_hz;
+ else {
+ printf("Didn't get source clock value..\n");
+ return -EINVAL;
+ }
+
+ div = DIV_ROUND_UP(sclk, 2 * freq);
+
+ dwmci_writel(host, DWMCI_CLKENA, 0);
+ dwmci_writel(host, DWMCI_CLKSRC, 0);
+
+ dwmci_writel(host, DWMCI_CLKDIV, div);
+ dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT |
+ DWMCI_CMD_UPD_CLK | DWMCI_CMD_START);
+
+ do {
+ status = dwmci_readl(host, DWMCI_CMD);
+ if (timeout-- < 0) {
+ printf("TIMEOUT error!!\n");
+ return -ETIMEDOUT;
+ }
+ } while (status & DWMCI_CMD_START);
+
+ dwmci_writel(host, DWMCI_CLKENA, DWMCI_CLKEN_ENABLE |
+ DWMCI_CLKEN_LOW_PWR);
+
+ dwmci_writel(host, DWMCI_CMD, DWMCI_CMD_PRV_DAT_WAIT |
+ DWMCI_CMD_UPD_CLK | DWMCI_CMD_START);
+
+ timeout = 10000;
+ do {
+ status = dwmci_readl(host, DWMCI_CMD);
+ if (timeout-- < 0) {
+ printf("TIMEOUT error!!\n");
+ return -ETIMEDOUT;
+ }
+ } while (status & DWMCI_CMD_START);
+
+ host->clock = freq;
+
+ return 0;
+}
+
+static void dwmci_set_ios(struct mmc *mmc)
+{
+ struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
+ u32 ctype;
+
+ debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock);
+
+ dwmci_setup_bus(host, mmc->clock);
+ switch (mmc->bus_width) {
+ case 8:
+ ctype = DWMCI_CTYPE_8BIT;
+ break;
+ case 4:
+ ctype = DWMCI_CTYPE_4BIT;
+ break;
+ default:
+ ctype = DWMCI_CTYPE_1BIT;
+ break;
+ }
+
+ dwmci_writel(host, DWMCI_CTYPE, ctype);
+
+ if (host->clksel)
+ host->clksel(host);
+}
+
+static int dwmci_init(struct mmc *mmc)
+{
+ struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
+ u32 fifo_size, fifoth_val;
+
+ dwmci_writel(host, DWMCI_PWREN, 1);
+
+ if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) {
+ debug("%s[%d] Fail-reset!!\n",__func__,__LINE__);
+ return -1;
+ }
+
+ dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
+ dwmci_writel(host, DWMCI_INTMASK, 0);
+
+ dwmci_writel(host, DWMCI_TMOUT, 0xFFFFFFFF);
+
+ dwmci_writel(host, DWMCI_IDINTEN, 0);
+ dwmci_writel(host, DWMCI_BMOD, 1);
+
+ fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+ if (host->fifoth_val)
+ fifoth_val = host->fifoth_val;
+ else
+ fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
+ TX_WMARK(fifo_size/2);
+ dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);
+
+ dwmci_writel(host, DWMCI_CLKENA, 0);
+ dwmci_writel(host, DWMCI_CLKSRC, 0);
+
+ return 0;
+}
+
+int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk)
+{
+ struct mmc *mmc;
+ int err = 0;
+
+ mmc = malloc(sizeof(struct mmc));
+ if (!mmc) {
+ printf("mmc malloc fail!\n");
+ return -1;
+ }
+
+ mmc->priv = host;
+ host->mmc = mmc;
+
+ sprintf(mmc->name, "%s", host->name);
+ mmc->send_cmd = dwmci_send_cmd;
+ mmc->set_ios = dwmci_set_ios;
+ mmc->init = dwmci_init;
+ mmc->f_min = min_clk;
+ mmc->f_max = max_clk;
+
+ mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
+
+ mmc->host_caps = host->caps;
+
+ if (host->buswidth == 8) {
+ mmc->host_caps |= MMC_MODE_8BIT;
+ mmc->host_caps &= ~MMC_MODE_4BIT;
+ } else {
+ mmc->host_caps |= MMC_MODE_4BIT;
+ mmc->host_caps &= ~MMC_MODE_8BIT;
+ }
+ mmc->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_HC;
+
+ err = mmc_register(mmc);
+
+ return err;
+}
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index a60cfe1cb0..5fbf956302 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -47,93 +47,6 @@ int __board_mmc_getcd(struct mmc *mmc) {
int board_mmc_getcd(struct mmc *mmc)__attribute__((weak,
alias("__board_mmc_getcd")));
-#ifdef CONFIG_MMC_BOUNCE_BUFFER
-static int mmc_bounce_need_bounce(struct mmc_data *orig)
-{
- ulong addr, len;
-
- if (orig->flags & MMC_DATA_READ)
- addr = (ulong)orig->dest;
- else
- addr = (ulong)orig->src;
-
- if (addr % ARCH_DMA_MINALIGN) {
- debug("MMC: Unaligned data destination address %08lx!\n", addr);
- return 1;
- }
-
- len = (ulong)(orig->blocksize * orig->blocks);
- if (len % ARCH_DMA_MINALIGN) {
- debug("MMC: Unaligned data destination length %08lx!\n", len);
- return 1;
- }
-
- return 0;
-}
-
-static int mmc_bounce_buffer_start(struct mmc_data *backup,
- struct mmc_data *orig)
-{
- ulong origlen, len;
- void *buffer;
-
- if (!orig)
- return 0;
-
- if (!mmc_bounce_need_bounce(orig))
- return 0;
-
- memcpy(backup, orig, sizeof(struct mmc_data));
-
- origlen = orig->blocksize * orig->blocks;
- len = roundup(origlen, ARCH_DMA_MINALIGN);
- buffer = memalign(ARCH_DMA_MINALIGN, len);
- if (!buffer) {
- puts("MMC: Error allocating MMC bounce buffer!\n");
- return 1;
- }
-
- if (orig->flags & MMC_DATA_READ) {
- orig->dest = buffer;
- } else {
- memcpy(buffer, orig->src, origlen);
- orig->src = buffer;
- }
-
- return 0;
-}
-
-static void mmc_bounce_buffer_stop(struct mmc_data *backup,
- struct mmc_data *orig)
-{
- ulong len;
-
- if (!orig)
- return;
-
- if (!mmc_bounce_need_bounce(backup))
- return;
-
- if (backup->flags & MMC_DATA_READ) {
- len = backup->blocksize * backup->blocks;
- memcpy(backup->dest, orig->dest, len);
- free(orig->dest);
- orig->dest = backup->dest;
- } else {
- free((void *)orig->src);
- orig->src = backup->src;
- }
-
- return;
-
-}
-#else
-static inline int mmc_bounce_buffer_start(struct mmc_data *backup,
- struct mmc_data *orig) { return 0; }
-static inline void mmc_bounce_buffer_stop(struct mmc_data *backup,
- struct mmc_data *orig) { }
-#endif
-
int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
{
struct mmc_data backup;
@@ -141,10 +54,6 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
memset(&backup, 0, sizeof(backup));
- ret = mmc_bounce_buffer_start(&backup, data);
- if (ret)
- return ret;
-
#ifdef CONFIG_MMC_TRACE
int i;
u8 *ptr;
@@ -196,7 +105,6 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
#else
ret = mmc->send_cmd(mmc, cmd, data);
#endif
- mmc_bounce_buffer_stop(&backup, data);
return ret;
}
diff --git a/drivers/mmc/mmc_spi.c b/drivers/mmc/mmc_spi.c
index de43a85355..11ba532b0c 100644
--- a/drivers/mmc/mmc_spi.c
+++ b/drivers/mmc/mmc_spi.c
@@ -176,8 +176,8 @@ static int mmc_spi_request(struct mmc *mmc, struct mmc_cmd *cmd,
u8 r1;
int i;
int ret = 0;
- debug("%s:cmd%d %x %x %x\n", __func__,
- cmd->cmdidx, cmd->resp_type, cmd->cmdarg, cmd->flags);
+ debug("%s:cmd%d %x %x\n", __func__,
+ cmd->cmdidx, cmd->resp_type, cmd->cmdarg);
spi_claim_bus(spi);
spi_cs_activate(spi);
r1 = mmc_spi_sendcmd(mmc, cmd->cmdidx, cmd->cmdarg);
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index c80b41b192..109acbf623 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -42,6 +42,7 @@
#include <asm/arch/imx-regs.h>
#include <asm/arch/sys_proto.h>
#include <asm/arch/dma.h>
+#include <bouncebuf.h>
struct mxsmmc_priv {
int id;
@@ -95,28 +96,33 @@ static int mxsmmc_send_cmd_pio(struct mxsmmc_priv *priv, struct mmc_data *data)
static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
{
uint32_t data_count = data->blocksize * data->blocks;
- uint32_t cache_data_count;
+ uint32_t cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN);
int dmach;
struct mxs_dma_desc *desc = priv->desc;
+ void *addr, *backup;
+ uint8_t flags;
memset(desc, 0, sizeof(struct mxs_dma_desc));
desc->address = (dma_addr_t)desc;
- if (data_count % ARCH_DMA_MINALIGN)
- cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN);
- else
- cache_data_count = data_count;
-
if (data->flags & MMC_DATA_READ) {
priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_WRITE;
- priv->desc->cmd.address = (dma_addr_t)data->dest;
+ addr = data->dest;
+ flags = GEN_BB_WRITE;
} else {
priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ;
- priv->desc->cmd.address = (dma_addr_t)data->src;
+ addr = (void *)data->src;
+ flags = GEN_BB_READ;
+ }
+
+ bounce_buffer_start(&addr, data_count, &backup, flags);
+
+ priv->desc->cmd.address = (dma_addr_t)addr;
+ if (data->flags & MMC_DATA_WRITE) {
/* Flush data to DRAM so DMA can pick them up */
- flush_dcache_range((uint32_t)priv->desc->cmd.address,
- (uint32_t)(priv->desc->cmd.address + cache_data_count));
+ flush_dcache_range((uint32_t)addr,
+ (uint32_t)(addr) + cache_data_count);
}
/* Invalidate the area, so no writeback into the RAM races with DMA */
@@ -128,15 +134,19 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->id;
mxs_dma_desc_append(dmach, priv->desc);
- if (mxs_dma_go(dmach))
+ if (mxs_dma_go(dmach)) {
+ bounce_buffer_stop(&addr, data_count, &backup, flags);
return COMM_ERR;
+ }
/* The data arrived into DRAM, invalidate cache over them */
if (data->flags & MMC_DATA_READ) {
- invalidate_dcache_range((uint32_t)priv->desc->cmd.address,
- (uint32_t)(priv->desc->cmd.address + cache_data_count));
+ invalidate_dcache_range((uint32_t)addr,
+ (uint32_t)(addr) + cache_data_count);
}
+ bounce_buffer_stop(&addr, data_count, &backup, flags);
+
return 0;
}
diff --git a/drivers/mmc/pxa_mmc.c b/drivers/mmc/pxa_mmc.c
deleted file mode 100644
index 80c4445034..0000000000
--- a/drivers/mmc/pxa_mmc.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * (C) Copyright 2003
- * Kyle Harris, Nexus Technologies, Inc. kharris@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 <config.h>
-#include <common.h>
-#include <mmc.h>
-#include <asm/errno.h>
-#include <asm/arch/hardware.h>
-#include <part.h>
-#include <asm/io.h>
-
-#include "pxa_mmc.h"
-
-extern int fat_register_device(block_dev_desc_t * dev_desc, int part_no);
-
-static block_dev_desc_t mmc_dev;
-
-block_dev_desc_t *mmc_get_dev(int dev)
-{
- return ((block_dev_desc_t *) & mmc_dev);
-}
-
-/*
- * FIXME needs to read cid and csd info to determine block size
- * and other parameters
- */
-static uchar mmc_buf[MMC_BLOCK_SIZE];
-static uchar spec_ver;
-static int mmc_ready = 0;
-static int wide = 0;
-
-static uint32_t *
-/****************************************************/
-mmc_cmd(ushort cmd, ushort argh, ushort argl, ushort cmdat)
-/****************************************************/
-{
- static uint32_t resp[4], a, b, c;
- uint32_t status;
- int i;
-
- debug("mmc_cmd %u 0x%04x 0x%04x 0x%04x\n", cmd, argh, argl,
- cmdat | wide);
- writel(MMC_STRPCL_STOP_CLK, MMC_STRPCL);
- writel(~MMC_I_MASK_CLK_IS_OFF, MMC_I_MASK);
- while (!(readl(MMC_I_REG) & MMC_I_REG_CLK_IS_OFF))
- ;
- writel(cmd, MMC_CMD);
- writel(argh, MMC_ARGH);
- writel(argl, MMC_ARGL);
- writel(cmdat | wide, MMC_CMDAT);
- writel(~MMC_I_MASK_END_CMD_RES, MMC_I_MASK);
- writel(MMC_STRPCL_START_CLK, MMC_STRPCL);
- while (!(readl(MMC_I_REG) & MMC_I_REG_END_CMD_RES))
- ;
-
- status = readl(MMC_STAT);
- debug("MMC status 0x%08x\n", status);
- if (status & MMC_STAT_TIME_OUT_RESPONSE) {
- return 0;
- }
-
- /* Linux says:
- * Did I mention this is Sick. We always need to
- * discard the upper 8 bits of the first 16-bit word.
- */
- a = (readl(MMC_RES) & 0xffff);
- for (i = 0; i < 4; i++) {
- b = (readl(MMC_RES) & 0xffff);
- c = (readl(MMC_RES) & 0xffff);
- resp[i] = (a << 24) | (b << 8) | (c >> 8);
- a = c;
- debug("MMC resp[%d] = %#08x\n", i, resp[i]);
- }
-
- return resp;
-}
-
-int
-/****************************************************/
-mmc_block_read(uchar * dst, uint32_t src, int len)
-/****************************************************/
-{
- ushort argh, argl;
- ulong status;
-
- if (len == 0) {
- return 0;
- }
-
- debug("mmc_block_rd dst %p src %08x len %d\n", dst, src, len);
-
- argh = len >> 16;
- argl = len & 0xffff;
-
- /* set block len */
- mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1);
-
- /* send read command */
- argh = src >> 16;
- argl = src & 0xffff;
- writel(MMC_STRPCL_STOP_CLK, MMC_STRPCL);
- writel(0xffff, MMC_RDTO);
- writel(1, MMC_NOB);
- writel(len, MMC_BLKLEN);
- mmc_cmd(MMC_CMD_READ_SINGLE_BLOCK, argh, argl,
- MMC_CMDAT_R1 | MMC_CMDAT_READ | MMC_CMDAT_BLOCK |
- MMC_CMDAT_DATA_EN);
-
- writel(~MMC_I_MASK_RXFIFO_RD_REQ, MMC_I_MASK);
- while (len) {
- if (readl(MMC_I_REG) & MMC_I_REG_RXFIFO_RD_REQ) {
-#if defined(CONFIG_CPU_PXA27X) || defined(CONFIG_CPU_MONAHANS)
- int i;
- for (i = min(len, 32); i; i--) {
- *dst++ = readb(MMC_RXFIFO);
- len--;
- }
-#else
- *dst++ = readb(MMC_RXFIFO);
- len--;
-#endif
- }
- status = readl(MMC_STAT);
- if (status & MMC_STAT_ERRORS) {
- printf("MMC_STAT error %lx\n", status);
- return -1;
- }
- }
- writel(~MMC_I_MASK_DATA_TRAN_DONE, MMC_I_MASK);
- while (!(readl(MMC_I_REG) & MMC_I_REG_DATA_TRAN_DONE))
- ;
- status = readl(MMC_STAT);
- if (status & MMC_STAT_ERRORS) {
- printf("MMC_STAT error %lx\n", status);
- return -1;
- }
- return 0;
-}
-
-int
-/****************************************************/
-mmc_block_write(ulong dst, uchar * src, int len)
-/****************************************************/
-{
- ushort argh, argl;
- ulong status;
-
- if (len == 0) {
- return 0;
- }
-
- debug("mmc_block_wr dst %lx src %lx len %d\n", dst, (ulong) src, len);
-
- argh = len >> 16;
- argl = len & 0xffff;
-
- /* set block len */
- mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1);
-
- /* send write command */
- argh = dst >> 16;
- argl = dst & 0xffff;
- writel(MMC_STRPCL_STOP_CLK, MMC_STRPCL);
- writel(1, MMC_NOB);
- writel(len, MMC_BLKLEN);
- mmc_cmd(MMC_CMD_WRITE_SINGLE_BLOCK, argh, argl,
- MMC_CMDAT_R1 | MMC_CMDAT_WRITE | MMC_CMDAT_BLOCK |
- MMC_CMDAT_DATA_EN);
-
- writel(~MMC_I_MASK_TXFIFO_WR_REQ, MMC_I_MASK);
- while (len) {
- if (readl(MMC_I_REG) & MMC_I_REG_TXFIFO_WR_REQ) {
- int i, bytes = min(32, len);
-
- for (i = 0; i < bytes; i++) {
- writel(*src++, MMC_TXFIFO);
- }
- if (bytes < 32) {
- writel(MMC_PRTBUF_BUF_PART_FULL, MMC_PRTBUF);
- }
- len -= bytes;
- }
- status = readl(MMC_STAT);
- if (status & MMC_STAT_ERRORS) {
- printf("MMC_STAT error %lx\n", status);
- return -1;
- }
- }
- writel(~MMC_I_MASK_DATA_TRAN_DONE, MMC_I_MASK);
- while (!(readl(MMC_I_REG) & MMC_I_REG_DATA_TRAN_DONE))
- ;
- writel(~MMC_I_MASK_PRG_DONE, MMC_I_MASK);
- while (!(readl(MMC_I_REG) & MMC_I_REG_PRG_DONE))
- ;
- status = readl(MMC_STAT);
- if (status & MMC_STAT_ERRORS) {
- printf("MMC_STAT error %lx\n", status);
- return -1;
- }
- return 0;
-}
-
-int
-/****************************************************/
-pxa_mmc_read(long src, uchar * dst, int size)
-/****************************************************/
-{
- ulong end, part_start, part_end, part_len, aligned_start, aligned_end;
- ulong mmc_block_size, mmc_block_address;
-
- if (size == 0) {
- return 0;
- }
-
- if (!mmc_ready) {
- printf("Please initial the MMC first\n");
- return -1;
- }
-
- mmc_block_size = MMC_BLOCK_SIZE;
- mmc_block_address = ~(mmc_block_size - 1);
-
- src -= CONFIG_SYS_MMC_BASE;
- end = src + size;
- part_start = ~mmc_block_address & src;
- part_end = ~mmc_block_address & end;
- aligned_start = mmc_block_address & src;
- aligned_end = mmc_block_address & end;
-
- /* all block aligned accesses */
- debug
- ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, (ulong) dst, end, part_start, part_end, aligned_start,
- aligned_end);
- if (part_start) {
- part_len = mmc_block_size - part_start;
- debug
- ("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, (ulong) dst, end, part_start, part_end, aligned_start,
- aligned_end);
- if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) <
- 0) {
- return -1;
- }
- memcpy(dst, mmc_buf + part_start, part_len);
- dst += part_len;
- src += part_len;
- }
- debug
- ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, (ulong) dst, end, part_start, part_end, aligned_start,
- aligned_end);
- for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
- debug
- ("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, (ulong) dst, end, part_start, part_end, aligned_start,
- aligned_end);
- if ((mmc_block_read((uchar *) (dst), src, mmc_block_size)) < 0) {
- return -1;
- }
- }
- debug
- ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, (ulong) dst, end, part_start, part_end, aligned_start,
- aligned_end);
- if (part_end && src < end) {
- debug
- ("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, (ulong) dst, end, part_start, part_end, aligned_start,
- aligned_end);
- if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) {
- return -1;
- }
- memcpy(dst, mmc_buf, part_end);
- }
- return 0;
-}
-
-int
-/****************************************************/
-pxa_mmc_write(uchar * src, uint32_t dst, int size)
-/****************************************************/
-{
- ulong end, part_start, part_end, part_len, aligned_start, aligned_end;
- ulong mmc_block_size, mmc_block_address;
-
- if (size == 0) {
- return 0;
- }
-
- if (!mmc_ready) {
- printf("Please initial the MMC first\n");
- return -1;
- }
-
- mmc_block_size = MMC_BLOCK_SIZE;
- mmc_block_address = ~(mmc_block_size - 1);
-
- dst -= CONFIG_SYS_MMC_BASE;
- end = dst + size;
- part_start = ~mmc_block_address & dst;
- part_end = ~mmc_block_address & end;
- aligned_start = mmc_block_address & dst;
- aligned_end = mmc_block_address & end;
-
- /* all block aligned accesses */
- debug
- ("src %p dst %08x end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, dst, end, part_start, part_end, aligned_start,
- aligned_end);
- if (part_start) {
- part_len = mmc_block_size - part_start;
- debug
- ("ps src %p dst %08x end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, dst, end, part_start, part_end, aligned_start,
- aligned_end);
- if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) <
- 0) {
- return -1;
- }
- memcpy(mmc_buf + part_start, src, part_len);
- if ((mmc_block_write(aligned_start, mmc_buf, mmc_block_size)) <
- 0) {
- return -1;
- }
- dst += part_len;
- src += part_len;
- }
- debug
- ("src %p dst %08x end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, dst, end, part_start, part_end, aligned_start,
- aligned_end);
- for (; dst < aligned_end; src += mmc_block_size, dst += mmc_block_size) {
- debug
- ("al src %p dst %08x end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, dst, end, part_start, part_end, aligned_start,
- aligned_end);
- if ((mmc_block_write(dst, (uchar *) src, mmc_block_size)) < 0) {
- return -1;
- }
- }
- debug
- ("src %p dst %08x end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, dst, end, part_start, part_end, aligned_start,
- aligned_end);
- if (part_end && dst < end) {
- debug
- ("pe src %p dst %08x end %lx pstart %lx pend %lx astart %lx aend %lx\n",
- src, dst, end, part_start, part_end, aligned_start,
- aligned_end);
- if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) {
- return -1;
- }
- memcpy(mmc_buf, src, part_end);
- if ((mmc_block_write(aligned_end, mmc_buf, mmc_block_size)) < 0) {
- return -1;
- }
- }
- return 0;
-}
-
-static ulong
-/****************************************************/
-mmc_bread(int dev_num, ulong blknr, lbaint_t blkcnt, void *dst)
-/****************************************************/
-{
- int mmc_block_size = MMC_BLOCK_SIZE;
- ulong src = blknr * mmc_block_size + CONFIG_SYS_MMC_BASE;
-
- pxa_mmc_read(src, (uchar *) dst, blkcnt * mmc_block_size);
- return blkcnt;
-}
-
-#ifdef __GNUC__
-#define likely(x) __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-#else
-#define likely(x) (x)
-#define unlikely(x) (x)
-#endif
-
-#define UNSTUFF_BITS(resp,start,size) \
- ({ \
- const int __size = size; \
- const uint32_t __mask = (__size < 32 ? 1 << __size : 0) - 1; \
- const int32_t __off = 3 - ((start) / 32); \
- const int32_t __shft = (start) & 31; \
- uint32_t __res; \
- \
- __res = resp[__off] >> __shft; \
- if (__size + __shft > 32) \
- __res |= resp[__off-1] << ((32 - __shft) % 32); \
- __res & __mask; \
- })
-
-/*
- * Given the decoded CSD structure, decode the raw CID to our CID structure.
- */
-static void mmc_decode_cid(uint32_t * resp)
-{
- if (IF_TYPE_SD == mmc_dev.if_type) {
- /*
- * SD doesn't currently have a version field so we will
- * have to assume we can parse this.
- */
- sprintf((char *)mmc_dev.vendor,
- "Man %02x OEM %c%c \"%c%c%c%c%c\" Date %02u/%04u",
- UNSTUFF_BITS(resp, 120, 8), UNSTUFF_BITS(resp, 112, 8),
- UNSTUFF_BITS(resp, 104, 8), UNSTUFF_BITS(resp, 96, 8),
- UNSTUFF_BITS(resp, 88, 8), UNSTUFF_BITS(resp, 80, 8),
- UNSTUFF_BITS(resp, 72, 8), UNSTUFF_BITS(resp, 64, 8),
- UNSTUFF_BITS(resp, 8, 4), UNSTUFF_BITS(resp, 12,
- 8) + 2000);
- sprintf((char *)mmc_dev.revision, "%d.%d",
- UNSTUFF_BITS(resp, 60, 4), UNSTUFF_BITS(resp, 56, 4));
- sprintf((char *)mmc_dev.product, "%u",
- UNSTUFF_BITS(resp, 24, 32));
- } else {
- /*
- * The selection of the format here is based upon published
- * specs from sandisk and from what people have reported.
- */
- switch (spec_ver) {
- case 0: /* MMC v1.0 - v1.2 */
- case 1: /* MMC v1.4 */
- sprintf((char *)mmc_dev.vendor,
- "Man %02x%02x%02x \"%c%c%c%c%c%c%c\" Date %02u/%04u",
- UNSTUFF_BITS(resp, 120, 8), UNSTUFF_BITS(resp,
- 112,
- 8),
- UNSTUFF_BITS(resp, 104, 8), UNSTUFF_BITS(resp,
- 96, 8),
- UNSTUFF_BITS(resp, 88, 8), UNSTUFF_BITS(resp,
- 80, 8),
- UNSTUFF_BITS(resp, 72, 8), UNSTUFF_BITS(resp,
- 64, 8),
- UNSTUFF_BITS(resp, 56, 8), UNSTUFF_BITS(resp,
- 48, 8),
- UNSTUFF_BITS(resp, 12, 4), UNSTUFF_BITS(resp, 8,
- 4) +
- 1997);
- sprintf((char *)mmc_dev.revision, "%d.%d",
- UNSTUFF_BITS(resp, 44, 4), UNSTUFF_BITS(resp,
- 40, 4));
- sprintf((char *)mmc_dev.product, "%u",
- UNSTUFF_BITS(resp, 16, 24));
- break;
-
- case 2: /* MMC v2.0 - v2.2 */
- case 3: /* MMC v3.1 - v3.3 */
- case 4: /* MMC v4 */
- sprintf((char *)mmc_dev.vendor,
- "Man %02x OEM %04x \"%c%c%c%c%c%c\" Date %02u/%04u",
- UNSTUFF_BITS(resp, 120, 8), UNSTUFF_BITS(resp,
- 104,
- 16),
- UNSTUFF_BITS(resp, 96, 8), UNSTUFF_BITS(resp,
- 88, 8),
- UNSTUFF_BITS(resp, 80, 8), UNSTUFF_BITS(resp,
- 72, 8),
- UNSTUFF_BITS(resp, 64, 8), UNSTUFF_BITS(resp,
- 56, 8),
- UNSTUFF_BITS(resp, 12, 4), UNSTUFF_BITS(resp, 8,
- 4) +
- 1997);
- sprintf((char *)mmc_dev.product, "%u",
- UNSTUFF_BITS(resp, 16, 32));
- sprintf((char *)mmc_dev.revision, "N/A");
- break;
-
- default:
- printf("MMC card has unknown MMCA version %d\n",
- spec_ver);
- break;
- }
- }
- printf("%s card.\nVendor: %s\nProduct: %s\nRevision: %s\n",
- (IF_TYPE_SD == mmc_dev.if_type) ? "SD" : "MMC", mmc_dev.vendor,
- mmc_dev.product, mmc_dev.revision);
-}
-
-/*
- * Given a 128-bit response, decode to our card CSD structure.
- */
-static void mmc_decode_csd(uint32_t * resp)
-{
- unsigned int mult, csd_struct;
-
- if (IF_TYPE_SD == mmc_dev.if_type) {
- csd_struct = UNSTUFF_BITS(resp, 126, 2);
- if (csd_struct != 0) {
- printf("SD: unrecognised CSD structure version %d\n",
- csd_struct);
- return;
- }
- } else {
- /*
- * We only understand CSD structure v1.1 and v1.2.
- * v1.2 has extra information in bits 15, 11 and 10.
- */
- csd_struct = UNSTUFF_BITS(resp, 126, 2);
- if (csd_struct != 1 && csd_struct != 2) {
- printf("MMC: unrecognised CSD structure version %d\n",
- csd_struct);
- return;
- }
-
- spec_ver = UNSTUFF_BITS(resp, 122, 4);
- mmc_dev.if_type = IF_TYPE_MMC;
- }
-
- mult = 1 << (UNSTUFF_BITS(resp, 47, 3) + 2);
- mmc_dev.lba = (1 + UNSTUFF_BITS(resp, 62, 12)) * mult;
- mmc_dev.blksz = 1 << UNSTUFF_BITS(resp, 80, 4);
-
- /* FIXME: The following just makes assumes that's the partition type -- should really read it */
- mmc_dev.part_type = PART_TYPE_DOS;
- mmc_dev.dev = 0;
- mmc_dev.lun = 0;
- mmc_dev.type = DEV_TYPE_HARDDISK;
- mmc_dev.removable = 0;
- mmc_dev.block_read = mmc_bread;
-
- printf("Detected: %lu blocks of %lu bytes (%luMB) ",
- mmc_dev.lba,
- mmc_dev.blksz,
- mmc_dev.lba * mmc_dev.blksz / (1024 * 1024));
-}
-
-int
-/****************************************************/
-mmc_legacy_init(int verbose)
-/****************************************************/
-{
- int retries, rc = -ENODEV;
- uint32_t cid_resp[4];
- uint32_t *resp;
- uint16_t rca = 0;
-
- /* Reset device interface type */
- mmc_dev.if_type = IF_TYPE_UNKNOWN;
-
-#ifdef CONFIG_CPU_MONAHANS /* pxa3xx */
- writel(readl(CKENA) | CKENA_12_MMC0 | CKENA_13_MMC1, CKENA);
-#else /* pxa2xx */
- writel(readl(CKEN) | CKEN12_MMC, CKEN); /* enable MMC unit clock */
-#endif
- writel(MMC_CLKRT_0_3125MHZ, MMC_CLKRT);
- writel(MMC_RES_TO_MAX, MMC_RESTO);
- writel(MMC_SPI_DISABLE, MMC_SPI);
-
- /* reset */
- mmc_cmd(MMC_CMD_GO_IDLE_STATE, 0, 0, MMC_CMDAT_INIT | MMC_CMDAT_R0);
- udelay(200000);
- retries = 3;
- while (retries--) {
- resp = mmc_cmd(MMC_CMD_APP_CMD, 0, 0, MMC_CMDAT_R1);
- if (!(resp[0] & 0x00000020)) { /* Card does not support APP_CMD */
- debug("Card does not support APP_CMD\n");
- break;
- }
-
- /* Select 3.2-3.3V and 3.3-3.4V */
- resp = mmc_cmd(SD_CMD_APP_SEND_OP_COND, 0x0030, 0x0000,
- MMC_CMDAT_R3 | (retries < 2 ? 0
- : MMC_CMDAT_INIT));
- if (resp[0] & 0x80000000) {
- mmc_dev.if_type = IF_TYPE_SD;
- debug("Detected SD card\n");
- break;
- }
- udelay(200000);
- }
-
- if (retries <= 0 || !(IF_TYPE_SD == mmc_dev.if_type)) {
- debug("Failed to detect SD Card, trying MMC\n");
- resp =
- mmc_cmd(MMC_CMD_SEND_OP_COND, 0x00ff, 0x8000, MMC_CMDAT_R3);
-
- retries = 10;
- while (retries-- && resp && !(resp[0] & 0x80000000)) {
- udelay(200000);
- resp =
- mmc_cmd(MMC_CMD_SEND_OP_COND, 0x00ff, 0x8000,
- MMC_CMDAT_R3);
- }
- }
-
- /* try to get card id */
- resp =
- mmc_cmd(MMC_CMD_ALL_SEND_CID, 0, 0, MMC_CMDAT_R2 | MMC_CMDAT_BUSY);
- if (resp) {
- memcpy(cid_resp, resp, sizeof(cid_resp));
-
- /* MMC exists, get CSD too */
- resp = mmc_cmd(MMC_CMD_SET_RELATIVE_ADDR, 0, 0, MMC_CMDAT_R1);
- if (IF_TYPE_SD == mmc_dev.if_type)
- rca = ((resp[0] & 0xffff0000) >> 16);
- resp = mmc_cmd(MMC_CMD_SEND_CSD, rca, 0, MMC_CMDAT_R2);
- if (resp) {
- mmc_decode_csd(resp);
- rc = 0;
- mmc_ready = 1;
- }
-
- mmc_decode_cid(cid_resp);
- }
-
- writel(0, MMC_CLKRT); /* 20 MHz */
- resp = mmc_cmd(MMC_CMD_SELECT_CARD, rca, 0, MMC_CMDAT_R1);
-
-#if defined(CONFIG_CPU_PXA27X) || defined(CONFIG_CPU_MONAHANS)
- if (IF_TYPE_SD == mmc_dev.if_type) {
- resp = mmc_cmd(MMC_CMD_APP_CMD, rca, 0, MMC_CMDAT_R1);
- resp = mmc_cmd(SD_CMD_APP_SET_BUS_WIDTH, 0, 2, MMC_CMDAT_R1);
- wide = MMC_CMDAT_SD_4DAT;
- }
-#endif
-
- fat_register_device(&mmc_dev, 1); /* partitions start counting with 1 */
-
- return rc;
-}
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c
index b9782367e2..dc49d37f5c 100644
--- a/drivers/mmc/s5p_sdhci.c
+++ b/drivers/mmc/s5p_sdhci.c
@@ -83,7 +83,8 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width)
host->ioaddr = (void *)regbase;
host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE |
- SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR;
+ SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR |
+ SDHCI_QUIRK_WAIT_SEND_CMD;
host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195;
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 2e3c408bc5..7845f873ac 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -82,8 +82,15 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
unsigned int start_addr)
{
unsigned int stat, rdy, mask, timeout, block = 0;
+#ifdef CONFIG_MMC_SDMA
+ unsigned char ctrl;
+ ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL);
+ ctrl &= ~SDHCI_CTRL_DMA_MASK;
+ ctrl |= SDHCI_CTRL_SDMA;
+ sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL);
+#endif
- timeout = 10000;
+ timeout = 1000000;
rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL;
mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE;
do {
@@ -233,6 +240,9 @@ int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
if (!ret && data)
ret = sdhci_transfer_data(host, data, start_addr);
+ if (host->quirks & SDHCI_QUIRK_WAIT_SEND_CMD)
+ udelay(1000);
+
stat = sdhci_readl(host, SDHCI_INT_STATUS);
sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_STATUS);
if (!ret) {
diff --git a/drivers/net/fm/Makefile b/drivers/net/fm/Makefile
index cc57354755..7a1fcdd81f 100644
--- a/drivers/net/fm/Makefile
+++ b/drivers/net/fm/Makefile
@@ -32,6 +32,10 @@ COBJS-y += init.o
COBJS-y += tgec.o
COBJS-y += tgec_phy.o
+# Soc have FMAN v3 with mEMAC
+COBJS-$(CONFIG_SYS_FMAN_V3) += memac_phy.o
+COBJS-$(CONFIG_SYS_FMAN_V3) += memac.o
+
# SoC specific SERDES support
COBJS-$(CONFIG_P1017) += p1023.o
COBJS-$(CONFIG_P1023) += p1023.o
@@ -40,6 +44,8 @@ COBJS-$(CONFIG_PPC_P2041) += p5020.o
COBJS-$(CONFIG_PPC_P3041) += p5020.o
COBJS-$(CONFIG_PPC_P4080) += p4080.o
COBJS-$(CONFIG_PPC_P5020) += p5020.o
+COBJS-$(CONFIG_PPC_T4240) += t4240.o
+COBJS-$(CONFIG_PPC_B4860) += b4860.o
endif
COBJS := $(COBJS-y)
diff --git a/drivers/net/fm/eth.c b/drivers/net/fm/eth.c
index 2b616adb6e..82c787bf38 100644
--- a/drivers/net/fm/eth.c
+++ b/drivers/net/fm/eth.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
* Dave Liu <daveliu@freescale.com>
*
* This program is free software; you can redistribute it and/or
@@ -28,6 +28,7 @@
#include <phy.h>
#include <asm/fsl_dtsec.h>
#include <asm/fsl_tgec.h>
+#include <asm/fsl_memac.h>
#include "fm.h"
@@ -47,6 +48,28 @@ static int num_controllers;
/* Configure the TBI for SGMII operation */
void dtsec_configure_serdes(struct fm_eth *priv)
{
+#ifdef CONFIG_SYS_FMAN_V3
+ u32 value;
+ struct mii_dev bus;
+ bus.priv = priv->mac->phyregs;
+
+ /* SGMII IF mode + AN enable */
+ value = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII;
+ memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value);
+
+ /* Dev ability according to SGMII specification */
+ value = PHY_SGMII_DEV_ABILITY_SGMII;
+ memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x4, value);
+
+ /* Adjust link timer for SGMII -
+ 1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40 */
+ memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x3);
+ memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xd40);
+
+ /* Restart AN */
+ value = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+ memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0, value);
+#else
struct dtsec *regs = priv->mac->base;
struct tsec_mii_mng *phyregs = priv->mac->phyregs;
@@ -60,15 +83,18 @@ void dtsec_configure_serdes(struct fm_eth *priv)
TBIANA_SGMII_ACK);
tsec_local_mdio_write(phyregs, in_be32(&regs->tbipa), 0,
TBI_CR, TBICR_SETTINGS);
+#endif
}
static void dtsec_init_phy(struct eth_device *dev)
{
struct fm_eth *fm_eth = dev->priv;
- struct dtsec *regs = (struct dtsec *)fm_eth->mac->base;
+#ifndef CONFIG_SYS_FMAN_V3
+ struct dtsec *regs = (struct dtsec *)CONFIG_SYS_FSL_FM1_DTSEC1_ADDR;
/* Assign a Physical address to the TBI */
out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
+#endif
if (fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII)
dtsec_configure_serdes(fm_eth);
@@ -541,6 +567,10 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
num = fm_eth->num;
+#ifdef CONFIG_SYS_FMAN_V3
+ base = &reg->memac[num].fm_memac;
+ phyregs = &reg->memac[num].fm_memac_mdio;
+#else
/* Get the mac registers base address */
if (fm_eth->type == FM_ETH_1G_E) {
base = &reg->mac_1g[num].fm_dtesc;
@@ -549,6 +579,7 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
base = &reg->mac_10g[num].fm_10gec;
phyregs = &reg->mac_10g[num].fm_10gec_mdio;
}
+#endif
/* alloc mac controller */
mac = malloc(sizeof(struct fsl_enet_mac));
@@ -559,10 +590,14 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
/* save the mac to fm_eth struct */
fm_eth->mac = mac;
+#ifdef CONFIG_SYS_FMAN_V3
+ init_memac(mac, base, phyregs, MAX_RXBUF_LEN);
+#else
if (fm_eth->type == FM_ETH_1G_E)
init_dtsec(mac, base, phyregs, MAX_RXBUF_LEN);
else
init_tgec(mac, base, phyregs, MAX_RXBUF_LEN);
+#endif
return 1;
}
diff --git a/drivers/net/fm/init.c b/drivers/net/fm/init.c
index 736b8b9582..ae389b8842 100644
--- a/drivers/net/fm/init.c
+++ b/drivers/net/fm/init.c
@@ -38,6 +38,15 @@ struct fm_eth_info fm_info[] = {
#if (CONFIG_SYS_NUM_FM1_DTSEC >= 5)
FM_DTSEC_INFO_INITIALIZER(1, 5),
#endif
+#if (CONFIG_SYS_NUM_FM1_DTSEC >= 6)
+ FM_DTSEC_INFO_INITIALIZER(1, 6),
+#endif
+#if (CONFIG_SYS_NUM_FM1_DTSEC >= 7)
+ FM_DTSEC_INFO_INITIALIZER(1, 9),
+#endif
+#if (CONFIG_SYS_NUM_FM1_DTSEC >= 8)
+ FM_DTSEC_INFO_INITIALIZER(1, 10),
+#endif
#if (CONFIG_SYS_NUM_FM2_DTSEC >= 1)
FM_DTSEC_INFO_INITIALIZER(2, 1),
#endif
@@ -53,6 +62,15 @@ struct fm_eth_info fm_info[] = {
#if (CONFIG_SYS_NUM_FM2_DTSEC >= 5)
FM_DTSEC_INFO_INITIALIZER(2, 5),
#endif
+#if (CONFIG_SYS_NUM_FM2_DTSEC >= 6)
+ FM_DTSEC_INFO_INITIALIZER(2, 6),
+#endif
+#if (CONFIG_SYS_NUM_FM2_DTSEC >= 7)
+ FM_DTSEC_INFO_INITIALIZER(2, 9),
+#endif
+#if (CONFIG_SYS_NUM_FM2_DTSEC >= 8)
+ FM_DTSEC_INFO_INITIALIZER(2, 10),
+#endif
#if (CONFIG_SYS_NUM_FM1_10GEC >= 1)
FM_TGEC_INFO_INITIALIZER(1, 1),
#endif
diff --git a/drivers/net/fm/memac.c b/drivers/net/fm/memac.c
new file mode 100644
index 0000000000..32c7054e35
--- /dev/null
+++ b/drivers/net/fm/memac.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * 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
+ */
+
+/* MAXFRM - maximum frame length */
+#define MAXFRM_MASK 0x0000ffff
+
+#include <common.h>
+#include <phy.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/fsl_enet.h>
+#include <asm/fsl_memac.h>
+
+#include "fm.h"
+
+static void memac_init_mac(struct fsl_enet_mac *mac)
+{
+ struct memac *regs = mac->base;
+
+ /* mask all interrupt */
+ out_be32(&regs->imask, IMASK_MASK_ALL);
+
+ /* clear all events */
+ out_be32(&regs->ievent, IEVENT_CLEAR_ALL);
+
+ /* set the max receive length */
+ out_be32(&regs->maxfrm, mac->max_rx_len & MAXFRM_MASK);
+
+ /* multicast frame reception for the hash entry disable */
+ out_be32(&regs->hashtable_ctrl, 0);
+}
+
+static void memac_enable_mac(struct fsl_enet_mac *mac)
+{
+ struct memac *regs = mac->base;
+
+ setbits_be32(&regs->command_config, MEMAC_CMD_CFG_RXTX_EN);
+}
+
+static void memac_disable_mac(struct fsl_enet_mac *mac)
+{
+ struct memac *regs = mac->base;
+
+ clrbits_be32(&regs->command_config, MEMAC_CMD_CFG_RXTX_EN);
+}
+
+static void memac_set_mac_addr(struct fsl_enet_mac *mac, u8 *mac_addr)
+{
+ struct memac *regs = mac->base;
+ u32 mac_addr0, mac_addr1;
+
+ /*
+ * if a station address of 0x12345678ABCD, perform a write to
+ * MAC_ADDR0 of 0x78563412, MAC_ADDR1 of 0x0000CDAB
+ */
+ mac_addr0 = (mac_addr[3] << 24) | (mac_addr[2] << 16) | \
+ (mac_addr[1] << 8) | (mac_addr[0]);
+ out_be32(&regs->mac_addr_0, mac_addr0);
+
+ mac_addr1 = ((mac_addr[5] << 8) | mac_addr[4]) & 0x0000ffff;
+ out_be32(&regs->mac_addr_1, mac_addr1);
+}
+
+static void memac_set_interface_mode(struct fsl_enet_mac *mac,
+ phy_interface_t type, int speed)
+{
+ /* Roy need more work here */
+
+ struct memac *regs = mac->base;
+ u32 if_mode, if_status;
+
+ /* clear all bits relative with interface mode */
+ if_mode = in_be32(&regs->if_mode);
+ if_status = in_be32(&regs->if_status);
+
+ /* set interface mode */
+ switch (type) {
+ case PHY_INTERFACE_MODE_GMII:
+ if_mode &= ~IF_MODE_MASK;
+ if_mode |= IF_MODE_GMII;
+ break;
+ case PHY_INTERFACE_MODE_RGMII:
+ if_mode |= (IF_MODE_GMII | IF_MODE_RG);
+ break;
+ case PHY_INTERFACE_MODE_RMII:
+ if_mode |= (IF_MODE_GMII | IF_MODE_RM);
+ break;
+ case PHY_INTERFACE_MODE_SGMII:
+ if_mode &= ~IF_MODE_MASK;
+ if_mode |= (IF_MODE_GMII);
+ break;
+ default:
+ break;
+ }
+ /* Enable automatic speed selection */
+ if_mode |= IF_MODE_EN_AUTO;
+
+ debug(" %s, if_mode = %x\n", __func__, if_mode);
+ debug(" %s, if_status = %x\n", __func__, if_status);
+ out_be32(&regs->if_mode, if_mode);
+ return;
+}
+
+void init_memac(struct fsl_enet_mac *mac, void *base,
+ void *phyregs, int max_rx_len)
+{
+ mac->base = base;
+ mac->phyregs = phyregs;
+ mac->max_rx_len = max_rx_len;
+ mac->init_mac = memac_init_mac;
+ mac->enable_mac = memac_enable_mac;
+ mac->disable_mac = memac_disable_mac;
+ mac->set_mac_addr = memac_set_mac_addr;
+ mac->set_if_mode = memac_set_interface_mode;
+}
diff --git a/drivers/net/fm/memac_phy.c b/drivers/net/fm/memac_phy.c
new file mode 100644
index 0000000000..ea6118b9b9
--- /dev/null
+++ b/drivers/net/fm/memac_phy.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Andy Fleming <afleming@freescale.com>
+ * Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * 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
+ * Some part is taken from tsec.c
+ */
+#include <common.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <asm/io.h>
+#include <asm/fsl_memac.h>
+#include <fm_eth.h>
+
+/*
+ * Write value to the PHY for this device to the register at regnum, waiting
+ * until the write is done before it returns. All PHY configuration has to be
+ * done through the TSEC1 MIIM regs
+ */
+int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
+ int regnum, u16 value)
+{
+ u32 mdio_ctl;
+ struct memac_mdio_controller *regs = bus->priv;
+ u32 c45 = 1; /* Default to 10G interface */
+
+ if (dev_addr == MDIO_DEVAD_NONE) {
+ c45 = 0; /* clause 22 */
+ dev_addr = regnum & 0x1f;
+ clrbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+ } else {
+ setbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+ setbits_be32(&regs->mdio_stat, MDIO_STAT_HOLD_15_CLK);
+ }
+
+ /* Wait till the bus is free */
+ while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+ ;
+
+ /* Set the port and dev addr */
+ mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
+ out_be32(&regs->mdio_ctl, mdio_ctl);
+
+ /* Set the register address */
+ if (c45)
+ out_be32(&regs->mdio_addr, regnum & 0xffff);
+
+ /* Wait till the bus is free */
+ while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+ ;
+
+ /* Write the value to the register */
+ out_be32(&regs->mdio_data, MDIO_DATA(value));
+
+ /* Wait till the MDIO write is complete */
+ while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
+ ;
+
+ return 0;
+}
+
+/*
+ * Reads from register regnum in the PHY for device dev, returning the value.
+ * Clears miimcom first. All PHY configuration has to be done through the
+ * TSEC1 MIIM regs
+ */
+int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
+ int regnum)
+{
+ u32 mdio_ctl;
+ struct memac_mdio_controller *regs = bus->priv;
+ u32 c45 = 1;
+
+ if (dev_addr == MDIO_DEVAD_NONE) {
+ c45 = 0; /* clause 22 */
+ dev_addr = regnum & 0x1f;
+ clrbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+ } else {
+ setbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+ setbits_be32(&regs->mdio_stat, MDIO_STAT_HOLD_15_CLK);
+ }
+
+ /* Wait till the bus is free */
+ while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+ ;
+
+ /* Set the Port and Device Addrs */
+ mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
+ out_be32(&regs->mdio_ctl, mdio_ctl);
+
+ /* Set the register address */
+ if (c45)
+ out_be32(&regs->mdio_addr, regnum & 0xffff);
+
+ /* Wait till the bus is free */
+ while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+ ;
+
+ /* Initiate the read */
+ mdio_ctl |= MDIO_CTL_READ;
+ out_be32(&regs->mdio_ctl, mdio_ctl);
+
+ /* Wait till the MDIO write is complete */
+ while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
+ ;
+
+ /* Return all Fs if nothing was there */
+ if (in_be32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
+ return 0xffff;
+
+ return in_be32(&regs->mdio_data) & 0xffff;
+}
+
+int memac_mdio_reset(struct mii_dev *bus)
+{
+ return 0;
+}
+
+int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info)
+{
+ struct mii_dev *bus = mdio_alloc();
+
+ if (!bus) {
+ printf("Failed to allocate FM TGEC MDIO bus\n");
+ return -1;
+ }
+
+ bus->read = memac_mdio_read;
+ bus->write = memac_mdio_write;
+ bus->reset = memac_mdio_reset;
+ sprintf(bus->name, info->name);
+
+ bus->priv = info->regs;
+
+ return mdio_register(bus);
+}
diff --git a/drivers/net/fm/t4240.c b/drivers/net/fm/t4240.c
new file mode 100644
index 0000000000..48c530c915
--- /dev/null
+++ b/drivers/net/fm/t4240.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * 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 <phy.h>
+#include <fm_eth.h>
+#include <asm/io.h>
+#include <asm/immap_85xx.h>
+#include <asm/fsl_serdes.h>
+
+u32 port_to_devdisr[] = {
+ [FM1_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC1_1,
+ [FM1_DTSEC2] = FSL_CORENET_DEVDISR2_DTSEC1_2,
+ [FM1_DTSEC3] = FSL_CORENET_DEVDISR2_DTSEC1_3,
+ [FM1_DTSEC4] = FSL_CORENET_DEVDISR2_DTSEC1_4,
+ [FM1_DTSEC5] = FSL_CORENET_DEVDISR2_DTSEC1_5,
+ [FM1_DTSEC6] = FSL_CORENET_DEVDISR2_DTSEC1_6,
+ [FM1_DTSEC9] = FSL_CORENET_DEVDISR2_DTSEC1_9,
+ [FM1_DTSEC10] = FSL_CORENET_DEVDISR2_DTSEC1_10,
+ [FM1_10GEC1] = FSL_CORENET_DEVDISR2_10GEC1_1,
+ [FM1_10GEC2] = FSL_CORENET_DEVDISR2_10GEC1_2,
+ [FM2_DTSEC1] = FSL_CORENET_DEVDISR2_DTSEC2_1,
+ [FM2_DTSEC2] = FSL_CORENET_DEVDISR2_DTSEC2_2,
+ [FM2_DTSEC3] = FSL_CORENET_DEVDISR2_DTSEC2_3,
+ [FM2_DTSEC4] = FSL_CORENET_DEVDISR2_DTSEC2_4,
+ [FM2_DTSEC5] = FSL_CORENET_DEVDISR2_DTSEC2_5,
+ [FM2_DTSEC6] = FSL_CORENET_DEVDISR2_DTSEC2_6,
+ [FM2_DTSEC9] = FSL_CORENET_DEVDISR2_DTSEC2_9,
+ [FM2_DTSEC10] = FSL_CORENET_DEVDISR2_DTSEC2_10,
+ [FM2_10GEC1] = FSL_CORENET_DEVDISR2_10GEC2_1,
+ [FM2_10GEC2] = FSL_CORENET_DEVDISR2_10GEC2_2,
+};
+
+static int is_device_disabled(enum fm_port port)
+{
+ ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 devdisr2 = in_be32(&gur->devdisr2);
+
+ return port_to_devdisr[port] & devdisr2;
+}
+
+void fman_disable_port(enum fm_port port)
+{
+ ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+
+ setbits_be32(&gur->devdisr2, port_to_devdisr[port]);
+}
+
+phy_interface_t fman_port_enet_if(enum fm_port port)
+{
+ ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
+ u32 rcwsr13 = in_be32(&gur->rcwsr[13]);
+
+ if (is_device_disabled(port))
+ return PHY_INTERFACE_MODE_NONE;
+
+ if ((port == FM1_10GEC1 || port == FM1_10GEC2)
+ && (is_serdes_configured(XAUI_FM1)))
+ return PHY_INTERFACE_MODE_XGMII;
+
+ if ((port == FM2_10GEC1 || port == FM2_10GEC2)
+ && (is_serdes_configured(XAUI_FM2)))
+ return PHY_INTERFACE_MODE_XGMII;
+
+#define FSL_CORENET_RCWSR13_EC1 0x60000000 /* bits 417..418 */
+#define FSL_CORENET_RCWSR13_EC1_FM2_DTSEC5_RGMII 0x00000000
+#define FSL_CORENET_RCWSR13_EC1_FM2_GPIO 0x40000000
+#define FSL_CORENET_RCWSR13_EC2 0x18000000 /* bits 419..420 */
+#define FSL_CORENET_RCWSR13_EC2_FM1_DTSEC5_RGMII 0x00000000
+#define FSL_CORENET_RCWSR13_EC2_FM2_DTSEC6_RGMII 0x08000000
+#define FSL_CORENET_RCWSR13_EC2_FM1_GPIO 0x10000000
+ /* handle RGMII first */
+ if ((port == FM2_DTSEC5) && ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) ==
+ FSL_CORENET_RCWSR13_EC1_FM2_DTSEC5_RGMII))
+ return PHY_INTERFACE_MODE_RGMII;
+
+ if ((port == FM1_DTSEC5) && ((rcwsr13 & FSL_CORENET_RCWSR13_EC2) ==
+ FSL_CORENET_RCWSR13_EC2_FM1_DTSEC5_RGMII))
+ return PHY_INTERFACE_MODE_RGMII;
+
+ if ((port == FM2_DTSEC6) && ((rcwsr13 & FSL_CORENET_RCWSR13_EC2) ==
+ FSL_CORENET_RCWSR13_EC2_FM2_DTSEC6_RGMII))
+ return PHY_INTERFACE_MODE_RGMII;
+ switch (port) {
+ case FM1_DTSEC1:
+ case FM1_DTSEC2:
+ case FM1_DTSEC3:
+ case FM1_DTSEC4:
+ case FM1_DTSEC5:
+ case FM1_DTSEC6:
+ case FM1_DTSEC9:
+ case FM1_DTSEC10:
+ if (is_serdes_configured(SGMII_FM1_DTSEC1 + port - FM1_DTSEC1))
+ return PHY_INTERFACE_MODE_SGMII;
+ break;
+ case FM2_DTSEC1:
+ case FM2_DTSEC2:
+ case FM2_DTSEC3:
+ case FM2_DTSEC4:
+ case FM2_DTSEC5:
+ case FM2_DTSEC6:
+ case FM2_DTSEC9:
+ case FM2_DTSEC10:
+ if (is_serdes_configured(SGMII_FM2_DTSEC1 + port - FM2_DTSEC1))
+ return PHY_INTERFACE_MODE_SGMII;
+ break;
+ default:
+ return PHY_INTERFACE_MODE_NONE;
+ }
+
+ return PHY_INTERFACE_MODE_NONE;
+}
diff --git a/drivers/net/mcfmii.c b/drivers/net/mcfmii.c
index 471c5efea1..5e64dbdd17 100644
--- a/drivers/net/mcfmii.c
+++ b/drivers/net/mcfmii.c
@@ -315,13 +315,11 @@ int mcffec_miiphy_read(const char *devname, unsigned char addr, unsigned char re
int mcffec_miiphy_write(const char *devname, unsigned char addr, unsigned char reg,
unsigned short value)
{
- short rdreg; /* register working value */
-
#ifdef MII_DEBUG
printf("miiphy_write(0x%x) @ 0x%x = ", reg, addr);
#endif
- rdreg = mii_send(mk_mii_write(addr, reg, value));
+ mii_send(mk_mii_write(addr, reg, value));
#ifdef MII_DEBUG
printf("0x%04x\n", value);
diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c
index 0d46c96312..48ae16374d 100644
--- a/drivers/pci/fsl_pci_init.c
+++ b/drivers/pci/fsl_pci_init.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2011 Freescale Semiconductor, Inc.
+ * Copyright 2007-2012 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
@@ -211,7 +211,7 @@ static int fsl_pci_setup_inbound_windows(struct pci_controller *hose,
return 1;
}
-#ifdef CONFIG_FSL_CORENET
+#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
static void fsl_pcie_boot_master(pit_t *pi)
{
/* configure inbound window for slave's u-boot image */
@@ -276,14 +276,18 @@ static void fsl_pcie_boot_master_release_slave(int port)
release_addr = CONFIG_SYS_PCIE1_MEM_VIRT
+ CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET;
break;
+#ifdef CONFIG_SYS_PCIE2_MEM_VIRT
case 2:
release_addr = CONFIG_SYS_PCIE2_MEM_VIRT
+ CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET;
break;
+#endif
+#ifdef CONFIG_SYS_PCIE3_MEM_VIRT
case 3:
release_addr = CONFIG_SYS_PCIE3_MEM_VIRT
+ CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET;
break;
+#endif
default:
release_addr = 0;
break;
@@ -384,7 +388,7 @@ void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info)
/* see if we are a PCIe or PCI controller */
pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);
-#ifdef CONFIG_FSL_CORENET
+#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
/* boot from PCIE --master */
char *s = getenv("bootmaster");
char pcie[6];
@@ -499,13 +503,7 @@ void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info)
}
#ifndef CONFIG_PCI_NOSCAN
- pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &temp8);
-
- /* Programming Interface (PCI_CLASS_PROG)
- * 0 == pci host or pcie root-complex,
- * 1 == pci agent or pcie end-point
- */
- if (!temp8) {
+ if (!fsl_is_pci_agent(hose)) {
debug(" Scanning PCI bus %02x\n",
hose->current_busno);
hose->last_busno = pci_hose_scan_bus(hose, hose->current_busno);
@@ -543,12 +541,22 @@ void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info)
int fsl_is_pci_agent(struct pci_controller *hose)
{
- u8 prog_if;
+ u8 pcie_cap;
pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0);
- pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prog_if);
+ pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);
+ if (pcie_cap == PCI_CAP_ID_EXP) {
+ u8 header_type;
- return (prog_if == FSL_PROG_IF_AGENT);
+ pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE,
+ &header_type);
+ return (header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL;
+ } else {
+ u8 prog_if;
+
+ pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prog_if);
+ return (prog_if == FSL_PROG_IF_AGENT);
+ }
}
int fsl_pci_init_port(struct fsl_pci_info *pci_info,
@@ -594,7 +602,7 @@ int fsl_pci_init_port(struct fsl_pci_info *pci_info,
if (fsl_is_pci_agent(hose)) {
fsl_pci_config_unlock(hose);
hose->last_busno = hose->first_busno;
-#ifdef CONFIG_FSL_CORENET
+#ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER
} else {
/* boot from PCIE --master releases slave's core 0 */
char *s = getenv("bootmaster");
@@ -618,12 +626,10 @@ int fsl_pci_init_port(struct fsl_pci_info *pci_info,
void fsl_pci_config_unlock(struct pci_controller *hose)
{
pci_dev_t dev = PCI_BDF(hose->first_busno,0,0);
- u8 agent;
u8 pcie_cap;
u16 pbfr;
- pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &agent);
- if (!agent)
+ if (!fsl_is_pci_agent(hose))
return;
pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap);
@@ -660,10 +666,17 @@ int fsl_configure_pcie(struct fsl_pci_info *info,
}
#if defined(CONFIG_FSL_CORENET)
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+ #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR3_PCIE1
+ #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR3_PCIE2
+ #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR3_PCIE3
+ #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR3_PCIE4
+#else
#define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR_PCIE1
#define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR_PCIE2
#define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR_PCIE3
#define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR_PCIE4
+#endif
#define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR
#elif defined(CONFIG_MPC85xx)
#define _DEVDISR_PCIE1 MPC85xx_DEVDISR_PCIE
@@ -743,34 +756,42 @@ int fsl_pcie_init_board(int busno)
{
struct fsl_pci_info pci_info;
ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC8xxx_GUTS_ADDR;
- u32 devdisr = in_be32(&gur->devdisr);
+ u32 devdisr;
+ u32 *addr;
+
+#ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2
+ addr = &gur->devdisr3;
+#else
+ addr = &gur->devdisr;
+#endif
+ devdisr = in_be32(addr);
#ifdef CONFIG_PCIE1
SET_STD_PCIE_INFO(pci_info, 1);
busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE1, &pci_info);
#else
- setbits_be32(&gur->devdisr, _DEVDISR_PCIE1); /* disable */
+ setbits_be32(addr, _DEVDISR_PCIE1); /* disable */
#endif
#ifdef CONFIG_PCIE2
SET_STD_PCIE_INFO(pci_info, 2);
busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE2, &pci_info);
#else
- setbits_be32(&gur->devdisr, _DEVDISR_PCIE2); /* disable */
+ setbits_be32(addr, _DEVDISR_PCIE2); /* disable */
#endif
#ifdef CONFIG_PCIE3
SET_STD_PCIE_INFO(pci_info, 3);
busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE3, &pci_info);
#else
- setbits_be32(&gur->devdisr, _DEVDISR_PCIE3); /* disable */
+ setbits_be32(addr, _DEVDISR_PCIE3); /* disable */
#endif
#ifdef CONFIG_PCIE4
SET_STD_PCIE_INFO(pci_info, 4);
busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE4, &pci_info);
#else
- setbits_be32(&gur->devdisr, _DEVDISR_PCIE4); /* disable */
+ setbits_be32(addr, _DEVDISR_PCIE4); /* disable */
#endif
return busno;
diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c
index 9f711519ed..345587be63 100644
--- a/drivers/qe/qe.c
+++ b/drivers/qe/qe.c
@@ -113,18 +113,21 @@ static void qe_sdma_init(void)
* we just need to know what the SNUMs are for the threads.
*/
static u8 thread_snum[] = {
+/* Evthreads 16-29 are not supported in MPC8309 */
+#if !defined(CONFIG_MPC8309)
0x04, 0x05, 0x0c, 0x0d,
0x14, 0x15, 0x1c, 0x1d,
0x24, 0x25, 0x2c, 0x2d,
- 0x34, 0x35, 0x88, 0x89,
- 0x98, 0x99, 0xa8, 0xa9,
- 0xb8, 0xb9, 0xc8, 0xc9,
- 0xd8, 0xd9, 0xe8, 0xe9,
- 0x08, 0x09, 0x18, 0x19,
- 0x28, 0x29, 0x38, 0x39,
- 0x48, 0x49, 0x58, 0x59,
- 0x68, 0x69, 0x78, 0x79,
- 0x80, 0x81
+ 0x34, 0x35,
+#endif
+ 0x88, 0x89, 0x98, 0x99,
+ 0xa8, 0xa9, 0xb8, 0xb9,
+ 0xc8, 0xc9, 0xd8, 0xd9,
+ 0xe8, 0xe9, 0x08, 0x09,
+ 0x18, 0x19, 0x28, 0x29,
+ 0x38, 0x39, 0x48, 0x49,
+ 0x58, 0x59, 0x68, 0x69,
+ 0x78, 0x79, 0x80, 0x81
};
static void qe_snums_init(void)
diff --git a/drivers/serial/altera_jtag_uart.c b/drivers/serial/altera_jtag_uart.c
index 654b5019eb..28319baf18 100644
--- a/drivers/serial/altera_jtag_uart.c
+++ b/drivers/serial/altera_jtag_uart.c
@@ -59,12 +59,6 @@ static void altera_jtag_serial_putc(char c)
writel ((unsigned char)c, &jtag->data);
}
-static void altera_jtag_serial_puts(const char *s)
-{
- while (*s != 0)
- serial_putc (*s++);
-}
-
static int altera_jtag_serial_tstc(void)
{
return ( readl (&jtag->control) & NIOS_JTAG_RRDY);
@@ -91,7 +85,7 @@ static struct serial_device altera_jtag_serial_drv = {
.stop = NULL,
.setbrg = altera_jtag_serial_setbrg,
.putc = altera_jtag_serial_putc,
- .puts = altera_jtag_serial_puts,
+ .puts = default_serial_puts,
.getc = altera_jtag_serial_getc,
.tstc = altera_jtag_serial_tstc,
};
diff --git a/drivers/serial/altera_uart.c b/drivers/serial/altera_uart.c
index 27550ed48d..118cd58ece 100644
--- a/drivers/serial/altera_uart.c
+++ b/drivers/serial/altera_uart.c
@@ -82,13 +82,6 @@ static void altera_serial_putc(char c)
writel ((unsigned char)c, &uart->txdata);
}
-static void altera_serial_puts(const char *s)
-{
- while (*s != 0) {
- serial_putc (*s++);
- }
-}
-
static int altera_serial_tstc(void)
{
return (readl (&uart->status) & NIOS_UART_RRDY);
@@ -107,7 +100,7 @@ static struct serial_device altera_serial_drv = {
.stop = NULL,
.setbrg = altera_serial_setbrg,
.putc = altera_serial_putc,
- .puts = altera_serial_puts,
+ .puts = default_serial_puts,
.getc = altera_serial_getc,
.tstc = altera_serial_tstc,
};
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c
index 130303129e..c4d7432efc 100644
--- a/drivers/serial/atmel_usart.c
+++ b/drivers/serial/atmel_usart.c
@@ -86,12 +86,6 @@ static void atmel_serial_putc(char c)
writel(c, &usart->thr);
}
-static void atmel_serial_puts(const char *s)
-{
- while (*s)
- serial_putc(*s++);
-}
-
static int atmel_serial_getc(void)
{
atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
@@ -113,7 +107,7 @@ static struct serial_device atmel_serial_drv = {
.stop = NULL,
.setbrg = atmel_serial_setbrg,
.putc = atmel_serial_putc,
- .puts = atmel_serial_puts,
+ .puts = default_serial_puts,
.getc = atmel_serial_getc,
.tstc = atmel_serial_tstc,
};
diff --git a/drivers/serial/lpc32xx_hsuart.c b/drivers/serial/lpc32xx_hsuart.c
index 02429b5541..7559916578 100644
--- a/drivers/serial/lpc32xx_hsuart.c
+++ b/drivers/serial/lpc32xx_hsuart.c
@@ -77,19 +77,13 @@ static int lpc32xx_serial_init(void)
return 0;
}
-static void lpc32xx_serial_puts(const char *s)
-{
- while (*s)
- serial_putc(*s++);
-}
-
static struct serial_device lpc32xx_serial_drv = {
.name = "lpc32xx_serial",
.start = lpc32xx_serial_init,
.stop = NULL,
.setbrg = lpc32xx_serial_setbrg,
.putc = lpc32xx_serial_putc,
- .puts = lpc32xx_serial_puts,
+ .puts = default_serial_puts,
.getc = lpc32xx_serial_getc,
.tstc = lpc32xx_serial_tstc,
};
diff --git a/drivers/serial/mcfuart.c b/drivers/serial/mcfuart.c
index 00a7114691..7e25797661 100644
--- a/drivers/serial/mcfuart.c
+++ b/drivers/serial/mcfuart.c
@@ -28,6 +28,8 @@
*/
#include <common.h>
+#include <serial.h>
+#include <linux/compiler.h>
#include <asm/immap.h>
#include <asm/uart.h>
@@ -87,13 +89,6 @@ static void mcf_serial_putc(const char c)
uart->utb = c;
}
-static void mcf_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc(*s++);
- }
-}
-
static int mcf_serial_getc(void)
{
volatile uart_t *uart = (volatile uart_t *)(CONFIG_SYS_UART_BASE);
@@ -136,7 +131,7 @@ static struct serial_device mcf_serial_drv = {
.stop = NULL,
.setbrg = mcf_serial_setbrg,
.putc = mcf_serial_putc,
- .puts = mcf_serial_puts,
+ .puts = default_serial_puts,
.getc = mcf_serial_getc,
.tstc = mcf_serial_tstc,
};
diff --git a/drivers/serial/ns9750_serial.c b/drivers/serial/ns9750_serial.c
index cb545c4065..85fc68a076 100644
--- a/drivers/serial/ns9750_serial.c
+++ b/drivers/serial/ns9750_serial.c
@@ -100,19 +100,6 @@ static void ns9750_serial_putc(const char c)
}
/***********************************************************************
- * @Function: serial_puts
- * @Return: n/a
- * @Descr: writes non-zero string to the FIFO.
- ***********************************************************************/
-
-static void ns9750_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc( *s++ );
- }
-}
-
-/***********************************************************************
* @Function: serial_getc
* @Return: the character read
* @Descr: performs only 8bit accesses to the FIFO. No error handling
@@ -215,7 +202,7 @@ static struct serial_device ns9750_serial_drv = {
.stop = NULL,
.setbrg = ns9750_serial_setbrg,
.putc = ns9750_serial_putc,
- .puts = ns9750_serial_puts,
+ .puts = default_serial_puts,
.getc = ns9750_serial_getc,
.tstc = ns9750_serial_tstc,
};
diff --git a/drivers/serial/opencores_yanu.c b/drivers/serial/opencores_yanu.c
index 49bccf3a6c..4ca6ef0b25 100644
--- a/drivers/serial/opencores_yanu.c
+++ b/drivers/serial/opencores_yanu.c
@@ -161,14 +161,6 @@ static void oc_serial_putc(char c)
writel((unsigned char)c, &uart->data);
}
-static void oc_serial_puts(const char *s)
-{
- while (*s != 0) {
- serial_putc (*s++);
- }
-}
-
-
static int oc_serial_tstc(void)
{
unsigned status ;
@@ -195,7 +187,7 @@ static struct serial_device oc_serial_drv = {
.stop = NULL,
.setbrg = oc_serial_setbrg,
.putc = oc_serial_putc,
- .puts = oc_serial_puts,
+ .puts = default_serial_puts,
.getc = oc_serial_getc,
.tstc = oc_serial_tstc,
};
diff --git a/drivers/serial/s3c4510b_uart.c b/drivers/serial/s3c4510b_uart.c
index 423d26e678..c460229e05 100644
--- a/drivers/serial/s3c4510b_uart.c
+++ b/drivers/serial/s3c4510b_uart.c
@@ -199,12 +199,10 @@ static int s3c4510b_serial_getc(void)
static void s3c4510b_serial_puts(const char *s)
{
- while (*s) {
- serial_putc (*s++);
- }
+ default_serial_puts(s);
/* busy wait for tx complete */
- while ( !uart->m_stat.bf.txComplete);
+ while (!uart->m_stat.bf.txComplete);
/* clear break */
uart->m_ctrl.bf.sendBreak = 0;
diff --git a/drivers/serial/s3c64xx.c b/drivers/serial/s3c64xx.c
index 9ab8a28d83..ea8d734a9e 100644
--- a/drivers/serial/s3c64xx.c
+++ b/drivers/serial/s3c64xx.c
@@ -166,19 +166,13 @@ static int s3c64xx_serial_tstc(void)
return uart->UTRSTAT & 0x1;
}
-static void s3c64xx_serial_puts(const char *s)
-{
- while (*s)
- serial_putc(*s++);
-}
-
static struct serial_device s3c64xx_serial_drv = {
.name = "s3c64xx_serial",
.start = s3c64xx_serial_init,
.stop = NULL,
.setbrg = s3c64xx_serial_setbrg,
.putc = s3c64xx_serial_putc,
- .puts = s3c64xx_serial_puts,
+ .puts = default_serial_puts,
.getc = s3c64xx_serial_getc,
.tstc = s3c64xx_serial_tstc,
};
diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index 5bbf3aeb44..e0886d562e 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -26,16 +26,35 @@
#include <stdio_dev.h>
#include <post.h>
#include <linux/compiler.h>
+#include <errno.h>
DECLARE_GLOBAL_DATA_PTR;
static struct serial_device *serial_devices;
static struct serial_device *serial_current;
+/**
+ * serial_null() - Void registration routine of a serial driver
+ *
+ * This routine implements a void registration routine of a serial
+ * driver. The registration routine of a particular driver is aliased
+ * to this empty function in case the driver is not compiled into
+ * U-Boot.
+ */
static void serial_null(void)
{
}
+/**
+ * serial_initfunc() - Forward declare of driver registration routine
+ * @name: Name of the real driver registration routine.
+ *
+ * This macro expands onto forward declaration of a driver registration
+ * routine, which is then used below in serial_initialize() function.
+ * The declaration is made weak and aliases to serial_null() so in case
+ * the driver is not compiled in, the function is still declared and can
+ * be used, but aliases to serial_null() and thus is optimized away.
+ */
#define serial_initfunc(name) \
void name(void) \
__attribute__((weak, alias("serial_null")));
@@ -94,6 +113,16 @@ serial_initfunc(s3c44b0_serial_initialize);
serial_initfunc(sa1100_serial_initialize);
serial_initfunc(sh_serial_initialize);
+/**
+ * serial_register() - Register serial driver with serial driver core
+ * @dev: Pointer to the serial driver structure
+ *
+ * This function registers the serial driver supplied via @dev with
+ * serial driver core, thus making U-Boot aware of it and making it
+ * available for U-Boot to use. On platforms that still require manual
+ * relocation of constant variables, relocation of the supplied structure
+ * is performed.
+ */
void serial_register(struct serial_device *dev)
{
#ifdef CONFIG_NEEDS_MANUAL_RELOC
@@ -117,6 +146,15 @@ void serial_register(struct serial_device *dev)
serial_devices = dev;
}
+/**
+ * serial_initialize() - Register all compiled-in serial port drivers
+ *
+ * This function registers all serial port drivers that are compiled
+ * into the U-Boot binary with the serial core, thus making them
+ * available to U-Boot to use. Lastly, this function assigns a default
+ * serial port to the serial core. That serial port is then used as a
+ * default output.
+ */
void serial_initialize(void)
{
mpc8xx_serial_initialize();
@@ -176,6 +214,13 @@ void serial_initialize(void)
serial_assign(default_serial_console()->name);
}
+/**
+ * serial_stdio_init() - Register serial ports with STDIO core
+ *
+ * This function generates a proxy driver for each serial port driver.
+ * These proxy drivers then register with the STDIO core, making the
+ * serial drivers available as STDIO devices.
+ */
void serial_stdio_init(void)
{
struct stdio_dev dev;
@@ -200,20 +245,38 @@ void serial_stdio_init(void)
}
}
+/**
+ * serial_assign() - Select the serial output device by name
+ * @name: Name of the serial driver to be used as default output
+ *
+ * This function configures the serial output multiplexing by
+ * selecting which serial device will be used as default. In case
+ * the STDIO "serial" device is selected as stdin/stdout/stderr,
+ * the serial device previously configured by this function will be
+ * used for the particular operation.
+ *
+ * Returns 0 on success, negative on error.
+ */
int serial_assign(const char *name)
{
struct serial_device *s;
for (s = serial_devices; s; s = s->next) {
- if (strcmp(s->name, name) == 0) {
- serial_current = s;
- return 0;
- }
+ if (strcmp(s->name, name))
+ continue;
+ serial_current = s;
+ return 0;
}
- return 1;
+ return -EINVAL;
}
+/**
+ * serial_reinit_all() - Reinitialize all compiled-in serial ports
+ *
+ * This function reinitializes all serial ports that are compiled
+ * into U-Boot by calling their serial_start() functions.
+ */
void serial_reinit_all(void)
{
struct serial_device *s;
@@ -222,60 +285,173 @@ void serial_reinit_all(void)
s->start();
}
+/**
+ * get_current() - Return pointer to currently selected serial port
+ *
+ * This function returns a pointer to currently selected serial port.
+ * The currently selected serial port is altered by serial_assign()
+ * function.
+ *
+ * In case this function is called before relocation or before any serial
+ * port is configured, this function calls default_serial_console() to
+ * determine the serial port. Otherwise, the configured serial port is
+ * returned.
+ *
+ * Returns pointer to the currently selected serial port on success,
+ * NULL on error.
+ */
static struct serial_device *get_current(void)
{
struct serial_device *dev;
- if (!(gd->flags & GD_FLG_RELOC) || !serial_current) {
+ if (!(gd->flags & GD_FLG_RELOC))
+ dev = default_serial_console();
+ else if (!serial_current)
dev = default_serial_console();
+ else
+ dev = serial_current;
- /* We must have a console device */
- if (!dev) {
+ /* We must have a console device */
+ if (!dev) {
#ifdef CONFIG_SPL_BUILD
- puts("Cannot find console\n");
- hang();
+ puts("Cannot find console\n");
+ hang();
#else
- panic("Cannot find console\n");
+ panic("Cannot find console\n");
#endif
- }
- } else
- dev = serial_current;
+ }
+
return dev;
}
+/**
+ * serial_init() - Initialize currently selected serial port
+ *
+ * This function initializes the currently selected serial port. This
+ * usually involves setting up the registers of that particular port,
+ * enabling clock and such. This function uses the get_current() call
+ * to determine which port is selected.
+ *
+ * Returns 0 on success, negative on error.
+ */
int serial_init(void)
{
return get_current()->start();
}
+/**
+ * serial_setbrg() - Configure baud-rate of currently selected serial port
+ *
+ * This function configures the baud-rate of the currently selected
+ * serial port. The baud-rate is retrieved from global data within
+ * the serial port driver. This function uses the get_current() call
+ * to determine which port is selected.
+ *
+ * Returns 0 on success, negative on error.
+ */
void serial_setbrg(void)
{
get_current()->setbrg();
}
+/**
+ * serial_getc() - Read character from currently selected serial port
+ *
+ * This function retrieves a character from currently selected serial
+ * port. In case there is no character waiting on the serial port,
+ * this function will block and wait for the character to appear. This
+ * function uses the get_current() call to determine which port is
+ * selected.
+ *
+ * Returns the character on success, negative on error.
+ */
int serial_getc(void)
{
return get_current()->getc();
}
+/**
+ * serial_tstc() - Test if data is available on currently selected serial port
+ *
+ * This function tests if one or more characters are available on
+ * currently selected serial port. This function never blocks. This
+ * function uses the get_current() call to determine which port is
+ * selected.
+ *
+ * Returns positive if character is available, zero otherwise.
+ */
int serial_tstc(void)
{
return get_current()->tstc();
}
+/**
+ * serial_putc() - Output character via currently selected serial port
+ * @c: Single character to be output from the serial port.
+ *
+ * This function outputs a character via currently selected serial
+ * port. This character is passed to the serial port driver responsible
+ * for controlling the hardware. The hardware may still be in process
+ * of transmitting another character, therefore this function may block
+ * for a short amount of time. This function uses the get_current()
+ * call to determine which port is selected.
+ */
void serial_putc(const char c)
{
get_current()->putc(c);
}
+/**
+ * serial_puts() - Output string via currently selected serial port
+ * @s: Zero-terminated string to be output from the serial port.
+ *
+ * This function outputs a zero-terminated string via currently
+ * selected serial port. This function behaves as an accelerator
+ * in case the hardware can queue multiple characters for transfer.
+ * The whole string that is to be output is available to the function
+ * implementing the hardware manipulation. Transmitting the whole
+ * string may take some time, thus this function may block for some
+ * amount of time. This function uses the get_current() call to
+ * determine which port is selected.
+ */
void serial_puts(const char *s)
{
get_current()->puts(s);
}
+/**
+ * default_serial_puts() - Output string by calling serial_putc() in loop
+ * @s: Zero-terminated string to be output from the serial port.
+ *
+ * This function outputs a zero-terminated string by calling serial_putc()
+ * in a loop. Most drivers do not support queueing more than one byte for
+ * transfer, thus this function precisely implements their serial_puts().
+ *
+ * To optimize the number of get_current() calls, this function only
+ * calls get_current() once and then directly accesses the putc() call
+ * of the &struct serial_device .
+ */
+void default_serial_puts(const char *s)
+{
+ struct serial_device *dev = get_current();
+ while (*s)
+ dev->putc(*s++);
+}
+
#if CONFIG_POST & CONFIG_SYS_POST_UART
static const int bauds[] = CONFIG_SYS_BAUDRATE_TABLE;
+/**
+ * uart_post_test() - Test the currently selected serial port using POST
+ * @flags: POST framework flags
+ *
+ * Do a loopback test of the currently selected serial port. This
+ * function is only useful in the context of the POST testing framwork.
+ * The serial port is firstly configured into loopback mode and then
+ * characters are sent through it.
+ *
+ * Returns 0 on success, value otherwise.
+ */
/* Mark weak until post/cpu/.../uart.c migrate over */
__weak
int uart_post_test(int flags)
diff --git a/drivers/serial/serial_clps7111.c b/drivers/serial/serial_clps7111.c
index 65473e8608..c292ed8756 100644
--- a/drivers/serial/serial_clps7111.c
+++ b/drivers/serial/serial_clps7111.c
@@ -112,20 +112,13 @@ static int clps7111_serial_getc(void)
return IO_UARTDR1 & 0xff;
}
-static void clps7111_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc (*s++);
- }
-}
-
static struct serial_device clps7111_serial_drv = {
.name = "clps7111_serial",
.start = clps7111_serial_init,
.stop = NULL,
.setbrg = clps7111_serial_setbrg,
.putc = clps7111_serial_putc,
- .puts = clps7111_serial_puts,
+ .puts = default_serial_puts,
.getc = clps7111_serial_getc,
.tstc = clps7111_serial_tstc,
};
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
index 6c075b5b91..9b9be44c52 100644
--- a/drivers/serial/serial_imx.c
+++ b/drivers/serial/serial_imx.c
@@ -214,20 +214,13 @@ static int imx_serial_tstc(void)
return 1;
}
-static void imx_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc (*s++);
- }
-}
-
static struct serial_device imx_serial_drv = {
.name = "imx_serial",
.start = imx_serial_init,
.stop = NULL,
.setbrg = imx_serial_setbrg,
.putc = imx_serial_putc,
- .puts = imx_serial_puts,
+ .puts = default_serial_puts,
.getc = imx_serial_getc,
.tstc = imx_serial_tstc,
};
diff --git a/drivers/serial/serial_ixp.c b/drivers/serial/serial_ixp.c
index c8b3658d47..09a3df4016 100644
--- a/drivers/serial/serial_ixp.c
+++ b/drivers/serial/serial_ixp.c
@@ -121,20 +121,13 @@ static int ixp_serial_getc(void)
return (char) RBR(CONFIG_SYS_IXP425_CONSOLE) & 0xff;
}
-static void ixp_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc (*s++);
- }
-}
-
static struct serial_device ixp_serial_drv = {
.name = "ixp_serial",
.start = ixp_serial_init,
.stop = NULL,
.setbrg = ixp_serial_setbrg,
.putc = ixp_serial_putc,
- .puts = ixp_serial_puts,
+ .puts = default_serial_puts,
.getc = ixp_serial_getc,
.tstc = ixp_serial_tstc,
};
diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c
index 60e8007201..8b1c974de9 100644
--- a/drivers/serial/serial_ks8695.c
+++ b/drivers/serial/serial_ks8695.c
@@ -102,13 +102,6 @@ static int ks8695_serial_tstc(void)
return 0;
}
-static void ks8695_serial_puts(const char *s)
-{
- char c;
- while ((c = *s++) != 0)
- serial_putc(c);
-}
-
static int ks8695_serial_getc(void)
{
volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
@@ -124,7 +117,7 @@ static struct serial_device ks8695_serial_drv = {
.stop = NULL,
.setbrg = ks8695_serial_setbrg,
.putc = ks8695_serial_putc,
- .puts = ks8695_serial_puts,
+ .puts = default_serial_puts,
.getc = ks8695_serial_getc,
.tstc = ks8695_serial_tstc,
};
diff --git a/drivers/serial/serial_lpc2292.c b/drivers/serial/serial_lpc2292.c
index fcab20280e..8abc476713 100644
--- a/drivers/serial/serial_lpc2292.c
+++ b/drivers/serial/serial_lpc2292.c
@@ -89,13 +89,6 @@ static int lpc2292_serial_getc(void)
return GET8(U0RBR);
}
-static void lpc2292_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc (*s++);
- }
-}
-
/* Test if there is a byte to read */
static int lpc2292_serial_tstc(void)
{
@@ -108,7 +101,7 @@ static struct serial_device lpc2292_serial_drv = {
.stop = NULL,
.setbrg = lpc2292_serial_setbrg,
.putc = lpc2292_serial_putc,
- .puts = lpc2292_serial_puts,
+ .puts = default_serial_puts,
.getc = lpc2292_serial_getc,
.tstc = lpc2292_serial_tstc,
};
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c
index b0612f5aca..9227d64088 100644
--- a/drivers/serial/serial_mxc.c
+++ b/drivers/serial/serial_mxc.c
@@ -187,13 +187,6 @@ static int mxc_serial_tstc(void)
return 1;
}
-static void mxc_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc (*s++);
- }
-}
-
/*
* Initialise the serial port with the given baudrate. The settings
* are always 8 data bits, no parity, 1 stop bit, no start bits.
@@ -228,7 +221,7 @@ static struct serial_device mxc_serial_drv = {
.stop = NULL,
.setbrg = mxc_serial_setbrg,
.putc = mxc_serial_putc,
- .puts = mxc_serial_puts,
+ .puts = default_serial_puts,
.getc = mxc_serial_getc,
.tstc = mxc_serial_tstc,
};
diff --git a/drivers/serial/serial_netarm.c b/drivers/serial/serial_netarm.c
index d30adc3183..44d7c500c7 100644
--- a/drivers/serial/serial_netarm.c
+++ b/drivers/serial/serial_netarm.c
@@ -182,20 +182,13 @@ static int netarm_serial_getc(void)
return ch_uint & 0xff;
}
-static void netarm_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc (*s++);
- }
-}
-
static struct serial_device netarm_serial_drv = {
.name = "netarm_serial",
.start = netarm_serial_init,
.stop = NULL,
.setbrg = netarm_serial_setbrg,
.putc = netarm_serial_putc,
- .puts = netarm_serial_puts,
+ .puts = default_serial_puts,
.getc = netarm_serial_getc,
.tstc = netarm_serial_tstc,
};
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index 7db7b65c3f..b331be794b 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -179,13 +179,6 @@ static void pl01x_serial_putc(const char c)
pl01x_putc (CONSOLE_PORT, c);
}
-static void pl01x_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc (*s++);
- }
-}
-
static int pl01x_serial_getc(void)
{
return pl01x_getc (CONSOLE_PORT);
@@ -259,7 +252,7 @@ static struct serial_device pl01x_serial_drv = {
.stop = NULL,
.setbrg = pl01x_serial_setbrg,
.putc = pl01x_serial_putc,
- .puts = pl01x_serial_puts,
+ .puts = default_serial_puts,
.getc = pl01x_serial_getc,
.tstc = pl01x_serial_tstc,
};
diff --git a/drivers/serial/serial_s3c44b0.c b/drivers/serial/serial_s3c44b0.c
index a4428e0f47..9cae843088 100644
--- a/drivers/serial/serial_s3c44b0.c
+++ b/drivers/serial/serial_s3c44b0.c
@@ -209,20 +209,13 @@ static int s3c44b0_serial_getc(void)
}
}
-static void s3c44b0_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc (*s++);
- }
-}
-
static struct serial_device s3c44b0_serial_drv = {
.name = "s3c44b0_serial",
.start = s3c44b0_serial_init,
.stop = NULL,
.setbrg = s3c44b0_serial_setbrg,
.putc = s3c44b0_serial_putc,
- .puts = s3c44b0_serial_puts,
+ .puts = default_serial_puts,
.getc = s3c44b0_serial_getc,
.tstc = s3c44b0_serial_tstc,
};
diff --git a/drivers/serial/serial_sa1100.c b/drivers/serial/serial_sa1100.c
index c6b34db7c6..3c0f4c59fb 100644
--- a/drivers/serial/serial_sa1100.c
+++ b/drivers/serial/serial_sa1100.c
@@ -153,20 +153,13 @@ static int sa1100_serial_getc(void)
#endif
}
-static void sa1100_serial_puts(const char *s)
-{
- while (*s) {
- serial_putc (*s++);
- }
-}
-
static struct serial_device sa1100_serial_drv = {
.name = "sa1100_serial",
.start = sa1100_serial_init,
.stop = NULL,
.setbrg = sa1100_serial_setbrg,
.putc = sa1100_serial_putc,
- .puts = sa1100_serial_puts,
+ .puts = default_serial_puts,
.getc = sa1100_serial_getc,
.tstc = sa1100_serial_tstc,
};
diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c
index 1ddfc7d87f..3c931d0212 100644
--- a/drivers/serial/serial_sh.c
+++ b/drivers/serial/serial_sh.c
@@ -136,13 +136,6 @@ static void sh_serial_putc(const char c)
serial_raw_putc(c);
}
-static void sh_serial_puts(const char *s)
-{
- char c;
- while ((c = *s++) != 0)
- serial_putc(c);
-}
-
static int sh_serial_tstc(void)
{
return serial_rx_fifo_level() ? 1 : 0;
@@ -196,7 +189,7 @@ static struct serial_device sh_serial_drv = {
.stop = NULL,
.setbrg = sh_serial_setbrg,
.putc = sh_serial_putc,
- .puts = sh_serial_puts,
+ .puts = default_serial_puts,
.getc = sh_serial_getc,
.tstc = sh_serial_tstc,
};
diff --git a/drivers/spi/fsl_espi.c b/drivers/spi/fsl_espi.c
index a1ebd330d7..eb99e90bec 100644
--- a/drivers/spi/fsl_espi.c
+++ b/drivers/spi/fsl_espi.c
@@ -216,10 +216,8 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out,
return 1;
}
memcpy(buffer, cmd_buf, cmd_len);
- if (cmd_len != 1) {
- if (data_in == NULL)
- memcpy(buffer + cmd_len, data_out, data_len);
- }
+ if (data_in == NULL)
+ memcpy(buffer + cmd_len, data_out, data_len);
break;
case SPI_XFER_BEGIN | SPI_XFER_END:
len = data_len;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 7b8f033b03..f54b408966 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -30,6 +30,18 @@
#include "ehci.h"
+/* Check USB PHY clock valid */
+static int usb_phy_clk_valid(struct usb_ehci *ehci)
+{
+ if (!((in_be32(&ehci->control) & PHY_CLK_VALID) ||
+ in_be32(&ehci->prictrl))) {
+ printf("USB PHY clock invalid!\n");
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
/*
* Create the appropriate control structures to manage
* a new EHCI host controller.
@@ -82,18 +94,16 @@ int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor)
udelay(1000); /* delay required for PHY Clk to appear */
#endif
out_le32(&(*hcor)->or_portsc[0], PORT_PTS_UTMI);
+ setbits_be32(&ehci->control, USB_EN);
} else {
-#if defined(CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY)
- clrbits_be32(&ehci->control, UTMI_PHY_EN);
setbits_be32(&ehci->control, PHY_CLK_SEL_ULPI);
+ clrsetbits_be32(&ehci->control, UTMI_PHY_EN, USB_EN);
udelay(1000); /* delay required for PHY Clk to appear */
-#endif
+ if (!usb_phy_clk_valid(ehci))
+ return -EINVAL;
out_le32(&(*hcor)->or_portsc[0], PORT_PTS_ULPI);
}
- /* Enable interface. */
- setbits_be32(&ehci->control, USB_EN);
-
out_be32(&ehci->prictrl, 0x0000000c);
out_be32(&ehci->age_cnt_limit, 0x00000040);
out_be32(&ehci->sictrl, 0x00000001);
OpenPOWER on IntegriCloud