From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DDF4CC47093 for ; Wed, 2 Jun 2021 20:40:18 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 42861613DA for ; Wed, 2 Jun 2021 20:40:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 42861613DA Authentication-Results: mail.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=libero.it Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id BE57282F79; Wed, 2 Jun 2021 22:38:50 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=libero.it Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=libero.it header.i=@libero.it header.b="aaFHGLJq"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9795D82F42; Wed, 2 Jun 2021 22:38:35 +0200 (CEST) Received: from libero.it (smtp-35-i2.italiaonline.it [213.209.12.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 6C42482F4C for ; Wed, 2 Jun 2021 22:38:27 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=quarantine dis=none) header.from=libero.it Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=dariobin@libero.it Received: from passgat-Modern-14-A10M.homenet.telecomitalia.it ([79.17.119.101]) by smtp-35.iol.local with ESMTPA id oXctlNwhysptioXdDlNDiU; Wed, 02 Jun 2021 22:38:27 +0200 x-libjamoibt: 1601 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=libero.it; s=s2021; t=1622666307; bh=ssM4J7+GIPWj6ZZhdG8RcIrF5STMeO4wX8V5KxxolCg=; h=From; b=aaFHGLJq8ejLe5jQyghUSirx/R06AJPml5k2Uqs10JboiN14xt5dymEpN5pfhyZrX CLVelzjrASFj+XY4Fahb9+rAaQCqyEvW12c34/YLyxrqopvtJLHKaq8zcbTYQiypXk qfoH+5KldQJKRbyUdQMwO0HIqmJRyQCotYGo0RAhl/yNtehbbBAAVgdJFy4CdHJbnU gCv/mm6Z20la7ORtmu+ZWlISp57oZYFr+pelObdXBXdQjV7alUumztyff4Yese1cLM G3h+rPOduGAkocPAHK3DeUl2ymGkAhIkxjK4JhWYgGagVjjoXdhPPyhx1eysKt4pde T8p6/0a9NPYoQ== X-CNFS-Analysis: v=2.4 cv=Bo1Yfab5 c=1 sm=1 tr=0 ts=60b7ec43 cx=a_exe a=do1bHx4A/kh2kuTIUQHSxQ==:117 a=do1bHx4A/kh2kuTIUQHSxQ==:17 a=MQ0KurTrLJtgj8GxUgAA:9 From: Dario Binacchi To: u-boot@lists.denx.de Cc: Dario Binacchi , Lokesh Vutla Subject: [PATCH v2 7/8] rtc: davinci: add driver model support Date: Wed, 2 Jun 2021 22:38:04 +0200 Message-Id: <20210602203805.11494-8-dariobin@libero.it> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210602203805.11494-1-dariobin@libero.it> References: <20210602203805.11494-1-dariobin@libero.it> X-CMAE-Envelope: MS4xfP5wprdIZ8mHEl+Ffoz6LEO1+O1PgMB9Jj3IYPiMzoQ54W2SWHWwdTfp8RvYL1IaBVQGPh9Zsuz/8vDCmgyxx4zp6t5TtxMuFg9fpwxjl+9giIw9FRZg iILPEC10Cmgp8fGP+wP9kMzA8EPIEQV40T18/qW6RtOIMBufe8v1ch1dxlleQ1+IJ+Q1bbdGWm/PYlUhLj2kG0uiSt0EvS5Jekxww1sUO8Zb41tswkQoNtdS WlL+tfKlOyi6PAjm7tEmBNOXBo+MpSwHB3EibzcI7xndMGB5gov4OMiapfCCqf7M X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.4 at phobos.denx.de X-Virus-Status: Clean Update the driver to support the device tree and the driver model. The read / write helpers in rtc_ops allow access to scratch registers only. The offset parameter is added to the address of the scratch0 register. Support for non-DM has been removed as there were no users. Signed-off-by: Dario Binacchi --- Changes in v2: - Use consistent naming (omap_rtc_. - Remove non-DM support. It's no more used. drivers/rtc/davinci.c | 428 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 367 insertions(+), 61 deletions(-) diff --git a/drivers/rtc/davinci.c b/drivers/rtc/davinci.c index 82e5eb3b43..21e5234477 100644 --- a/drivers/rtc/davinci.c +++ b/drivers/rtc/davinci.c @@ -2,127 +2,433 @@ /* * (C) Copyright 2011 DENX Software Engineering GmbH * Heiko Schocher + * Copyright (C) 2021 Dario Binacchi */ #include #include +#include +#include #include #include #include -#include -#include +#include #include -#if !defined(RTC_BASE) && defined(DAVINCI_RTC_BASE) -#define RTC_BASE DAVINCI_RTC_BASE -#endif +/* RTC registers */ +#define OMAP_RTC_SECONDS_REG 0x00 +#define OMAP_RTC_MINUTES_REG 0x04 +#define OMAP_RTC_HOURS_REG 0x08 +#define OMAP_RTC_DAYS_REG 0x0C +#define OMAP_RTC_MONTHS_REG 0x10 +#define OMAP_RTC_YEARS_REG 0x14 +#define OMAP_RTC_WEEKS_REG 0x18 -static void davinci_rtc_lock(struct davinci_rtc *rtc) +#define OMAP_RTC_CTRL_REG 0x40 +#define OMAP_RTC_STATUS_REG 0x44 +#define OMAP_RTC_INTERRUPTS_REG 0x48 + +#define OMAP_RTC_OSC_REG 0x54 + +#define OMAP_RTC_SCRATCH0_REG 0x60 +#define OMAP_RTC_SCRATCH1_REG 0x64 +#define OMAP_RTC_SCRATCH2_REG 0x68 + +#define OMAP_RTC_KICK0_REG 0x6c +#define OMAP_RTC_KICK1_REG 0x70 + +#define OMAP_RTC_PMIC_REG 0x98 + +/* OMAP_RTC_CTRL_REG bit fields: */ +#define OMAP_RTC_CTRL_SPLIT BIT(7) +#define OMAP_RTC_CTRL_DISABLE BIT(6) +#define OMAP_RTC_CTRL_SET_32_COUNTER BIT(5) +#define OMAP_RTC_CTRL_TEST BIT(4) +#define OMAP_RTC_CTRL_MODE_12_24 BIT(3) +#define OMAP_RTC_CTRL_AUTO_COMP BIT(2) +#define OMAP_RTC_CTRL_ROUND_30S BIT(1) +#define OMAP_RTC_CTRL_STOP BIT(0) + +/* OMAP_RTC_STATUS_REG bit fields */ +#define OMAP_RTC_STATUS_POWER_UP BIT(7) +#define OMAP_RTC_STATUS_ALARM2 BIT(7) +#define OMAP_RTC_STATUS_ALARM BIT(6) +#define OMAP_RTC_STATUS_1D_EVENT BIT(5) +#define OMAP_RTC_STATUS_1H_EVENT BIT(4) +#define OMAP_RTC_STATUS_1M_EVENT BIT(3) +#define OMAP_RTC_STATUS_1S_EVENT BIT(2) +#define OMAP_RTC_STATUS_RUN BIT(1) +#define OMAP_RTC_STATUS_BUSY BIT(0) + +/* OMAP_RTC_OSC_REG bit fields */ +#define OMAP_RTC_OSC_32KCLK_EN BIT(6) +#define OMAP_RTC_OSC_SEL_32KCLK_SRC BIT(3) +#define OMAP_RTC_OSC_OSC32K_GZ_DISABLE BIT(4) + +/* OMAP_RTC_KICKER values */ +#define OMAP_RTC_KICK0_VALUE 0x83e70b13 +#define OMAP_RTC_KICK1_VALUE 0x95a4f1e0 + +struct omap_rtc_device_type { + bool has_32kclk_en; + bool has_irqwakeen; + bool has_pmic_mode; + bool has_power_up_reset; +}; + +struct omap_rtc_priv { + fdt_addr_t base; + u8 max_reg; + struct udevice *dev; + struct clk clk; + bool has_ext_clk; + const struct omap_rtc_device_type *type; +}; + +static inline u8 omap_rtc_readb(struct omap_rtc_priv *priv, unsigned int reg) +{ + return readb(priv->base + reg); +} + +static inline u32 omap_rtc_readl(struct omap_rtc_priv *priv, unsigned int reg) +{ + return readl(priv->base + reg); +} + +static inline void omap_rtc_writeb(struct omap_rtc_priv *priv, unsigned int reg, + u8 val) +{ + writeb(val, priv->base + reg); +} + +static inline void omap_rtc_writel(struct omap_rtc_priv *priv, unsigned int reg, + u32 val) +{ + writel(val, priv->base + reg); +} + +static inline void omap_rtc_unlock(struct omap_rtc_priv *priv) { - writel(0, &rtc->kick0r); - writel(0, &rtc->kick1r); + omap_rtc_writel(priv, OMAP_RTC_KICK0_REG, OMAP_RTC_KICK0_VALUE); + omap_rtc_writel(priv, OMAP_RTC_KICK1_REG, OMAP_RTC_KICK1_VALUE); } -static void davinci_rtc_unlock(struct davinci_rtc *rtc) +static inline void omap_rtc_lock(struct omap_rtc_priv *priv) { - writel(RTC_KICK0R_WE, &rtc->kick0r); - writel(RTC_KICK1R_WE, &rtc->kick1r); + omap_rtc_writel(priv, OMAP_RTC_KICK0_REG, 0); + omap_rtc_writel(priv, OMAP_RTC_KICK1_REG, 0); } -static int davinci_rtc_wait_not_busy(struct davinci_rtc *rtc) +static int omap_rtc_wait_not_busy(struct omap_rtc_priv *priv) { int count; u8 status; - status = readb(&rtc->status); - if ((status & RTC_STATE_RUN) != RTC_STATE_RUN) { + status = omap_rtc_readb(priv, OMAP_RTC_STATUS_REG); + if ((status & OMAP_RTC_STATUS_RUN) != OMAP_RTC_STATUS_RUN) { printf("RTC doesn't run\n"); return -1; } /* BUSY may stay active for 1/32768 second (~30 usec) */ for (count = 0; count < 50; count++) { - if (!(status & RTC_STATE_BUSY)) + if (!(status & OMAP_RTC_STATUS_BUSY)) break; udelay(1); - status = readb(&rtc->status); + status = omap_rtc_readb(priv, OMAP_RTC_STATUS_REG); } /* now we have ~15 usec to read/write various registers */ return 0; } -int rtc_get(struct rtc_time *tmp) +static int omap_rtc_reset(struct udevice *dev) +{ + struct omap_rtc_priv *priv = dev_get_priv(dev); + + /* run RTC counter */ + omap_rtc_writeb(priv, OMAP_RTC_CTRL_REG, 0x01); + return 0; +} + +static int omap_rtc_set(struct udevice *dev, const struct rtc_time *tm) +{ + struct omap_rtc_priv *priv = dev_get_priv(dev); + int ret; + + ret = omap_rtc_wait_not_busy(priv); + if (ret) + return ret; + + omap_rtc_unlock(priv); + omap_rtc_writeb(priv, OMAP_RTC_YEARS_REG, bin2bcd(tm->tm_year % 100)); + omap_rtc_writeb(priv, OMAP_RTC_MONTHS_REG, bin2bcd(tm->tm_mon)); + omap_rtc_writeb(priv, OMAP_RTC_WEEKS_REG, bin2bcd(tm->tm_wday)); + omap_rtc_writeb(priv, OMAP_RTC_DAYS_REG, bin2bcd(tm->tm_mday)); + omap_rtc_writeb(priv, OMAP_RTC_HOURS_REG, bin2bcd(tm->tm_hour)); + omap_rtc_writeb(priv, OMAP_RTC_MINUTES_REG, bin2bcd(tm->tm_min)); + omap_rtc_writeb(priv, OMAP_RTC_SECONDS_REG, bin2bcd(tm->tm_sec)); + omap_rtc_lock(priv); + + dev_dbg(dev, "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, tm->tm_hour, + tm->tm_min, tm->tm_sec); + + return 0; +} + +static int omap_rtc_get(struct udevice *dev, struct rtc_time *tm) { - struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE; + struct omap_rtc_priv *priv = dev_get_priv(dev); unsigned long sec, min, hour, mday, wday, mon_cent, year; int ret; - ret = davinci_rtc_wait_not_busy(rtc); + ret = omap_rtc_wait_not_busy(priv); if (ret) return ret; - sec = readb(&rtc->second); - min = readb(&rtc->minutes); - hour = readb(&rtc->hours); - mday = readb(&rtc->day); - wday = readb(&rtc->dotw); - mon_cent = readb(&rtc->month); - year = readb(&rtc->year); + sec = omap_rtc_readb(priv, OMAP_RTC_SECONDS_REG); + min = omap_rtc_readb(priv, OMAP_RTC_MINUTES_REG); + hour = omap_rtc_readb(priv, OMAP_RTC_HOURS_REG); + mday = omap_rtc_readb(priv, OMAP_RTC_DAYS_REG); + wday = omap_rtc_readb(priv, OMAP_RTC_WEEKS_REG); + mon_cent = omap_rtc_readb(priv, OMAP_RTC_MONTHS_REG); + year = omap_rtc_readb(priv, OMAP_RTC_YEARS_REG); - debug("Get RTC year: %02lx mon/cent: %02lx mday: %02lx wday: %02lx " + dev_dbg(dev, + "Get RTC year: %02lx mon/cent: %02lx mday: %02lx wday: %02lx " "hr: %02lx min: %02lx sec: %02lx\n", year, mon_cent, mday, wday, hour, min, sec); - tmp->tm_sec = bcd2bin(sec & 0x7F); - tmp->tm_min = bcd2bin(min & 0x7F); - tmp->tm_hour = bcd2bin(hour & 0x3F); - tmp->tm_mday = bcd2bin(mday & 0x3F); - tmp->tm_mon = bcd2bin(mon_cent & 0x1F); - tmp->tm_year = bcd2bin(year) + 2000; - tmp->tm_wday = bcd2bin(wday & 0x07); - tmp->tm_yday = 0; - tmp->tm_isdst = 0; + tm->tm_sec = bcd2bin(sec & 0x7F); + tm->tm_min = bcd2bin(min & 0x7F); + tm->tm_hour = bcd2bin(hour & 0x3F); + tm->tm_mday = bcd2bin(mday & 0x3F); + tm->tm_mon = bcd2bin(mon_cent & 0x1F); + tm->tm_year = bcd2bin(year) + 2000; + tm->tm_wday = bcd2bin(wday & 0x07); + tm->tm_yday = 0; + tm->tm_isdst = 0; - debug("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); + dev_dbg(dev, "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, tm->tm_hour, + tm->tm_min, tm->tm_sec); return 0; } -int rtc_set(struct rtc_time *tmp) +static int omap_rtc_scratch_read(struct udevice *dev, uint offset, + u8 *buffer, uint len) { - struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE; - int ret; + struct omap_rtc_priv *priv = dev_get_priv(dev); + u32 *val = (u32 *)buffer; + unsigned int reg; + int i; - ret = davinci_rtc_wait_not_busy(rtc); - if (ret) - return ret; + if (len & 3) + return -EFAULT; + + for (i = 0; i < len / 4; i++) { + reg = OMAP_RTC_SCRATCH0_REG + offset + (i * 4); + if (reg >= OMAP_RTC_KICK0_REG) + return -EFAULT; + + val[i] = omap_rtc_readl(priv, reg); + } + + return 0; +} + +static int omap_rtc_scratch_write(struct udevice *dev, uint offset, + const u8 *buffer, uint len) +{ + struct omap_rtc_priv *priv = dev_get_priv(dev); + u32 *val = (u32 *)buffer; + unsigned int reg; + int i; - davinci_rtc_unlock(rtc); - writeb(bin2bcd(tmp->tm_year % 100), &rtc->year); - writeb(bin2bcd(tmp->tm_mon), &rtc->month); + if (len & 3) + return -EFAULT; - writeb(bin2bcd(tmp->tm_wday), &rtc->dotw); - writeb(bin2bcd(tmp->tm_mday), &rtc->day); - writeb(bin2bcd(tmp->tm_hour), &rtc->hours); - writeb(bin2bcd(tmp->tm_min), &rtc->minutes); - writeb(bin2bcd(tmp->tm_sec), &rtc->second); - davinci_rtc_lock(rtc); + omap_rtc_unlock(priv); + for (i = 0; i < len / 4; i++) { + reg = OMAP_RTC_SCRATCH0_REG + offset + (i * 4); + if (reg >= OMAP_RTC_KICK0_REG) + return -EFAULT; - debug("Set 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); + omap_rtc_writel(priv, reg, val[i]); + } + omap_rtc_lock(priv); return 0; } -void rtc_reset(void) +static int omap_rtc_remove(struct udevice *dev) { - struct davinci_rtc *rtc = (struct davinci_rtc *)RTC_BASE; + struct omap_rtc_priv *priv = dev_get_priv(dev); + u8 reg; - /* run RTC counter */ - writeb(0x01, &rtc->ctrl); + if (priv->clk.dev) + clk_disable(&priv->clk); + + omap_rtc_unlock(priv); + + /* leave rtc running, but disable irqs */ + omap_rtc_writeb(priv, OMAP_RTC_INTERRUPTS_REG, 0); + + if (priv->has_ext_clk) { + reg = omap_rtc_readb(priv, OMAP_RTC_OSC_REG); + reg &= ~OMAP_RTC_OSC_SEL_32KCLK_SRC; + omap_rtc_writeb(priv, OMAP_RTC_OSC_REG, reg); + } + + omap_rtc_lock(priv); + return 0; +} + +static int omap_rtc_probe(struct udevice *dev) +{ + struct omap_rtc_priv *priv = dev_get_priv(dev); + u8 reg, mask, new_ctrl; + + priv->dev = dev; + priv->type = (struct omap_rtc_device_type *)dev_get_driver_data(dev); + priv->max_reg = OMAP_RTC_PMIC_REG; + + if (!clk_get_by_name(dev, "ext-clk", &priv->clk)) + priv->has_ext_clk = true; + else + clk_get_by_name(dev, "int-clk", &priv->clk); + + if (priv->clk.dev) + clk_enable(&priv->clk); + else + dev_warn(dev, "missing clock\n"); + + omap_rtc_unlock(priv); + + /* + * disable interrupts + * + * NOTE: ALARM2 is not cleared on AM3352 if rtc_write (writeb) is used + */ + omap_rtc_writel(priv, OMAP_RTC_INTERRUPTS_REG, 0); + + if (priv->type->has_32kclk_en) { + reg = omap_rtc_readb(priv, OMAP_RTC_OSC_REG); + omap_rtc_writeb(priv, OMAP_RTC_OSC_REG, + reg | OMAP_RTC_OSC_32KCLK_EN); + } + + /* clear old status */ + reg = omap_rtc_readb(priv, OMAP_RTC_STATUS_REG); + + mask = OMAP_RTC_STATUS_ALARM; + + if (priv->type->has_pmic_mode) + mask |= OMAP_RTC_STATUS_ALARM2; + + if (priv->type->has_power_up_reset) { + mask |= OMAP_RTC_STATUS_POWER_UP; + if (reg & OMAP_RTC_STATUS_POWER_UP) + dev_info(dev, "RTC power up reset detected\n"); + } + + if (reg & mask) + omap_rtc_writeb(priv, OMAP_RTC_STATUS_REG, reg & mask); + + /* On boards with split power, RTC_ON_NOFF won't reset the RTC */ + reg = omap_rtc_readb(priv, OMAP_RTC_CTRL_REG); + if (reg & OMAP_RTC_CTRL_STOP) + dev_info(dev, "already running\n"); + + /* force to 24 hour mode */ + new_ctrl = reg & (OMAP_RTC_CTRL_SPLIT | OMAP_RTC_CTRL_AUTO_COMP); + new_ctrl |= OMAP_RTC_CTRL_STOP; + + /* + * BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE: + * + * - Device wake-up capability setting should come through chip + * init logic. OMAP1 boards should initialize the "wakeup capable" + * flag in the platform device if the board is wired right for + * being woken up by RTC alarm. For OMAP-L138, this capability + * is built into the SoC by the "Deep Sleep" capability. + * + * - Boards wired so RTC_ON_nOFF is used as the reset signal, + * rather than nPWRON_RESET, should forcibly enable split + * power mode. (Some chip errata report that RTC_CTRL_SPLIT + * is write-only, and always reads as zero...) + */ + + if (new_ctrl & OMAP_RTC_CTRL_SPLIT) + dev_info(dev, "split power mode\n"); + + if (reg != new_ctrl) + omap_rtc_writeb(priv, OMAP_RTC_CTRL_REG, new_ctrl); + + /* + * If we have the external clock then switch to it so we can keep + * ticking across suspend. + */ + if (priv->has_ext_clk) { + reg = omap_rtc_readb(priv, OMAP_RTC_OSC_REG); + reg &= ~OMAP_RTC_OSC_OSC32K_GZ_DISABLE; + reg |= OMAP_RTC_OSC_32KCLK_EN | OMAP_RTC_OSC_SEL_32KCLK_SRC; + omap_rtc_writeb(priv, OMAP_RTC_OSC_REG, reg); + } + + omap_rtc_lock(priv); + return 0; } + +static int omap_rtc_of_to_plat(struct udevice *dev) +{ + struct omap_rtc_priv *priv = dev_get_priv(dev); + + priv->base = dev_read_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) { + dev_err(dev, "invalid address\n"); + return -EINVAL; + } + + dev_dbg(dev, "base=%pa\n", &priv->base); + return 0; +} + +static const struct rtc_ops omap_rtc_ops = { + .get = omap_rtc_get, + .set = omap_rtc_set, + .reset = omap_rtc_reset, + .read = omap_rtc_scratch_read, + .write = omap_rtc_scratch_write, +}; + +static const struct omap_rtc_device_type omap_rtc_am3352_type = { + .has_32kclk_en = true, + .has_irqwakeen = true, + .has_pmic_mode = true, +}; + +static const struct omap_rtc_device_type omap_rtc_da830_type = { + .has_32kclk_en = false, + .has_irqwakeen = false, + .has_pmic_mode = false, +}; + +static const struct udevice_id omap_rtc_ids[] = { + {.compatible = "ti,am3352-rtc", .data = (ulong)&omap_rtc_am3352_type}, + {.compatible = "ti,da830-rtc", .data = (ulong)&omap_rtc_da830_type } +}; + +U_BOOT_DRIVER(omap_rtc) = { + .name = "omap_rtc", + .id = UCLASS_RTC, + .of_match = omap_rtc_ids, + .ops = &omap_rtc_ops, + .of_to_plat = omap_rtc_of_to_plat, + .probe = omap_rtc_probe, + .remove = omap_rtc_remove, + .priv_auto = sizeof(struct omap_rtc_priv), +}; -- 2.17.1