summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorWolfgang Denk <wd@denx.de>2010-10-13 20:59:47 +0200
committerWolfgang Denk <wd@denx.de>2010-10-13 20:59:47 +0200
commite1b4c57096b87b4ada56df4154d9acee6a59141f (patch)
tree4d1ab61fd347a63410bcffc1ac2d85beeb247058 /drivers
parentda61f6c45ad4a126bf0a9a8184fadc13073ecb3f (diff)
parent89bca0ab697fc75160dd0d685d7cb2ed26609a6d (diff)
downloadu-boot-imx-e1b4c57096b87b4ada56df4154d9acee6a59141f.zip
u-boot-imx-e1b4c57096b87b4ada56df4154d9acee6a59141f.tar.gz
u-boot-imx-e1b4c57096b87b4ada56df4154d9acee6a59141f.tar.bz2
Merge branch 'master' of git://git.denx.de/u-boot-arm
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/mvsata_ide.c42
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/mxc_gpio.c (renamed from drivers/gpio/mx31_gpio.c)47
-rw-r--r--drivers/misc/fsl_pmic.c10
-rw-r--r--drivers/net/at91_emac.c22
-rw-r--r--drivers/serial/atmel_usart.c36
-rw-r--r--drivers/serial/atmel_usart.h56
-rw-r--r--drivers/serial/serial_mxc.c7
-rw-r--r--drivers/serial/serial_pl01x.c93
-rw-r--r--drivers/spi/mxc_spi.c168
10 files changed, 298 insertions, 185 deletions
diff --git a/drivers/block/mvsata_ide.c b/drivers/block/mvsata_ide.c
index 077b278..3d6993a 100644
--- a/drivers/block/mvsata_ide.c
+++ b/drivers/block/mvsata_ide.c
@@ -91,29 +91,48 @@ struct mvsata_port_registers {
#define MVSATA_SSTATUS_DET_DEVCOMM 0x00000003
/*
+ * Status codes to return to client callers. Currently, callers ignore
+ * exact value and only care for zero or nonzero, so no need to make this
+ * public, it is only #define'd for clarity.
+ * If/when standard negative codes are implemented in U-boot, then these
+ * #defines should be moved to, or replaced by ones from, the common list
+ * of status codes.
+ */
+
+#define MVSATA_STATUS_OK 0
+#define MVSATA_STATUS_TIMEOUT -1
+
+/*
* Initialize one MVSATAHC port: set SControl's IPM to "always active"
* and DET to "reset", then wait for SStatus's DET to become "device and
* comm ok" (or time out after 50 us if no device), then set SControl's
* DET back to "no action".
*/
-static void mvsata_ide_initialize_port(struct mvsata_port_registers *port)
+static int mvsata_ide_initialize_port(struct mvsata_port_registers *port)
{
u32 control;
u32 status;
- u32 tout = 50; /* wait at most 50 us for SATA reset to complete */
+ u32 timeleft = 10000; /* wait at most 10 ms for SATA reset to complete */
+ /* Set control IPM to 3 (no low power) and DET to 1 (initialize) */
control = readl(&port->scontrol);
control = (control & ~MVSATA_SCONTROL_MASK) | MVSATA_PORT_INIT;
writel(control, &port->scontrol);
- while (--tout) {
+ /* Toggle control DET back to 0 (normal operation) */
+ control = (control & ~MVSATA_SCONTROL_MASK) | MVSATA_PORT_USE;
+ writel(control, &port->scontrol);
+ /* wait for status DET to become 3 (device and communication OK) */
+ while (--timeleft) {
status = readl(&port->sstatus) & MVSATA_SSTATUS_DET_MASK;
if (status == MVSATA_SSTATUS_DET_DEVCOMM)
break;
udelay(1);
}
- control = (control & ~MVSATA_SCONTROL_MASK) | MVSATA_PORT_USE;
- writel(control, &port->scontrol);
+ /* return success or time-out error depending on time left */
+ if (!timeleft)
+ return MVSATA_STATUS_TIMEOUT;
+ return MVSATA_STATUS_OK;
}
/*
@@ -123,18 +142,23 @@ static void mvsata_ide_initialize_port(struct mvsata_port_registers *port)
int ide_preinit(void)
{
+ int status;
/* Enable ATA port 0 (could be SATA port 0 or 1) if declared */
#if defined(CONFIG_SYS_ATA_IDE0_OFFSET)
- mvsata_ide_initialize_port(
+ status = mvsata_ide_initialize_port(
(struct mvsata_port_registers *)
(CONFIG_SYS_ATA_BASE_ADDR + CONFIG_SYS_ATA_IDE0_OFFSET));
+ if (status)
+ return status;
#endif
/* Enable ATA port 1 (could be SATA port 0 or 1) if declared */
#if defined(CONFIG_SYS_ATA_IDE1_OFFSET)
- mvsata_ide_initialize_port(
+ status = mvsata_ide_initialize_port(
(struct mvsata_port_registers *)
(CONFIG_SYS_ATA_BASE_ADDR + CONFIG_SYS_ATA_IDE1_OFFSET));
+ if (status)
+ return status;
#endif
- /* return 0 as we always succeed */
- return 0;
+ /* return success if all ports initializations succeeded */
+ return MVSATA_STATUS_OK;
}
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 07d395d..a0f4552 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -27,7 +27,7 @@ LIB := $(obj)libgpio.a
COBJS-$(CONFIG_AT91_GPIO) += at91_gpio.o
COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
-COBJS-$(CONFIG_MX31_GPIO) += mx31_gpio.o
+COBJS-$(CONFIG_MXC_GPIO) += mxc_gpio.o
COBJS-$(CONFIG_PCA953X) += pca953x.o
COBJS-$(CONFIG_S5P) += s5p_gpio.o
diff --git a/drivers/gpio/mx31_gpio.c b/drivers/gpio/mxc_gpio.c
index b07f038..663141f 100644
--- a/drivers/gpio/mx31_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -21,19 +21,29 @@
* MA 02111-1307 USA
*/
#include <common.h>
-#include <asm/arch/mx31.h>
+#ifdef CONFIG_MX31
#include <asm/arch/mx31-regs.h>
+#endif
+#ifdef CONFIG_MX51
+#include <asm/arch/imx-regs.h>
+#endif
+#include <asm/io.h>
+#include <mxc_gpio.h>
/* GPIO port description */
static unsigned long gpio_ports[] = {
- [0] = GPIO1_BASE,
- [1] = GPIO2_BASE,
- [2] = GPIO3_BASE,
+ [0] = GPIO1_BASE_ADDR,
+ [1] = GPIO2_BASE_ADDR,
+ [2] = GPIO3_BASE_ADDR,
+#ifdef CONFIG_MX51
+ [3] = GPIO4_BASE_ADDR,
+#endif
};
-int mx31_gpio_direction(unsigned int gpio, enum mx31_gpio_direction direction)
+int mxc_gpio_direction(unsigned int gpio, enum mxc_gpio_direction direction)
{
unsigned int port = gpio >> 5;
+ struct gpio_regs *regs;
u32 l;
if (port >= ARRAY_SIZE(gpio_ports))
@@ -41,22 +51,26 @@ int mx31_gpio_direction(unsigned int gpio, enum mx31_gpio_direction direction)
gpio &= 0x1f;
- l = __REG(gpio_ports[port] + GPIO_GDIR);
+ regs = (struct gpio_regs *)gpio_ports[port];
+
+ l = readl(&regs->gpio_dir);
+
switch (direction) {
- case MX31_GPIO_DIRECTION_OUT:
+ case MXC_GPIO_DIRECTION_OUT:
l |= 1 << gpio;
break;
- case MX31_GPIO_DIRECTION_IN:
+ case MXC_GPIO_DIRECTION_IN:
l &= ~(1 << gpio);
}
- __REG(gpio_ports[port] + GPIO_GDIR) = l;
+ writel(l, &regs->gpio_dir);
return 0;
}
-void mx31_gpio_set(unsigned int gpio, unsigned int value)
+void mxc_gpio_set(unsigned int gpio, unsigned int value)
{
unsigned int port = gpio >> 5;
+ struct gpio_regs *regs;
u32 l;
if (port >= ARRAY_SIZE(gpio_ports))
@@ -64,17 +78,20 @@ void mx31_gpio_set(unsigned int gpio, unsigned int value)
gpio &= 0x1f;
- l = __REG(gpio_ports[port] + GPIO_DR);
+ regs = (struct gpio_regs *)gpio_ports[port];
+
+ l = readl(&regs->gpio_dr);
if (value)
l |= 1 << gpio;
else
l &= ~(1 << gpio);
- __REG(gpio_ports[port] + GPIO_DR) = l;
+ writel(l, &regs->gpio_dr);
}
-int mx31_gpio_get(unsigned int gpio)
+int mxc_gpio_get(unsigned int gpio)
{
unsigned int port = gpio >> 5;
+ struct gpio_regs *regs;
u32 l;
if (port >= ARRAY_SIZE(gpio_ports))
@@ -82,7 +99,9 @@ int mx31_gpio_get(unsigned int gpio)
gpio &= 0x1f;
- l = (__REG(gpio_ports[port] + GPIO_DR) >> gpio) & 0x01;
+ regs = (struct gpio_regs *)gpio_ports[port];
+
+ l = (readl(&regs->gpio_dr) >> gpio) & 0x01;
return l;
}
diff --git a/drivers/misc/fsl_pmic.c b/drivers/misc/fsl_pmic.c
index dca0a1d..5ee1de1 100644
--- a/drivers/misc/fsl_pmic.c
+++ b/drivers/misc/fsl_pmic.c
@@ -46,6 +46,7 @@ void pmic_spi_free(struct spi_slave *slave)
u32 pmic_reg(u32 reg, u32 val, u32 write)
{
u32 pmic_tx, pmic_rx;
+ u32 tmp;
if (!slave) {
slave = pmic_spi_probe();
@@ -65,7 +66,9 @@ u32 pmic_reg(u32 reg, u32 val, u32 write)
pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF);
- if (spi_xfer(slave, 4 << 3, &pmic_tx, &pmic_rx,
+ tmp = cpu_to_be32(pmic_tx);
+
+ if (spi_xfer(slave, 4 << 3, &tmp, &pmic_rx,
SPI_XFER_BEGIN | SPI_XFER_END)) {
spi_release_bus(slave);
return -1;
@@ -73,7 +76,8 @@ u32 pmic_reg(u32 reg, u32 val, u32 write)
if (write) {
pmic_tx &= ~(1 << 31);
- if (spi_xfer(slave, 4 << 3, &pmic_tx, &pmic_rx,
+ tmp = cpu_to_be32(pmic_tx);
+ if (spi_xfer(slave, 4 << 3, &tmp, &pmic_rx,
SPI_XFER_BEGIN | SPI_XFER_END)) {
spi_release_bus(slave);
return -1;
@@ -81,7 +85,7 @@ u32 pmic_reg(u32 reg, u32 val, u32 write)
}
spi_release_bus(slave);
- return pmic_rx;
+ return cpu_to_be32(pmic_rx);
}
void pmic_reg_write(u32 reg, u32 value)
diff --git a/drivers/net/at91_emac.c b/drivers/net/at91_emac.c
index c525eed..4e5685c 100644
--- a/drivers/net/at91_emac.c
+++ b/drivers/net/at91_emac.c
@@ -127,13 +127,19 @@ void at91emac_DisableMDIO(at91_emac_t *at91mac)
int at91emac_read(at91_emac_t *at91mac, unsigned char addr,
unsigned char reg, unsigned short *value)
{
+ unsigned long netstat;
at91emac_EnableMDIO(at91mac);
writel(AT91_EMAC_MAN_HIGH | AT91_EMAC_MAN_RW_R |
AT91_EMAC_MAN_REGA(reg) | AT91_EMAC_MAN_CODE_802_3 |
AT91_EMAC_MAN_PHYA(addr),
&at91mac->man);
- udelay(10000);
+
+ do {
+ netstat = readl(&at91mac->sr);
+ DEBUG_AT91PHY("poll SR %08lx\n", netstat);
+ } while (!(netstat & AT91_EMAC_SR_IDLE));
+
*value = readl(&at91mac->man) & AT91_EMAC_MAN_DATA_MASK;
at91emac_DisableMDIO(at91mac);
@@ -146,6 +152,7 @@ int at91emac_read(at91_emac_t *at91mac, unsigned char addr,
int at91emac_write(at91_emac_t *at91mac, unsigned char addr,
unsigned char reg, unsigned short value)
{
+ unsigned long netstat;
DEBUG_AT91PHY("AT91PHY write %x REG(%d)=%x\n", at91mac, reg, &value)
at91emac_EnableMDIO(at91mac);
@@ -154,9 +161,14 @@ int at91emac_write(at91_emac_t *at91mac, unsigned char addr,
AT91_EMAC_MAN_REGA(reg) | AT91_EMAC_MAN_CODE_802_3 |
AT91_EMAC_MAN_PHYA(addr) | (value & AT91_EMAC_MAN_DATA_MASK),
&at91mac->man);
- udelay(10000);
+
+ do {
+ netstat = readl(&at91mac->sr);
+ DEBUG_AT91PHY("poll SR %08lx\n", netstat);
+ } while (!(netstat & AT91_EMAC_SR_IDLE));
at91emac_DisableMDIO(at91mac);
+
return 0;
}
@@ -500,11 +512,7 @@ int at91emac_register(bd_t *bis, unsigned long iobase)
memset(emacfix, 0, sizeof(emac_device));
memset(dev, 0, sizeof(*dev));
-#ifndef CONFIG_RMII
- sprintf(dev->name, "AT91 EMAC");
-#else
- sprintf(dev->name, "AT91 EMAC RMII");
-#endif
+ sprintf(dev->name, "emac");
dev->iobase = iobase;
dev->priv = emacfix;
dev->init = at91emac_init;
diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c
index cad3412..bfa1f3a 100644
--- a/drivers/serial/atmel_usart.c
+++ b/drivers/serial/atmel_usart.c
@@ -1,6 +1,9 @@
/*
* Copyright (C) 2004-2006 Atmel Corporation
*
+ * Modified to support C structur SoC access by
+ * Andreas Bießmann <biessmann@corscience.de>
+ *
* 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
@@ -16,10 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <common.h>
-#ifndef CONFIG_AT91_LEGACY
-#define CONFIG_AT91_LEGACY
-#warning Please update to use C structur SoC access !
-#endif
#include <watchdog.h>
#include <asm/io.h>
@@ -46,6 +45,7 @@ DECLARE_GLOBAL_DATA_PTR;
void serial_setbrg(void)
{
+ atmel_usart3_t *usart = (atmel_usart3_t*)USART_BASE;
unsigned long divisor;
unsigned long usart_hz;
@@ -56,32 +56,37 @@ void serial_setbrg(void)
*/
usart_hz = get_usart_clk_rate(USART_ID);
divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate;
- usart3_writel(BRGR, USART3_BF(CD, divisor));
+ writel(USART3_BF(CD, divisor), &usart->brgr);
}
int serial_init(void)
{
- usart3_writel(CR, USART3_BIT(RSTRX) | USART3_BIT(RSTTX));
+ atmel_usart3_t *usart = (atmel_usart3_t*)USART_BASE;
+
+ writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr);
serial_setbrg();
- usart3_writel(CR, USART3_BIT(RXEN) | USART3_BIT(TXEN));
- usart3_writel(MR, (USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
+ writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr);
+ writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
| USART3_BF(USCLKS, USART3_USCLKS_MCK)
| USART3_BF(CHRL, USART3_CHRL_8)
| USART3_BF(PAR, USART3_PAR_NONE)
- | USART3_BF(NBSTOP, USART3_NBSTOP_1)));
+ | USART3_BF(NBSTOP, USART3_NBSTOP_1)),
+ &usart->mr);
return 0;
}
void serial_putc(char c)
{
+ atmel_usart3_t *usart = (atmel_usart3_t*)USART_BASE;
+
if (c == '\n')
serial_putc('\r');
- while (!(usart3_readl(CSR) & USART3_BIT(TXRDY))) ;
- usart3_writel(THR, c);
+ while (!(readl(&usart->csr) & USART3_BIT(TXRDY)));
+ writel(c, &usart->thr);
}
void serial_puts(const char *s)
@@ -92,12 +97,15 @@ void serial_puts(const char *s)
int serial_getc(void)
{
- while (!(usart3_readl(CSR) & USART3_BIT(RXRDY)))
+ atmel_usart3_t *usart = (atmel_usart3_t*)USART_BASE;
+
+ while (!(readl(&usart->csr) & USART3_BIT(RXRDY)))
WATCHDOG_RESET();
- return usart3_readl(RHR);
+ return readl(&usart->rhr);
}
int serial_tstc(void)
{
- return (usart3_readl(CSR) & USART3_BIT(RXRDY)) != 0;
+ atmel_usart3_t *usart = (atmel_usart3_t*)USART_BASE;
+ return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0;
}
diff --git a/drivers/serial/atmel_usart.h b/drivers/serial/atmel_usart.h
index af3773a..7cfc2d5 100644
--- a/drivers/serial/atmel_usart.h
+++ b/drivers/serial/atmel_usart.h
@@ -3,6 +3,9 @@
*
* Copyright (C) 2005-2006 Atmel Corporation
*
+ * Modified to support C structure SoC access by
+ * Andreas Bießmann <biessmann@corscience.de>
+ *
* 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
@@ -20,32 +23,27 @@
#ifndef __DRIVERS_ATMEL_USART_H__
#define __DRIVERS_ATMEL_USART_H__
-/* USART3 register offsets */
-#define USART3_CR 0x0000
-#define USART3_MR 0x0004
-#define USART3_IER 0x0008
-#define USART3_IDR 0x000c
-#define USART3_IMR 0x0010
-#define USART3_CSR 0x0014
-#define USART3_RHR 0x0018
-#define USART3_THR 0x001c
-#define USART3_BRGR 0x0020
-#define USART3_RTOR 0x0024
-#define USART3_TTGR 0x0028
-#define USART3_FIDI 0x0040
-#define USART3_NER 0x0044
-#define USART3_XXR 0x0048
-#define USART3_IFR 0x004c
-#define USART3_RPR 0x0100
-#define USART3_RCR 0x0104
-#define USART3_TPR 0x0108
-#define USART3_TCR 0x010c
-#define USART3_RNPR 0x0110
-#define USART3_RNCR 0x0114
-#define USART3_TNPR 0x0118
-#define USART3_TNCR 0x011c
-#define USART3_PTCR 0x0120
-#define USART3_PTSR 0x0124
+/* USART3 register footprint */
+typedef struct atmel_usart3 {
+ u32 cr;
+ u32 mr;
+ u32 ier;
+ u32 idr;
+ u32 imr;
+ u32 csr;
+ u32 rhr;
+ u32 thr;
+ u32 brgr;
+ u32 rtor;
+ u32 ttgr;
+ u32 reserved0[5];
+ u32 fidi;
+ u32 ner;
+ u32 reserved1;
+ u32 ifr;
+ u32 man;
+ u32 reserved2[54]; // version and PDC not needed
+} atmel_usart3_t;
/* Bitfields in CR */
#define USART3_RSTRX_OFFSET 2
@@ -305,10 +303,4 @@
<< USART3_##name##_OFFSET)) \
| USART3_BF(name,value))
-/* Register access macros */
-#define usart3_readl(reg) \
- readl((void *)USART_BASE + USART3_##reg)
-#define usart3_writel(reg,value) \
- writel((value), (void *)USART_BASE + USART3_##reg)
-
#endif /* __DRIVERS_ATMEL_USART_H__ */
diff --git a/drivers/serial/serial_mxc.c b/drivers/serial/serial_mxc.c
index 4b93e7b..f96b21f 100644
--- a/drivers/serial/serial_mxc.c
+++ b/drivers/serial/serial_mxc.c
@@ -18,6 +18,7 @@
*/
#include <common.h>
+#include <watchdog.h>
#ifdef CONFIG_MX31
#include <asm/arch/mx31.h>
#else
@@ -189,7 +190,8 @@ void serial_setbrg (void)
int serial_getc (void)
{
- while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY);
+ while (__REG(UART_PHYS + UTS) & UTS_RXEMPTY)
+ WATCHDOG_RESET();
return (__REG(UART_PHYS + URXD) & URXD_RX_DATA); /* mask out status from upper word */
}
@@ -198,7 +200,8 @@ void serial_putc (const char c)
__REG(UART_PHYS + UTXD) = c;
/* wait for transmitter to be ready */
- while(!(__REG(UART_PHYS + UTS) & UTS_TXEMPTY));
+ while (!(__REG(UART_PHYS + UTS) & UTS_TXEMPTY))
+ WATCHDOG_RESET();
/* If \n, also do \r */
if (c == '\n')
diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c
index c645cef..c0ae947 100644
--- a/drivers/serial/serial_pl01x.c
+++ b/drivers/serial/serial_pl01x.c
@@ -29,25 +29,23 @@
#include <common.h>
#include <watchdog.h>
-
+#include <asm/io.h>
#include "serial_pl01x.h"
-#define IO_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (val))
-#define IO_READ(addr) (*(volatile unsigned int *)(addr))
-
/*
* Integrator AP has two UARTs, we use the first one, at 38400-8-N-1
* Integrator CP has two UARTs, use the first one, at 38400-8-N-1
* Versatile PB has four UARTs.
*/
#define CONSOLE_PORT CONFIG_CONS_INDEX
-#define baudRate CONFIG_BAUDRATE
static volatile unsigned char *const port[] = CONFIG_PL01x_PORTS;
#define NUM_PORTS (sizeof(port)/sizeof(port[0]))
static void pl01x_putc (int portnum, char c);
static int pl01x_getc (int portnum);
static int pl01x_tstc (int portnum);
+unsigned int baudrate = CONFIG_BAUDRATE;
+DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_PL010_SERIAL
@@ -55,16 +53,11 @@ int serial_init (void)
{
unsigned int divisor;
- /*
- ** First, disable everything.
- */
- IO_WRITE (port[CONSOLE_PORT] + UART_PL010_CR, 0x0);
+ /* First, disable everything */
+ writel(0x0, port[CONSOLE_PORT] + UART_PL010_CR);
- /*
- ** Set baud rate
- **
- */
- switch (baudRate) {
+ /* Set baud rate */
+ switch (baudrate) {
case 9600:
divisor = UART_PL010_BAUD_9600;
break;
@@ -89,20 +82,15 @@ int serial_init (void)
divisor = UART_PL010_BAUD_38400;
}
- IO_WRITE (port[CONSOLE_PORT] + UART_PL010_LCRM,
- ((divisor & 0xf00) >> 8));
- IO_WRITE (port[CONSOLE_PORT] + UART_PL010_LCRL, (divisor & 0xff));
+ writel(((divisor & 0xf00) >> 8), port[CONSOLE_PORT] + UART_PL010_LCRM);
+ writel((divisor & 0xff), port[CONSOLE_PORT] + UART_PL010_LCRL);
- /*
- ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled.
- */
- IO_WRITE (port[CONSOLE_PORT] + UART_PL010_LCRH,
- (UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN));
+ /* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */
+ writel((UART_PL010_LCRH_WLEN_8 | UART_PL010_LCRH_FEN),
+ port[CONSOLE_PORT] + UART_PL010_LCRH);
- /*
- ** Finally, enable the UART
- */
- IO_WRITE (port[CONSOLE_PORT] + UART_PL010_CR, (UART_PL010_CR_UARTEN));
+ /* Finally, enable the UART */
+ writel((UART_PL010_CR_UARTEN), port[CONSOLE_PORT] + UART_PL010_CR);
return 0;
}
@@ -118,38 +106,31 @@ int serial_init (void)
unsigned int remainder;
unsigned int fraction;
- /*
- ** First, disable everything.
- */
- IO_WRITE (port[CONSOLE_PORT] + UART_PL011_CR, 0x0);
+ /* First, disable everything */
+ writel(0x0, port[CONSOLE_PORT] + UART_PL011_CR);
/*
- ** Set baud rate
- **
- ** IBRD = UART_CLK / (16 * BAUD_RATE)
- ** FBRD = ROUND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) / (16 * BAUD_RATE))
+ * Set baud rate
+ *
+ * IBRD = UART_CLK / (16 * BAUD_RATE)
+ * FBRD = RND((64 * MOD(UART_CLK,(16 * BAUD_RATE))) / (16 * BAUD_RATE))
*/
- temp = 16 * baudRate;
+ temp = 16 * baudrate;
divider = CONFIG_PL011_CLOCK / temp;
remainder = CONFIG_PL011_CLOCK % temp;
- temp = (8 * remainder) / baudRate;
+ temp = (8 * remainder) / baudrate;
fraction = (temp >> 1) + (temp & 1);
- IO_WRITE (port[CONSOLE_PORT] + UART_PL011_IBRD, divider);
- IO_WRITE (port[CONSOLE_PORT] + UART_PL011_FBRD, fraction);
+ writel(divider, port[CONSOLE_PORT] + UART_PL011_IBRD);
+ writel(fraction, port[CONSOLE_PORT] + UART_PL011_FBRD);
- /*
- ** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled.
- */
- IO_WRITE (port[CONSOLE_PORT] + UART_PL011_LCRH,
- (UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN));
+ /* Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled */
+ writel((UART_PL011_LCRH_WLEN_8 | UART_PL011_LCRH_FEN),
+ port[CONSOLE_PORT] + UART_PL011_LCRH);
- /*
- ** Finally, enable the UART
- */
- IO_WRITE (port[CONSOLE_PORT] + UART_PL011_CR,
- (UART_PL011_CR_UARTEN | UART_PL011_CR_TXE |
- UART_PL011_CR_RXE));
+ /* Finally, enable the UART */
+ writel((UART_PL011_CR_UARTEN | UART_PL011_CR_TXE | UART_PL011_CR_RXE),
+ port[CONSOLE_PORT] + UART_PL011_CR);
return 0;
}
@@ -183,16 +164,18 @@ int serial_tstc (void)
void serial_setbrg (void)
{
+ baudrate = gd->baudrate;
+ serial_init();
}
static void pl01x_putc (int portnum, char c)
{
/* Wait until there is space in the FIFO */
- while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_TXFF)
+ while (readl(port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_TXFF)
WATCHDOG_RESET();
/* Send the character */
- IO_WRITE (port[portnum] + UART_PL01x_DR, c);
+ writel(c, port[portnum] + UART_PL01x_DR);
}
static int pl01x_getc (int portnum)
@@ -200,15 +183,15 @@ static int pl01x_getc (int portnum)
unsigned int data;
/* Wait until there is data in the FIFO */
- while (IO_READ (port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE)
+ while (readl(port[portnum] + UART_PL01x_FR) & UART_PL01x_FR_RXFE)
WATCHDOG_RESET();
- data = IO_READ (port[portnum] + UART_PL01x_DR);
+ data = readl(port[portnum] + UART_PL01x_DR);
/* Check for an error flag */
if (data & 0xFFFFFF00) {
/* Clear the error */
- IO_WRITE (port[portnum] + UART_PL01x_ECR, 0xFFFFFFFF);
+ writel(0xFFFFFFFF, port[portnum] + UART_PL01x_ECR);
return -1;
}
@@ -218,6 +201,6 @@ static int pl01x_getc (int portnum)
static int pl01x_tstc (int portnum)
{
WATCHDOG_RESET();
- return !(IO_READ (port[portnum] + UART_PL01x_FR) &
+ return !(readl(port[portnum] + UART_PL01x_FR) &
UART_PL01x_FR_RXFE);
}
diff --git a/drivers/spi/mxc_spi.c b/drivers/spi/mxc_spi.c
index e15a63c..d558137 100644
--- a/drivers/spi/mxc_spi.c
+++ b/drivers/spi/mxc_spi.c
@@ -23,6 +23,7 @@
#include <spi.h>
#include <asm/errno.h>
#include <asm/io.h>
+#include <mxc_gpio.h>
#ifdef CONFIG_MX27
/* i.MX27 has a completely wrong register layout and register definitions in the
@@ -61,6 +62,7 @@
#define MXC_CSPICTRL_MAXBITS 0x1f
#define MXC_CSPIPERIOD_32KHZ (1 << 15)
+#define MAX_SPI_BYTES 4
static unsigned long spi_bases[] = {
0x43fa4000,
@@ -68,9 +70,6 @@ static unsigned long spi_bases[] = {
0x53f84000,
};
-#define OUT MX31_GPIO_DIRECTION_OUT
-#define mxc_gpio_direction mx31_gpio_direction
-#define mxc_gpio_set mx31_gpio_set
#elif defined(CONFIG_MX51)
#include <asm/arch/imx-regs.h>
#include <asm/arch/clock.h>
@@ -97,6 +96,7 @@ static unsigned long spi_bases[] = {
#define MXC_CSPICTRL_RXOVF (1 << 6)
#define MXC_CSPIPERIOD_32KHZ (1 << 15)
+#define MAX_SPI_BYTES 32
/* Bit position inside CTRL register to be associated with SS */
#define MXC_CSPICTRL_CHAN 18
@@ -111,13 +111,12 @@ static unsigned long spi_bases[] = {
CSPI2_BASE_ADDR,
CSPI3_BASE_ADDR,
};
-#define mxc_gpio_direction(gpio, dir) (0)
-#define mxc_gpio_set(gpio, value) {}
-#define OUT 1
#else
#error "Unsupported architecture"
#endif
+#define OUT MXC_GPIO_DIRECTION_OUT
+
struct mxc_spi_slave {
struct spi_slave slave;
unsigned long base;
@@ -126,6 +125,7 @@ struct mxc_spi_slave {
u32 cfg_reg;
#endif
int gpio;
+ int ss_pol;
};
static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave)
@@ -147,7 +147,7 @@ void spi_cs_activate(struct spi_slave *slave)
{
struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
if (mxcs->gpio > 0)
- mxc_gpio_set(mxcs->gpio, mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL);
+ mxc_gpio_set(mxcs->gpio, mxcs->ss_pol);
}
void spi_cs_deactivate(struct spi_slave *slave)
@@ -155,7 +155,7 @@ void spi_cs_deactivate(struct spi_slave *slave)
struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
if (mxcs->gpio > 0)
mxc_gpio_set(mxcs->gpio,
- !(mxcs->ctrl_reg & MXC_CSPICTRL_SSPOL));
+ !(mxcs->ss_pol));
}
#ifdef CONFIG_MX51
@@ -217,7 +217,7 @@ static s32 spi_cfg(struct mxc_spi_slave *mxcs, unsigned int cs,
if (mode & SPI_CS_HIGH)
ss_pol = 1;
- if (!(mode & SPI_CPOL))
+ if (mode & SPI_CPOL)
sclkpol = 1;
if (mode & SPI_CPHA)
@@ -254,13 +254,15 @@ static s32 spi_cfg(struct mxc_spi_slave *mxcs, unsigned int cs,
}
#endif
-static u32 spi_xchg_single(struct spi_slave *slave, u32 data, int bitlen,
- unsigned long flags)
+int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
+ const u8 *dout, u8 *din, unsigned long flags)
{
struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+ int nbytes = (bitlen + 7) / 8;
+ u32 data, cnt, i;
- if (flags & SPI_XFER_BEGIN)
- spi_cs_activate(slave);
+ debug("%s: bitlen %d dout 0x%x din 0x%x\n",
+ __func__, bitlen, (u32)dout, (u32)din);
mxcs->ctrl_reg = (mxcs->ctrl_reg &
~MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS)) |
@@ -275,8 +277,46 @@ static u32 spi_xchg_single(struct spi_slave *slave, u32 data, int bitlen,
reg_write(mxcs->base + MXC_CSPISTAT,
MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
- debug("Sending SPI 0x%x\n", data);
- reg_write(mxcs->base + MXC_CSPITXDATA, data);
+ /*
+ * The SPI controller works only with words,
+ * check if less than a word is sent.
+ * Access to the FIFO is only 32 bit
+ */
+ if (bitlen % 32) {
+ data = 0;
+ cnt = (bitlen % 32) / 8;
+ if (dout) {
+ for (i = 0; i < cnt; i++) {
+ data = (data << 8) | (*dout++ & 0xFF);
+ }
+ }
+ debug("Sending SPI 0x%x\n", data);
+
+ reg_write(mxcs->base + MXC_CSPITXDATA, data);
+ nbytes -= cnt;
+ }
+
+ data = 0;
+
+ while (nbytes > 0) {
+ data = 0;
+ if (dout) {
+ /* Buffer is not 32-bit aligned */
+ if ((unsigned long)dout & 0x03) {
+ data = 0;
+ for (i = 0; i < 4; i++, data <<= 8) {
+ data = (data << 8) | (*dout++ & 0xFF);
+ }
+ } else {
+ data = *(u32 *)dout;
+ data = cpu_to_be32(data);
+ }
+ dout += 4;
+ }
+ debug("Sending SPI 0x%x\n", data);
+ reg_write(mxcs->base + MXC_CSPITXDATA, data);
+ nbytes -= 4;
+ }
/* FIFO is written, now starts the transfer setting the XCH bit */
reg_write(mxcs->base + MXC_CSPICTRL, mxcs->ctrl_reg |
@@ -290,49 +330,78 @@ static u32 spi_xchg_single(struct spi_slave *slave, u32 data, int bitlen,
reg_write(mxcs->base + MXC_CSPISTAT,
MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
- data = reg_read(mxcs->base + MXC_CSPIRXDATA);
- debug("SPI Rx: 0x%x\n", data);
+ nbytes = (bitlen + 7) / 8;
- if (flags & SPI_XFER_END)
- spi_cs_deactivate(slave);
+ cnt = nbytes % 32;
+
+ if (bitlen % 32) {
+ data = reg_read(mxcs->base + MXC_CSPIRXDATA);
+ cnt = (bitlen % 32) / 8;
+ debug("SPI Rx unaligned: 0x%x\n", data);
+ if (din) {
+ for (i = 0; i < cnt; i++, data >>= 8) {
+ *din++ = data & 0xFF;
+ }
+ }
+ nbytes -= cnt;
+ }
- return data;
+ while (nbytes > 0) {
+ u32 tmp;
+ tmp = reg_read(mxcs->base + MXC_CSPIRXDATA);
+ data = cpu_to_be32(tmp);
+ debug("SPI Rx: 0x%x 0x%x\n", tmp, data);
+ cnt = min(nbytes, sizeof(data));
+ if (din) {
+ memcpy(din, &data, cnt);
+ din += cnt;
+ }
+ nbytes -= cnt;
+ }
+
+ return 0;
}
+
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
void *din, unsigned long flags)
{
- int n_blks = (bitlen + 31) / 32;
- u32 *out_l, *in_l;
- int i;
+ int n_bytes = (bitlen + 7) / 8;
+ int n_bits;
+ int ret;
+ u32 blk_size;
+ u8 *p_outbuf = (u8 *)dout;
+ u8 *p_inbuf = (u8 *)din;
- if ((int)dout & 3 || (int)din & 3) {
- printf("Error: unaligned buffers in: %p, out: %p\n", din, dout);
- return 1;
- }
+ if (!slave)
+ return -1;
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ while (n_bytes > 0) {
+
+ if (n_bytes < MAX_SPI_BYTES)
+ blk_size = n_bytes;
+ else
+ blk_size = MAX_SPI_BYTES;
+
+ n_bits = blk_size * 8;
- /* This driver is currently partly broken, alert the user */
- if (bitlen > 16 && (bitlen % 32)) {
- printf("Error: SPI transfer with bitlen=%d is broken.\n",
- bitlen);
- return 1;
+ ret = spi_xchg_single(slave, n_bits, p_outbuf, p_inbuf, 0);
+
+ if (ret)
+ return ret;
+ if (dout)
+ p_outbuf += blk_size;
+ if (din)
+ p_inbuf += blk_size;
+ n_bytes -= blk_size;
}
- for (i = 0, in_l = (u32 *)din, out_l = (u32 *)dout;
- i < n_blks;
- i++, in_l++, out_l++, bitlen -= 32) {
- u32 data = spi_xchg_single(slave, *out_l, bitlen, flags);
-
- /* Check if we're only transfering 8 or 16 bits */
- if (!i) {
- if (bitlen < 9)
- *(u8 *)din = data;
- else if (bitlen < 17)
- *(u16 *)din = data;
- else
- *in_l = data;
- }
+ if (flags & SPI_XFER_END) {
+ spi_cs_deactivate(slave);
}
return 0;
@@ -380,8 +449,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
return NULL;
mxcs = malloc(sizeof(struct mxc_spi_slave));
- if (!mxcs)
+ if (!mxcs) {
+ puts("mxc_spi: SPI Slave not allocated !\n");
return NULL;
+ }
ret = decode_cs(mxcs, cs);
if (ret < 0) {
@@ -394,6 +465,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
mxcs->slave.bus = bus;
mxcs->slave.cs = cs;
mxcs->base = spi_bases[bus];
+ mxcs->ss_pol = (mode & SPI_CS_HIGH) ? 1 : 0;
#ifdef CONFIG_MX51
/* Can be used for i.MX31 too ? */
@@ -413,7 +485,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
if (mode & SPI_CPHA)
ctrl_reg |= MXC_CSPICTRL_PHA;
- if (!(mode & SPI_CPOL))
+ if (mode & SPI_CPOL)
ctrl_reg |= MXC_CSPICTRL_POL;
if (mode & SPI_CS_HIGH)
ctrl_reg |= MXC_CSPICTRL_SSPOL;