Merge branch 'master' of git://git.denx.de/u-boot-uniphier
This commit is contained in:
commit
ff62bdfbd5
|
@ -85,3 +85,11 @@
|
||||||
&serial0 {
|
&serial0 {
|
||||||
u-boot,dm-pre-reloc;
|
u-boot,dm-pre-reloc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&mio {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
};
|
||||||
|
|
||||||
|
&emmc {
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
};
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#size-cells = <1>;
|
#size-cells = <1>;
|
||||||
ranges;
|
ranges;
|
||||||
interrupt-parent = <&intc>;
|
interrupt-parent = <&intc>;
|
||||||
|
u-boot,dm-pre-reloc;
|
||||||
|
|
||||||
timer@20000200 {
|
timer@20000200 {
|
||||||
compatible = "arm,cortex-a9-global-timer";
|
compatible = "arm,cortex-a9-global-timer";
|
||||||
|
|
|
@ -151,3 +151,8 @@ int __secure psci_cpu_on(u32 function_id, u32 cpuid, u32 entry_point)
|
||||||
|
|
||||||
return PSCI_RET_SUCCESS;
|
return PSCI_RET_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __secure psci_system_reset(u32 function_id)
|
||||||
|
{
|
||||||
|
reset_cpu(0);
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
|
* Copyright (C) 2012-2015 Panasonic Corporation
|
||||||
|
* Copyright (C) 2015-2016 Socionext Inc.
|
||||||
|
* Author: Masahiro Yamada <yamada.masahiro@socionext.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: GPL-2.0+
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
*/
|
*/
|
||||||
|
@ -38,7 +40,12 @@ static int support_card_show_revision(void)
|
||||||
u32 revision;
|
u32 revision;
|
||||||
|
|
||||||
revision = readl(MICRO_SUPPORT_CARD_REVISION);
|
revision = readl(MICRO_SUPPORT_CARD_REVISION);
|
||||||
printf("(CPLD version %d.%d)\n", revision >> 4, revision & 0xf);
|
revision &= 0xff;
|
||||||
|
|
||||||
|
/* revision 3.6.x card changed the revision format */
|
||||||
|
printf("(CPLD version %s%d.%d)\n", revision >> 4 == 6 ? "3." : "",
|
||||||
|
revision >> 4, revision & 0xf);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,25 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2012-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
|
* Copyright (C) 2012-2014 Panasonic Corporation
|
||||||
|
* Copyright (C) 2015-2016 Socionext Inc.
|
||||||
|
* Author: Masahiro Yamada <yamada.masahiro@socionext.com>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: GPL-2.0+
|
* SPDX-License-Identifier: GPL-2.0+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
#include <asm/secure.h>
|
||||||
|
|
||||||
#include "sc-regs.h"
|
#include "sc-regs.h"
|
||||||
|
|
||||||
void reset_cpu(unsigned long ignored)
|
/* If PSCI is enabled, this is used for SYSTEM_RESET function */
|
||||||
|
#ifdef CONFIG_ARMV7_PSCI
|
||||||
|
#define __SECURE __secure
|
||||||
|
#else
|
||||||
|
#define __SECURE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void __SECURE reset_cpu(unsigned long ignored)
|
||||||
{
|
{
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ CONFIG_CMD_USB=y
|
||||||
CONFIG_CMD_GPIO=y
|
CONFIG_CMD_GPIO=y
|
||||||
CONFIG_CMD_TFTPPUT=y
|
CONFIG_CMD_TFTPPUT=y
|
||||||
CONFIG_CMD_PING=y
|
CONFIG_CMD_PING=y
|
||||||
|
CONFIG_CMD_CACHE=y
|
||||||
CONFIG_CMD_TIME=y
|
CONFIG_CMD_TIME=y
|
||||||
# CONFIG_CMD_MISC is not set
|
# CONFIG_CMD_MISC is not set
|
||||||
CONFIG_CMD_FAT=y
|
CONFIG_CMD_FAT=y
|
||||||
|
@ -25,7 +26,6 @@ CONFIG_MISC=y
|
||||||
CONFIG_I2C_EEPROM=y
|
CONFIG_I2C_EEPROM=y
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_SPL_PINCTRL=y
|
CONFIG_SPL_PINCTRL=y
|
||||||
CONFIG_UNIPHIER_SERIAL=y
|
|
||||||
CONFIG_USB=y
|
CONFIG_USB=y
|
||||||
CONFIG_DM_USB=y
|
CONFIG_DM_USB=y
|
||||||
CONFIG_USB_EHCI_HCD=y
|
CONFIG_USB_EHCI_HCD=y
|
||||||
|
|
|
@ -15,6 +15,7 @@ CONFIG_CMD_USB=y
|
||||||
CONFIG_CMD_GPIO=y
|
CONFIG_CMD_GPIO=y
|
||||||
CONFIG_CMD_TFTPPUT=y
|
CONFIG_CMD_TFTPPUT=y
|
||||||
CONFIG_CMD_PING=y
|
CONFIG_CMD_PING=y
|
||||||
|
CONFIG_CMD_CACHE=y
|
||||||
CONFIG_CMD_TIME=y
|
CONFIG_CMD_TIME=y
|
||||||
# CONFIG_CMD_MISC is not set
|
# CONFIG_CMD_MISC is not set
|
||||||
CONFIG_CMD_FAT=y
|
CONFIG_CMD_FAT=y
|
||||||
|
@ -26,7 +27,6 @@ CONFIG_I2C_EEPROM=y
|
||||||
CONFIG_MMC_UNIPHIER=y
|
CONFIG_MMC_UNIPHIER=y
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_SPL_PINCTRL=y
|
CONFIG_SPL_PINCTRL=y
|
||||||
CONFIG_UNIPHIER_SERIAL=y
|
|
||||||
CONFIG_USB=y
|
CONFIG_USB=y
|
||||||
CONFIG_USB_XHCI_HCD=y
|
CONFIG_USB_XHCI_HCD=y
|
||||||
CONFIG_USB_STORAGE=y
|
CONFIG_USB_STORAGE=y
|
||||||
|
|
|
@ -17,6 +17,7 @@ CONFIG_CMD_USB=y
|
||||||
CONFIG_CMD_GPIO=y
|
CONFIG_CMD_GPIO=y
|
||||||
CONFIG_CMD_TFTPPUT=y
|
CONFIG_CMD_TFTPPUT=y
|
||||||
CONFIG_CMD_PING=y
|
CONFIG_CMD_PING=y
|
||||||
|
CONFIG_CMD_CACHE=y
|
||||||
CONFIG_CMD_TIME=y
|
CONFIG_CMD_TIME=y
|
||||||
# CONFIG_CMD_MISC is not set
|
# CONFIG_CMD_MISC is not set
|
||||||
CONFIG_CMD_FAT=y
|
CONFIG_CMD_FAT=y
|
||||||
|
@ -31,7 +32,6 @@ CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
|
||||||
CONFIG_SPL_NAND_DENALI=y
|
CONFIG_SPL_NAND_DENALI=y
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_SPL_PINCTRL=y
|
CONFIG_SPL_PINCTRL=y
|
||||||
CONFIG_UNIPHIER_SERIAL=y
|
|
||||||
CONFIG_USB=y
|
CONFIG_USB=y
|
||||||
CONFIG_DM_USB=y
|
CONFIG_DM_USB=y
|
||||||
CONFIG_USB_EHCI_HCD=y
|
CONFIG_USB_EHCI_HCD=y
|
||||||
|
|
|
@ -16,6 +16,7 @@ CONFIG_CMD_USB=y
|
||||||
CONFIG_CMD_GPIO=y
|
CONFIG_CMD_GPIO=y
|
||||||
CONFIG_CMD_TFTPPUT=y
|
CONFIG_CMD_TFTPPUT=y
|
||||||
CONFIG_CMD_PING=y
|
CONFIG_CMD_PING=y
|
||||||
|
CONFIG_CMD_CACHE=y
|
||||||
CONFIG_CMD_TIME=y
|
CONFIG_CMD_TIME=y
|
||||||
# CONFIG_CMD_MISC is not set
|
# CONFIG_CMD_MISC is not set
|
||||||
CONFIG_CMD_FAT=y
|
CONFIG_CMD_FAT=y
|
||||||
|
@ -30,7 +31,6 @@ CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
|
||||||
CONFIG_SPL_NAND_DENALI=y
|
CONFIG_SPL_NAND_DENALI=y
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_SPL_PINCTRL=y
|
CONFIG_SPL_PINCTRL=y
|
||||||
CONFIG_UNIPHIER_SERIAL=y
|
|
||||||
CONFIG_USB=y
|
CONFIG_USB=y
|
||||||
CONFIG_USB_XHCI_HCD=y
|
CONFIG_USB_XHCI_HCD=y
|
||||||
CONFIG_USB_STORAGE=y
|
CONFIG_USB_STORAGE=y
|
||||||
|
|
|
@ -17,6 +17,7 @@ CONFIG_CMD_USB=y
|
||||||
CONFIG_CMD_GPIO=y
|
CONFIG_CMD_GPIO=y
|
||||||
CONFIG_CMD_TFTPPUT=y
|
CONFIG_CMD_TFTPPUT=y
|
||||||
CONFIG_CMD_PING=y
|
CONFIG_CMD_PING=y
|
||||||
|
CONFIG_CMD_CACHE=y
|
||||||
CONFIG_CMD_TIME=y
|
CONFIG_CMD_TIME=y
|
||||||
# CONFIG_CMD_MISC is not set
|
# CONFIG_CMD_MISC is not set
|
||||||
CONFIG_CMD_FAT=y
|
CONFIG_CMD_FAT=y
|
||||||
|
@ -31,7 +32,6 @@ CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
|
||||||
CONFIG_SPL_NAND_DENALI=y
|
CONFIG_SPL_NAND_DENALI=y
|
||||||
CONFIG_PINCTRL=y
|
CONFIG_PINCTRL=y
|
||||||
CONFIG_SPL_PINCTRL=y
|
CONFIG_SPL_PINCTRL=y
|
||||||
CONFIG_UNIPHIER_SERIAL=y
|
|
||||||
CONFIG_USB=y
|
CONFIG_USB=y
|
||||||
CONFIG_USB_XHCI_HCD=y
|
CONFIG_USB_XHCI_HCD=y
|
||||||
CONFIG_USB_STORAGE=y
|
CONFIG_USB_STORAGE=y
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
CONFIG_ARM=y
|
CONFIG_ARM=y
|
||||||
CONFIG_ARCH_UNIPHIER=y
|
CONFIG_ARCH_UNIPHIER=y
|
||||||
|
CONFIG_SYS_MALLOC_F_LEN=0x2000
|
||||||
CONFIG_ARCH_UNIPHIER_SLD3=y
|
CONFIG_ARCH_UNIPHIER_SLD3=y
|
||||||
CONFIG_MICRO_SUPPORT_CARD=y
|
CONFIG_MICRO_SUPPORT_CARD=y
|
||||||
CONFIG_SYS_TEXT_BASE=0x84000000
|
CONFIG_SYS_TEXT_BASE=0x84000000
|
||||||
|
@ -16,6 +17,7 @@ CONFIG_CMD_USB=y
|
||||||
CONFIG_CMD_GPIO=y
|
CONFIG_CMD_GPIO=y
|
||||||
CONFIG_CMD_TFTPPUT=y
|
CONFIG_CMD_TFTPPUT=y
|
||||||
CONFIG_CMD_PING=y
|
CONFIG_CMD_PING=y
|
||||||
|
CONFIG_CMD_CACHE=y
|
||||||
CONFIG_CMD_TIME=y
|
CONFIG_CMD_TIME=y
|
||||||
# CONFIG_CMD_MISC is not set
|
# CONFIG_CMD_MISC is not set
|
||||||
CONFIG_CMD_FAT=y
|
CONFIG_CMD_FAT=y
|
||||||
|
@ -28,7 +30,6 @@ CONFIG_NAND_DENALI=y
|
||||||
CONFIG_SYS_NAND_DENALI_64BIT=y
|
CONFIG_SYS_NAND_DENALI_64BIT=y
|
||||||
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
|
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
|
||||||
CONFIG_SPL_NAND_DENALI=y
|
CONFIG_SPL_NAND_DENALI=y
|
||||||
CONFIG_UNIPHIER_SERIAL=y
|
|
||||||
CONFIG_USB=y
|
CONFIG_USB=y
|
||||||
CONFIG_DM_USB=y
|
CONFIG_DM_USB=y
|
||||||
CONFIG_USB_EHCI_HCD=y
|
CONFIG_USB_EHCI_HCD=y
|
||||||
|
|
|
@ -80,6 +80,7 @@ config ROCKCHIP_SDHCI
|
||||||
config MMC_UNIPHIER
|
config MMC_UNIPHIER
|
||||||
bool "UniPhier SD/MMC Host Controller support"
|
bool "UniPhier SD/MMC Host Controller support"
|
||||||
depends on ARCH_UNIPHIER
|
depends on ARCH_UNIPHIER
|
||||||
|
select DM_MMC_OPS
|
||||||
help
|
help
|
||||||
This selects support for the SD/MMC Host Controller on UniPhier SoCs.
|
This selects support for the SD/MMC Host Controller on UniPhier SoCs.
|
||||||
|
|
||||||
|
|
|
@ -122,7 +122,6 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||||
struct uniphier_sd_priv {
|
struct uniphier_sd_priv {
|
||||||
struct mmc_config cfg;
|
struct mmc_config cfg;
|
||||||
struct mmc *mmc;
|
struct mmc *mmc;
|
||||||
struct udevice *dev;
|
|
||||||
void __iomem *regbase;
|
void __iomem *regbase;
|
||||||
unsigned long mclk;
|
unsigned long mclk;
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
|
@ -152,8 +151,9 @@ static void __dma_unmap_single(dma_addr_t addr, size_t size,
|
||||||
invalidate_dcache_range(addr, addr + size);
|
invalidate_dcache_range(addr, addr + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uniphier_sd_check_error(struct uniphier_sd_priv *priv)
|
static int uniphier_sd_check_error(struct udevice *dev)
|
||||||
{
|
{
|
||||||
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
u32 info2 = readl(priv->regbase + UNIPHIER_SD_INFO2);
|
u32 info2 = readl(priv->regbase + UNIPHIER_SD_INFO2);
|
||||||
|
|
||||||
if (info2 & UNIPHIER_SD_INFO2_ERR_RTO) {
|
if (info2 & UNIPHIER_SD_INFO2_ERR_RTO) {
|
||||||
|
@ -166,38 +166,39 @@ static int uniphier_sd_check_error(struct uniphier_sd_priv *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info2 & UNIPHIER_SD_INFO2_ERR_TO) {
|
if (info2 & UNIPHIER_SD_INFO2_ERR_TO) {
|
||||||
dev_err(priv->dev, "timeout error\n");
|
dev_err(dev, "timeout error\n");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info2 & (UNIPHIER_SD_INFO2_ERR_END | UNIPHIER_SD_INFO2_ERR_CRC |
|
if (info2 & (UNIPHIER_SD_INFO2_ERR_END | UNIPHIER_SD_INFO2_ERR_CRC |
|
||||||
UNIPHIER_SD_INFO2_ERR_IDX)) {
|
UNIPHIER_SD_INFO2_ERR_IDX)) {
|
||||||
dev_err(priv->dev, "communication out of sync\n");
|
dev_err(dev, "communication out of sync\n");
|
||||||
return -EILSEQ;
|
return -EILSEQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info2 & (UNIPHIER_SD_INFO2_ERR_ILA | UNIPHIER_SD_INFO2_ERR_ILR |
|
if (info2 & (UNIPHIER_SD_INFO2_ERR_ILA | UNIPHIER_SD_INFO2_ERR_ILR |
|
||||||
UNIPHIER_SD_INFO2_ERR_ILW)) {
|
UNIPHIER_SD_INFO2_ERR_ILW)) {
|
||||||
dev_err(priv->dev, "illegal access\n");
|
dev_err(dev, "illegal access\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uniphier_sd_wait_for_irq(struct uniphier_sd_priv *priv,
|
static int uniphier_sd_wait_for_irq(struct udevice *dev, unsigned int reg,
|
||||||
unsigned int reg, u32 flag)
|
u32 flag)
|
||||||
{
|
{
|
||||||
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
long wait = 1000000;
|
long wait = 1000000;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
while (!(readl(priv->regbase + reg) & flag)) {
|
while (!(readl(priv->regbase + reg) & flag)) {
|
||||||
if (wait-- < 0) {
|
if (wait-- < 0) {
|
||||||
dev_err(priv->dev, "timeout\n");
|
dev_err(dev, "timeout\n");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = uniphier_sd_check_error(priv);
|
ret = uniphier_sd_check_error(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -207,14 +208,14 @@ static int uniphier_sd_wait_for_irq(struct uniphier_sd_priv *priv,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uniphier_sd_pio_read_one_block(struct mmc *mmc, u32 **pbuf,
|
static int uniphier_sd_pio_read_one_block(struct udevice *dev, u32 **pbuf,
|
||||||
uint blocksize)
|
uint blocksize)
|
||||||
{
|
{
|
||||||
struct uniphier_sd_priv *priv = mmc->priv;
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
/* wait until the buffer is filled with data */
|
/* wait until the buffer is filled with data */
|
||||||
ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO2,
|
ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO2,
|
||||||
UNIPHIER_SD_INFO2_BRE);
|
UNIPHIER_SD_INFO2_BRE);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -237,14 +238,14 @@ static int uniphier_sd_pio_read_one_block(struct mmc *mmc, u32 **pbuf,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uniphier_sd_pio_write_one_block(struct mmc *mmc, const u32 **pbuf,
|
static int uniphier_sd_pio_write_one_block(struct udevice *dev,
|
||||||
uint blocksize)
|
const u32 **pbuf, uint blocksize)
|
||||||
{
|
{
|
||||||
struct uniphier_sd_priv *priv = mmc->priv;
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
/* wait until the buffer becomes empty */
|
/* wait until the buffer becomes empty */
|
||||||
ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO2,
|
ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO2,
|
||||||
UNIPHIER_SD_INFO2_BWE);
|
UNIPHIER_SD_INFO2_BWE);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -263,7 +264,7 @@ static int uniphier_sd_pio_write_one_block(struct mmc *mmc, const u32 **pbuf,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uniphier_sd_pio_xfer(struct mmc *mmc, struct mmc_data *data)
|
static int uniphier_sd_pio_xfer(struct udevice *dev, struct mmc_data *data)
|
||||||
{
|
{
|
||||||
u32 *dest = (u32 *)data->dest;
|
u32 *dest = (u32 *)data->dest;
|
||||||
const u32 *src = (const u32 *)data->src;
|
const u32 *src = (const u32 *)data->src;
|
||||||
|
@ -271,10 +272,10 @@ static int uniphier_sd_pio_xfer(struct mmc *mmc, struct mmc_data *data)
|
||||||
|
|
||||||
for (i = 0; i < data->blocks; i++) {
|
for (i = 0; i < data->blocks; i++) {
|
||||||
if (data->flags & MMC_DATA_READ)
|
if (data->flags & MMC_DATA_READ)
|
||||||
ret = uniphier_sd_pio_read_one_block(mmc, &dest,
|
ret = uniphier_sd_pio_read_one_block(dev, &dest,
|
||||||
data->blocksize);
|
data->blocksize);
|
||||||
else
|
else
|
||||||
ret = uniphier_sd_pio_write_one_block(mmc, &src,
|
ret = uniphier_sd_pio_write_one_block(dev, &src,
|
||||||
data->blocksize);
|
data->blocksize);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -306,14 +307,15 @@ static void uniphier_sd_dma_start(struct uniphier_sd_priv *priv,
|
||||||
writel(UNIPHIER_SD_DMA_CTL_START, priv->regbase + UNIPHIER_SD_DMA_CTL);
|
writel(UNIPHIER_SD_DMA_CTL_START, priv->regbase + UNIPHIER_SD_DMA_CTL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uniphier_sd_dma_wait_for_irq(struct uniphier_sd_priv *priv, u32 flag,
|
static int uniphier_sd_dma_wait_for_irq(struct udevice *dev, u32 flag,
|
||||||
unsigned int blocks)
|
unsigned int blocks)
|
||||||
{
|
{
|
||||||
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
long wait = 1000000 + 10 * blocks;
|
long wait = 1000000 + 10 * blocks;
|
||||||
|
|
||||||
while (!(readl(priv->regbase + UNIPHIER_SD_DMA_INFO1) & flag)) {
|
while (!(readl(priv->regbase + UNIPHIER_SD_DMA_INFO1) & flag)) {
|
||||||
if (wait-- < 0) {
|
if (wait-- < 0) {
|
||||||
dev_err(priv->dev, "timeout during DMA\n");
|
dev_err(dev, "timeout during DMA\n");
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,16 +323,16 @@ static int uniphier_sd_dma_wait_for_irq(struct uniphier_sd_priv *priv, u32 flag,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) {
|
if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) {
|
||||||
dev_err(priv->dev, "error during DMA\n");
|
dev_err(dev, "error during DMA\n");
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uniphier_sd_dma_xfer(struct mmc *mmc, struct mmc_data *data)
|
static int uniphier_sd_dma_xfer(struct udevice *dev, struct mmc_data *data)
|
||||||
{
|
{
|
||||||
struct uniphier_sd_priv *priv = mmc->priv;
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
size_t len = data->blocks * data->blocksize;
|
size_t len = data->blocks * data->blocksize;
|
||||||
void *buf;
|
void *buf;
|
||||||
enum dma_data_direction dir;
|
enum dma_data_direction dir;
|
||||||
|
@ -358,7 +360,7 @@ static int uniphier_sd_dma_xfer(struct mmc *mmc, struct mmc_data *data)
|
||||||
|
|
||||||
uniphier_sd_dma_start(priv, dma_addr);
|
uniphier_sd_dma_start(priv, dma_addr);
|
||||||
|
|
||||||
ret = uniphier_sd_dma_wait_for_irq(priv, poll_flag, data->blocks);
|
ret = uniphier_sd_dma_wait_for_irq(dev, poll_flag, data->blocks);
|
||||||
|
|
||||||
__dma_unmap_single(dma_addr, len, dir);
|
__dma_unmap_single(dma_addr, len, dir);
|
||||||
|
|
||||||
|
@ -384,15 +386,15 @@ static bool uniphier_sd_addr_is_dmaable(unsigned long addr)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uniphier_sd_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
static int uniphier_sd_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
|
||||||
struct mmc_data *data)
|
struct mmc_data *data)
|
||||||
{
|
{
|
||||||
struct uniphier_sd_priv *priv = mmc->priv;
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
int ret;
|
int ret;
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
if (readl(priv->regbase + UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) {
|
if (readl(priv->regbase + UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) {
|
||||||
dev_err(priv->dev, "command busy\n");
|
dev_err(dev, "command busy\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,15 +448,15 @@ static int uniphier_sd_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
tmp |= UNIPHIER_SD_CMD_RSP_R3;
|
tmp |= UNIPHIER_SD_CMD_RSP_R3;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(priv->dev, "unknown response type\n");
|
dev_err(dev, "unknown response type\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(priv->dev, "sending CMD%d (SD_CMD=%08x, SD_ARG=%08x)\n",
|
dev_dbg(dev, "sending CMD%d (SD_CMD=%08x, SD_ARG=%08x)\n",
|
||||||
cmd->cmdidx, tmp, cmd->cmdarg);
|
cmd->cmdidx, tmp, cmd->cmdarg);
|
||||||
writel(tmp, priv->regbase + UNIPHIER_SD_CMD);
|
writel(tmp, priv->regbase + UNIPHIER_SD_CMD);
|
||||||
|
|
||||||
ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO1,
|
ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO1,
|
||||||
UNIPHIER_SD_INFO1_RSP);
|
UNIPHIER_SD_INFO1_RSP);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -481,11 +483,11 @@ static int uniphier_sd_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
/* use DMA if the HW supports it and the buffer is aligned */
|
/* use DMA if the HW supports it and the buffer is aligned */
|
||||||
if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL &&
|
if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL &&
|
||||||
uniphier_sd_addr_is_dmaable((long)data->src))
|
uniphier_sd_addr_is_dmaable((long)data->src))
|
||||||
ret = uniphier_sd_dma_xfer(mmc, data);
|
ret = uniphier_sd_dma_xfer(dev, data);
|
||||||
else
|
else
|
||||||
ret = uniphier_sd_pio_xfer(mmc, data);
|
ret = uniphier_sd_pio_xfer(dev, data);
|
||||||
|
|
||||||
ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO1,
|
ret = uniphier_sd_wait_for_irq(dev, UNIPHIER_SD_INFO1,
|
||||||
UNIPHIER_SD_INFO1_CMP);
|
UNIPHIER_SD_INFO1_CMP);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -494,8 +496,8 @@ static int uniphier_sd_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uniphier_sd_set_bus_width(struct uniphier_sd_priv *priv,
|
static int uniphier_sd_set_bus_width(struct uniphier_sd_priv *priv,
|
||||||
struct mmc *mmc)
|
struct mmc *mmc)
|
||||||
{
|
{
|
||||||
u32 val, tmp;
|
u32 val, tmp;
|
||||||
|
|
||||||
|
@ -510,14 +512,15 @@ static void uniphier_sd_set_bus_width(struct uniphier_sd_priv *priv,
|
||||||
val = UNIPHIER_SD_OPTION_WIDTH_8;
|
val = UNIPHIER_SD_OPTION_WIDTH_8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
return -EINVAL;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = readl(priv->regbase + UNIPHIER_SD_OPTION);
|
tmp = readl(priv->regbase + UNIPHIER_SD_OPTION);
|
||||||
tmp &= ~UNIPHIER_SD_OPTION_WIDTH_MASK;
|
tmp &= ~UNIPHIER_SD_OPTION_WIDTH_MASK;
|
||||||
tmp |= val;
|
tmp |= val;
|
||||||
writel(tmp, priv->regbase + UNIPHIER_SD_OPTION);
|
writel(tmp, priv->regbase + UNIPHIER_SD_OPTION);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uniphier_sd_set_ddr_mode(struct uniphier_sd_priv *priv,
|
static void uniphier_sd_set_ddr_mode(struct uniphier_sd_priv *priv,
|
||||||
|
@ -568,6 +571,9 @@ static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv,
|
||||||
val = UNIPHIER_SD_CLKCTL_DIV1024;
|
val = UNIPHIER_SD_CLKCTL_DIV1024;
|
||||||
|
|
||||||
tmp = readl(priv->regbase + UNIPHIER_SD_CLKCTL);
|
tmp = readl(priv->regbase + UNIPHIER_SD_CLKCTL);
|
||||||
|
if (tmp & UNIPHIER_SD_CLKCTL_SCLKEN &&
|
||||||
|
(tmp & UNIPHIER_SD_CLKCTL_DIV_MASK) == val)
|
||||||
|
return;
|
||||||
|
|
||||||
/* stop the clock before changing its rate to avoid a glitch signal */
|
/* stop the clock before changing its rate to avoid a glitch signal */
|
||||||
tmp &= ~UNIPHIER_SD_CLKCTL_SCLKEN;
|
tmp &= ~UNIPHIER_SD_CLKCTL_SCLKEN;
|
||||||
|
@ -579,25 +585,47 @@ static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv,
|
||||||
|
|
||||||
tmp |= UNIPHIER_SD_CLKCTL_SCLKEN;
|
tmp |= UNIPHIER_SD_CLKCTL_SCLKEN;
|
||||||
writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
|
writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
|
||||||
}
|
|
||||||
|
|
||||||
static void uniphier_sd_set_ios(struct mmc *mmc)
|
|
||||||
{
|
|
||||||
struct uniphier_sd_priv *priv = mmc->priv;
|
|
||||||
|
|
||||||
dev_dbg(priv->dev, "clock %uHz, DDRmode %d, width %u\n",
|
|
||||||
mmc->clock, mmc->ddr_mode, mmc->bus_width);
|
|
||||||
|
|
||||||
uniphier_sd_set_bus_width(priv, mmc);
|
|
||||||
uniphier_sd_set_ddr_mode(priv, mmc);
|
|
||||||
uniphier_sd_set_clk_rate(priv, mmc);
|
|
||||||
|
|
||||||
udelay(1000);
|
udelay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uniphier_sd_init(struct mmc *mmc)
|
static int uniphier_sd_set_ios(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
|
struct mmc *mmc = mmc_get_mmc_dev(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dev_dbg(dev, "clock %uHz, DDRmode %d, width %u\n",
|
||||||
|
mmc->clock, mmc->ddr_mode, mmc->bus_width);
|
||||||
|
|
||||||
|
ret = uniphier_sd_set_bus_width(priv, mmc);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
uniphier_sd_set_ddr_mode(priv, mmc);
|
||||||
|
uniphier_sd_set_clk_rate(priv, mmc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int uniphier_sd_get_cd(struct udevice *dev)
|
||||||
|
{
|
||||||
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
if (priv->caps & UNIPHIER_SD_CAP_NONREMOVABLE)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return !!(readl(priv->regbase + UNIPHIER_SD_INFO1) &
|
||||||
|
UNIPHIER_SD_INFO1_CD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dm_mmc_ops uniphier_sd_ops = {
|
||||||
|
.send_cmd = uniphier_sd_send_cmd,
|
||||||
|
.set_ios = uniphier_sd_set_ios,
|
||||||
|
.get_cd = uniphier_sd_get_cd,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void uniphier_sd_host_init(struct uniphier_sd_priv *priv)
|
||||||
{
|
{
|
||||||
struct uniphier_sd_priv *priv = mmc->priv;
|
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
/* soft reset of the host */
|
/* soft reset of the host */
|
||||||
|
@ -624,29 +652,9 @@ static int uniphier_sd_init(struct mmc *mmc)
|
||||||
tmp |= UNIPHIER_SD_DMA_MODE_ADDR_INC;
|
tmp |= UNIPHIER_SD_DMA_MODE_ADDR_INC;
|
||||||
writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE);
|
writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uniphier_sd_getcd(struct mmc *mmc)
|
static int uniphier_sd_probe(struct udevice *dev)
|
||||||
{
|
|
||||||
struct uniphier_sd_priv *priv = mmc->priv;
|
|
||||||
|
|
||||||
if (priv->caps & UNIPHIER_SD_CAP_NONREMOVABLE)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return !!(readl(priv->regbase + UNIPHIER_SD_INFO1) &
|
|
||||||
UNIPHIER_SD_INFO1_CD);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct mmc_ops uniphier_sd_ops = {
|
|
||||||
.send_cmd = uniphier_sd_send_cmd,
|
|
||||||
.set_ios = uniphier_sd_set_ios,
|
|
||||||
.init = uniphier_sd_init,
|
|
||||||
.getcd = uniphier_sd_getcd,
|
|
||||||
};
|
|
||||||
|
|
||||||
int uniphier_sd_probe(struct udevice *dev)
|
|
||||||
{
|
{
|
||||||
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
|
||||||
|
@ -654,8 +662,6 @@ int uniphier_sd_probe(struct udevice *dev)
|
||||||
struct clk clk;
|
struct clk clk;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
priv->dev = dev;
|
|
||||||
|
|
||||||
base = dev_get_addr(dev);
|
base = dev_get_addr(dev);
|
||||||
if (base == FDT_ADDR_T_NONE)
|
if (base == FDT_ADDR_T_NONE)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -686,7 +692,6 @@ int uniphier_sd_probe(struct udevice *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->cfg.name = dev->name;
|
priv->cfg.name = dev->name;
|
||||||
priv->cfg.ops = &uniphier_sd_ops;
|
|
||||||
priv->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
|
priv->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
|
||||||
|
|
||||||
switch (fdtdec_get_int(gd->fdt_blob, dev->of_offset, "bus-width", 1)) {
|
switch (fdtdec_get_int(gd->fdt_blob, dev->of_offset, "bus-width", 1)) {
|
||||||
|
@ -715,6 +720,8 @@ int uniphier_sd_probe(struct udevice *dev)
|
||||||
priv->caps |= UNIPHIER_SD_CAP_DIV1024;
|
priv->caps |= UNIPHIER_SD_CAP_DIV1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uniphier_sd_host_init(priv);
|
||||||
|
|
||||||
priv->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
|
priv->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||||
priv->cfg.f_min = priv->mclk /
|
priv->cfg.f_min = priv->mclk /
|
||||||
(priv->caps & UNIPHIER_SD_CAP_DIV1024 ? 1024 : 512);
|
(priv->caps & UNIPHIER_SD_CAP_DIV1024 ? 1024 : 512);
|
||||||
|
@ -731,7 +738,7 @@ int uniphier_sd_probe(struct udevice *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int uniphier_sd_remove(struct udevice *dev)
|
static int uniphier_sd_remove(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
struct uniphier_sd_priv *priv = dev_get_priv(dev);
|
||||||
|
|
||||||
|
@ -752,4 +759,5 @@ U_BOOT_DRIVER(uniphier_mmc) = {
|
||||||
.probe = uniphier_sd_probe,
|
.probe = uniphier_sd_probe,
|
||||||
.remove = uniphier_sd_remove,
|
.remove = uniphier_sd_remove,
|
||||||
.priv_auto_alloc_size = sizeof(struct uniphier_sd_priv),
|
.priv_auto_alloc_size = sizeof(struct uniphier_sd_priv),
|
||||||
|
.ops = &uniphier_sd_ops,
|
||||||
};
|
};
|
||||||
|
|
|
@ -344,6 +344,7 @@ config SANDBOX_SERIAL
|
||||||
config UNIPHIER_SERIAL
|
config UNIPHIER_SERIAL
|
||||||
bool "Support for UniPhier on-chip UART"
|
bool "Support for UniPhier on-chip UART"
|
||||||
depends on ARCH_UNIPHIER
|
depends on ARCH_UNIPHIER
|
||||||
|
default y
|
||||||
help
|
help
|
||||||
If you have a UniPhier based board and want to use the on-chip
|
If you have a UniPhier based board and want to use the on-chip
|
||||||
serial ports, say Y to this option. If unsure, say N.
|
serial ports, say Y to this option. If unsure, say N.
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#define __CONFIG_UNIPHIER_COMMON_H__
|
#define __CONFIG_UNIPHIER_COMMON_H__
|
||||||
|
|
||||||
#define CONFIG_ARMV7_PSCI
|
#define CONFIG_ARMV7_PSCI
|
||||||
|
#define CONFIG_ARMV7_PSCI_1_0
|
||||||
#define CONFIG_ARMV7_PSCI_NR_CPUS 4
|
#define CONFIG_ARMV7_PSCI_NR_CPUS 4
|
||||||
|
|
||||||
#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10
|
#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 10
|
||||||
|
|
Loading…
Reference in New Issue