Commit 7d971406 authored by Vladimir Skvortsov's avatar Vladimir Skvortsov

RT #83884. Support SPI Flash in U-boot for LPC4350.

parent 38988ff8
......@@ -477,37 +477,6 @@ struct lpc18xx_otp_area {
#define LPC18XX_OTP_CTRL_BOOTSRC_BITS 25
#define LPC18XX_OTP_CTRL_BOOTSRC_MSK (0xF << LPC18XX_OTP_CTRL_BOOTSRC_BITS)
/*
* GPIO (GPIO ports) register map
*/
struct lpc18xx_gpio_regs {
u8 pbyte[256]; /* GPIO port byte pin registers */
u32 rsv0[960];
u32 pword[256]; /* GPIO port word pin registers */
u32 rsv1[768];
u32 dir[8]; /* GPIO port direction registers */
u32 rsv2[24];
u32 mask[8]; /* GPIO port mask registers */
u32 rsv3[24];
u32 pin[8]; /* GPIO port pin registers */
u32 rsv4[24];
u32 mpin[8]; /* GPIO masked port pin registers */
u32 rsv5[24];
u32 set[8]; /* GPIO port set registers */
u32 rsv6[24];
u32 clr[8]; /* GPIO port clear registers */
u32 rsv7[24];
u32 not[8]; /* GPIO port toggle registers */
};
/*
* GPIO registers base
*/
#define LPC18XX_GPIO_BASE 0x400F4000
#define LPC18XX_GPIO ((volatile struct lpc18xx_gpio_regs *) \
LPC18XX_GPIO_BASE)
#define LPC18XX_GPIO_B(port,pin) (LPC18XX_GPIO->pbyte[32*(port) + (pin)])
/*
* Configuration of boot pins as GPIO inputs
*/
......
......@@ -25,6 +25,9 @@
#include <common.h>
#include <netdev.h>
#if defined(CONFIG_LPC_SPI)
#include <spi.h>
#endif
#include <asm/arch/lpc18xx_gpio.h>
#include <asm/arch/lpc18xx_scu.h>
......@@ -469,7 +472,6 @@ struct lpc18xx_otp_area {
#define LPC18XX_OTP_BASE 0x40045000
#define LPC18XX_OTP ((volatile struct lpc18xx_otp_area *) \
LPC18XX_OTP_BASE)
/*
* Customer control data
*/
......@@ -477,37 +479,6 @@ struct lpc18xx_otp_area {
#define LPC18XX_OTP_CTRL_BOOTSRC_BITS 25
#define LPC18XX_OTP_CTRL_BOOTSRC_MSK (0xF << LPC18XX_OTP_CTRL_BOOTSRC_BITS)
/*
* GPIO (GPIO ports) register map
*/
struct lpc18xx_gpio_regs {
u8 pbyte[256]; /* GPIO port byte pin registers */
u32 rsv0[960];
u32 pword[256]; /* GPIO port word pin registers */
u32 rsv1[768];
u32 dir[8]; /* GPIO port direction registers */
u32 rsv2[24];
u32 mask[8]; /* GPIO port mask registers */
u32 rsv3[24];
u32 pin[8]; /* GPIO port pin registers */
u32 rsv4[24];
u32 mpin[8]; /* GPIO masked port pin registers */
u32 rsv5[24];
u32 set[8]; /* GPIO port set registers */
u32 rsv6[24];
u32 clr[8]; /* GPIO port clear registers */
u32 rsv7[24];
u32 not[8]; /* GPIO port toggle registers */
};
/*
* GPIO registers base
*/
#define LPC18XX_GPIO_BASE 0x400F4000
#define LPC18XX_GPIO ((volatile struct lpc18xx_gpio_regs *) \
LPC18XX_GPIO_BASE)
#define LPC18XX_GPIO_B(port,pin) (LPC18XX_GPIO->pbyte[32*(port) + (pin)])
/*
* Configuration of boot pins as GPIO inputs
*/
......@@ -681,6 +652,11 @@ int board_init(void)
st->wr = CONFIG_SYS_FLASH_WR;
st->ta = CONFIG_SYS_FLASH_TA;
#endif
#if defined(CONFIG_LPC_SPI)
spi_init();
#endif
return 0;
}
......
......@@ -340,6 +340,14 @@ static void clock_setup(void)
LPC18XX_CGU_AUTOBLOCK_MSK;
LPC18XX_CGU->uart3_clk = LPC18XX_CGU_CLKSEL_PLL1 |
LPC18XX_CGU_AUTOBLOCK_MSK;
#if defined(CONFIG_LPC_SPI)
/*
* Set-up clocks for SPI
*/
LPC18XX_CGU->spifi_clk = LPC18XX_CGU_CLKSEL_PLL1 |
LPC18XX_CGU_AUTOBLOCK_MSK;
#endif
}
/*
......@@ -423,6 +431,13 @@ void clock_init(void)
clock_val[CLOCK_UART1] = LPC18XX_PLL1_CLK_OUT;
clock_val[CLOCK_UART2] = LPC18XX_PLL1_CLK_OUT;
clock_val[CLOCK_UART3] = LPC18XX_PLL1_CLK_OUT;
/*
* Set SPI base clock rate
*/
#if defined(CONFIG_LPC_SPI)
clock_val[CLOCK_SPI] = LPC18XX_PLL1_CLK_OUT;
#endif
}
/*
......
......@@ -126,3 +126,25 @@ int
out:
return rv;
}
/*
* Set direction for GPIO pin.
*/
void lpc_gpio_dir(struct lpc18xx_iomux_dsc pin, u8 dir)
{
if (dir) {
LPC18XX_GPIO->dir[pin.group] |= (1 << pin.pin);
} else {
LPC18XX_GPIO->dir[pin.group] &= ~(1 << pin.pin);
}
}
void lpc_gpio_set(struct lpc18xx_iomux_dsc pin)
{
LPC18XX_GPIO->set[pin.group] = (1 << pin.pin);
}
void lpc_gpio_clear(struct lpc18xx_iomux_dsc pin)
{
LPC18XX_GPIO->clr[pin.group] = (1 << pin.pin);
}
......@@ -50,10 +50,12 @@
#define SPSN_ID_S25FL016A 0x0214
#define SPSN_ID_S25FL032A 0x0215
#define SPSN_ID_S25FL064A 0x0216
#define SPSN_ID_S25FL064P 0x0216
#define SPSN_ID_S25FL128 0x2018
#define SPSN_EXT_ID_S25FL128P_256KB 0x0300
#define SPSN_EXT_ID_S25FL128P_64KB 0x0301
#define SPSN_EXT_ID_S25FL128S_64KB 0x4D01
#define SPSN_EXT_ID_S25FL064P 0x4D00
#define SPANSION_SR_WIP (1 << 0) /* Write-in-Progress */
......@@ -125,6 +127,14 @@ static struct spansion_spi_flash_params spansion_spi_flash_table[] = {
.nr_sectors[0] = 128,
.name = "S25FL064A",
},
{
.idcode1 = SPSN_ID_S25FL064P,
.idcode2 = SPSN_EXT_ID_S25FL064P,
.page_size = 256,
.pages_per_sector[0] = 256,
.nr_sectors[0] = 128,
.name = "S25FL064P",
},
{
.idcode1 = SPSN_ID_S25FL128,
.idcode2 = SPSN_EXT_ID_S25FL128P_64KB,
......
......@@ -28,6 +28,7 @@ LIB := $(obj)libspi.a
COBJS-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
COBJS-$(CONFIG_ATMEL_SPI) += atmel_spi.o
COBJS-$(CONFIG_M2S_SPI) += m2s_spi.o
COBJS-$(CONFIG_LPC_SPI) += lpc_spi.o
COBJS-$(CONFIG_BFIN_SPI) += bfin_spi.o
COBJS-$(CONFIG_CF_SPI) += cf_spi.o
COBJS-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
......
#include <common.h>
#include <clock.h>
#include <malloc.h>
#include <spi.h>
#include <asm/arch/lpc18xx_scu.h>
#include <asm/arch/lpc18xx_gpio.h>
/* Control Register bits definition */
#define SPI_CR_BITENABLE (1 << 2)
#define SPI_CR_CPHA (1 << 3)
#define SPI_CR_CPOL (1 << 4)
#define SPI_CR_MSTR (1 << 5)
#define SPI_CR_LSBF (1 << 6)
#define SPI_CR_SPIE (1 << 7)
#define SPI_CR_BITS(x) ((x) << 8)
/* Status Register bits definition */
#define SPI_SR_ABRT (1 << 3)
#define SPI_SR_MODF (1 << 4)
#define SPI_SR_ROVR (1 << 5)
#define SPI_SR_WCOL (1 << 6)
#define SPI_SR_SPIF (1 << 7)
/* SPI Clock Counter Register */
#define SPI_CCR_COUNTER(x) ((x) << 0)
/*
* SPI registers
*/
struct lpc_spi {
u32 cr;
u32 sr;
u32 dr;
u32 ccr;
u32 tcr;
u32 tsr;
u32 reserved;
u32 interrupt;
};
#define LPC_SPI_BASE 0x40100000
static volatile struct lpc_spi *lpc_spi = (struct lpc_spi *)LPC_SPI_BASE;
/* SPI pins configuration */
static const struct lpc18xx_pin_config
lpc_spi_pins_config[] = CONFIG_LPC_SPI_PINS;
static const struct lpc18xx_iomux_dsc lpc_cs_gpio = CONFIG_LPC_CS_GPIO;
/*
* Private data structure for an SPI slave
*/
struct lpc_spi_slave {
struct spi_slave slave; /* Generic slave */
u32 spccr; /* SPI bus rate */
u32 mode; /* SPI bus mode */
};
/*
* Handler to get access to the driver specific slave data structure
* @param c generic slave
* @returns driver specific slave
*/
static inline struct lpc_spi_slave *to_lpc_spi(struct spi_slave *slave)
{
return container_of(slave, struct lpc_spi_slave, slave);
}
/*
* Initialization of the entire driver
*/
void spi_init()
{
/* Configure PINs */
lpc18xx_pin_config_table(lpc_spi_pins_config,
ARRAY_SIZE(lpc_spi_pins_config));
/* Configure Chip Select GPIO */
lpc_gpio_dir(lpc_cs_gpio, 1);
lpc_gpio_set(lpc_cs_gpio);
/* The SPI operates in Master mode. */
lpc_spi->cr = SPI_CR_MSTR;
}
/*
* Prepare to use an SPI slave
* @param b SPI controller
* @param cs slave Chip Select
* @param hz max freq this slave can run at
* @param m slave access mode
* @returns driver specific slave
*/
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
unsigned int hz, unsigned int mode)
{
struct lpc_spi_slave *s;
struct spi_slave *slave = NULL;
unsigned int spccr;
if (bus != 0 || cs != 0) {
goto done;
}
spccr = (clock_get(CLOCK_SPI) / hz) & 0xfe;
if (spccr < 8) {
goto done;
}
s = malloc(sizeof(struct lpc_spi_slave));
if (!s) {
goto done;
}
s->spccr = spccr;
s->mode = mode;
slave = &s->slave;
slave->bus = bus;
slave->cs = cs;
done:
return slave;
}
/*
* Done with an an SPI slave
* @param slv SPI slave
*/
void spi_free_slave(struct spi_slave *slv)
{
struct lpc_spi_slave *s = to_lpc_spi(slv);
free(s);
}
/*
* Set up the SPI controller
* @param slv SPI slave
* @returns 0->success; !0->failure
*/
int spi_claim_bus(struct spi_slave *slv)
{
struct lpc_spi_slave *s = to_lpc_spi(slv);
/* set speed */
lpc_spi->ccr = s->spccr;
/* set mode */
if (s->mode & SPI_CPHA) {
lpc_spi->cr |= SPI_CR_CPHA;
} else {
lpc_spi->cr &= ~SPI_CR_CPHA;
}
if (s->mode & SPI_CPOL) {
lpc_spi->cr |= SPI_CR_CPOL;
} else {
lpc_spi->cr &= ~SPI_CR_CPOL;
}
return 0;
}
/*
* Shut down the SPI controller
* @param slv SPI slave
*/
void spi_release_bus(struct spi_slave *slv)
{
}
/*
* Perform an SPI transfer
* @param slv SPI slave
* @param bl transfer length (in bits)
* @param dout data out
* @param din data in
* @param fl transfer flags
* @returns 0->success; !0->failure
*/
int spi_xfer(struct spi_slave *slv, unsigned int bl,
const void *dout, void *din, unsigned long fl)
{
u8 dummy = 0xff;
int i;
u32 sr;
int ret = 0;
const u8 *_dout = dout;
u8 *_din = din;
int len = bl >> 3;
if (fl & SPI_XFER_BEGIN) {
/* Enable chip select */
lpc_gpio_clear(lpc_cs_gpio);
}
for (i = 0; i < len; i++) {
if (dout == NULL) {
lpc_spi->dr = dummy;
} else {
lpc_spi->dr = _dout[i];
}
do {
sr = lpc_spi->sr;
}
while ((sr & SPI_SR_SPIF) == 0);
sr = lpc_spi->sr;
if (din == NULL) {
dummy = lpc_spi->dr;
} else {
_din[i] = lpc_spi->dr;
}
sr = lpc_spi->tsr;
}
if (fl & SPI_XFER_END) {
/* Disable chip select */
lpc_gpio_set(lpc_cs_gpio);
}
return ret;
}
......@@ -54,6 +54,7 @@ enum clock {
CLOCK_UART1, /* UART1 base clock rate expressed in Hz */
CLOCK_UART2, /* UART2 base clock rate expressed in Hz */
CLOCK_UART3, /* UART3 base clock rate expressed in Hz */
CLOCK_SPI, /* SPI base clock rate expressed in Hz */
CLOCK_END /* for internal usage */
};
......
......@@ -96,4 +96,41 @@ int lpc18xx_iomux_config(const struct lpc18xx_iomux_dsc *dsc, u32 regval);
extern int lpc18xx_pin_config_table(
const struct lpc18xx_pin_config *table, unsigned int len);
/*
* GPIO (GPIO ports) register map
*/
struct lpc18xx_gpio_regs {
u8 pbyte[256]; /* GPIO port byte pin registers */
u32 rsv0[960];
u32 pword[256]; /* GPIO port word pin registers */
u32 rsv1[768];
u32 dir[8]; /* GPIO port direction registers */
u32 rsv2[24];
u32 mask[8]; /* GPIO port mask registers */
u32 rsv3[24];
u32 pin[8]; /* GPIO port pin registers */
u32 rsv4[24];
u32 mpin[8]; /* GPIO masked port pin registers */
u32 rsv5[24];
u32 set[8]; /* GPIO port set registers */
u32 rsv6[24];
u32 clr[8]; /* GPIO port clear registers */
u32 rsv7[24];
u32 not[8]; /* GPIO port toggle registers */
};
/*
* GPIO registers base
*/
#define LPC18XX_GPIO_BASE 0x400F4000
#define LPC18XX_GPIO ((volatile struct lpc18xx_gpio_regs *) \
LPC18XX_GPIO_BASE)
#define LPC18XX_GPIO_B(port,pin) (LPC18XX_GPIO->pbyte[32*(port) + (pin)])
void lpc_gpio_dir(struct lpc18xx_iomux_dsc pin, u8 dir);
void lpc_gpio_set(struct lpc18xx_iomux_dsc pin);
void lpc_gpio_clear(struct lpc18xx_iomux_dsc pin);
#endif /* _LPC18XX_IOMUX_H_ */
......@@ -172,6 +172,31 @@
#define CONFIG_SYS_MAX_FLASH_BANKS 1
#define CONFIG_SYS_MAX_FLASH_SECT 1024
#define CONFIG_LPC_SPI 1
#define CONFIG_LPC_SPI_PINS { \
{{0x3, 3}, LPC18XX_IOMUX_CONFIG(1, 0, 0, 1, 0, 0)}, \
{{0x3, 6}, LPC18XX_IOMUX_CONFIG(1, 0, 0, 1, 1, 1)}, \
{{0x3, 7}, LPC18XX_IOMUX_CONFIG(1, 0, 0, 1, 0, 0)}, \
{{0x3, 8}, LPC18XX_IOMUX_CONFIG(4, 0, 0, 1, 0, 0)} \
}
#define CONFIG_LPC_CS_GPIO {5, 11}
/*
* Configure SPI Flash
*/
#define CONFIG_SPI_FLASH 1
#define CONFIG_SPI_FLASH_SPANSION 1
#define CONFIG_SPI_FLASH_BUS 0
#define CONFIG_SPI_FLASH_CS 0
#define CONFIG_SPI_FLASH_MODE 0
#define CONFIG_SPI_FLASH_SPEED (clock_get(CLOCK_SPI) / 8)
#define CONFIG_SF_DEFAULT_SPEED CONFIG_SPI_FLASH_SPEED
#define CONFIG_SF_DEFAULT_MODE CONFIG_SPI_FLASH_MODE
/*
* Store env in flash.
*/
......@@ -303,6 +328,9 @@
#undef CONFIG_CMD_NFS
#undef CONFIG_CMD_SOURCE
#undef CONFIG_CMD_XIMG
#if defined(CONFIG_SPI_FLASH)
#define CONFIG_CMD_SF
#endif
/*
* To save memory disable long help
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment