Message ID | 1381237942-30354-1-git-send-email-rajeshwari.s@samsung.com |
---|---|
State | New |
Headers | show |
Hi Minkyu Kang, Since this patch is related to arch/arm spi booting, I had a doubt where would it get merged in u-boot-samsung.git or u-boot-spi.git. This patch is based on "[U-Boot] [PATCH 4/4] spi: exynos: Support word transfers" which is already merged in u-boot-spi.git. Regards, Rajeshwari Shinde. On Tue, Oct 8, 2013 at 6:42 PM, Rajeshwari S Shinde <rajeshwari.s@samsung.com> wrote: > This patch implements a custom spi_copy funtion to copy u-boot from SF > to RAM. This is faster then iROM spi_copy funtion as this runs spi at > 50Mhz and also in WORD mode of operation. > > Changed a printf in pinmux.c to debug just to avoid the compilation > error in SPL. > > Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com> > Signed-off-by: Tom Wai-Hong Tam <waihong@chromium.org> > Signed-off-by: Rajeshwari S Shinde <rajeshwari.s@samsung.com> > --- > Based on following patch yet to be merged: > "[U-Boot] [PATCH 4/4] spi: exynos: Support word transfers" > Changes in V2: > - Corrected the commit message. > - Added a SPI timeout check. > - Corrected the comments. > Changes in V3: > - Rebased on the latest u-boot-spi tree. > arch/arm/cpu/armv7/exynos/pinmux.c | 2 +- > arch/arm/cpu/armv7/exynos/spl_boot.c | 122 ++++++++++++++++++++++++++++++++- > arch/arm/include/asm/arch-exynos/spi.h | 1 + > include/configs/exynos5250-dt.h | 2 + > 4 files changed, 123 insertions(+), 4 deletions(-) > > diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c > index 8002bce..74cc700 100644 > --- a/arch/arm/cpu/armv7/exynos/pinmux.c > +++ b/arch/arm/cpu/armv7/exynos/pinmux.c > @@ -462,7 +462,7 @@ static int exynos4_pinmux_config(int peripheral, int flags) > case PERIPH_ID_SDMMC1: > case PERIPH_ID_SDMMC3: > case PERIPH_ID_SDMMC4: > - printf("SDMMC device %d not implemented\n", peripheral); > + debug("SDMMC device %d not implemented\n", peripheral); > return -1; > default: > debug("%s: invalid peripheral %d", __func__, peripheral); > diff --git a/arch/arm/cpu/armv7/exynos/spl_boot.c b/arch/arm/cpu/armv7/exynos/spl_boot.c > index 3651c00..6faf13f 100644 > --- a/arch/arm/cpu/armv7/exynos/spl_boot.c > +++ b/arch/arm/cpu/armv7/exynos/spl_boot.c > @@ -10,8 +10,11 @@ > #include <asm/arch/clock.h> > #include <asm/arch/clk.h> > #include <asm/arch/dmc.h> > +#include <asm/arch/periph.h> > +#include <asm/arch/pinmux.h> > #include <asm/arch/power.h> > #include <asm/arch/spl.h> > +#include <asm/arch/spi.h> > > #include "common_setup.h" > #include "clock_init.h" > @@ -59,6 +62,119 @@ static int config_branch_prediction(int set_cr_z) > } > #endif > > +static void spi_rx_tx(struct exynos_spi *regs, int todo, > + void *dinp, void const *doutp, int i) > +{ > + uint *rxp = (uint *)(dinp + (i * (32 * 1024))); > + int rx_lvl, tx_lvl; > + uint out_bytes, in_bytes; > + > + out_bytes = todo; > + in_bytes = todo; > + setbits_le32(®s->ch_cfg, SPI_CH_RST); > + clrbits_le32(®s->ch_cfg, SPI_CH_RST); > + writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, ®s->pkt_cnt); > + > + while (in_bytes) { > + uint32_t spi_sts; > + int temp; > + > + spi_sts = readl(®s->spi_sts); > + rx_lvl = ((spi_sts >> 15) & 0x7f); > + tx_lvl = ((spi_sts >> 6) & 0x7f); > + while (tx_lvl < 32 && out_bytes) { > + temp = 0xffffffff; > + writel(temp, ®s->tx_data); > + out_bytes -= 4; > + tx_lvl += 4; > + } > + while (rx_lvl >= 4 && in_bytes) { > + temp = readl(®s->rx_data); > + if (rxp) > + *rxp++ = temp; > + in_bytes -= 4; > + rx_lvl -= 4; > + } > + } > +} > + > +/* > + * Copy uboot from spi flash to RAM > + * > + * @parma uboot_size size of u-boot to copy > + * @param uboot_addr address in u-boot to copy > + */ > +static void exynos_spi_copy(unsigned int uboot_size, unsigned int uboot_addr) > +{ > + int upto, todo; > + int i, timeout = 100; > + struct exynos_spi *regs = (struct exynos_spi *)CONFIG_ENV_SPI_BASE; > + > + set_spi_clk(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ > + /* set the spi1 GPIO */ > + exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); > + > + /* set pktcnt and enable it */ > + writel(4 | SPI_PACKET_CNT_EN, ®s->pkt_cnt); > + /* set FB_CLK_SEL */ > + writel(SPI_FB_DELAY_180, ®s->fb_clk); > + /* set CH_WIDTH and BUS_WIDTH as word */ > + setbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | > + SPI_MODE_BUS_WIDTH_WORD); > + clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */ > + > + /* clear rx and tx channel if set priveously */ > + clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); > + > + setbits_le32(®s->swap_cfg, SPI_RX_SWAP_EN | > + SPI_RX_BYTE_SWAP | > + SPI_RX_HWORD_SWAP); > + > + /* do a soft reset */ > + setbits_le32(®s->ch_cfg, SPI_CH_RST); > + clrbits_le32(®s->ch_cfg, SPI_CH_RST); > + > + /* now set rx and tx channel ON */ > + setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); > + clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ > + > + /* Send read instruction (0x3h) followed by a 24 bit addr */ > + writel((SF_READ_DATA_CMD << 24) | SPI_FLASH_UBOOT_POS, ®s->tx_data); > + > + /* waiting for TX done */ > + while (!(readl(®s->spi_sts) & SPI_ST_TX_DONE)) { > + if (!timeout) { > + debug("SPI TIMEOUT\n"); > + break; > + } > + timeout--; > + } > + > + for (upto = 0, i = 0; upto < uboot_size; upto += todo, i++) { > + todo = min(uboot_size - upto, (1 << 15)); > + spi_rx_tx(regs, todo, (void *)(uboot_addr), > + (void *)(SPI_FLASH_UBOOT_POS), i); > + } > + > + setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ > + > + /* > + * Let put controller mode to BYTE as > + * SPI driver does not support WORD mode yet > + */ > + clrbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | > + SPI_MODE_BUS_WIDTH_WORD); > + writel(0, ®s->swap_cfg); > + > + /* > + * Flush spi tx, rx fifos and reset the SPI controller > + * and clear rx/tx channel > + */ > + clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); > + clrbits_le32(®s->ch_cfg, SPI_CH_RST); > + clrbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); > +} > + > /* > * Copy U-boot from mmc to RAM: > * COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains > @@ -70,6 +186,7 @@ void copy_uboot_to_ram(void) > > u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL; > u32 offset = 0, size = 0; > + struct spl_machine_param *param = spl_get_machine_params(); > #ifdef CONFIG_SUPPORT_EMMC_BOOT > u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst); > void (*end_bootop_from_emmc)(void); > @@ -91,9 +208,8 @@ void copy_uboot_to_ram(void) > switch (bootmode) { > #ifdef CONFIG_SPI_BOOTING > case BOOT_MODE_SERIAL: > - offset = SPI_FLASH_UBOOT_POS; > - size = CONFIG_BL2_SIZE; > - copy_bl2 = get_irom_func(SPI_INDEX); > + /* Customised function to copy u-boot from SF */ > + exynos_spi_copy(param->uboot_size, CONFIG_SYS_TEXT_BASE); > break; > #endif > case BOOT_MODE_MMC: > diff --git a/arch/arm/include/asm/arch-exynos/spi.h b/arch/arm/include/asm/arch-exynos/spi.h > index 147c1a7..0ba931b 100644 > --- a/arch/arm/include/asm/arch-exynos/spi.h > +++ b/arch/arm/include/asm/arch-exynos/spi.h > @@ -30,6 +30,7 @@ struct exynos_spi { > #define EXYNOS_SPI_MAX_FREQ 50000000 > > #define SPI_TIMEOUT_MS 10 > +#define SF_READ_DATA_CMD 0x3 > > /* SPI_CHCFG */ > #define SPI_CH_HS_EN (1 << 6) > diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h > index 8c21909..1d32396 100644 > --- a/include/configs/exynos5250-dt.h > +++ b/include/configs/exynos5250-dt.h > @@ -154,6 +154,7 @@ > #define COPY_BL2_FNPTR_ADDR 0x02020030 > > #define CONFIG_SPL_LIBCOMMON_SUPPORT > +#define CONFIG_SPL_GPIO_SUPPORT > > /* specific .lds file */ > #define CONFIG_SPL_LDSCRIPT "board/samsung/common/exynos-uboot-spl.lds" > @@ -292,6 +293,7 @@ > /* SPI */ > #define CONFIG_ENV_IS_IN_SPI_FLASH > #define CONFIG_SPI_FLASH > +#define CONFIG_ENV_SPI_BASE 0x12D30000 > > #ifdef CONFIG_SPI_FLASH > #define CONFIG_EXYNOS_SPI > -- > 1.7.12.4 > > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > http://lists.denx.de/mailman/listinfo/u-boot
On 09/10/13 16:55, Rajeshwari Birje wrote: > Hi Minkyu Kang, > > Since this patch is related to arch/arm spi booting, I had a doubt > where would it get merged in u-boot-samsung.git or u-boot-spi.git. > > This patch is based on "[U-Boot] [PATCH 4/4] spi: exynos: Support word > transfers" which is already merged in u-boot-spi.git. Now, that patch is merged to u-boot-samsung. Anyway I'm OK to pick this patch to u-boot-spi. > > Regards, > Rajeshwari Shinde. > > On Tue, Oct 8, 2013 at 6:42 PM, Rajeshwari S Shinde > <rajeshwari.s@samsung.com> wrote: >> This patch implements a custom spi_copy funtion to copy u-boot from SF >> to RAM. This is faster then iROM spi_copy funtion as this runs spi at >> 50Mhz and also in WORD mode of operation. >> >> Changed a printf in pinmux.c to debug just to avoid the compilation >> error in SPL. >> >> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com> >> Signed-off-by: Tom Wai-Hong Tam <waihong@chromium.org> >> Signed-off-by: Rajeshwari S Shinde <rajeshwari.s@samsung.com> >> --- >> Based on following patch yet to be merged: >> "[U-Boot] [PATCH 4/4] spi: exynos: Support word transfers" >> Changes in V2: >> - Corrected the commit message. >> - Added a SPI timeout check. >> - Corrected the comments. >> Changes in V3: >> - Rebased on the latest u-boot-spi tree. >> arch/arm/cpu/armv7/exynos/pinmux.c | 2 +- >> arch/arm/cpu/armv7/exynos/spl_boot.c | 122 ++++++++++++++++++++++++++++++++- >> arch/arm/include/asm/arch-exynos/spi.h | 1 + >> include/configs/exynos5250-dt.h | 2 + >> 4 files changed, 123 insertions(+), 4 deletions(-) >> >> diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c >> index 8002bce..74cc700 100644 >> --- a/arch/arm/cpu/armv7/exynos/pinmux.c >> +++ b/arch/arm/cpu/armv7/exynos/pinmux.c >> @@ -462,7 +462,7 @@ static int exynos4_pinmux_config(int peripheral, int flags) >> case PERIPH_ID_SDMMC1: >> case PERIPH_ID_SDMMC3: >> case PERIPH_ID_SDMMC4: >> - printf("SDMMC device %d not implemented\n", peripheral); >> + debug("SDMMC device %d not implemented\n", peripheral); unrelated change. >> return -1; >> default: >> debug("%s: invalid peripheral %d", __func__, peripheral); >> diff --git a/arch/arm/cpu/armv7/exynos/spl_boot.c b/arch/arm/cpu/armv7/exynos/spl_boot.c >> index 3651c00..6faf13f 100644 >> --- a/arch/arm/cpu/armv7/exynos/spl_boot.c >> +++ b/arch/arm/cpu/armv7/exynos/spl_boot.c >> @@ -10,8 +10,11 @@ >> #include <asm/arch/clock.h> >> #include <asm/arch/clk.h> >> #include <asm/arch/dmc.h> >> +#include <asm/arch/periph.h> >> +#include <asm/arch/pinmux.h> >> #include <asm/arch/power.h> >> #include <asm/arch/spl.h> >> +#include <asm/arch/spi.h> >> >> #include "common_setup.h" >> #include "clock_init.h" >> @@ -59,6 +62,119 @@ static int config_branch_prediction(int set_cr_z) >> } >> #endif >> >> +static void spi_rx_tx(struct exynos_spi *regs, int todo, >> + void *dinp, void const *doutp, int i) >> +{ >> + uint *rxp = (uint *)(dinp + (i * (32 * 1024))); >> + int rx_lvl, tx_lvl; >> + uint out_bytes, in_bytes; >> + >> + out_bytes = todo; >> + in_bytes = todo; >> + setbits_le32(®s->ch_cfg, SPI_CH_RST); >> + clrbits_le32(®s->ch_cfg, SPI_CH_RST); >> + writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, ®s->pkt_cnt); >> + >> + while (in_bytes) { >> + uint32_t spi_sts; >> + int temp; >> + >> + spi_sts = readl(®s->spi_sts); >> + rx_lvl = ((spi_sts >> 15) & 0x7f); >> + tx_lvl = ((spi_sts >> 6) & 0x7f); >> + while (tx_lvl < 32 && out_bytes) { >> + temp = 0xffffffff; >> + writel(temp, ®s->tx_data); >> + out_bytes -= 4; >> + tx_lvl += 4; >> + } >> + while (rx_lvl >= 4 && in_bytes) { >> + temp = readl(®s->rx_data); >> + if (rxp) >> + *rxp++ = temp; >> + in_bytes -= 4; >> + rx_lvl -= 4; >> + } >> + } >> +} >> + >> +/* >> + * Copy uboot from spi flash to RAM >> + * >> + * @parma uboot_size size of u-boot to copy >> + * @param uboot_addr address in u-boot to copy >> + */ >> +static void exynos_spi_copy(unsigned int uboot_size, unsigned int uboot_addr) >> +{ >> + int upto, todo; >> + int i, timeout = 100; >> + struct exynos_spi *regs = (struct exynos_spi *)CONFIG_ENV_SPI_BASE; >> + >> + set_spi_clk(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ >> + /* set the spi1 GPIO */ >> + exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); >> + >> + /* set pktcnt and enable it */ >> + writel(4 | SPI_PACKET_CNT_EN, ®s->pkt_cnt); >> + /* set FB_CLK_SEL */ >> + writel(SPI_FB_DELAY_180, ®s->fb_clk); >> + /* set CH_WIDTH and BUS_WIDTH as word */ >> + setbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | >> + SPI_MODE_BUS_WIDTH_WORD); >> + clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */ >> + >> + /* clear rx and tx channel if set priveously */ >> + clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); >> + >> + setbits_le32(®s->swap_cfg, SPI_RX_SWAP_EN | >> + SPI_RX_BYTE_SWAP | >> + SPI_RX_HWORD_SWAP); >> + >> + /* do a soft reset */ >> + setbits_le32(®s->ch_cfg, SPI_CH_RST); >> + clrbits_le32(®s->ch_cfg, SPI_CH_RST); >> + >> + /* now set rx and tx channel ON */ >> + setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); >> + clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ >> + >> + /* Send read instruction (0x3h) followed by a 24 bit addr */ >> + writel((SF_READ_DATA_CMD << 24) | SPI_FLASH_UBOOT_POS, ®s->tx_data); >> + >> + /* waiting for TX done */ >> + while (!(readl(®s->spi_sts) & SPI_ST_TX_DONE)) { >> + if (!timeout) { >> + debug("SPI TIMEOUT\n"); >> + break; >> + } >> + timeout--; >> + } >> + >> + for (upto = 0, i = 0; upto < uboot_size; upto += todo, i++) { >> + todo = min(uboot_size - upto, (1 << 15)); >> + spi_rx_tx(regs, todo, (void *)(uboot_addr), >> + (void *)(SPI_FLASH_UBOOT_POS), i); >> + } >> + >> + setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ >> + >> + /* >> + * Let put controller mode to BYTE as >> + * SPI driver does not support WORD mode yet >> + */ >> + clrbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | >> + SPI_MODE_BUS_WIDTH_WORD); >> + writel(0, ®s->swap_cfg); >> + >> + /* >> + * Flush spi tx, rx fifos and reset the SPI controller >> + * and clear rx/tx channel >> + */ >> + clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); >> + clrbits_le32(®s->ch_cfg, SPI_CH_RST); >> + clrbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); >> +} >> + >> /* >> * Copy U-boot from mmc to RAM: >> * COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains >> @@ -70,6 +186,7 @@ void copy_uboot_to_ram(void) >> >> u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL; >> u32 offset = 0, size = 0; >> + struct spl_machine_param *param = spl_get_machine_params(); >> #ifdef CONFIG_SUPPORT_EMMC_BOOT >> u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst); >> void (*end_bootop_from_emmc)(void); >> @@ -91,9 +208,8 @@ void copy_uboot_to_ram(void) >> switch (bootmode) { >> #ifdef CONFIG_SPI_BOOTING >> case BOOT_MODE_SERIAL: >> - offset = SPI_FLASH_UBOOT_POS; >> - size = CONFIG_BL2_SIZE; >> - copy_bl2 = get_irom_func(SPI_INDEX); >> + /* Customised function to copy u-boot from SF */ >> + exynos_spi_copy(param->uboot_size, CONFIG_SYS_TEXT_BASE); >> break; >> #endif >> case BOOT_MODE_MMC: >> diff --git a/arch/arm/include/asm/arch-exynos/spi.h b/arch/arm/include/asm/arch-exynos/spi.h >> index 147c1a7..0ba931b 100644 >> --- a/arch/arm/include/asm/arch-exynos/spi.h >> +++ b/arch/arm/include/asm/arch-exynos/spi.h >> @@ -30,6 +30,7 @@ struct exynos_spi { >> #define EXYNOS_SPI_MAX_FREQ 50000000 >> >> #define SPI_TIMEOUT_MS 10 >> +#define SF_READ_DATA_CMD 0x3 >> >> /* SPI_CHCFG */ >> #define SPI_CH_HS_EN (1 << 6) >> diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h >> index 8c21909..1d32396 100644 >> --- a/include/configs/exynos5250-dt.h >> +++ b/include/configs/exynos5250-dt.h >> @@ -154,6 +154,7 @@ >> #define COPY_BL2_FNPTR_ADDR 0x02020030 >> >> #define CONFIG_SPL_LIBCOMMON_SUPPORT >> +#define CONFIG_SPL_GPIO_SUPPORT >> >> /* specific .lds file */ >> #define CONFIG_SPL_LDSCRIPT "board/samsung/common/exynos-uboot-spl.lds" >> @@ -292,6 +293,7 @@ >> /* SPI */ >> #define CONFIG_ENV_IS_IN_SPI_FLASH >> #define CONFIG_SPI_FLASH >> +#define CONFIG_ENV_SPI_BASE 0x12D30000 >> >> #ifdef CONFIG_SPI_FLASH >> #define CONFIG_EXYNOS_SPI >> -- >> 1.7.12.4 >> >> _______________________________________________ >> U-Boot mailing list >> U-Boot@lists.denx.de >> http://lists.denx.de/mailman/listinfo/u-boot > > > Thanks, Minkyu Kang.
Hi Minkyu Kang, Thank you for comments. On Mon, Dec 2, 2013 at 2:18 PM, Minkyu Kang <mk7.kang@samsung.com> wrote: > On 09/10/13 16:55, Rajeshwari Birje wrote: >> Hi Minkyu Kang, >> >> Since this patch is related to arch/arm spi booting, I had a doubt >> where would it get merged in u-boot-samsung.git or u-boot-spi.git. >> >> This patch is based on "[U-Boot] [PATCH 4/4] spi: exynos: Support word >> transfers" which is already merged in u-boot-spi.git. > > Now, that patch is merged to u-boot-samsung. > Anyway I'm OK to pick this patch to u-boot-spi. > >> >> Regards, >> Rajeshwari Shinde. >> >> On Tue, Oct 8, 2013 at 6:42 PM, Rajeshwari S Shinde >> <rajeshwari.s@samsung.com> wrote: >>> This patch implements a custom spi_copy funtion to copy u-boot from SF >>> to RAM. This is faster then iROM spi_copy funtion as this runs spi at >>> 50Mhz and also in WORD mode of operation. >>> >>> Changed a printf in pinmux.c to debug just to avoid the compilation >>> error in SPL. >>> >>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com> >>> Signed-off-by: Tom Wai-Hong Tam <waihong@chromium.org> >>> Signed-off-by: Rajeshwari S Shinde <rajeshwari.s@samsung.com> >>> --- >>> Based on following patch yet to be merged: >>> "[U-Boot] [PATCH 4/4] spi: exynos: Support word transfers" >>> Changes in V2: >>> - Corrected the commit message. >>> - Added a SPI timeout check. >>> - Corrected the comments. >>> Changes in V3: >>> - Rebased on the latest u-boot-spi tree. >>> arch/arm/cpu/armv7/exynos/pinmux.c | 2 +- >>> arch/arm/cpu/armv7/exynos/spl_boot.c | 122 ++++++++++++++++++++++++++++++++- >>> arch/arm/include/asm/arch-exynos/spi.h | 1 + >>> include/configs/exynos5250-dt.h | 2 + >>> 4 files changed, 123 insertions(+), 4 deletions(-) >>> >>> diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c >>> index 8002bce..74cc700 100644 >>> --- a/arch/arm/cpu/armv7/exynos/pinmux.c >>> +++ b/arch/arm/cpu/armv7/exynos/pinmux.c >>> @@ -462,7 +462,7 @@ static int exynos4_pinmux_config(int peripheral, int flags) >>> case PERIPH_ID_SDMMC1: >>> case PERIPH_ID_SDMMC3: >>> case PERIPH_ID_SDMMC4: >>> - printf("SDMMC device %d not implemented\n", peripheral); >>> + debug("SDMMC device %d not implemented\n", peripheral); > > unrelated change. > As mentioned commit message "Changed a printf in pinmux.c to debug just to avoid the compilation error in SPL." >>> return -1; >>> default: >>> debug("%s: invalid peripheral %d", __func__, peripheral); >>> diff --git a/arch/arm/cpu/armv7/exynos/spl_boot.c b/arch/arm/cpu/armv7/exynos/spl_boot.c >>> index 3651c00..6faf13f 100644 >>> --- a/arch/arm/cpu/armv7/exynos/spl_boot.c >>> +++ b/arch/arm/cpu/armv7/exynos/spl_boot.c >>> @@ -10,8 +10,11 @@ >>> #include <asm/arch/clock.h> >>> #include <asm/arch/clk.h> >>> #include <asm/arch/dmc.h> >>> +#include <asm/arch/periph.h> >>> +#include <asm/arch/pinmux.h> >>> #include <asm/arch/power.h> >>> #include <asm/arch/spl.h> >>> +#include <asm/arch/spi.h> >>> >>> #include "common_setup.h" >>> #include "clock_init.h" >>> @@ -59,6 +62,119 @@ static int config_branch_prediction(int set_cr_z) >>> } >>> #endif >>> >>> +static void spi_rx_tx(struct exynos_spi *regs, int todo, >>> + void *dinp, void const *doutp, int i) >>> +{ >>> + uint *rxp = (uint *)(dinp + (i * (32 * 1024))); >>> + int rx_lvl, tx_lvl; >>> + uint out_bytes, in_bytes; >>> + >>> + out_bytes = todo; >>> + in_bytes = todo; >>> + setbits_le32(®s->ch_cfg, SPI_CH_RST); >>> + clrbits_le32(®s->ch_cfg, SPI_CH_RST); >>> + writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, ®s->pkt_cnt); >>> + >>> + while (in_bytes) { >>> + uint32_t spi_sts; >>> + int temp; >>> + >>> + spi_sts = readl(®s->spi_sts); >>> + rx_lvl = ((spi_sts >> 15) & 0x7f); >>> + tx_lvl = ((spi_sts >> 6) & 0x7f); >>> + while (tx_lvl < 32 && out_bytes) { >>> + temp = 0xffffffff; >>> + writel(temp, ®s->tx_data); >>> + out_bytes -= 4; >>> + tx_lvl += 4; >>> + } >>> + while (rx_lvl >= 4 && in_bytes) { >>> + temp = readl(®s->rx_data); >>> + if (rxp) >>> + *rxp++ = temp; >>> + in_bytes -= 4; >>> + rx_lvl -= 4; >>> + } >>> + } >>> +} >>> + >>> +/* >>> + * Copy uboot from spi flash to RAM >>> + * >>> + * @parma uboot_size size of u-boot to copy >>> + * @param uboot_addr address in u-boot to copy >>> + */ >>> +static void exynos_spi_copy(unsigned int uboot_size, unsigned int uboot_addr) >>> +{ >>> + int upto, todo; >>> + int i, timeout = 100; >>> + struct exynos_spi *regs = (struct exynos_spi *)CONFIG_ENV_SPI_BASE; >>> + >>> + set_spi_clk(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ >>> + /* set the spi1 GPIO */ >>> + exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); >>> + >>> + /* set pktcnt and enable it */ >>> + writel(4 | SPI_PACKET_CNT_EN, ®s->pkt_cnt); >>> + /* set FB_CLK_SEL */ >>> + writel(SPI_FB_DELAY_180, ®s->fb_clk); >>> + /* set CH_WIDTH and BUS_WIDTH as word */ >>> + setbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | >>> + SPI_MODE_BUS_WIDTH_WORD); >>> + clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */ >>> + >>> + /* clear rx and tx channel if set priveously */ >>> + clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); >>> + >>> + setbits_le32(®s->swap_cfg, SPI_RX_SWAP_EN | >>> + SPI_RX_BYTE_SWAP | >>> + SPI_RX_HWORD_SWAP); >>> + >>> + /* do a soft reset */ >>> + setbits_le32(®s->ch_cfg, SPI_CH_RST); >>> + clrbits_le32(®s->ch_cfg, SPI_CH_RST); >>> + >>> + /* now set rx and tx channel ON */ >>> + setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); >>> + clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ >>> + >>> + /* Send read instruction (0x3h) followed by a 24 bit addr */ >>> + writel((SF_READ_DATA_CMD << 24) | SPI_FLASH_UBOOT_POS, ®s->tx_data); >>> + >>> + /* waiting for TX done */ >>> + while (!(readl(®s->spi_sts) & SPI_ST_TX_DONE)) { >>> + if (!timeout) { >>> + debug("SPI TIMEOUT\n"); >>> + break; >>> + } >>> + timeout--; >>> + } >>> + >>> + for (upto = 0, i = 0; upto < uboot_size; upto += todo, i++) { >>> + todo = min(uboot_size - upto, (1 << 15)); >>> + spi_rx_tx(regs, todo, (void *)(uboot_addr), >>> + (void *)(SPI_FLASH_UBOOT_POS), i); >>> + } >>> + >>> + setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ >>> + >>> + /* >>> + * Let put controller mode to BYTE as >>> + * SPI driver does not support WORD mode yet >>> + */ >>> + clrbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | >>> + SPI_MODE_BUS_WIDTH_WORD); >>> + writel(0, ®s->swap_cfg); >>> + >>> + /* >>> + * Flush spi tx, rx fifos and reset the SPI controller >>> + * and clear rx/tx channel >>> + */ >>> + clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); >>> + clrbits_le32(®s->ch_cfg, SPI_CH_RST); >>> + clrbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); >>> +} >>> + >>> /* >>> * Copy U-boot from mmc to RAM: >>> * COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains >>> @@ -70,6 +186,7 @@ void copy_uboot_to_ram(void) >>> >>> u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL; >>> u32 offset = 0, size = 0; >>> + struct spl_machine_param *param = spl_get_machine_params(); >>> #ifdef CONFIG_SUPPORT_EMMC_BOOT >>> u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst); >>> void (*end_bootop_from_emmc)(void); >>> @@ -91,9 +208,8 @@ void copy_uboot_to_ram(void) >>> switch (bootmode) { >>> #ifdef CONFIG_SPI_BOOTING >>> case BOOT_MODE_SERIAL: >>> - offset = SPI_FLASH_UBOOT_POS; >>> - size = CONFIG_BL2_SIZE; >>> - copy_bl2 = get_irom_func(SPI_INDEX); >>> + /* Customised function to copy u-boot from SF */ >>> + exynos_spi_copy(param->uboot_size, CONFIG_SYS_TEXT_BASE); >>> break; >>> #endif >>> case BOOT_MODE_MMC: >>> diff --git a/arch/arm/include/asm/arch-exynos/spi.h b/arch/arm/include/asm/arch-exynos/spi.h >>> index 147c1a7..0ba931b 100644 >>> --- a/arch/arm/include/asm/arch-exynos/spi.h >>> +++ b/arch/arm/include/asm/arch-exynos/spi.h >>> @@ -30,6 +30,7 @@ struct exynos_spi { >>> #define EXYNOS_SPI_MAX_FREQ 50000000 >>> >>> #define SPI_TIMEOUT_MS 10 >>> +#define SF_READ_DATA_CMD 0x3 >>> >>> /* SPI_CHCFG */ >>> #define SPI_CH_HS_EN (1 << 6) >>> diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h >>> index 8c21909..1d32396 100644 >>> --- a/include/configs/exynos5250-dt.h >>> +++ b/include/configs/exynos5250-dt.h >>> @@ -154,6 +154,7 @@ >>> #define COPY_BL2_FNPTR_ADDR 0x02020030 >>> >>> #define CONFIG_SPL_LIBCOMMON_SUPPORT >>> +#define CONFIG_SPL_GPIO_SUPPORT >>> >>> /* specific .lds file */ >>> #define CONFIG_SPL_LDSCRIPT "board/samsung/common/exynos-uboot-spl.lds" >>> @@ -292,6 +293,7 @@ >>> /* SPI */ >>> #define CONFIG_ENV_IS_IN_SPI_FLASH >>> #define CONFIG_SPI_FLASH >>> +#define CONFIG_ENV_SPI_BASE 0x12D30000 >>> >>> #ifdef CONFIG_SPI_FLASH >>> #define CONFIG_EXYNOS_SPI >>> -- >>> 1.7.12.4 >>> >>> _______________________________________________ >>> U-Boot mailing list >>> U-Boot@lists.denx.de >>> http://lists.denx.de/mailman/listinfo/u-boot >> >> >> > > Thanks, > Minkyu Kang. >
On 02/12/13 22:17, Rajeshwari Birje wrote: > Hi Minkyu Kang, > > Thank you for comments. > > > > On Mon, Dec 2, 2013 at 2:18 PM, Minkyu Kang <mk7.kang@samsung.com> wrote: >> On 09/10/13 16:55, Rajeshwari Birje wrote: >>> Hi Minkyu Kang, >>> >>> Since this patch is related to arch/arm spi booting, I had a doubt >>> where would it get merged in u-boot-samsung.git or u-boot-spi.git. >>> >>> This patch is based on "[U-Boot] [PATCH 4/4] spi: exynos: Support word >>> transfers" which is already merged in u-boot-spi.git. >> >> Now, that patch is merged to u-boot-samsung. >> Anyway I'm OK to pick this patch to u-boot-spi. >> >>> >>> Regards, >>> Rajeshwari Shinde. >>> >>> On Tue, Oct 8, 2013 at 6:42 PM, Rajeshwari S Shinde >>> <rajeshwari.s@samsung.com> wrote: >>>> This patch implements a custom spi_copy funtion to copy u-boot from SF >>>> to RAM. This is faster then iROM spi_copy funtion as this runs spi at >>>> 50Mhz and also in WORD mode of operation. >>>> >>>> Changed a printf in pinmux.c to debug just to avoid the compilation >>>> error in SPL. >>>> >>>> Signed-off-by: Alim Akhtar <alim.akhtar@samsung.com> >>>> Signed-off-by: Tom Wai-Hong Tam <waihong@chromium.org> >>>> Signed-off-by: Rajeshwari S Shinde <rajeshwari.s@samsung.com> >>>> --- >>>> Based on following patch yet to be merged: >>>> "[U-Boot] [PATCH 4/4] spi: exynos: Support word transfers" >>>> Changes in V2: >>>> - Corrected the commit message. >>>> - Added a SPI timeout check. >>>> - Corrected the comments. >>>> Changes in V3: >>>> - Rebased on the latest u-boot-spi tree. >>>> arch/arm/cpu/armv7/exynos/pinmux.c | 2 +- >>>> arch/arm/cpu/armv7/exynos/spl_boot.c | 122 ++++++++++++++++++++++++++++++++- >>>> arch/arm/include/asm/arch-exynos/spi.h | 1 + >>>> include/configs/exynos5250-dt.h | 2 + >>>> 4 files changed, 123 insertions(+), 4 deletions(-) >>>> >>>> diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c >>>> index 8002bce..74cc700 100644 >>>> --- a/arch/arm/cpu/armv7/exynos/pinmux.c >>>> +++ b/arch/arm/cpu/armv7/exynos/pinmux.c >>>> @@ -462,7 +462,7 @@ static int exynos4_pinmux_config(int peripheral, int flags) >>>> case PERIPH_ID_SDMMC1: >>>> case PERIPH_ID_SDMMC3: >>>> case PERIPH_ID_SDMMC4: >>>> - printf("SDMMC device %d not implemented\n", peripheral); >>>> + debug("SDMMC device %d not implemented\n", peripheral); >> >> unrelated change. >> > As mentioned commit message > "Changed a printf in pinmux.c to debug just to avoid the compilation > error in SPL." >>>> return -1; >>>> default: >>>> debug("%s: invalid peripheral %d", __func__, peripheral); >>>> diff --git a/arch/arm/cpu/armv7/exynos/spl_boot.c b/arch/arm/cpu/armv7/exynos/spl_boot.c >>>> index 3651c00..6faf13f 100644 >>>> --- a/arch/arm/cpu/armv7/exynos/spl_boot.c >>>> +++ b/arch/arm/cpu/armv7/exynos/spl_boot.c >>>> @@ -10,8 +10,11 @@ >>>> #include <asm/arch/clock.h> >>>> #include <asm/arch/clk.h> >>>> #include <asm/arch/dmc.h> >>>> +#include <asm/arch/periph.h> >>>> +#include <asm/arch/pinmux.h> >>>> #include <asm/arch/power.h> >>>> #include <asm/arch/spl.h> >>>> +#include <asm/arch/spi.h> >>>> >>>> #include "common_setup.h" >>>> #include "clock_init.h" >>>> @@ -59,6 +62,119 @@ static int config_branch_prediction(int set_cr_z) >>>> } >>>> #endif >>>> >>>> +static void spi_rx_tx(struct exynos_spi *regs, int todo, >>>> + void *dinp, void const *doutp, int i) >>>> +{ >>>> + uint *rxp = (uint *)(dinp + (i * (32 * 1024))); >>>> + int rx_lvl, tx_lvl; >>>> + uint out_bytes, in_bytes; >>>> + >>>> + out_bytes = todo; >>>> + in_bytes = todo; >>>> + setbits_le32(®s->ch_cfg, SPI_CH_RST); >>>> + clrbits_le32(®s->ch_cfg, SPI_CH_RST); >>>> + writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, ®s->pkt_cnt); >>>> + >>>> + while (in_bytes) { >>>> + uint32_t spi_sts; >>>> + int temp; >>>> + >>>> + spi_sts = readl(®s->spi_sts); >>>> + rx_lvl = ((spi_sts >> 15) & 0x7f); >>>> + tx_lvl = ((spi_sts >> 6) & 0x7f); >>>> + while (tx_lvl < 32 && out_bytes) { >>>> + temp = 0xffffffff; >>>> + writel(temp, ®s->tx_data); >>>> + out_bytes -= 4; >>>> + tx_lvl += 4; >>>> + } >>>> + while (rx_lvl >= 4 && in_bytes) { >>>> + temp = readl(®s->rx_data); >>>> + if (rxp) >>>> + *rxp++ = temp; >>>> + in_bytes -= 4; >>>> + rx_lvl -= 4; >>>> + } >>>> + } >>>> +} >>>> + >>>> +/* >>>> + * Copy uboot from spi flash to RAM >>>> + * >>>> + * @parma uboot_size size of u-boot to copy >>>> + * @param uboot_addr address in u-boot to copy >>>> + */ >>>> +static void exynos_spi_copy(unsigned int uboot_size, unsigned int uboot_addr) >>>> +{ >>>> + int upto, todo; >>>> + int i, timeout = 100; >>>> + struct exynos_spi *regs = (struct exynos_spi *)CONFIG_ENV_SPI_BASE; >>>> + >>>> + set_spi_clk(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ >>>> + /* set the spi1 GPIO */ >>>> + exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); >>>> + >>>> + /* set pktcnt and enable it */ >>>> + writel(4 | SPI_PACKET_CNT_EN, ®s->pkt_cnt); >>>> + /* set FB_CLK_SEL */ >>>> + writel(SPI_FB_DELAY_180, ®s->fb_clk); >>>> + /* set CH_WIDTH and BUS_WIDTH as word */ >>>> + setbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | >>>> + SPI_MODE_BUS_WIDTH_WORD); >>>> + clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */ >>>> + >>>> + /* clear rx and tx channel if set priveously */ >>>> + clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); >>>> + >>>> + setbits_le32(®s->swap_cfg, SPI_RX_SWAP_EN | >>>> + SPI_RX_BYTE_SWAP | >>>> + SPI_RX_HWORD_SWAP); >>>> + >>>> + /* do a soft reset */ >>>> + setbits_le32(®s->ch_cfg, SPI_CH_RST); >>>> + clrbits_le32(®s->ch_cfg, SPI_CH_RST); >>>> + >>>> + /* now set rx and tx channel ON */ >>>> + setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); >>>> + clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ >>>> + >>>> + /* Send read instruction (0x3h) followed by a 24 bit addr */ >>>> + writel((SF_READ_DATA_CMD << 24) | SPI_FLASH_UBOOT_POS, ®s->tx_data); >>>> + >>>> + /* waiting for TX done */ >>>> + while (!(readl(®s->spi_sts) & SPI_ST_TX_DONE)) { >>>> + if (!timeout) { >>>> + debug("SPI TIMEOUT\n"); >>>> + break; >>>> + } >>>> + timeout--; >>>> + } >>>> + >>>> + for (upto = 0, i = 0; upto < uboot_size; upto += todo, i++) { >>>> + todo = min(uboot_size - upto, (1 << 15)); >>>> + spi_rx_tx(regs, todo, (void *)(uboot_addr), >>>> + (void *)(SPI_FLASH_UBOOT_POS), i); >>>> + } >>>> + >>>> + setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ >>>> + >>>> + /* >>>> + * Let put controller mode to BYTE as >>>> + * SPI driver does not support WORD mode yet >>>> + */ >>>> + clrbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | >>>> + SPI_MODE_BUS_WIDTH_WORD); >>>> + writel(0, ®s->swap_cfg); >>>> + >>>> + /* >>>> + * Flush spi tx, rx fifos and reset the SPI controller >>>> + * and clear rx/tx channel >>>> + */ >>>> + clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); >>>> + clrbits_le32(®s->ch_cfg, SPI_CH_RST); >>>> + clrbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); >>>> +} >>>> + >>>> /* >>>> * Copy U-boot from mmc to RAM: >>>> * COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains >>>> @@ -70,6 +186,7 @@ void copy_uboot_to_ram(void) >>>> >>>> u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL; >>>> u32 offset = 0, size = 0; >>>> + struct spl_machine_param *param = spl_get_machine_params(); >>>> #ifdef CONFIG_SUPPORT_EMMC_BOOT >>>> u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst); >>>> void (*end_bootop_from_emmc)(void); >>>> @@ -91,9 +208,8 @@ void copy_uboot_to_ram(void) >>>> switch (bootmode) { >>>> #ifdef CONFIG_SPI_BOOTING >>>> case BOOT_MODE_SERIAL: >>>> - offset = SPI_FLASH_UBOOT_POS; >>>> - size = CONFIG_BL2_SIZE; >>>> - copy_bl2 = get_irom_func(SPI_INDEX); >>>> + /* Customised function to copy u-boot from SF */ >>>> + exynos_spi_copy(param->uboot_size, CONFIG_SYS_TEXT_BASE); >>>> break; >>>> #endif >>>> case BOOT_MODE_MMC: >>>> diff --git a/arch/arm/include/asm/arch-exynos/spi.h b/arch/arm/include/asm/arch-exynos/spi.h >>>> index 147c1a7..0ba931b 100644 >>>> --- a/arch/arm/include/asm/arch-exynos/spi.h >>>> +++ b/arch/arm/include/asm/arch-exynos/spi.h >>>> @@ -30,6 +30,7 @@ struct exynos_spi { >>>> #define EXYNOS_SPI_MAX_FREQ 50000000 >>>> >>>> #define SPI_TIMEOUT_MS 10 >>>> +#define SF_READ_DATA_CMD 0x3 >>>> >>>> /* SPI_CHCFG */ >>>> #define SPI_CH_HS_EN (1 << 6) >>>> diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h >>>> index 8c21909..1d32396 100644 >>>> --- a/include/configs/exynos5250-dt.h >>>> +++ b/include/configs/exynos5250-dt.h >>>> @@ -154,6 +154,7 @@ >>>> #define COPY_BL2_FNPTR_ADDR 0x02020030 >>>> >>>> #define CONFIG_SPL_LIBCOMMON_SUPPORT >>>> +#define CONFIG_SPL_GPIO_SUPPORT >>>> >>>> /* specific .lds file */ >>>> #define CONFIG_SPL_LDSCRIPT "board/samsung/common/exynos-uboot-spl.lds" >>>> @@ -292,6 +293,7 @@ >>>> /* SPI */ >>>> #define CONFIG_ENV_IS_IN_SPI_FLASH >>>> #define CONFIG_SPI_FLASH >>>> +#define CONFIG_ENV_SPI_BASE 0x12D30000 >>>> >>>> #ifdef CONFIG_SPI_FLASH >>>> #define CONFIG_EXYNOS_SPI >>>> -- >>>> 1.7.12.4 >>>> >>>> _______________________________________________ >>>> U-Boot mailing list >>>> U-Boot@lists.denx.de >>>> http://lists.denx.de/mailman/listinfo/u-boot >>> >>> >>> >> >> Thanks, >> Minkyu Kang. >> applied to u-boot-samsung. Thanks, Minkyu Kang.
diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index 8002bce..74cc700 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -462,7 +462,7 @@ static int exynos4_pinmux_config(int peripheral, int flags) case PERIPH_ID_SDMMC1: case PERIPH_ID_SDMMC3: case PERIPH_ID_SDMMC4: - printf("SDMMC device %d not implemented\n", peripheral); + debug("SDMMC device %d not implemented\n", peripheral); return -1; default: debug("%s: invalid peripheral %d", __func__, peripheral); diff --git a/arch/arm/cpu/armv7/exynos/spl_boot.c b/arch/arm/cpu/armv7/exynos/spl_boot.c index 3651c00..6faf13f 100644 --- a/arch/arm/cpu/armv7/exynos/spl_boot.c +++ b/arch/arm/cpu/armv7/exynos/spl_boot.c @@ -10,8 +10,11 @@ #include <asm/arch/clock.h> #include <asm/arch/clk.h> #include <asm/arch/dmc.h> +#include <asm/arch/periph.h> +#include <asm/arch/pinmux.h> #include <asm/arch/power.h> #include <asm/arch/spl.h> +#include <asm/arch/spi.h> #include "common_setup.h" #include "clock_init.h" @@ -59,6 +62,119 @@ static int config_branch_prediction(int set_cr_z) } #endif +static void spi_rx_tx(struct exynos_spi *regs, int todo, + void *dinp, void const *doutp, int i) +{ + uint *rxp = (uint *)(dinp + (i * (32 * 1024))); + int rx_lvl, tx_lvl; + uint out_bytes, in_bytes; + + out_bytes = todo; + in_bytes = todo; + setbits_le32(®s->ch_cfg, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_CH_RST); + writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, ®s->pkt_cnt); + + while (in_bytes) { + uint32_t spi_sts; + int temp; + + spi_sts = readl(®s->spi_sts); + rx_lvl = ((spi_sts >> 15) & 0x7f); + tx_lvl = ((spi_sts >> 6) & 0x7f); + while (tx_lvl < 32 && out_bytes) { + temp = 0xffffffff; + writel(temp, ®s->tx_data); + out_bytes -= 4; + tx_lvl += 4; + } + while (rx_lvl >= 4 && in_bytes) { + temp = readl(®s->rx_data); + if (rxp) + *rxp++ = temp; + in_bytes -= 4; + rx_lvl -= 4; + } + } +} + +/* + * Copy uboot from spi flash to RAM + * + * @parma uboot_size size of u-boot to copy + * @param uboot_addr address in u-boot to copy + */ +static void exynos_spi_copy(unsigned int uboot_size, unsigned int uboot_addr) +{ + int upto, todo; + int i, timeout = 100; + struct exynos_spi *regs = (struct exynos_spi *)CONFIG_ENV_SPI_BASE; + + set_spi_clk(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ + /* set the spi1 GPIO */ + exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); + + /* set pktcnt and enable it */ + writel(4 | SPI_PACKET_CNT_EN, ®s->pkt_cnt); + /* set FB_CLK_SEL */ + writel(SPI_FB_DELAY_180, ®s->fb_clk); + /* set CH_WIDTH and BUS_WIDTH as word */ + setbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | + SPI_MODE_BUS_WIDTH_WORD); + clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */ + + /* clear rx and tx channel if set priveously */ + clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); + + setbits_le32(®s->swap_cfg, SPI_RX_SWAP_EN | + SPI_RX_BYTE_SWAP | + SPI_RX_HWORD_SWAP); + + /* do a soft reset */ + setbits_le32(®s->ch_cfg, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_CH_RST); + + /* now set rx and tx channel ON */ + setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); + clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ + + /* Send read instruction (0x3h) followed by a 24 bit addr */ + writel((SF_READ_DATA_CMD << 24) | SPI_FLASH_UBOOT_POS, ®s->tx_data); + + /* waiting for TX done */ + while (!(readl(®s->spi_sts) & SPI_ST_TX_DONE)) { + if (!timeout) { + debug("SPI TIMEOUT\n"); + break; + } + timeout--; + } + + for (upto = 0, i = 0; upto < uboot_size; upto += todo, i++) { + todo = min(uboot_size - upto, (1 << 15)); + spi_rx_tx(regs, todo, (void *)(uboot_addr), + (void *)(SPI_FLASH_UBOOT_POS), i); + } + + setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ + + /* + * Let put controller mode to BYTE as + * SPI driver does not support WORD mode yet + */ + clrbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | + SPI_MODE_BUS_WIDTH_WORD); + writel(0, ®s->swap_cfg); + + /* + * Flush spi tx, rx fifos and reset the SPI controller + * and clear rx/tx channel + */ + clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); +} + /* * Copy U-boot from mmc to RAM: * COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains @@ -70,6 +186,7 @@ void copy_uboot_to_ram(void) u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst) = NULL; u32 offset = 0, size = 0; + struct spl_machine_param *param = spl_get_machine_params(); #ifdef CONFIG_SUPPORT_EMMC_BOOT u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst); void (*end_bootop_from_emmc)(void); @@ -91,9 +208,8 @@ void copy_uboot_to_ram(void) switch (bootmode) { #ifdef CONFIG_SPI_BOOTING case BOOT_MODE_SERIAL: - offset = SPI_FLASH_UBOOT_POS; - size = CONFIG_BL2_SIZE; - copy_bl2 = get_irom_func(SPI_INDEX); + /* Customised function to copy u-boot from SF */ + exynos_spi_copy(param->uboot_size, CONFIG_SYS_TEXT_BASE); break; #endif case BOOT_MODE_MMC: diff --git a/arch/arm/include/asm/arch-exynos/spi.h b/arch/arm/include/asm/arch-exynos/spi.h index 147c1a7..0ba931b 100644 --- a/arch/arm/include/asm/arch-exynos/spi.h +++ b/arch/arm/include/asm/arch-exynos/spi.h @@ -30,6 +30,7 @@ struct exynos_spi { #define EXYNOS_SPI_MAX_FREQ 50000000 #define SPI_TIMEOUT_MS 10 +#define SF_READ_DATA_CMD 0x3 /* SPI_CHCFG */ #define SPI_CH_HS_EN (1 << 6) diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h index 8c21909..1d32396 100644 --- a/include/configs/exynos5250-dt.h +++ b/include/configs/exynos5250-dt.h @@ -154,6 +154,7 @@ #define COPY_BL2_FNPTR_ADDR 0x02020030 #define CONFIG_SPL_LIBCOMMON_SUPPORT +#define CONFIG_SPL_GPIO_SUPPORT /* specific .lds file */ #define CONFIG_SPL_LDSCRIPT "board/samsung/common/exynos-uboot-spl.lds" @@ -292,6 +293,7 @@ /* SPI */ #define CONFIG_ENV_IS_IN_SPI_FLASH #define CONFIG_SPI_FLASH +#define CONFIG_ENV_SPI_BASE 0x12D30000 #ifdef CONFIG_SPI_FLASH #define CONFIG_EXYNOS_SPI