summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/crypto/fsl/jr.c9
-rw-r--r--drivers/crypto/fsl/jr.h2
-rw-r--r--drivers/gpio/mxc_gpio.c22
-rw-r--r--drivers/misc/mxc_ocotp.c7
-rw-r--r--drivers/mmc/fsl_esdhc.c395
-rw-r--r--drivers/net/e1000.c294
-rw-r--r--drivers/net/e1000.h3
-rw-r--r--drivers/net/fec_mxc.c78
-rw-r--r--drivers/power/pmic/Makefile2
-rw-r--r--drivers/power/regulator/Makefile2
-rw-r--r--drivers/rtc/Kconfig6
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rx8010sj.c378
13 files changed, 1120 insertions, 79 deletions
diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c
index 986eabfb088..a05779826fe 100644
--- a/drivers/crypto/fsl/jr.c
+++ b/drivers/crypto/fsl/jr.c
@@ -566,6 +566,8 @@ int sec_init_idx(uint8_t sec_idx)
{
ccsr_sec_t *sec = (void *)SEC_ADDR(sec_idx);
uint32_t mcr = sec_in32(&sec->mcfgr);
+ uint32_t jrown_ns;
+ int i;
int ret = 0;
#ifdef CONFIG_FSL_CORENET
@@ -621,6 +623,13 @@ int sec_init_idx(uint8_t sec_idx)
#endif
#endif
+ /* Set ownership of job rings to non-TrustZone mode by default */
+ for (i = 0; i < ARRAY_SIZE(sec->jrliodnr); i++) {
+ jrown_ns = sec_in32(&sec->jrliodnr[i].ms);
+ jrown_ns |= JROWN_NS | JRMID_NS;
+ sec_out32(&sec->jrliodnr[i].ms, jrown_ns);
+ }
+
ret = jr_init(sec_idx);
if (ret < 0) {
printf("SEC initialization failed\n");
diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h
index d897e572d6e..8aab4c988da 100644
--- a/drivers/crypto/fsl/jr.h
+++ b/drivers/crypto/fsl/jr.h
@@ -34,6 +34,8 @@
#define JRNSLIODN_MASK 0x0fff0000
#define JRSLIODN_SHIFT 0
#define JRSLIODN_MASK 0x00000fff
+#define JROWN_NS 0x00000008
+#define JRMID_NS 0x00000001
#define JQ_DEQ_ERR -1
#define JQ_DEQ_TO_ERR -2
diff --git a/drivers/gpio/mxc_gpio.c b/drivers/gpio/mxc_gpio.c
index cfa620bceb3..d0e365a54b0 100644
--- a/drivers/gpio/mxc_gpio.c
+++ b/drivers/gpio/mxc_gpio.c
@@ -41,13 +41,13 @@ static unsigned long gpio_ports[] = {
[2] = GPIO3_BASE_ADDR,
#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
- defined(CONFIG_MX7)
+ defined(CONFIG_MX7) || defined(CONFIG_MX8M)
[3] = GPIO4_BASE_ADDR,
#endif
#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
- defined(CONFIG_MX7)
+ defined(CONFIG_MX7) || defined(CONFIG_MX8M)
[4] = GPIO5_BASE_ADDR,
-#if !(defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL))
+#if !(defined(CONFIG_MX6UL) || defined(CONFIG_MX6ULL) || defined(CONFIG_MX8M))
[5] = GPIO6_BASE_ADDR,
#endif
#endif
@@ -349,13 +349,17 @@ static const struct mxc_gpio_plat mxc_plat[] = {
{ 1, (struct gpio_regs *)GPIO2_BASE_ADDR },
{ 2, (struct gpio_regs *)GPIO3_BASE_ADDR },
#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
- defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
+ defined(CONFIG_MX8M)
{ 3, (struct gpio_regs *)GPIO4_BASE_ADDR },
#endif
-#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
+ defined(CONFIG_MX8M)
{ 4, (struct gpio_regs *)GPIO5_BASE_ADDR },
+#ifndef CONFIG_MX8M
{ 5, (struct gpio_regs *)GPIO6_BASE_ADDR },
#endif
+#endif
#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
{ 6, (struct gpio_regs *)GPIO7_BASE_ADDR },
#endif
@@ -366,13 +370,17 @@ U_BOOT_DEVICES(mxc_gpios) = {
{ "gpio_mxc", &mxc_plat[1] },
{ "gpio_mxc", &mxc_plat[2] },
#if defined(CONFIG_MX25) || defined(CONFIG_MX27) || defined(CONFIG_MX51) || \
- defined(CONFIG_MX53) || defined(CONFIG_MX6)
+ defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
+ defined(CONFIG_MX8M)
{ "gpio_mxc", &mxc_plat[3] },
#endif
-#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6)
+#if defined(CONFIG_MX27) || defined(CONFIG_MX53) || defined(CONFIG_MX6) || \
+ defined(CONFIG_MX8M)
{ "gpio_mxc", &mxc_plat[4] },
+#ifndef CONFIG_MX8M
{ "gpio_mxc", &mxc_plat[5] },
#endif
+#endif
#if defined(CONFIG_MX53) || defined(CONFIG_MX6)
{ "gpio_mxc", &mxc_plat[6] },
#endif
diff --git a/drivers/misc/mxc_ocotp.c b/drivers/misc/mxc_ocotp.c
index 18a2730909f..8662e82cfa1 100644
--- a/drivers/misc/mxc_ocotp.c
+++ b/drivers/misc/mxc_ocotp.c
@@ -35,6 +35,8 @@
#define BM_OUT_STATUS_DED 0x00000400
#define BM_OUT_STATUS_LOCKED 0x00000800
#define BM_OUT_STATUS_PROGFAIL 0x00001000
+#elif defined(CONFIG_MX8M)
+#define BM_CTRL_ADDR 0x000000ff
#else
#define BM_CTRL_ADDR 0x0000007f
#endif
@@ -79,6 +81,9 @@
#elif defined(CONFIG_MX7ULP)
#define FUSE_BANK_SIZE 0x80
#define FUSE_BANKS 31
+#elif defined(CONFIG_MX8M)
+#define FUSE_BANK_SIZE 0x40
+#define FUSE_BANKS 64
#else
#error "Unsupported architecture\n"
#endif
@@ -294,6 +299,8 @@ static void setup_direct_access(struct ocotp_regs *regs, u32 bank, u32 word,
u32 wr_unlock = write ? BV_CTRL_WR_UNLOCK_KEY : 0;
#ifdef CONFIG_MX7
u32 addr = bank;
+#elif defined CONFIG_MX8M
+ u32 addr = bank << 2 | word;
#else
u32 addr;
/* Bank 7 and Bank 8 only supports 4 words each for i.MX6ULL */
diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
index 8d1e2f8a01c..6018f84307d 100644
--- a/drivers/mmc/fsl_esdhc.c
+++ b/drivers/mmc/fsl_esdhc.c
@@ -23,6 +23,7 @@
#include <asm/io.h>
#include <dm.h>
#include <asm-generic/gpio.h>
+#include <dm/pinctrl.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -32,6 +33,7 @@ DECLARE_GLOBAL_DATA_PTR;
IRQSTATEN_CIE | IRQSTATEN_DTOE | IRQSTATEN_DCE | \
IRQSTATEN_DEBE | IRQSTATEN_BRR | IRQSTATEN_BWR | \
IRQSTATEN_DINT)
+#define MAX_TUNING_LOOP 40
struct fsl_esdhc {
uint dsaddr; /* SDMA system address register */
@@ -61,23 +63,27 @@ struct fsl_esdhc {
uint dllctrl;
uint dllstat;
uint clktunectrlstatus;
- char reserved3[84];
+ char reserved3[4];
+ uint strobe_dllctrl;
+ uint strobe_dllstat;
+ char reserved4[72];
uint vendorspec;
uint mmcboot;
uint vendorspec2;
- char reserved4[48];
+ uint tuning_ctrl; /* on i.MX6/7/8 */
+ char reserved5[44];
uint hostver; /* Host controller version register */
- char reserved5[4]; /* reserved */
- uint dmaerraddr; /* DMA error address register */
char reserved6[4]; /* reserved */
- uint dmaerrattr; /* DMA error attribute register */
+ uint dmaerraddr; /* DMA error address register */
char reserved7[4]; /* reserved */
+ uint dmaerrattr; /* DMA error attribute register */
+ char reserved8[4]; /* reserved */
uint hostcapblt2; /* Host controller capabilities register 2 */
- char reserved8[8]; /* reserved */
+ char reserved9[8]; /* reserved */
uint tcr; /* Tuning control register */
- char reserved9[28]; /* reserved */
+ char reserved10[28]; /* reserved */
uint sddirctl; /* SD direction control register */
- char reserved10[712];/* reserved */
+ char reserved11[712];/* reserved */
uint scr; /* eSDHC control register */
};
@@ -86,6 +92,11 @@ struct fsl_esdhc_plat {
struct mmc mmc;
};
+struct esdhc_soc_data {
+ u32 flags;
+ u32 caps;
+};
+
/**
* struct fsl_esdhc_priv
*
@@ -99,12 +110,20 @@ struct fsl_esdhc_plat {
* @non_removable: 0: removable; 1: non-removable
* @wp_enable: 1: enable checking wp; 0: no check
* @vs18_enable: 1: use 1.8V voltage; 0: use 3.3V
+ * @flags: ESDHC_FLAG_xx in include/fsl_esdhc.h
+ * @caps: controller capabilities
+ * @tuning_step: tuning step setting in tuning_ctrl register
+ * @start_tuning_tap: the start point for tuning in tuning_ctrl register
+ * @strobe_dll_delay_target: settings in strobe_dllctrl
+ * @signal_voltage: indicating the current voltage
* @cd_gpio: gpio for card detection
* @wp_gpio: gpio for write protection
*/
struct fsl_esdhc_priv {
struct fsl_esdhc *esdhc_regs;
unsigned int sdhc_clk;
+ unsigned int clock;
+ unsigned int mode;
unsigned int bus_width;
#if !CONFIG_IS_ENABLED(BLK)
struct mmc *mmc;
@@ -113,6 +132,16 @@ struct fsl_esdhc_priv {
int non_removable;
int wp_enable;
int vs18_enable;
+ u32 flags;
+ u32 caps;
+ u32 tuning_step;
+ u32 tuning_start_tap;
+ u32 strobe_dll_delay_target;
+ u32 signal_voltage;
+#if IS_ENABLED(CONFIG_DM_REGULATOR)
+ struct udevice *vqmmc_dev;
+ struct udevice *vmmc_dev;
+#endif
#ifdef CONFIG_DM_GPIO
struct gpio_desc cd_gpio;
struct gpio_desc wp_gpio;
@@ -228,7 +257,8 @@ static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
{
int timeout;
struct fsl_esdhc *regs = priv->esdhc_regs;
-#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
+#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234) || \
+ defined(CONFIG_MX8M)
dma_addr_t addr;
#endif
uint wml_value;
@@ -241,7 +271,8 @@ static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
+#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234) || \
+ defined(CONFIG_MX8M)
addr = virt_to_phys((void *)(data->dest));
if (upper_32_bits(addr))
printf("Error found for upper 32 bits\n");
@@ -270,7 +301,8 @@ static int esdhc_setup_data(struct fsl_esdhc_priv *priv, struct mmc *mmc,
esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
wml_value << 16);
#ifndef CONFIG_SYS_FSL_ESDHC_USE_PIO
-#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
+#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234) || \
+ defined(CONFIG_MX8M)
addr = virt_to_phys((void *)(data->src));
if (upper_32_bits(addr))
printf("Error found for upper 32 bits\n");
@@ -335,7 +367,8 @@ static void check_and_invalidate_dcache_range
unsigned end = 0;
unsigned size = roundup(ARCH_DMA_MINALIGN,
data->blocks*data->blocksize);
-#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234)
+#if defined(CONFIG_FSL_LAYERSCAPE) || defined(CONFIG_S32V234) || \
+ defined(CONFIG_MX8M)
dma_addr_t addr;
addr = virt_to_phys((void *)(data->dest));
@@ -360,6 +393,7 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
int err = 0;
uint xfertyp;
uint irqstat;
+ u32 flags = IRQSTAT_CC | IRQSTAT_CTOE;
struct fsl_esdhc *regs = priv->esdhc_regs;
#ifdef CONFIG_SYS_FSL_ERRATUM_ESDHC111
@@ -413,8 +447,12 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
esdhc_write32(&regs->xfertyp, xfertyp);
#endif
+ if ((cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK) ||
+ (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200))
+ flags = IRQSTAT_BRR;
+
/* Wait for the command to complete */
- while (!(esdhc_read32(&regs->irqstat) & (IRQSTAT_CC | IRQSTAT_CTOE)))
+ while (!(esdhc_read32(&regs->irqstat) & flags))
;
irqstat = esdhc_read32(&regs->irqstat);
@@ -476,6 +514,12 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
esdhc_pio_read_write(priv, data);
#else
+ flags = DATA_COMPLETE;
+ if ((cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK) ||
+ (cmd->cmdidx == MMC_CMD_SEND_TUNING_BLOCK_HS200)) {
+ flags = IRQSTAT_BRR;
+ }
+
do {
irqstat = esdhc_read32(&regs->irqstat);
@@ -488,7 +532,7 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc,
err = -ECOMM;
goto out;
}
- } while ((irqstat & DATA_COMPLETE) != DATA_COMPLETE);
+ } while ((irqstat & flags) != flags);
/*
* Need invalidate the dcache here again to avoid any
@@ -574,6 +618,7 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock)
esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
#endif
+ priv->clock = clock;
}
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
@@ -605,9 +650,239 @@ static void esdhc_clock_control(struct fsl_esdhc_priv *priv, bool enable)
}
#endif
+#ifdef MMC_SUPPORTS_TUNING
+static int esdhc_change_pinstate(struct udevice *dev)
+{
+ struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+ int ret;
+
+ switch (priv->mode) {
+ case UHS_SDR50:
+ case UHS_DDR50:
+ ret = pinctrl_select_state(dev, "state_100mhz");
+ break;
+ case UHS_SDR104:
+ case MMC_HS_200:
+ ret = pinctrl_select_state(dev, "state_200mhz");
+ break;
+ default:
+ ret = pinctrl_select_state(dev, "default");
+ break;
+ }
+
+ if (ret)
+ printf("%s %d error\n", __func__, priv->mode);
+
+ return ret;
+}
+
+static void esdhc_reset_tuning(struct mmc *mmc)
+{
+ struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev);
+ struct fsl_esdhc *regs = priv->esdhc_regs;
+
+ if (priv->flags & ESDHC_FLAG_USDHC) {
+ if (priv->flags & ESDHC_FLAG_STD_TUNING) {
+ esdhc_clrbits32(&regs->autoc12err,
+ MIX_CTRL_SMPCLK_SEL |
+ MIX_CTRL_EXE_TUNE);
+ }
+ }
+}
+
+static int esdhc_set_timing(struct mmc *mmc)
+{
+ struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev);
+ struct fsl_esdhc *regs = priv->esdhc_regs;
+ u32 mixctrl;
+
+ mixctrl = readl(&regs->mixctrl);
+ mixctrl &= ~(MIX_CTRL_DDREN | MIX_CTRL_HS400_EN);
+
+ switch (mmc->selected_mode) {
+ case MMC_LEGACY:
+ case SD_LEGACY:
+ esdhc_reset_tuning(mmc);
+ break;
+ case MMC_HS:
+ case MMC_HS_52:
+ case MMC_HS_200:
+ case SD_HS:
+ case UHS_SDR12:
+ case UHS_SDR25:
+ case UHS_SDR50:
+ case UHS_SDR104:
+ writel(mixctrl, &regs->mixctrl);
+ break;
+ case UHS_DDR50:
+ case MMC_DDR_52:
+ mixctrl |= MIX_CTRL_DDREN;
+ writel(mixctrl, &regs->mixctrl);
+ break;
+ default:
+ printf("Not supported %d\n", mmc->selected_mode);
+ return -EINVAL;
+ }
+
+ priv->mode = mmc->selected_mode;
+
+ return esdhc_change_pinstate(mmc->dev);
+}
+
+static int esdhc_set_voltage(struct mmc *mmc)
+{
+ struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev);
+ struct fsl_esdhc *regs = priv->esdhc_regs;
+ int ret;
+
+ priv->signal_voltage = mmc->signal_voltage;
+ switch (mmc->signal_voltage) {
+ case MMC_SIGNAL_VOLTAGE_330:
+ if (priv->vs18_enable)
+ return -EIO;
+#ifdef CONFIG_DM_REGULATOR
+ if (!IS_ERR_OR_NULL(priv->vqmmc_dev)) {
+ ret = regulator_set_value(priv->vqmmc_dev, 3300000);
+ if (ret) {
+ printf("Setting to 3.3V error");
+ return -EIO;
+ }
+ /* Wait for 5ms */
+ mdelay(5);
+ }
+#endif
+
+ esdhc_clrbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
+ if (!(esdhc_read32(&regs->vendorspec) &
+ ESDHC_VENDORSPEC_VSELECT))
+ return 0;
+
+ return -EAGAIN;
+ case MMC_SIGNAL_VOLTAGE_180:
+#ifdef CONFIG_DM_REGULATOR
+ if (!IS_ERR_OR_NULL(priv->vqmmc_dev)) {
+ ret = regulator_set_value(priv->vqmmc_dev, 1800000);
+ if (ret) {
+ printf("Setting to 1.8V error");
+ return -EIO;
+ }
+ }
+#endif
+ esdhc_setbits32(&regs->vendorspec, ESDHC_VENDORSPEC_VSELECT);
+ if (esdhc_read32(&regs->vendorspec) & ESDHC_VENDORSPEC_VSELECT)
+ return 0;
+
+ return -EAGAIN;
+ case MMC_SIGNAL_VOLTAGE_120:
+ return -ENOTSUPP;
+ default:
+ return 0;
+ }
+}
+
+static void esdhc_stop_tuning(struct mmc *mmc)
+{
+ struct mmc_cmd cmd;
+
+ cmd.cmdidx = MMC_CMD_STOP_TRANSMISSION;
+ cmd.cmdarg = 0;
+ cmd.resp_type = MMC_RSP_R1b;
+
+ dm_mmc_send_cmd(mmc->dev, &cmd, NULL);
+}
+
+static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode)
+{
+ struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
+ struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+ struct fsl_esdhc *regs = priv->esdhc_regs;
+ struct mmc *mmc = &plat->mmc;
+ u32 irqstaten = readl(&regs->irqstaten);
+ u32 irqsigen = readl(&regs->irqsigen);
+ int i, ret = -ETIMEDOUT;
+ u32 val, mixctrl;
+
+ /* clock tuning is not needed for upto 52MHz */
+ if (mmc->clock <= 52000000)
+ return 0;
+
+ /* This is readw/writew SDHCI_HOST_CONTROL2 when tuning */
+ if (priv->flags & ESDHC_FLAG_STD_TUNING) {
+ val = readl(&regs->autoc12err);
+ mixctrl = readl(&regs->mixctrl);
+ val &= ~MIX_CTRL_SMPCLK_SEL;
+ mixctrl &= ~(MIX_CTRL_FBCLK_SEL | MIX_CTRL_AUTO_TUNE_EN);
+
+ val |= MIX_CTRL_EXE_TUNE;
+ mixctrl |= MIX_CTRL_FBCLK_SEL | MIX_CTRL_AUTO_TUNE_EN;
+
+ writel(val, &regs->autoc12err);
+ writel(mixctrl, &regs->mixctrl);
+ }
+
+ /* sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); */
+ mixctrl = readl(&regs->mixctrl);
+ mixctrl = MIX_CTRL_DTDSEL_READ | (mixctrl & ~MIX_CTRL_SDHCI_MASK);
+ writel(mixctrl, &regs->mixctrl);
+
+ writel(IRQSTATEN_BRR, &regs->irqstaten);
+ writel(IRQSTATEN_BRR, &regs->irqsigen);
+
+ /*
+ * Issue opcode repeatedly till Execute Tuning is set to 0 or the number
+ * of loops reaches 40 times.
+ */
+ for (i = 0; i < MAX_TUNING_LOOP; i++) {
+ u32 ctrl;
+
+ if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200) {
+ if (mmc->bus_width == 8)
+ writel(0x7080, &regs->blkattr);
+ else if (mmc->bus_width == 4)
+ writel(0x7040, &regs->blkattr);
+ } else {
+ writel(0x7040, &regs->blkattr);
+ }
+
+ /* sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE) */
+ val = readl(&regs->mixctrl);
+ val = MIX_CTRL_DTDSEL_READ | (val & ~MIX_CTRL_SDHCI_MASK);
+ writel(val, &regs->mixctrl);
+
+ /* We are using STD tuning, no need to check return value */
+ mmc_send_tuning(mmc, opcode, NULL);
+
+ ctrl = readl(&regs->autoc12err);
+ if ((!(ctrl & MIX_CTRL_EXE_TUNE)) &&
+ (ctrl & MIX_CTRL_SMPCLK_SEL)) {
+ /*
+ * need to wait some time, make sure sd/mmc fininsh
+ * send out tuning data, otherwise, the sd/mmc can't
+ * response to any command when the card still out
+ * put the tuning data.
+ */
+ mdelay(1);
+ ret = 0;
+ break;
+ }
+
+ /* Add 1ms delay for SD and eMMC */
+ mdelay(1);
+ }
+
+ writel(irqstaten, &regs->irqstaten);
+ writel(irqsigen, &regs->irqsigen);
+
+ esdhc_stop_tuning(mmc);
+
+ return ret;
+}
+#endif
+
static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
{
struct fsl_esdhc *regs = priv->esdhc_regs;
+ int ret __maybe_unused;
#ifdef CONFIG_FSL_ESDHC_USE_PERIPHERAL_CLK
/* Select to use peripheral clock */
@@ -616,7 +891,41 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc)
esdhc_clock_control(priv, true);
#endif
/* Set the clock speed */
- set_sysctl(priv, mmc, mmc->clock);
+ if (priv->clock != mmc->clock)
+ set_sysctl(priv, mmc, mmc->clock);
+
+#ifdef MMC_SUPPORTS_TUNING
+ if (mmc->clk_disable) {
+#ifdef CONFIG_FSL_USDHC
+ esdhc_clrbits32(&regs->vendorspec, VENDORSPEC_CKEN);
+#else
+ esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
+#endif
+ } else {
+#ifdef CONFIG_FSL_USDHC
+ esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN |
+ VENDORSPEC_CKEN);
+#else
+ esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_CKEN);
+#endif
+ }
+
+ if (priv->mode != mmc->selected_mode) {
+ ret = esdhc_set_timing(mmc);
+ if (ret) {
+ printf("esdhc_set_timing error %d\n", ret);
+ return ret;
+ }
+ }
+
+ if (priv->signal_voltage != mmc->signal_voltage) {
+ ret = esdhc_set_voltage(mmc);
+ if (ret) {
+ printf("esdhc_set_voltage error %d\n", ret);
+ return ret;
+ }
+ }
+#endif
/* Set the bus width */
esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
@@ -791,6 +1100,10 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv,
#ifndef CONFIG_FSL_USDHC
esdhc_setbits32(&regs->sysctl, SYSCTL_PEREN | SYSCTL_HCKEN
| SYSCTL_IPGEN | SYSCTL_CKEN);
+ /* Clearing tuning bits in case ROM has set it already */
+ esdhc_write32(&regs->mixctrl, 0);
+ esdhc_write32(&regs->autoc12err, 0);
+ esdhc_write32(&regs->clktunectrlstatus, 0);
#else
esdhc_setbits32(&regs->vendorspec, VENDORSPEC_PEREN |
VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN);
@@ -864,11 +1177,27 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv,
cfg->host_caps &= ~MMC_MODE_8BIT;
#endif
+ cfg->host_caps |= priv->caps;
+
cfg->f_min = 400000;
- cfg->f_max = min(priv->sdhc_clk, (u32)52000000);
+ cfg->f_max = min(priv->sdhc_clk, (u32)200000000);
cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+ writel(0, &regs->dllctrl);
+ if (priv->flags & ESDHC_FLAG_USDHC) {
+ if (priv->flags & ESDHC_FLAG_STD_TUNING) {
+ u32 val = readl(&regs->tuning_ctrl);
+
+ val |= ESDHC_STD_TUNING_EN;
+ val &= ~ESDHC_TUNING_START_TAP_MASK;
+ val |= priv->tuning_start_tap;
+ val &= ~ESDHC_TUNING_STEP_MASK;
+ val |= (priv->tuning_step) << ESDHC_TUNING_STEP_SHIFT;
+ writel(val, &regs->tuning_ctrl);
+ }
+ }
+
return 0;
}
@@ -1027,6 +1356,10 @@ static int fsl_esdhc_probe(struct udevice *dev)
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct fsl_esdhc_plat *plat = dev_get_platdata(dev);
struct fsl_esdhc_priv *priv = dev_get_priv(dev);
+ const void *fdt = gd->fdt_blob;
+ int node = dev_of_offset(dev);
+ struct esdhc_soc_data *data =
+ (struct esdhc_soc_data *)dev_get_driver_data(dev);
#ifdef CONFIG_DM_REGULATOR
struct udevice *vqmmc_dev;
#endif
@@ -1041,6 +1374,11 @@ static int fsl_esdhc_probe(struct udevice *dev)
priv->esdhc_regs = (struct fsl_esdhc *)addr;
priv->dev = dev;
+ priv->mode = -1;
+ if (data) {
+ priv->flags = data->flags;
+ priv->caps = data->caps;
+ }
val = dev_read_u32_default(dev, "bus-width", -1);
if (val == 8)
@@ -1050,6 +1388,15 @@ static int fsl_esdhc_probe(struct udevice *dev)
else
priv->bus_width = 1;
+ val = fdtdec_get_int(fdt, node, "fsl,tuning-step", 1);
+ priv->tuning_step = val;
+ val = fdtdec_get_int(fdt, node, "fsl,tuning-start-tap",
+ ESDHC_TUNING_START_TAP_DEFAULT);
+ priv->tuning_start_tap = val;
+ val = fdtdec_get_int(fdt, node, "fsl,strobe-dll-delay-target",
+ ESDHC_STROBE_DLL_CTRL_SLV_DLY_TARGET_DEFAULT);
+ priv->strobe_dll_delay_target = val;
+
if (dev_read_bool(dev, "non-removable")) {
priv->non_removable = 1;
} else {
@@ -1091,6 +1438,9 @@ static int fsl_esdhc_probe(struct udevice *dev)
}
#endif
+ if (fdt_get_property(fdt, node, "no-1-8-v", NULL))
+ priv->caps &= ~(UHS_CAPS | MMC_MODE_HS200);
+
/*
* TODO:
* Because lack of clk driver, if SDHC clk is not enabled,
@@ -1163,15 +1513,26 @@ static const struct dm_mmc_ops fsl_esdhc_ops = {
.get_cd = fsl_esdhc_get_cd,
.send_cmd = fsl_esdhc_send_cmd,
.set_ios = fsl_esdhc_set_ios,
+#ifdef MMC_SUPPORTS_TUNING
+ .execute_tuning = fsl_esdhc_execute_tuning,
+#endif
};
#endif
+static struct esdhc_soc_data usdhc_imx7d_data = {
+ .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
+ | ESDHC_FLAG_HAVE_CAP1 | ESDHC_FLAG_HS200
+ | ESDHC_FLAG_HS400,
+ .caps = UHS_CAPS | MMC_MODE_HS200 | MMC_MODE_DDR_52MHz |
+ MMC_MODE_HS_52MHz | MMC_MODE_HS,
+};
+
static const struct udevice_id fsl_esdhc_ids[] = {
{ .compatible = "fsl,imx6ul-usdhc", },
{ .compatible = "fsl,imx6sx-usdhc", },
{ .compatible = "fsl,imx6sl-usdhc", },
{ .compatible = "fsl,imx6q-usdhc", },
- { .compatible = "fsl,imx7d-usdhc", },
+ { .compatible = "fsl,imx7d-usdhc", .data = (ulong)&usdhc_imx7d_data,},
{ .compatible = "fsl,imx7ulp-usdhc", },
{ .compatible = "fsl,esdhc", },
{ /* sentinel */ }
diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c
index 875682b1b89..8316854bc17 100644
--- a/drivers/net/e1000.c
+++ b/drivers/net/e1000.c
@@ -150,6 +150,7 @@ static int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
#ifndef CONFIG_E1000_NO_NVM
static void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
+static int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
static int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset,
uint16_t words,
uint16_t *data);
@@ -861,6 +862,174 @@ e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset,
return E1000_SUCCESS;
}
+#ifndef CONFIG_DM_ETH
+/******************************************************************************
+ * e1000_write_eeprom_srwr - Write to Shadow Ram using EEWR
+ * @hw: pointer to the HW structure
+ * @offset: offset within the Shadow Ram to be written to
+ * @words: number of words to write
+ * @data: 16 bit word(s) to be written to the Shadow Ram
+ *
+ * Writes data to Shadow Ram at offset using EEWR register.
+ *
+ * If e1000_update_eeprom_checksum_i210 is not called after this function, the
+ * Shadow Ram will most likely contain an invalid checksum.
+ *****************************************************************************/
+static int32_t e1000_write_eeprom_srwr(struct e1000_hw *hw, uint16_t offset,
+ uint16_t words, uint16_t *data)
+{
+ struct e1000_eeprom_info *eeprom = &hw->eeprom;
+ uint32_t i, k, eewr = 0;
+ uint32_t attempts = 100000;
+ int32_t ret_val = 0;
+
+ /* A check for invalid values: offset too large, too many words,
+ * too many words for the offset, and not enough words.
+ */
+ if ((offset >= eeprom->word_size) ||
+ (words > (eeprom->word_size - offset)) || (words == 0)) {
+ DEBUGOUT("nvm parameter(s) out of bounds\n");
+ ret_val = -E1000_ERR_EEPROM;
+ goto out;
+ }
+
+ for (i = 0; i < words; i++) {
+ eewr = ((offset + i) << E1000_EEPROM_RW_ADDR_SHIFT)
+ | (data[i] << E1000_EEPROM_RW_REG_DATA) |
+ E1000_EEPROM_RW_REG_START;
+
+ E1000_WRITE_REG(hw, I210_EEWR, eewr);
+
+ for (k = 0; k < attempts; k++) {
+ if (E1000_EEPROM_RW_REG_DONE &
+ E1000_READ_REG(hw, I210_EEWR)) {
+ ret_val = 0;
+ break;
+ }
+ udelay(5);
+ }
+
+ if (ret_val) {
+ DEBUGOUT("Shadow RAM write EEWR timed out\n");
+ break;
+ }
+ }
+
+out:
+ return ret_val;
+}
+
+/******************************************************************************
+ * e1000_pool_flash_update_done_i210 - Pool FLUDONE status.
+ * @hw: pointer to the HW structure
+ *
+ *****************************************************************************/
+static int32_t e1000_pool_flash_update_done_i210(struct e1000_hw *hw)
+{
+ int32_t ret_val = -E1000_ERR_EEPROM;
+ uint32_t i, reg;
+
+ for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
+ reg = E1000_READ_REG(hw, EECD);
+ if (reg & E1000_EECD_FLUDONE_I210) {
+ ret_val = 0;
+ break;
+ }
+ udelay(5);
+ }
+
+ return ret_val;
+}
+
+/******************************************************************************
+ * e1000_update_flash_i210 - Commit EEPROM to the flash
+ * @hw: pointer to the HW structure
+ *
+ *****************************************************************************/
+static int32_t e1000_update_flash_i210(struct e1000_hw *hw)
+{
+ int32_t ret_val = 0;
+ uint32_t flup;
+
+ ret_val = e1000_pool_flash_update_done_i210(hw);
+ if (ret_val == -E1000_ERR_EEPROM) {
+ DEBUGOUT("Flash update time out\n");
+ goto out;
+ }
+
+ flup = E1000_READ_REG(hw, EECD) | E1000_EECD_FLUPD_I210;
+ E1000_WRITE_REG(hw, EECD, flup);
+
+ ret_val = e1000_pool_flash_update_done_i210(hw);
+ if (ret_val)
+ DEBUGOUT("Flash update time out\n");
+ else
+ DEBUGOUT("Flash update complete\n");
+
+out:
+ return ret_val;
+}
+
+/******************************************************************************
+ * e1000_update_eeprom_checksum_i210 - Update EEPROM checksum
+ * @hw: pointer to the HW structure
+ *
+ * Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ * up to the checksum. Then calculates the EEPROM checksum and writes the
+ * value to the EEPROM. Next commit EEPROM data onto the Flash.
+ *****************************************************************************/
+static int32_t e1000_update_eeprom_checksum_i210(struct e1000_hw *hw)
+{
+ int32_t ret_val = 0;
+ uint16_t checksum = 0;
+ uint16_t i, nvm_data;
+
+ /* Read the first word from the EEPROM. If this times out or fails, do
+ * not continue or we could be in for a very long wait while every
+ * EEPROM read fails
+ */
+ ret_val = e1000_read_eeprom_eerd(hw, 0, 1, &nvm_data);
+ if (ret_val) {
+ DEBUGOUT("EEPROM read failed\n");
+ goto out;
+ }
+
+ if (!(e1000_get_hw_eeprom_semaphore(hw))) {
+ /* Do not use hw->nvm.ops.write, hw->nvm.ops.read
+ * because we do not want to take the synchronization
+ * semaphores twice here.
+ */
+
+ for (i = 0; i < EEPROM_CHECKSUM_REG; i++) {
+ ret_val = e1000_read_eeprom_eerd(hw, i, 1, &nvm_data);
+ if (ret_val) {
+ e1000_put_hw_eeprom_semaphore(hw);
+ DEBUGOUT("EEPROM Read Error while updating checksum.\n");
+ goto out;
+ }
+ checksum += nvm_data;
+ }
+ checksum = (uint16_t)EEPROM_SUM - checksum;
+ ret_val = e1000_write_eeprom_srwr(hw, EEPROM_CHECKSUM_REG, 1,
+ &checksum);
+ if (ret_val) {
+ e1000_put_hw_eeprom_semaphore(hw);
+ DEBUGOUT("EEPROM Write Error while updating checksum.\n");
+ goto out;
+ }
+
+ e1000_put_hw_eeprom_semaphore(hw);
+
+ ret_val = e1000_update_flash_i210(hw);
+ } else {
+ ret_val = -E1000_ERR_SWFW_SYNC;
+ }
+
+out:
+ return ret_val;
+}
+#endif
+
/******************************************************************************
* Verifies that the EEPROM has a valid checksum
*
@@ -970,7 +1139,7 @@ e1000_get_software_semaphore(struct e1000_hw *hw)
DEBUGFUNC();
- if (hw->mac_type != e1000_80003es2lan)
+ if (hw->mac_type != e1000_80003es2lan && hw->mac_type != e1000_igb)
return E1000_SUCCESS;
while (timeout) {
@@ -1044,7 +1213,7 @@ e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
if (!hw->eeprom_semaphore_present)
return E1000_SUCCESS;
- if (hw->mac_type == e1000_80003es2lan) {
+ if (hw->mac_type == e1000_80003es2lan || hw->mac_type == e1000_igb) {
/* Get the SW semaphore. */
if (e1000_get_software_semaphore(hw) != E1000_SUCCESS)
return -E1000_ERR_EEPROM;
@@ -1144,33 +1313,21 @@ static bool e1000_is_second_port(struct e1000_hw *hw)
#ifndef CONFIG_E1000_NO_NVM
/******************************************************************************
- * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
- * second function of dual function devices
+ * Reads the adapter's MAC address from the EEPROM
*
- * nic - Struct containing variables accessed by shared code
+ * hw - Struct containing variables accessed by shared code
+ * enetaddr - buffering where the MAC address will be stored
*****************************************************************************/
-static int
-e1000_read_mac_addr(struct e1000_hw *hw, unsigned char enetaddr[6])
+static int e1000_read_mac_addr_from_eeprom(struct e1000_hw *hw,
+ unsigned char enetaddr[6])
{
uint16_t offset;
uint16_t eeprom_data;
- uint32_t reg_data = 0;
int i;
- DEBUGFUNC();
-
for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
offset = i >> 1;
- if (hw->mac_type == e1000_igb) {
- /* i210 preloads MAC address into RAL/RAH registers */
- if (offset == 0)
- reg_data = E1000_READ_REG_ARRAY(hw, RA, 0);
- else if (offset == 1)
- reg_data >>= 16;
- else if (offset == 2)
- reg_data = E1000_READ_REG_ARRAY(hw, RA, 1);
- eeprom_data = reg_data & 0xffff;
- } else if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
+ if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
@@ -1178,6 +1335,63 @@ e1000_read_mac_addr(struct e1000_hw *hw, unsigned char enetaddr[6])
enetaddr[i + 1] = (eeprom_data >> 8) & 0xff;
}
+ return 0;
+}
+
+/******************************************************************************
+ * Reads the adapter's MAC address from the RAL/RAH registers
+ *
+ * hw - Struct containing variables accessed by shared code
+ * enetaddr - buffering where the MAC address will be stored
+ *****************************************************************************/
+static int e1000_read_mac_addr_from_regs(struct e1000_hw *hw,
+ unsigned char enetaddr[6])
+{
+ uint16_t offset, tmp;
+ uint32_t reg_data = 0;
+ int i;
+
+ if (hw->mac_type != e1000_igb)
+ return -E1000_ERR_MAC_TYPE;
+
+ for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) {
+ offset = i >> 1;
+
+ if (offset == 0)
+ reg_data = E1000_READ_REG_ARRAY(hw, RA, 0);
+ else if (offset == 1)
+ reg_data >>= 16;
+ else if (offset == 2)
+ reg_data = E1000_READ_REG_ARRAY(hw, RA, 1);
+ tmp = reg_data & 0xffff;
+
+ enetaddr[i] = tmp & 0xff;
+ enetaddr[i + 1] = (tmp >> 8) & 0xff;
+ }
+
+ return 0;
+}
+
+/******************************************************************************
+ * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the
+ * second function of dual function devices
+ *
+ * hw - Struct containing variables accessed by shared code
+ * enetaddr - buffering where the MAC address will be stored
+ *****************************************************************************/
+static int e1000_read_mac_addr(struct e1000_hw *hw, unsigned char enetaddr[6])
+{
+ int ret_val;
+
+ if (hw->mac_type == e1000_igb) {
+ /* i210 preloads MAC address into RAL/RAH registers */
+ ret_val = e1000_read_mac_addr_from_regs(hw, enetaddr);
+ } else {
+ ret_val = e1000_read_mac_addr_from_eeprom(hw, enetaddr);
+ }
+ if (ret_val)
+ return ret_val;
+
/* Invert the last bit if this is the second device */
if (e1000_is_second_port(hw))
enetaddr[5] ^= 1;
@@ -5435,6 +5649,45 @@ e1000_poll(struct eth_device *nic)
return len ? 1 : 0;
}
+static int e1000_write_hwaddr(struct eth_device *dev)
+{
+#ifndef CONFIG_E1000_NO_NVM
+ unsigned char *mac = dev->enetaddr;
+ unsigned char current_mac[6];
+ struct e1000_hw *hw = dev->priv;
+ uint16_t data[3];
+ int ret_val, i;
+
+ DEBUGOUT("%s: mac=%pM\n", __func__, mac);
+
+ memset(current_mac, 0, 6);
+
+ /* Read from EEPROM, not from registers, to make sure
+ * the address is persistently configured
+ */
+ ret_val = e1000_read_mac_addr_from_eeprom(hw, current_mac);
+ DEBUGOUT("%s: current mac=%pM\n", __func__, current_mac);
+
+ /* Only write to EEPROM if the given address is different or
+ * reading the current address failed
+ */
+ if (!ret_val && memcmp(current_mac, mac, 6) == 0)
+ return 0;
+
+ for (i = 0; i < 3; ++i)
+ data[i] = mac[i * 2 + 1] << 8 | mac[i * 2];
+
+ ret_val = e1000_write_eeprom_srwr(hw, 0x0, 3, data);
+
+ if (!ret_val)
+ ret_val = e1000_update_eeprom_checksum_i210(hw);
+
+ return ret_val;
+#else
+ return 0;
+#endif
+}
+
/**************************************************************************
PROBE - Look for an adapter, this routine's visible to the outside
You should omit the last argument struct pci_device * for a non-PCI NIC
@@ -5484,6 +5737,7 @@ e1000_initialize(bd_t * bis)
nic->recv = e1000_poll;
nic->send = e1000_transmit;
nic->halt = e1000_disable;
+ nic->write_hwaddr = e1000_write_hwaddr;
eth_register(nic);
}
diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h
index fcb7df0d83f..6376de15ada 100644
--- a/drivers/net/e1000.h
+++ b/drivers/net/e1000.h
@@ -1242,6 +1242,9 @@ struct e1000_hw {
#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */
#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */
#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */
+#define E1000_EECD_FLUPD_I210 0x00800000 /* Update FLASH */
+#define E1000_EECD_FLUDONE_I210 0x04000000 /* Update FLASH done*/
+#define E1000_FLUDONE_ATTEMPTS 20000
#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 433e19f0f81..ff7ad91116c 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -284,7 +284,7 @@ static int fec_tx_task_disable(struct fec_priv *fec)
static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
{
uint32_t size;
- uint8_t *data;
+ ulong data;
int i;
/*
@@ -293,9 +293,9 @@ static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
*/
size = roundup(dsize, ARCH_DMA_MINALIGN);
for (i = 0; i < count; i++) {
- data = (uint8_t *)fec->rbd_base[i].data_pointer;
- memset(data, 0, dsize);
- flush_dcache_range((uint32_t)data, (uint32_t)data + size);
+ data = fec->rbd_base[i].data_pointer;
+ memset((void *)data, 0, dsize);
+ flush_dcache_range(data, data + size);
fec->rbd_base[i].status = FEC_RBD_EMPTY;
fec->rbd_base[i].data_length = 0;
@@ -305,8 +305,8 @@ static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
fec->rbd_base[i - 1].status = FEC_RBD_WRAP | FEC_RBD_EMPTY;
fec->rbd_index = 0;
- flush_dcache_range((unsigned)fec->rbd_base,
- (unsigned)fec->rbd_base + size);
+ flush_dcache_range((ulong)fec->rbd_base,
+ (ulong)fec->rbd_base + size);
}
/**
@@ -323,7 +323,7 @@ static void fec_rbd_init(struct fec_priv *fec, int count, int dsize)
*/
static void fec_tbd_init(struct fec_priv *fec)
{
- unsigned addr = (unsigned)fec->tbd_base;
+ ulong addr = (ulong)fec->tbd_base;
unsigned size = roundup(2 * sizeof(struct fec_bd),
ARCH_DMA_MINALIGN);
@@ -423,7 +423,7 @@ static int fec_open(struct eth_device *edev)
struct fec_priv *fec = (struct fec_priv *)edev->priv;
#endif
int speed;
- uint32_t addr, size;
+ ulong addr, size;
int i;
debug("fec_open: fec_open(dev)\n");
@@ -439,7 +439,7 @@ static int fec_open(struct eth_device *edev)
/* Flush the descriptors into RAM */
size = roundup(FEC_RBD_NUM * sizeof(struct fec_bd),
ARCH_DMA_MINALIGN);
- addr = (uint32_t)fec->rbd_base;
+ addr = (ulong)fec->rbd_base;
flush_dcache_range(addr, addr + size);
#ifdef FEC_QUIRK_ENET_MAC
@@ -533,8 +533,9 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
#else
struct fec_priv *fec = (struct fec_priv *)dev->priv;
#endif
- uint32_t mib_ptr = (uint32_t)&fec->eth->rmon_t_drop;
- int i;
+ u8 *mib_ptr = (uint8_t *)&fec->eth->rmon_t_drop;
+ u8 *i;
+ ulong addr;
/* Initialize MAC address */
#ifdef CONFIG_DM_ETH
@@ -562,8 +563,8 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
writel(0x00000000, &fec->eth->gaddr1);
writel(0x00000000, &fec->eth->gaddr2);
- /* Do not access reserved register for i.MX6UL */
- if (!is_mx6ul() && !is_mx6ull()) {
+ /* Do not access reserved register */
+ if (!is_mx6ul() && !is_mx6ull() && !is_mx8m()) {
/* clear MIB RAM */
for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
writel(0, i);
@@ -574,8 +575,12 @@ static int fec_init(struct eth_device *dev, bd_t *bd)
/* size and address of each buffer */
writel(FEC_MAX_PKT_SIZE, &fec->eth->emrbr);
- writel((uint32_t)fec->tbd_base, &fec->eth->etdsr);
- writel((uint32_t)fec->rbd_base, &fec->eth->erdsr);
+
+ addr = (ulong)fec->tbd_base;
+ writel((uint32_t)addr, &fec->eth->etdsr);
+
+ addr = (ulong)fec->rbd_base;
+ writel((uint32_t)addr, &fec->eth->erdsr);
#ifndef CONFIG_PHYLIB
if (fec->xcv_type != SEVENWIRE)
@@ -640,8 +645,8 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
#endif
{
unsigned int status;
- uint32_t size, end;
- uint32_t addr;
+ u32 size;
+ ulong addr, end;
int timeout = FEC_XFER_TIMEOUT;
int ret = 0;
@@ -672,13 +677,13 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
swap_packet((uint32_t *)packet, length);
#endif
- addr = (uint32_t)packet;
+ addr = (ulong)packet;
end = roundup(addr + length, ARCH_DMA_MINALIGN);
addr &= ~(ARCH_DMA_MINALIGN - 1);
flush_dcache_range(addr, end);
writew(length, &fec->tbd_base[fec->tbd_index].data_length);
- writel(addr, &fec->tbd_base[fec->tbd_index].data_pointer);
+ writel((uint32_t)addr, &fec->tbd_base[fec->tbd_index].data_pointer);
/*
* update BD's status now
@@ -698,7 +703,7 @@ static int fec_send(struct eth_device *dev, void *packet, int length)
* can start DMA.
*/
size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
- addr = (uint32_t)fec->tbd_base;
+ addr = (ulong)fec->tbd_base;
flush_dcache_range(addr, addr + size);
/*
@@ -799,7 +804,7 @@ static int fec_recv(struct eth_device *dev)
unsigned long ievent;
int frame_length, len = 0;
uint16_t bd_status;
- uint32_t addr, size, end;
+ ulong addr, size, end;
int i;
ALLOC_CACHE_ALIGN_BUFFER(uchar, buff, FEC_MAX_PKT_SIZE);
@@ -854,7 +859,7 @@ static int fec_recv(struct eth_device *dev)
* the descriptor. The solution is to mark the whole cache line when all
* descriptors in the cache line are processed.
*/
- addr = (uint32_t)rbd;
+ addr = (ulong)rbd;
addr &= ~(ARCH_DMA_MINALIGN - 1);
size = roundup(sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
invalidate_dcache_range(addr, addr + size);
@@ -882,8 +887,8 @@ static int fec_recv(struct eth_device *dev)
len = frame_length;
} else {
if (bd_status & FEC_RBD_ERR)
- debug("error frame: 0x%08x 0x%08x\n",
- addr, bd_status);
+ debug("error frame: 0x%08lx 0x%08x\n",
+ addr, bd_status);
}
/*
@@ -895,7 +900,7 @@ static int fec_recv(struct eth_device *dev)
size = RXDESC_PER_CACHELINE - 1;
if ((fec->rbd_index & size) == size) {
i = fec->rbd_index - size;
- addr = (uint32_t)&fec->rbd_base[i];
+ addr = (ulong)&fec->rbd_base[i];
for (; i <= fec->rbd_index ; i++) {
fec_rbd_clean(i == (FEC_RBD_NUM - 1),
&fec->rbd_base[i]);
@@ -922,6 +927,7 @@ static int fec_alloc_descs(struct fec_priv *fec)
unsigned int size;
int i;
uint8_t *data;
+ ulong addr;
/* Allocate TX descriptors. */
size = roundup(2 * sizeof(struct fec_bd), ARCH_DMA_MINALIGN);
@@ -950,11 +956,12 @@ static int fec_alloc_descs(struct fec_priv *fec)
memset(data, 0, size);
- fec->rbd_base[i].data_pointer = (uint32_t)data;
+ addr = (ulong)data;
+ fec->rbd_base[i].data_pointer = (uint32_t)addr;
fec->rbd_base[i].status = FEC_RBD_EMPTY;
fec->rbd_base[i].data_length = 0;
/* Flush the buffer to memory. */
- flush_dcache_range((uint32_t)data, (uint32_t)data + size);
+ flush_dcache_range(addr, addr + size);
}
/* Mark the last RBD to close the ring. */
@@ -966,8 +973,10 @@ static int fec_alloc_descs(struct fec_priv *fec)
return 0;
err_ring:
- for (; i >= 0; i--)
- free((void *)fec->rbd_base[i].data_pointer);
+ for (; i >= 0; i--) {
+ addr = fec->rbd_base[i].data_pointer;
+ free((void *)addr);
+ }
free(fec->rbd_base);
err_rx:
free(fec->tbd_base);
@@ -978,9 +987,12 @@ err_tx:
static void fec_free_descs(struct fec_priv *fec)
{
int i;
+ ulong addr;
- for (i = 0; i < FEC_RBD_NUM; i++)
- free((void *)fec->rbd_base[i].data_pointer);
+ for (i = 0; i < FEC_RBD_NUM; i++) {
+ addr = fec->rbd_base[i].data_pointer;
+ free((void *)addr);
+ }
free(fec->rbd_base);
free(fec->tbd_base);
}
@@ -995,7 +1007,7 @@ struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id)
struct fec_priv *priv = dev_get_priv(dev);
struct ethernet_regs *eth = priv->eth;
#else
- struct ethernet_regs *eth = (struct ethernet_regs *)base_addr;
+ struct ethernet_regs *eth = (struct ethernet_regs *)(ulong)base_addr;
#endif
struct mii_dev *bus;
int ret;
@@ -1065,7 +1077,7 @@ static int fec_probe(bd_t *bd, int dev_id, uint32_t base_addr,
edev->halt = fec_halt;
edev->write_hwaddr = fec_set_hwaddr;
- fec->eth = (struct ethernet_regs *)base_addr;
+ fec->eth = (struct ethernet_regs *)(ulong)base_addr;
fec->bd = bd;
fec->xcv_type = CONFIG_FEC_XCV_TYPE;
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 7d6c583d347..fc19fdc701c 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -8,7 +8,7 @@
obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
-obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze100.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
obj-$(CONFIG_PMIC_ACT8846) += act8846.o
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index 728e8144ded..f7873ad27af 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_$(SPL_)DM_REGULATOR) += regulator-uclass.o
obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o
obj-$(CONFIG_REGULATOR_AS3722) += as3722_regulator.o
obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
-obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o
+obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
obj-$(CONFIG_REGULATOR_PWM) += pwm_regulator.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o
obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2964bb22110..95ac0312439 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -30,6 +30,12 @@ config RTC_DS1307
Support for Dallas Semiconductor (now Maxim) DS1307 and DS1338/9 and
compatible Real Time Clock devices.
+config RTC_RX8010SJ
+ bool "Enable RX8010SJ driver"
+ depends on DM_RTC
+ help
+ Support for Epson RX8010SJ Real Time Clock devices.
+
config RTC_S35392A
bool "Enable S35392A driver"
select BITREVERSE
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 7a8f97a05fe..9723fb774c5 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_RTC_PT7C4338) += pt7c4338.o
obj-$(CONFIG_RTC_RS5C372A) += rs5c372.o
obj-$(CONFIG_RTC_RV3029) += rv3029.o
obj-$(CONFIG_RTC_RX8025) += rx8025.o
+obj-$(CONFIG_RTC_RX8010SJ) += rx8010sj.o
obj-$(CONFIG_RTC_S3C24X0) += s3c24x0_rtc.o
obj-$(CONFIG_RTC_S35392A) += s35392a.o
obj-$(CONFIG_SANDBOX) += sandbox_rtc.o
diff --git a/drivers/rtc/rx8010sj.c b/drivers/rtc/rx8010sj.c
new file mode 100644
index 00000000000..81560e16cef
--- /dev/null
+++ b/drivers/rtc/rx8010sj.c
@@ -0,0 +1,378 @@
+/*
+ * Epson RX8010 RTC driver.
+ *
+ * Copyright (c) 2017, General Electric Company
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <command.h>
+#include <common.h>
+#include <dm.h>
+#include <i2c.h>
+#include <rtc.h>
+
+/*---------------------------------------------------------------------*/
+/* #undef DEBUG_RTC */
+
+#ifdef DEBUG_RTC
+#define DEBUGR(fmt, args...) printf(fmt, ##args)
+#else
+#define DEBUGR(fmt, args...)
+#endif
+/*---------------------------------------------------------------------*/
+
+#ifndef CONFIG_SYS_I2C_RTC_ADDR
+# define CONFIG_SYS_I2C_RTC_ADDR 0x32
+#endif
+
+/*
+ * RTC register addresses
+ */
+#define RX8010_SEC 0x10
+#define RX8010_MIN 0x11
+#define RX8010_HOUR 0x12
+#define RX8010_WDAY 0x13
+#define RX8010_MDAY 0x14
+#define RX8010_MONTH 0x15
+#define RX8010_YEAR 0x16
+#define RX8010_YEAR 0x16
+#define RX8010_RESV17 0x17
+#define RX8010_ALMIN 0x18
+#define RX8010_ALHOUR 0x19
+#define RX8010_ALWDAY 0x1A
+#define RX8010_TCOUNT0 0x1B
+#define RX8010_TCOUNT1 0x1C
+#define RX8010_EXT 0x1D
+#define RX8010_FLAG 0x1E
+#define RX8010_CTRL 0x1F
+/* 0x20 to 0x2F are user registers */
+#define RX8010_RESV30 0x30
+#define RX8010_RESV31 0x32
+#define RX8010_IRQ 0x32
+
+#define RX8010_EXT_WADA BIT(3)
+
+#define RX8010_FLAG_VLF BIT(1)
+#define RX8010_FLAG_AF BIT(3)
+#define RX8010_FLAG_TF BIT(4)
+#define RX8010_FLAG_UF BIT(5)
+
+#define RX8010_CTRL_AIE BIT(3)
+#define RX8010_CTRL_UIE BIT(5)
+#define RX8010_CTRL_STOP BIT(6)
+#define RX8010_CTRL_TEST BIT(7)
+
+#define RX8010_ALARM_AE BIT(7)
+
+#ifdef CONFIG_DM_RTC
+
+#define DEV_TYPE struct udevice
+
+#else
+
+/* Local udevice */
+struct ludevice {
+ u8 chip;
+};
+
+#define DEV_TYPE struct ludevice
+
+#endif
+
+static int rx8010sj_rtc_read8(DEV_TYPE *dev, unsigned int reg)
+{
+ u8 val;
+ int ret;
+
+#ifdef CONFIG_DM_RTC
+ ret = dm_i2c_read(dev, reg, &val, sizeof(val));
+#else
+ ret = i2c_read(dev->chip, reg, 1, &val, 1);
+#endif
+
+ return ret < 0 ? ret : val;
+}
+
+static int rx8010sj_rtc_write8(DEV_TYPE *dev, unsigned int reg, int val)
+{
+ int ret;
+ u8 lval = val;
+
+#ifdef CONFIG_DM_RTC
+ ret = dm_i2c_write(dev, reg, &lval, 1);
+#else
+ ret = i2c_write(dev->chip, reg, 1, &lval, 1);
+#endif
+
+ return ret < 0 ? ret : 0;
+}
+
+static int validate_time(const struct rtc_time *tm)
+{
+ if ((tm->tm_year < 2000) || (tm->tm_year > 2099))
+ return -EINVAL;
+
+ if ((tm->tm_mon < 1) || (tm->tm_mon > 12))
+ return -EINVAL;
+
+ if ((tm->tm_mday < 1) || (tm->tm_mday > 31))
+ return -EINVAL;
+
+ if ((tm->tm_wday < 0) || (tm->tm_wday > 6))
+ return -EINVAL;
+
+ if ((tm->tm_hour < 0) || (tm->tm_hour > 23))
+ return -EINVAL;
+
+ if ((tm->tm_min < 0) || (tm->tm_min > 59))
+ return -EINVAL;
+
+ if ((tm->tm_sec < 0) || (tm->tm_sec > 59))
+ return -EINVAL;
+
+ return 0;
+}
+
+void rx8010sj_rtc_init(DEV_TYPE *dev)
+{
+ u8 ctrl[2];
+ int need_clear = 0, ret = 0;
+
+ /* Initialize reserved registers as specified in datasheet */
+ ret = rx8010sj_rtc_write8(dev, RX8010_RESV17, 0xD8);
+ if (ret < 0)
+ goto error;
+
+ ret = rx8010sj_rtc_write8(dev, RX8010_RESV30, 0x00);
+ if (ret < 0)
+ goto error;
+
+ ret = rx8010sj_rtc_write8(dev, RX8010_RESV31, 0x08);
+ if (ret < 0)
+ goto error;
+
+ ret = rx8010sj_rtc_write8(dev, RX8010_IRQ, 0x00);
+ if (ret < 0)
+ goto error;
+
+ for (int i = 0; i < 2; i++) {
+ ret = rx8010sj_rtc_read8(dev, RX8010_FLAG + i);
+ if (ret < 0)
+ goto error;
+
+ ctrl[i] = ret;
+ }
+
+ if (ctrl[0] & RX8010_FLAG_VLF)
+ printf("RTC low voltage detected\n");
+
+ if (ctrl[0] & RX8010_FLAG_AF) {
+ printf("Alarm was detected\n");
+ need_clear = 1;
+ }
+
+ if (ctrl[0] & RX8010_FLAG_TF)
+ need_clear = 1;
+
+ if (ctrl[0] & RX8010_FLAG_UF)
+ need_clear = 1;
+
+ if (need_clear) {
+ ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF);
+ ret = rx8010sj_rtc_write8(dev, RX8010_FLAG, ctrl[0]);
+ if (ret < 0)
+ goto error;
+ }
+
+ return;
+
+error:
+ printf("Error rtc init.\n");
+}
+
+/* Get the current time from the RTC */
+static int rx8010sj_rtc_get(DEV_TYPE *dev, struct rtc_time *tmp)
+{
+ u8 date[7];
+ int flagreg;
+ int ret;
+
+ flagreg = rx8010sj_rtc_read8(dev, RX8010_FLAG);
+ if (flagreg < 0) {
+ DEBUGR("Error reading from RTC. err: %d\n", flagreg);
+ return -EIO;
+ }
+
+ if (flagreg & RX8010_FLAG_VLF) {
+ DEBUGR("RTC low voltage detected\n");
+ return -EINVAL;
+ }
+
+ for (int i = 0; i < 7; i++) {
+ ret = rx8010sj_rtc_read8(dev, RX8010_SEC + i);
+ if (ret < 0) {
+ DEBUGR("Error reading from RTC. err: %d\n", ret);
+ return -EIO;
+ }
+ date[i] = ret;
+ }
+
+ tmp->tm_sec = bcd2bin(date[RX8010_SEC - RX8010_SEC] & 0x7f);
+ tmp->tm_min = bcd2bin(date[RX8010_MIN - RX8010_SEC] & 0x7f);
+ tmp->tm_hour = bcd2bin(date[RX8010_HOUR - RX8010_SEC] & 0x3f);
+ tmp->tm_mday = bcd2bin(date[RX8010_MDAY - RX8010_SEC] & 0x3f);
+ tmp->tm_mon = bcd2bin(date[RX8010_MONTH - RX8010_SEC] & 0x1f);
+ tmp->tm_year = bcd2bin(date[RX8010_YEAR - RX8010_SEC]) + 2000;
+ tmp->tm_wday = 0;
+ tmp->tm_yday = 0;
+ tmp->tm_isdst = 0;
+
+ DEBUGR("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
+ tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
+ tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+
+ return 0;
+}
+
+/* Set the RTC */
+static int rx8010sj_rtc_set(DEV_TYPE *dev, const struct rtc_time *tm)
+{
+ u8 date[7];
+ int ctrl, flagreg;
+ int ret;
+
+ ret = validate_time(tm);
+ if (ret < 0)
+ return -EINVAL;
+
+ /* set STOP bit before changing clock/calendar */
+ ctrl = rx8010sj_rtc_read8(dev, RX8010_CTRL);
+ if (ctrl < 0)
+ return ctrl;
+ ret = rx8010sj_rtc_write8(dev, RX8010_CTRL, ctrl | RX8010_CTRL_STOP);
+ if (ret < 0)
+ return ret;
+
+ date[RX8010_SEC - RX8010_SEC] = bin2bcd(tm->tm_sec);
+ date[RX8010_MIN - RX8010_SEC] = bin2bcd(tm->tm_min);
+ date[RX8010_HOUR - RX8010_SEC] = bin2bcd(tm->tm_hour);
+ date[RX8010_MDAY - RX8010_SEC] = bin2bcd(tm->tm_mday);
+ date[RX8010_MONTH - RX8010_SEC] = bin2bcd(tm->tm_mon);
+ date[RX8010_YEAR - RX8010_SEC] = bin2bcd(tm->tm_year - 2000);
+ date[RX8010_WDAY - RX8010_SEC] = bin2bcd(tm->tm_wday);
+
+ for (int i = 0; i < 7; i++) {
+ ret = rx8010sj_rtc_write8(dev, RX8010_SEC + i, date[i]);
+ if (ret < 0) {
+ DEBUGR("Error writing to RTC. err: %d\n", ret);
+ return -EIO;
+ }
+ }
+
+ /* clear STOP bit after changing clock/calendar */
+ ctrl = rx8010sj_rtc_read8(dev, RX8010_CTRL);
+ if (ctrl < 0)
+ return ctrl;
+
+ ret = rx8010sj_rtc_write8(dev, RX8010_CTRL, ctrl & ~RX8010_CTRL_STOP);
+ if (ret < 0)
+ return ret;
+
+ flagreg = rx8010sj_rtc_read8(dev, RX8010_FLAG);
+ if (flagreg < 0)
+ return flagreg;
+
+ if (flagreg & RX8010_FLAG_VLF)
+ ret = rx8010sj_rtc_write8(dev, RX8010_FLAG,
+ flagreg & ~RX8010_FLAG_VLF);
+
+ return 0;
+}
+
+/* Reset the RTC. */
+static int rx8010sj_rtc_reset(DEV_TYPE *dev)
+{
+ /* Not needed */
+ return 0;
+}
+
+#ifndef CONFIG_DM_RTC
+
+int rtc_get(struct rtc_time *tm)
+{
+ struct ludevice dev = {
+ .chip = CONFIG_SYS_I2C_RTC_ADDR,
+ };
+
+ return rx8010sj_rtc_get(&dev, tm);
+}
+
+int rtc_set(struct rtc_time *tm)
+{
+ struct ludevice dev = {
+ .chip = CONFIG_SYS_I2C_RTC_ADDR,
+ };
+
+ return rx8010sj_rtc_set(&dev, tm);
+}
+
+void rtc_reset(void)
+{
+ struct ludevice dev = {
+ .chip = CONFIG_SYS_I2C_RTC_ADDR,
+ };
+
+ rx8010sj_rtc_reset(&dev);
+}
+
+void rtc_init(void)
+{
+ struct ludevice dev = {
+ .chip = CONFIG_SYS_I2C_RTC_ADDR,
+ };
+
+ rx8010sj_rtc_init(&dev);
+}
+
+#else
+
+static int rx8010sj_probe(struct udevice *dev)
+{
+ rx8010sj_rtc_init(&dev);
+
+ return 0;
+}
+
+static const struct rtc_ops rx8010sj_rtc_ops = {
+ .get = rx8010sj_rtc_get,
+ .set = rx8010sj_rtc_set,
+ .read8 = rx8010sj_rtc_read8,
+ .write8 = rx8010sj_rtc_write8,
+ .reset = rx8010sj_rtc_reset,
+};
+
+static const struct udevice_id rx8010sj_rtc_ids[] = {
+ { .compatible = "epson,rx8010sj-rtc" },
+ { }
+};
+
+U_BOOT_DRIVER(rx8010sj_rtc) = {
+ .name = "rx8010sj_rtc",
+ .id = UCLASS_RTC,
+ .probe = rx8010sj_probe,
+ .of_match = rx8010sj_rtc_ids,
+ .ops = &rx8010sj_rtc_ops,
+};
+
+#endif